From c62cb18c482eebf5e48ddcc54b9fdba7d64c241e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Wed, 28 Aug 2019 23:25:45 +0200 Subject: [PATCH 01/66] added copy of libmdbx into folder tree(ref to git submodule will be added later) --- contrib/db/libmdbx/.circleci/config.yml | 20 + contrib/db/libmdbx/.clang-format | 3 + contrib/db/libmdbx/.gitignore | 38 + contrib/db/libmdbx/.travis.yml | 30 + contrib/db/libmdbx/AUTHORS | 31 + contrib/db/libmdbx/COPYRIGHT | 22 + contrib/db/libmdbx/LICENSE | 47 + contrib/db/libmdbx/Makefile | 270 + contrib/db/libmdbx/README-RU.md | 830 + contrib/db/libmdbx/README.md | 701 + contrib/db/libmdbx/appveyor.yml | 54 + contrib/db/libmdbx/dll.vcxproj | 223 + contrib/db/libmdbx/libmdbx.cflags | 1 + contrib/db/libmdbx/libmdbx.config | 2 + contrib/db/libmdbx/libmdbx.creator | 1 + contrib/db/libmdbx/libmdbx.cxxflags | 1 + contrib/db/libmdbx/libmdbx.files | 62 + contrib/db/libmdbx/libmdbx.includes | 4 + contrib/db/libmdbx/mdbx.h | 2005 +++ contrib/db/libmdbx/mdbx.sln | 97 + .../db/libmdbx/packages/rpm/CMakeLists.txt | 184 + contrib/db/libmdbx/packages/rpm/build.sh | 18 + contrib/db/libmdbx/packages/rpm/package.sh | 25 + contrib/db/libmdbx/src/bits.h | 1252 ++ contrib/db/libmdbx/src/defs.h | 447 + contrib/db/libmdbx/src/lck-linux.c | 428 + contrib/db/libmdbx/src/lck-posix.c | 389 + contrib/db/libmdbx/src/lck-windows.c | 707 + contrib/db/libmdbx/src/mdbx.c | 14492 ++++++++++++++++ contrib/db/libmdbx/src/ntdll.def | 1244 ++ contrib/db/libmdbx/src/osal.c | 1319 ++ contrib/db/libmdbx/src/osal.h | 899 + contrib/db/libmdbx/src/tools/CMakeLists.txt | 19 + contrib/db/libmdbx/src/tools/mdbx_chk.c | 1417 ++ contrib/db/libmdbx/src/tools/mdbx_chk.vcxproj | 166 + contrib/db/libmdbx/src/tools/mdbx_copy.1 | 57 + contrib/db/libmdbx/src/tools/mdbx_copy.c | 109 + .../db/libmdbx/src/tools/mdbx_copy.vcxproj | 166 + contrib/db/libmdbx/src/tools/mdbx_dump.1 | 77 + contrib/db/libmdbx/src/tools/mdbx_dump.c | 340 + .../db/libmdbx/src/tools/mdbx_dump.vcxproj | 166 + contrib/db/libmdbx/src/tools/mdbx_load.1 | 86 + contrib/db/libmdbx/src/tools/mdbx_load.c | 554 + .../db/libmdbx/src/tools/mdbx_load.vcxproj | 166 + contrib/db/libmdbx/src/tools/mdbx_stat.1 | 66 + contrib/db/libmdbx/src/tools/mdbx_stat.c | 392 + .../db/libmdbx/src/tools/mdbx_stat.vcxproj | 166 + contrib/db/libmdbx/src/tools/wingetopt.c | 95 + contrib/db/libmdbx/src/tools/wingetopt.h | 26 + contrib/db/libmdbx/src/version.c | 34 + contrib/db/libmdbx/test/CMakeLists.txt | 37 + contrib/db/libmdbx/test/append.cc | 165 + contrib/db/libmdbx/test/base.h | 113 + contrib/db/libmdbx/test/cases.cc | 99 + contrib/db/libmdbx/test/chrono.cc | 129 + contrib/db/libmdbx/test/chrono.h | 100 + contrib/db/libmdbx/test/config.cc | 576 + contrib/db/libmdbx/test/config.h | 326 + contrib/db/libmdbx/test/copy.cc | 26 + contrib/db/libmdbx/test/darwin/LICENSE | 24 + contrib/db/libmdbx/test/darwin/README.md | 8 + .../db/libmdbx/test/darwin/pthread_barrier.c | 110 + .../db/libmdbx/test/darwin/pthread_barrier.h | 83 + contrib/db/libmdbx/test/dead.cc | 35 + contrib/db/libmdbx/test/hill.cc | 321 + contrib/db/libmdbx/test/jitter.cc | 59 + contrib/db/libmdbx/test/keygen.cc | 275 + contrib/db/libmdbx/test/keygen.h | 130 + contrib/db/libmdbx/test/log.cc | 325 + contrib/db/libmdbx/test/log.h | 83 + contrib/db/libmdbx/test/long_stochastic.sh | 138 + contrib/db/libmdbx/test/main.cc | 488 + contrib/db/libmdbx/test/osal-unix.cc | 313 + contrib/db/libmdbx/test/osal-windows.cc | 419 + contrib/db/libmdbx/test/osal.h | 47 + contrib/db/libmdbx/test/pcrf/CMakeLists.txt | 7 + contrib/db/libmdbx/test/pcrf/README.md | 2 + contrib/db/libmdbx/test/pcrf/pcrf_test.c | 404 + contrib/db/libmdbx/test/test.cc | 601 + contrib/db/libmdbx/test/test.h | 218 + contrib/db/libmdbx/test/test.vcxproj | 209 + contrib/db/libmdbx/test/try.cc | 20 + contrib/db/libmdbx/test/ttl.cc | 179 + contrib/db/libmdbx/test/utils.cc | 367 + contrib/db/libmdbx/test/utils.h | 359 + contrib/db/libmdbx/tutorial/CMakeLists.txt | 7 + contrib/db/libmdbx/tutorial/README.md | 1 + contrib/db/libmdbx/tutorial/sample-bdb.txt | 77 + contrib/db/libmdbx/tutorial/sample-mdbx.c | 112 + 89 files changed, 36940 insertions(+) create mode 100644 contrib/db/libmdbx/.circleci/config.yml create mode 100644 contrib/db/libmdbx/.clang-format create mode 100644 contrib/db/libmdbx/.gitignore create mode 100644 contrib/db/libmdbx/.travis.yml create mode 100644 contrib/db/libmdbx/AUTHORS create mode 100644 contrib/db/libmdbx/COPYRIGHT create mode 100644 contrib/db/libmdbx/LICENSE create mode 100644 contrib/db/libmdbx/Makefile create mode 100644 contrib/db/libmdbx/README-RU.md create mode 100644 contrib/db/libmdbx/README.md create mode 100644 contrib/db/libmdbx/appveyor.yml create mode 100644 contrib/db/libmdbx/dll.vcxproj create mode 100644 contrib/db/libmdbx/libmdbx.cflags create mode 100644 contrib/db/libmdbx/libmdbx.config create mode 100644 contrib/db/libmdbx/libmdbx.creator create mode 100644 contrib/db/libmdbx/libmdbx.cxxflags create mode 100644 contrib/db/libmdbx/libmdbx.files create mode 100644 contrib/db/libmdbx/libmdbx.includes create mode 100644 contrib/db/libmdbx/mdbx.h create mode 100644 contrib/db/libmdbx/mdbx.sln create mode 100644 contrib/db/libmdbx/packages/rpm/CMakeLists.txt create mode 100644 contrib/db/libmdbx/packages/rpm/build.sh create mode 100644 contrib/db/libmdbx/packages/rpm/package.sh create mode 100644 contrib/db/libmdbx/src/bits.h create mode 100644 contrib/db/libmdbx/src/defs.h create mode 100644 contrib/db/libmdbx/src/lck-linux.c create mode 100644 contrib/db/libmdbx/src/lck-posix.c create mode 100644 contrib/db/libmdbx/src/lck-windows.c create mode 100644 contrib/db/libmdbx/src/mdbx.c create mode 100644 contrib/db/libmdbx/src/ntdll.def create mode 100644 contrib/db/libmdbx/src/osal.c create mode 100644 contrib/db/libmdbx/src/osal.h create mode 100644 contrib/db/libmdbx/src/tools/CMakeLists.txt create mode 100644 contrib/db/libmdbx/src/tools/mdbx_chk.c create mode 100644 contrib/db/libmdbx/src/tools/mdbx_chk.vcxproj create mode 100644 contrib/db/libmdbx/src/tools/mdbx_copy.1 create mode 100644 contrib/db/libmdbx/src/tools/mdbx_copy.c create mode 100644 contrib/db/libmdbx/src/tools/mdbx_copy.vcxproj create mode 100644 contrib/db/libmdbx/src/tools/mdbx_dump.1 create mode 100644 contrib/db/libmdbx/src/tools/mdbx_dump.c create mode 100644 contrib/db/libmdbx/src/tools/mdbx_dump.vcxproj create mode 100644 contrib/db/libmdbx/src/tools/mdbx_load.1 create mode 100644 contrib/db/libmdbx/src/tools/mdbx_load.c create mode 100644 contrib/db/libmdbx/src/tools/mdbx_load.vcxproj create mode 100644 contrib/db/libmdbx/src/tools/mdbx_stat.1 create mode 100644 contrib/db/libmdbx/src/tools/mdbx_stat.c create mode 100644 contrib/db/libmdbx/src/tools/mdbx_stat.vcxproj create mode 100644 contrib/db/libmdbx/src/tools/wingetopt.c create mode 100644 contrib/db/libmdbx/src/tools/wingetopt.h create mode 100644 contrib/db/libmdbx/src/version.c create mode 100644 contrib/db/libmdbx/test/CMakeLists.txt create mode 100644 contrib/db/libmdbx/test/append.cc create mode 100644 contrib/db/libmdbx/test/base.h create mode 100644 contrib/db/libmdbx/test/cases.cc create mode 100644 contrib/db/libmdbx/test/chrono.cc create mode 100644 contrib/db/libmdbx/test/chrono.h create mode 100644 contrib/db/libmdbx/test/config.cc create mode 100644 contrib/db/libmdbx/test/config.h create mode 100644 contrib/db/libmdbx/test/copy.cc create mode 100644 contrib/db/libmdbx/test/darwin/LICENSE create mode 100644 contrib/db/libmdbx/test/darwin/README.md create mode 100644 contrib/db/libmdbx/test/darwin/pthread_barrier.c create mode 100644 contrib/db/libmdbx/test/darwin/pthread_barrier.h create mode 100644 contrib/db/libmdbx/test/dead.cc create mode 100644 contrib/db/libmdbx/test/hill.cc create mode 100644 contrib/db/libmdbx/test/jitter.cc create mode 100644 contrib/db/libmdbx/test/keygen.cc create mode 100644 contrib/db/libmdbx/test/keygen.h create mode 100644 contrib/db/libmdbx/test/log.cc create mode 100644 contrib/db/libmdbx/test/log.h create mode 100644 contrib/db/libmdbx/test/long_stochastic.sh create mode 100644 contrib/db/libmdbx/test/main.cc create mode 100644 contrib/db/libmdbx/test/osal-unix.cc create mode 100644 contrib/db/libmdbx/test/osal-windows.cc create mode 100644 contrib/db/libmdbx/test/osal.h create mode 100644 contrib/db/libmdbx/test/pcrf/CMakeLists.txt create mode 100644 contrib/db/libmdbx/test/pcrf/README.md create mode 100644 contrib/db/libmdbx/test/pcrf/pcrf_test.c create mode 100644 contrib/db/libmdbx/test/test.cc create mode 100644 contrib/db/libmdbx/test/test.h create mode 100644 contrib/db/libmdbx/test/test.vcxproj create mode 100644 contrib/db/libmdbx/test/try.cc create mode 100644 contrib/db/libmdbx/test/ttl.cc create mode 100644 contrib/db/libmdbx/test/utils.cc create mode 100644 contrib/db/libmdbx/test/utils.h create mode 100644 contrib/db/libmdbx/tutorial/CMakeLists.txt create mode 100644 contrib/db/libmdbx/tutorial/README.md create mode 100644 contrib/db/libmdbx/tutorial/sample-bdb.txt create mode 100644 contrib/db/libmdbx/tutorial/sample-mdbx.c diff --git a/contrib/db/libmdbx/.circleci/config.yml b/contrib/db/libmdbx/.circleci/config.yml new file mode 100644 index 00000000..91e11a4b --- /dev/null +++ b/contrib/db/libmdbx/.circleci/config.yml @@ -0,0 +1,20 @@ +version: 2 +jobs: + build: + docker: + - image: circleci/buildpack-deps:artful + environment: + - TESTDB: /tmp/test.db + - TESTLOG: /tmp/test.log + steps: + - checkout + - run: make all + - run: ulimit -c unlimited && make check + - run: + command: | + mkdir -p /tmp/artifacts + mv -t /tmp/artifacts $TESTLOG $TESTDB core.* + when: on_fail + - store_artifacts: + path: /tmp/artifacts + destination: test-artifacts diff --git a/contrib/db/libmdbx/.clang-format b/contrib/db/libmdbx/.clang-format new file mode 100644 index 00000000..6c59ef3a --- /dev/null +++ b/contrib/db/libmdbx/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: LLVM +Standard: Cpp11 +ReflowComments: true diff --git a/contrib/db/libmdbx/.gitignore b/contrib/db/libmdbx/.gitignore new file mode 100644 index 00000000..2ea34c80 --- /dev/null +++ b/contrib/db/libmdbx/.gitignore @@ -0,0 +1,38 @@ +*.[ao] +*.bak +*.exe +*.gcda +*.gcno +*.gcov +*.lo +*.orig +*.rej +*.so +*[~#] +.idea +.le.ini +.vs/ +Win32/ +build-* +cmake-build-* +core +example +libmdbx.creator.user +mdbx-dll.VC.VC.opendb +mdbx-dll.VC.db +mdbx-dll.vcxproj.filters +mdbx_chk +mdbx_copy +mdbx_dump +mdbx_load +mdbx_stat +mdbx_test +test.log +test/test.vcxproj.user +test/tmp.db +test/tmp.db-lck +tmp.db +tmp.db-lck +valgrind.* +x64/ +x86/ diff --git a/contrib/db/libmdbx/.travis.yml b/contrib/db/libmdbx/.travis.yml new file mode 100644 index 00000000..e46991f5 --- /dev/null +++ b/contrib/db/libmdbx/.travis.yml @@ -0,0 +1,30 @@ +language: c +dist: xenial + +compiler: +- gcc +- clang + +os: +- linux +- osx + +script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make all check; fi + +env: + global: + - secure: "M+W+heGGyRQJoBq2W0uqWVrpL4KBXmL0MFL7FSs7f9vmAaDyEgziUXeZRj3GOKzW4kTef3LpIeiu9SmvqSMoQivGGiomZShqPVl045o/OUgRCAT7Al1RLzEZ0efSHpIPf0PZ6byEf6GR2ML76OfuL6JxTVdnz8iVyO2sgLE1HbX1VeB+wgd/jfMeOBhCCXskfK6MLyZihfMYsiYZYSaV98ZDhDLSlzuuRIgzb0bMi8aL6AErs0WLW0NelRBeHkKPYfAUc85pdQHscgrJw6Rh/zT6+8BQ/q5f4IgWhiu4xoRg3Ngl7SNoedRQh93ADM3UG2iGl6HDFpVORaXcFWKAtuYY+kHQ0HB84BRYpQmeBuXNpltsfxQ3d1Q3u0RlE45zRvmr2+X1mFnkcNUAWISLPbsOUlriDQM8irGwRpho77/uYnRC00bJsHW//s6+uPf9zrAw1nI4f0y3PAWukGF/xs6HAI3FZPsuSSnx18Tj3Opgbc9Spop+V3hkhdiJoPGpNKTkFX4ZRXfkPgoRVJmtp4PpbpH0Ps/mCriKjMEfGGi0HcVCi0pEGLXiecdqJ5KPg5+22zNycEujQBJcNTKd9shN+R3glrbmhAxTEzGdGwxXXJ2ybwJ2PWJLMYZ7g98nLyX+uQPaA3BlsbYJHNeS5283/9pJsd9DzfHKsN2nFSc=" + +before_install: + - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- + +addons: + coverity_scan: + project: + name: "ReOpen/libmdbx" + version: 0.1 + description: "Build submitted via Travis CI" + notification_email: leo@yuriev.ru + build_command_prepend: "make clean" + build_command: "make all -j 2" + branch_pattern: coverity_scan diff --git a/contrib/db/libmdbx/AUTHORS b/contrib/db/libmdbx/AUTHORS new file mode 100644 index 00000000..0a1a1996 --- /dev/null +++ b/contrib/db/libmdbx/AUTHORS @@ -0,0 +1,31 @@ +Contributors +============ + +Alexey Naumov +Chris Mikkelson +Claude Brisson +David Barbour +David Wilson +dreamsxin +Hallvard Furuseth , +Heiko Becker +Howard Chu , +Ignacio Casal Quinteiro +James Rouzier +Jean-Christophe DUBOIS +John Hewson +Klaus Malorny +Kurt Zeilenga +Leonid Yuriev , +Lorenz Bauer +Luke Yeager +Martin Hedenfalk +Ondrej Kuznik +Orivej Desh +Oskari Timperi +Pavel Medvedev +Philipp Storz +Quanah Gibson-Mount +Salvador Ortiz +Sebastien Launay +Vladimir Romanov diff --git a/contrib/db/libmdbx/COPYRIGHT b/contrib/db/libmdbx/COPYRIGHT new file mode 100644 index 00000000..46e09610 --- /dev/null +++ b/contrib/db/libmdbx/COPYRIGHT @@ -0,0 +1,22 @@ +Copyright 2015-2019 Leonid Yuriev . +Copyright 2011-2015 Howard Chu, Symas Corp. +Copyright 2015,2016 Peter-Service R&D LLC. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted only as authorized by the OpenLDAP +Public License. + +A copy of this license is available in the file LICENSE in the +top-level directory of the distribution or, alternatively, at +. + +OpenLDAP is a registered trademark of the OpenLDAP Foundation. + +Individual files and/or contributed packages may be copyright by +other parties and/or subject to additional restrictions. + +This work also contains materials derived from public sources. + +Additional information about OpenLDAP can be obtained at +. diff --git a/contrib/db/libmdbx/LICENSE b/contrib/db/libmdbx/LICENSE new file mode 100644 index 00000000..05ad7571 --- /dev/null +++ b/contrib/db/libmdbx/LICENSE @@ -0,0 +1,47 @@ +The OpenLDAP Public License + Version 2.8, 17 August 2003 + +Redistribution and use of this software and associated documentation +("Software"), with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions in source form must retain copyright statements + and notices, + +2. Redistributions in binary form must reproduce applicable copyright + statements and notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution, and + +3. Redistributions must contain a verbatim copy of this document. + +The OpenLDAP Foundation may revise this license from time to time. +Each revision is distinguished by a version number. You may use +this Software under terms of this license revision or under the +terms of any subsequent revision of the license. + +THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS +CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) +OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +The names of the authors and copyright holders must not be used in +advertising or otherwise to promote the sale, use or other dealing +in this Software without specific, written prior permission. Title +to copyright in this Software shall at all times remain with copyright +holders. + +OpenLDAP is a registered trademark of the OpenLDAP Foundation. + +Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, +California, USA. All Rights Reserved. Permission to copy and +distribute verbatim copies of this document is granted. diff --git a/contrib/db/libmdbx/Makefile b/contrib/db/libmdbx/Makefile new file mode 100644 index 00000000..2d261bc7 --- /dev/null +++ b/contrib/db/libmdbx/Makefile @@ -0,0 +1,270 @@ +# GNU Makefile for libmdbx, https://abf.io/erthink/libmdbx + +######################################################################## +# Configuration. The compiler options must enable threaded compilation. +# +# Preprocessor macros (for XCFLAGS) of interest... +# Note that the defaults should already be correct for most +# platforms; you should not need to change any of these. +# Read their descriptions in mdb.c if you do. There may be +# other macros of interest. You should read mdb.c +# before changing any of them. +# + +# install sandbox +SANDBOX ?= + +# install prefixes (inside sandbox) +prefix ?= /usr/local +mandir ?= $(prefix)/man + +# lib/bin suffix for multiarch/biarch, e.g. '.x86_64' +suffix ?= + +CC ?= gcc +CXX ?= g++ +LD ?= ld +CFLAGS ?= -O2 -g3 -Wall -Werror -Wextra -ffunction-sections -fPIC -fvisibility=hidden + +XCFLAGS ?= -DNDEBUG=1 -DLIBMDBX_EXPORTS=1 +CFLAGS += -D_GNU_SOURCE=1 -std=gnu11 -pthread $(XCFLAGS) +CXXFLAGS = -std=c++11 $(filter-out -std=gnu11,$(CFLAGS)) +TESTDB ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.db +TESTLOG ?= $(shell [ -d /dev/shm ] && echo /dev/shm || echo /tmp)/mdbx-test.log + +# LY: '--no-as-needed,-lrt' for ability to built with modern glibc, but then run with the old +LDFLAGS ?= $(shell $(LD) --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1')$(shell $(LD) --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip') +EXE_LDFLAGS ?= -pthread + +# LY: just for benchmarking +IOARENA ?= $(shell \ + (test -x ../ioarena/@BUILD/src/ioarena && echo ../ioarena/@BUILD/src/ioarena) || \ + (test -x ../../@BUILD/src/ioarena && echo ../../@BUILD/src/ioarena) || \ + (test -x ../../src/ioarena && echo ../../src/ioarena) || which ioarena) +NN ?= 25000000 + +######################################################################## + +ifdef MSVC + UNAME := Windows + LCK_IMPL := windows + TEST_OSAL := windows + TEST_ITER := 42 +else + UNAME := $(shell uname -s 2>/dev/null || echo Unknown) + define uname2lck + case "$(UNAME)" in + Linux) echo linux;; + CYGWIN*|MINGW*|MSYS*|Windows*) echo windows;; + *) echo posix;; + esac + endef + define uname2osal + case "$(UNAME)" in + CYGWIN*|MINGW*|MSYS*|Windows*) echo windows;; + *) echo unix;; + esac + endef + define uname2titer + case "$(UNAME)" in + Darwin*|Mach*) echo 3;; + *) echo 42;; + esac + endef + define uname2suffix + case "$(UNAME)" in + Darwin*|Mach*) echo dylib;; + CYGWIN*|MINGW*|MSYS*|Windows*) echo dll;; + *) echo so;; + esac + endef + LCK_IMPL := $(shell $(uname2lck)) + TEST_OSAL := $(shell $(uname2osal)) + TEST_ITER := $(shell $(uname2titer)) + SO_SUFFIX := $(shell $(uname2suffix)) +endif + +HEADERS := mdbx.h +LIBRARIES := libmdbx.a libmdbx.$(SO_SUFFIX) +TOOLS := mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_chk +MANPAGES := mdbx_stat.1 mdbx_copy.1 mdbx_dump.1 mdbx_load.1 +SHELL := /bin/bash + +CORE_SRC := src/lck-$(LCK_IMPL).c $(filter-out $(wildcard src/lck-*.c), $(wildcard src/*.c)) +CORE_INC := $(wildcard src/*.h) +CORE_OBJ := $(patsubst %.c,%.o,$(CORE_SRC)) +TEST_SRC := test/osal-$(TEST_OSAL).cc $(filter-out $(wildcard test/osal-*.cc), $(wildcard test/*.cc)) +TEST_INC := $(wildcard test/*.h) +TEST_OBJ := $(patsubst %.cc,%.o,$(TEST_SRC)) + +.PHONY: mdbx all install clean check coverage + +all: $(LIBRARIES) $(TOOLS) mdbx_test example + +mdbx: libmdbx.a libmdbx.$(SO_SUFFIX) + +example: mdbx.h tutorial/sample-mdbx.c libmdbx.$(SO_SUFFIX) + $(CC) $(CFLAGS) -I. tutorial/sample-mdbx.c ./libmdbx.$(SO_SUFFIX) -o example + +tools: $(TOOLS) + +install: $(LIBRARIES) $(TOOLS) $(HEADERS) + mkdir -p $(SANDBOX)$(prefix)/bin$(suffix) \ + && cp -t $(SANDBOX)$(prefix)/bin$(suffix) $(TOOLS) && \ + mkdir -p $(SANDBOX)$(prefix)/lib$(suffix) \ + && cp -t $(SANDBOX)$(prefix)/lib$(suffix) $(LIBRARIES) && \ + mkdir -p $(SANDBOX)$(prefix)/include \ + && cp -t $(SANDBOX)$(prefix)/include $(HEADERS) && \ + mkdir -p $(SANDBOX)$(mandir)/man1 \ + && cp -t $(SANDBOX)$(mandir)/man1 $(MANPAGES) + +clean: + rm -rf $(TOOLS) mdbx_test @* *.[ao] *.[ls]o *~ tmp.db/* *.gcov *.log *.err src/*.o test/*.o + +check: all + rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --repeat=$(TEST_ITER) --pathname=$(TESTDB) --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \ + && ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy + +check-singleprocess: all + rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; \ + ./mdbx_test --repeat=4 --pathname=$(TESTDB) --dont-cleanup-after --hill && \ + ./mdbx_test --repeat=2 --pathname=$(TESTDB) --dont-cleanup-before --dont-cleanup-after --copy \ + | tee -a $(TESTLOG) | tail -n 42) \ + && ./mdbx_chk -vvn $(TESTDB) && ./mdbx_chk -vvn $(TESTDB)-copy + +check-fault: all + rm -f $(TESTDB) $(TESTLOG) && (set -o pipefail; ./mdbx_test --pathname=$(TESTDB) --inject-writefault=42 --dump-config --dont-cleanup-after basic | tee -a $(TESTLOG) | tail -n 42) \ + ; ./mdbx_chk -vvnw $(TESTDB) && ([ ! -e $(TESTDB)-copy ] || ./mdbx_chk -vvn $(TESTDB)-copy) + +define core-rule +$(patsubst %.c,%.o,$(1)): $(1) $(CORE_INC) mdbx.h Makefile + $(CC) $(CFLAGS) -c $(1) -o $$@ + +endef +$(foreach file,$(CORE_SRC),$(eval $(call core-rule,$(file)))) + +define test-rule +$(patsubst %.cc,%.o,$(1)): $(1) $(TEST_INC) mdbx.h Makefile + $(CXX) $(CXXFLAGS) -c $(1) -o $$@ + +endef +$(foreach file,$(TEST_SRC),$(eval $(call test-rule,$(file)))) + +libmdbx.a: $(CORE_OBJ) + $(AR) rs $@ $? + +libmdbx.$(SO_SUFFIX): $(CORE_OBJ) + $(CC) $(CFLAGS) -save-temps $^ -pthread -shared $(LDFLAGS) -o $@ + +mdbx_%: src/tools/mdbx_%.c libmdbx.a + $(CC) $(CFLAGS) $^ $(EXE_LDFLAGS) -o $@ + +mdbx_test: $(TEST_OBJ) libmdbx.$(SO_SUFFIX) + $(CXX) $(CXXFLAGS) $(TEST_OBJ) -Wl,-rpath . -L . -l mdbx $(EXE_LDFLAGS) -o $@ + +############################################################################### + +ifneq ($(wildcard $(IOARENA)),) + +.PHONY: bench clean-bench re-bench + +clean-bench: + rm -rf bench-*.txt _ioarena/* + +re-bench: clean-bench bench + +define bench-rule +bench-$(1)_$(2).txt: $(3) $(IOARENA) Makefile + LD_LIBRARY_PATH="./:$$$${LD_LIBRARY_PATH}" \ + $(IOARENA) -D $(1) -B crud -m nosync -n $(2) \ + | tee $$@ | grep throughput && \ + LD_LIBRARY_PATH="./:$$$${LD_LIBRARY_PATH}" \ + $(IOARENA) -D $(1) -B get,iterate -m sync -r 4 -n $(2) \ + | tee -a $$@ | grep throughput \ + || mv -f $$@ $$@.error + +endef + +$(eval $(call bench-rule,mdbx,$(NN),libmdbx.$(SO_SUFFIX))) + +$(eval $(call bench-rule,sophia,$(NN))) +$(eval $(call bench-rule,leveldb,$(NN))) +$(eval $(call bench-rule,rocksdb,$(NN))) +$(eval $(call bench-rule,wiredtiger,$(NN))) +$(eval $(call bench-rule,forestdb,$(NN))) +$(eval $(call bench-rule,lmdb,$(NN))) +$(eval $(call bench-rule,nessdb,$(NN))) +$(eval $(call bench-rule,sqlite3,$(NN))) +$(eval $(call bench-rule,ejdb,$(NN))) +$(eval $(call bench-rule,vedisdb,$(NN))) +$(eval $(call bench-rule,dummy,$(NN))) + +$(eval $(call bench-rule,debug,10)) + +bench: bench-mdbx_$(NN).txt + +.PHONY: bench-debug + +bench-debug: bench-debug_10.txt + +bench-quartet: bench-mdbx_$(NN).txt bench-lmdb_$(NN).txt bench-rocksdb_$(NN).txt bench-wiredtiger_$(NN).txt + +endif + +############################################################################### + +ci-rule = ( CC=$$(which $1); if [ -n "$$CC" ]; then \ + echo -n "probe by $2 ($$(readlink -f $$(which $$CC))): " && \ + $(MAKE) clean >$1.log 2>$1.err && \ + $(MAKE) CC=$$(readlink -f $$CC) XCFLAGS="-UNDEBUG -DMDBX_DEBUG=2 -DLIBMDBX_EXPORTS=1" check 1>$1.log 2>$1.err && echo "OK" \ + || ( echo "FAILED"; cat $1.err >&2; exit 1 ); \ + else echo "no $2 ($1) for probe"; fi; ) +ci: + @if [ "$$(readlink -f $$(which $(CC)))" != "$$(readlink -f $$(which gcc || echo /bin/false))" -a \ + "$$(readlink -f $$(which $(CC)))" != "$$(readlink -f $$(which clang || echo /bin/false))" -a \ + "$$(readlink -f $$(which $(CC)))" != "$$(readlink -f $$(which icc || echo /bin/false))" ]; then \ + $(call ci-rule,$(CC),default C compiler); \ + fi + @$(call ci-rule,gcc,GCC) + @$(call ci-rule,clang,clang LLVM) + @$(call ci-rule,icc,Intel C) + +############################################################################### + +CROSS_LIST = mips-linux-gnu-gcc \ + powerpc64-linux-gnu-gcc powerpc-linux-gnu-gcc \ + arm-linux-gnueabihf-gcc aarch64-linux-gnu-gcc + +# hppa-linux-gnu-gcc - don't supported by current qemu release +# s390x-linux-gnu-gcc - qemu troubles (hang/abort) +# sh4-linux-gnu-gcc - qemu troubles (pread syscall, etc) +# mips64-linux-gnuabi64-gcc - qemu troubles (pread syscall, etc) +# sparc64-linux-gnu-gcc - qemu troubles (fcntl for F_SETLK/F_GETLK) +# alpha-linux-gnu-gcc - qemu (or gcc) troubles (coredump) + +CROSS_LIST_NOQEMU = hppa-linux-gnu-gcc s390x-linux-gnu-gcc \ + sh4-linux-gnu-gcc mips64-linux-gnuabi64-gcc \ + sparc64-linux-gnu-gcc alpha-linux-gnu-gcc + +cross-gcc: + @echo "CORRESPONDING CROSS-COMPILERs ARE REQUIRED." + @echo "FOR INSTANCE: apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" + @for CC in $(CROSS_LIST_NOQEMU) $(CROSS_LIST); do \ + echo "===================== $$CC"; \ + $(MAKE) clean && CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static $(MAKE) all || exit $$?; \ + done + +# +# Unfortunately qemu don't provide robust support for futexes. +# Therefore it is impossible to run full multi-process tests. +cross-qemu: + @echo "CORRESPONDING CROSS-COMPILERs AND QEMUs ARE REQUIRED." + @echo "FOR INSTANCE: " + @echo " 1) apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" + @echo " 2) apt install binfmt-support qemu-user-static qemu-user qemu-system-arm qemu-system-mips qemu-system-misc qemu-system-ppc qemu-system-sparc" + @for CC in $(CROSS_LIST); do \ + echo "===================== $$CC + qemu"; \ + $(MAKE) clean && \ + CC=$$CC CXX=$$(echo $$CC | sed 's/-gcc/-g++/') EXE_LDFLAGS=-static XCFLAGS="-DMDBX_SAFE4QEMU $(XCFLAGS)" \ + $(MAKE) check-singleprocess || exit $$?; \ + done diff --git a/contrib/db/libmdbx/README-RU.md b/contrib/db/libmdbx/README-RU.md new file mode 100644 index 00000000..e040b5c4 --- /dev/null +++ b/contrib/db/libmdbx/README-RU.md @@ -0,0 +1,830 @@ +### The [repository now only mirrored on the Github](https://abf.io/erthink/libmdbx) due to illegal discriminatory restrictions for Russian Crimea and for sovereign crimeans. + +----- + +libmdbx +====================================== +Доработанный и расширенный потомок [Lightning Memory-Mapped Database](https://ru.bmstu.wiki/LMDB_(Lightning_Memory-Mapped_Database)) (aka _LMDB_). +English version is [here](README.md). + +_libmdbx_ превосходит LMDB по возможностям и надежности, не уступая в +производительности. _libmdbx_ работает на Linux, FreeBSD, MacOS X и +других ОС соответствующих POSIX.1-2008, а также поддерживает Windows в +качестве дополнительной платформы. + +Отдельно ведётся не-публичная разработка следующей версии, в которой +будет кардинальное изменение как API, так и формата базы данных. Цель +этой революции - обеспечение более четкого и надежного API, добавление +новых функций, а также наделение базы данных новыми свойствами. + +*Всё будет хорошо. The Future will (be) [Positive](https://www.ptsecurity.ru).* + +[![Build Status](https://travis-ci.org/leo-yuriev/libmdbx.svg?branch=master)](https://travis-ci.org/leo-yuriev/libmdbx) +[![Build status](https://ci.appveyor.com/api/projects/status/ue94mlopn50dqiqg/branch/master?svg=true)](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master) +[![Coverity Scan Status](https://scan.coverity.com/projects/12915/badge.svg)](https://scan.coverity.com/projects/reopen-libmdbx) + +## Содержание +- [Обзор](#Обзор) + - [Сравнение с другими базами данных](#Сравнение-с-другими-базами-данных) + - [История & Выражение признательности](#История) +- [Описание](#Описание) + - [Ключевые свойства](#Ключевые-свойства) + - [Доработки и усовершенствования относительно LMDB](#Доработки-и-усовершенствования-относительно-lmdb) + - [Недостатки и Компромиссы](#Недостатки-и-Компромиссы) + - [Проблема долгих чтений](#Проблема-долгих-чтений) + - [Сохранность данных в режиме асинхронной фиксации](#Сохранность-данных-в-режиме-асинхронной-фиксации) +- [Использование](#Использование) + - [Сборка](#Сборка) + - [Привязки к другим языкам](#Привязки-к-другим-языкам) +- [Сравнение производительности](#Сравнение-производительности) + - [Интегральная производительность](#Интегральная-производительность) + - [Масштабируемость чтения](#Масштабируемость-чтения) + - [Синхронная фиксация](#Синхронная-фиксация) + - [Отложенная фиксация](#Отложенная-фиксация) + - [Асинхронная фиксация](#Асинхронная-фиксация) + - [Потребление ресурсов](#Потребление-ресурсов) + +----- + +## Обзор +_libmdbx_ - это встраиваемый key-value движок хранения со специфическим +набором свойств и возможностей, ориентированный на создание уникальных +легковесных решений с предельной производительностью. + +_libmdbx_ позволяет множеству процессов совместно читать и обновлять +несколько key-value таблиц с соблюдением +[ACID](https://ru.wikipedia.org/wiki/ACID), при минимальных накладных +расходах и амортизационной стоимости любых операций Olog(N). + +_libmdbx_ обеспечивает +[serializability](https://en.wikipedia.org/wiki/Serializability) +изменений и согласованность данных после аварий. При этом транзакции, +изменяющие данные, никак не мешают операциям чтения и выполняются строго +последовательно с использованием единственного +[мьютекса](https://en.wikipedia.org/wiki/Mutual_exclusion). + +_libmdbx_ позволяет выполнять операции чтения с гарантиями +[wait-free](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom), +параллельно на каждом ядре CPU, без использования атомарных операций +и/или примитивов синхронизации. + +_libmdbx_ не использует +[LSM](https://en.wikipedia.org/wiki/Log-structured_merge-tree), а +основан на [B+Tree](https://en.wikipedia.org/wiki/B%2B_tree) с +[отображением](https://en.wikipedia.org/wiki/Memory-mapped_file) всех +данных в память, при этом текущая версия не использует +[WAL](https://en.wikipedia.org/wiki/Write-ahead_logging). Это +предопределяет многие свойства, в том числе удачные и противопоказанные +сценарии использования. + + +### Сравнение с другими базами данных + +На данный момент, пожалуйста, обратитесь к [главе "сравнение BoltDB с +другими базами +данных"](https://github.com/coreos/bbolt#comparison-with-other-databases), +которая также (в основном) применима к MDBX. + + +### История +_libmdbx_ является результатом переработки и развития "Lightning +Memory-Mapped Database", известной под аббревиатурой +[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database). +Изначально доработка производилась в составе проекта +[ReOpenLDAP](https://github.com/leo-yuriev/ReOpenLDAP). Примерно за год +работы внесенные изменения приобрели самостоятельную ценность. Осенью +2015 доработанный движок был выделен в отдельный проект, который был +[представлен на конференции Highload++ +2015](http://www.highload.ru/2015/abstracts/1831.html). + +В начале 2017 года движок _libmdbx_ получил новый импульс развития, +благодаря использованию в [Fast Positive +Tables](https://github.com/leo-yuriev/libfpta), aka ["Позитивные +Таблицы"](https://github.com/leo-yuriev/libfpta) by [Positive +Technologies](https://www.ptsecurity.ru). + + +### Выражение признательности + +Говард Чу (Howard Chu) является автором движка LMDB, от +которого в 2015 году произошел MDBX. + +Мартин Хеденфальк (Martin Hedenfalk) является автором кода +`btree.c`, который использовался для начала разработки LMDB. + +----- + +Описание +======== + +## Ключевые свойства + +_libmdbx_ наследует все ключевые возможности и особенности своего +прародителя +[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database), +но с устранением ряда описываемых далее проблем и архитектурных +недочетов. + +1. Данные хранятся в упорядоченном отображении (ordered map), ключи +всегда отсортированы, поддерживается выборка диапазонов (range lookups). + +2. Данные отображается в память каждого работающего с БД процесса. К +данным и ключам обеспечивается прямой доступ в памяти без необходимости +их копирования. + +3. Транзакции согласно [ACID](https://ru.wikipedia.org/wiki/ACID), +посредством [MVCC](https://ru.wikipedia.org/wiki/MVCC) и +[COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8). +Изменения строго последовательны и не блокируются чтением, конфликты +между транзакциями невозможны. При этом гарантируется чтение только +зафиксированных данных, см [relaxing +serializability](https://en.wikipedia.org/wiki/Serializability). + +4. Чтение и поиск [без +блокировок](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F), +без [атомарных +операций](https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%BE%D0%BC%D0%B0%D1%80%D0%BD%D0%B0%D1%8F_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F). +Читатели не блокируются операциями записи и не конкурируют между собой, +чтение масштабируется линейно по ядрам CPU. + > Для точности следует отметить, что "подключение к БД" (старт первой + > читающей транзакции в потоке) и "отключение от БД" (закрытие БД или + > завершение потока) требуют краткосрочного захвата блокировки для + > регистрации/дерегистрации текущего потока в "таблице читателей". + +5. Эффективное хранение дубликатов (ключей с несколькими значениями), +без дублирования ключей, с сортировкой значений, в том числе +целочисленных (для вторичных индексов). + +6. Эффективная поддержка коротких ключей фиксированной длины, в том +числе целочисленных. + +7. Амортизационная стоимость любой операции Olog(N), +[WAF](https://en.wikipedia.org/wiki/Write_amplification) (Write +Amplification Factor) и RAF (Read Amplification Factor) также Olog(N). + +8. Нет [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) и +журнала транзакций, после сбоев не требуется восстановление. Не +требуется компактификация или какое-либо периодическое обслуживание. +Поддерживается резервное копирование "по горячему", на работающей БД без +приостановки изменения данных. + +9. Отсутствует какое-либо внутреннее управление памятью или +кэшированием. Всё необходимое штатно выполняет ядро ОС. + + +## Доработки и усовершенствования относительно LMDB + +1. Автоматическое динамическое управление размером БД согласно +параметрам задаваемым функцией `mdbx_env_set_geometry()`, включая шаг +приращения и порог уменьшения размера БД, а также выбор размера +страницы. Соответственно, это позволяет снизить фрагментированность +файла БД на диске и освободить место, в том числе в **Windows**. + +2. Автоматическая без-затратная компактификация БД путем возврата +освобождающихся страниц в область нераспределенного резерва в конце +файла данных. При этом уменьшается количество страниц находящихся в +памяти и участвующих в в обмене с диском. + +3. Режим `LIFO RECLAIM`. + + Для повторного использования выбираются не самые старые, а + самые новые страницы из доступных. За счет этого цикл + использования страниц всегда имеет минимальную длину и не + зависит от общего числа выделенных страниц. + + В результате механизмы кэширования и обратной записи работают с + максимально возможной эффективностью. В случае использования + контроллера дисков или системы хранения с + [BBWC](https://en.wikipedia.org/wiki/BBWC) возможно + многократное увеличение производительности по записи + (обновлению данных). + +4. Быстрая оценка количества элементов попадающих в запрашиваемый +диапазон значений ключа посредством функций `mdbx_estimate_range()`, +`mdbx_estimate_move()` и `mdbx_estimate_distance()` для выбора +оптимального плана выполнения запроса. + +5. Утилита `mdbx_chk` для проверки целостности структуры БД. + +6. Поддержка ключей и значений нулевой длины, включая сортированные +дубликаты. + +7. Возможность связать с каждой завершаемой транзакцией до 3 +дополнительных маркеров посредством `mdbx_canary_put()`, и прочитать их +в транзакции чтения посредством `mdbx_canary_get()`. + +8. Возможность посредством `mdbx_replace()` обновить или удалить запись +с получением предыдущего значения данных, а также адресно изменить +конкретное multi-значение. + +9. Генерация последовательностей посредством `mdbx_dbi_sequence()`. + +10. Обработчик `OOM-KICK`. + + Посредством `mdbx_env_set_oomfunc()` может быть установлен + внешний обработчик (callback), который будет вызван при + исчерпании свободных страниц по причине долгой операцией чтения + на фоне интенсивного изменения данных. + Обработчику будет передан PID и pthread_id виновника. + В свою очередь обработчик может предпринять одно из действий: + + * нейтрализовать виновника (отправить сигнал kill #9), если + долгое чтение выполняется сторонним процессом; + + * отменить или перезапустить проблемную операцию чтения, если + операция выполняется одним из потоков текущего процесса; + + * подождать некоторое время, в расчете на то, что проблемная операция + чтения будет штатно завершена; + + * прервать текущую операцию изменения данных с возвратом кода + ошибки. + +11. Возможность открыть БД в эксклюзивном режиме посредством флага + `MDBX_EXCLUSIVE`, в том числе на сетевом носителе. + +12. Возможность получить отставание текущей транзакции чтения от +последней версии данных в БД посредством `mdbx_txn_straggler()`. + +13. Возможность явно запросить обновление существующей записи, без +создания новой посредством флажка `MDBX_CURRENT` для `mdbx_put()`. + +14. Исправленный вариант `mdbx_cursor_count()`, возвращающий корректное +количество дубликатов для всех типов таблиц и любого положения курсора. + +15. Возможность получить посредством `mdbx_env_info()` дополнительную +информацию, включая номер самой старой версии БД (снимка данных), +который используется одним из читателей. + +16. Функция `mdbx_del()` не игнорирует дополнительный (уточняющий) +аргумент `data` для таблиц без дубликатов (без флажка `MDBX_DUPSORT`), а +при его ненулевом значении всегда использует его для сверки с удаляемой +записью. + +17. Возможность открыть dbi-таблицу, одновременно с установкой +компараторов для ключей и данных, посредством `mdbx_dbi_open_ex()`. + +18. Возможность посредством `mdbx_is_dirty()` определить находятся ли +некоторый ключ или данные в "грязной" странице БД. Таким образом, +избегая лишнего копирования данных перед выполнением модифицирующих +операций (значения, размещенные в "грязных" страницах, могут быть +перезаписаны при изменениях, иначе они будут неизменны). + +19. Корректное обновление текущей записи, в том числе сортированного +дубликата, при использовании режима `MDBX_CURRENT` в +`mdbx_cursor_put()`. + +20. Возможность узнать есть ли за текущей позицией курсора строка данных +посредством `mdbx_cursor_eof()`. + +21. Дополнительный код ошибки `MDBX_EMULTIVAL`, который возвращается из +`mdbx_put()` и `mdbx_replace()` при попытке выполнить неоднозначное +обновление или удаления одного из нескольких значений с одним ключом. + +22. Возможность посредством `mdbx_get_ex()` получить значение по +заданному ключу, одновременно с количеством дубликатов. + +23. Наличие функций `mdbx_cursor_on_first()` и `mdbx_cursor_on_last()`, +которые позволяют быстро выяснить стоит ли курсор на первой/последней +позиции. + +24. Возможность автоматического формирования контрольных точек (сброса +данных на диск) при накоплении заданного объёма изменений, +устанавливаемого функцией `mdbx_env_set_syncbytes()`. + +25. Управление отладкой и получение отладочных сообщений посредством +`mdbx_setup_debug()`. + +26. Функция `mdbx_env_pgwalk()` для обхода всех страниц БД. + +27. Три мета-страницы вместо двух, что позволяет гарантированно +консистентно обновлять слабые контрольные точки фиксации без риска +повредить крайнюю сильную точку фиксации. + +28. Гарантия сохранности БД в режиме `WRITEMAP+MAPSYNC`. + > В текущей версии _libmdbx_ вам предоставляется выбор между безопасным + > режимом (по умолчанию) асинхронной фиксации, и режимом `UTTERLY_NOSYNC` + > когда при системной аварии есть шанс полного разрушения БД как в LMDB. + > Для подробностей смотрите раздел + > [Сохранность данных в режиме асинхронной фиксации](#Сохранность-данных-в-режиме-асинхронной-фиксации). + +29. Возможность закрыть БД в "грязном" состоянии (без сброса данных и +формирования сильной точки фиксации) посредством `mdbx_env_close_ex()`. + +30. При завершении читающих транзакций, открытые в них DBI-хендлы не +закрываются и не теряются при завершении таких транзакций посредством +`mdbx_txn_abort()` или `mdbx_txn_reset()`. Что позволяет избавится от ряда +сложно обнаруживаемых ошибок. + +31. Все курсоры, как в транзакциях только для чтения, так и в пишущих, +могут быть переиспользованы посредством `mdbx_cursor_renew()` и ДОЛЖНЫ +ОСВОБОЖДАТЬСЯ ЯВНО. + > + > ## _ВАЖНО_, Обратите внимание! + > + > Это единственное изменение в API, которое значимо меняет + > семантику управления курсорами и может приводить к утечкам + > памяти. Следует отметить, что это изменение вынужденно. + > Так устраняется неоднозначность с массой тяжких последствий: + > + > - обращение к уже освобожденной памяти; + > - попытки повторного освобождения памяти; + > - повреждение памяти и ошибки сегментации. + +32. На **MacOS X** для синхронизации данных с диском _по-умолчанию_ +используется системная функция `fcntl(F_FULLFSYNC)`, так как [только +этим гарантируется сохранность +данных](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fsync.2.html) +при сбое электропитания. К сожалению, в сценариях с высокой +интенсивностью пишущих транзакций, использование `F_FULLFSYNC` приводит +к существенной деградации производительности в сравнении с LMDB, где +используется системная функция `fsync()`. Поэтому _libmdbx_ позволяет +переопределить это поведение определением опции +`MDBX_OSX_SPEED_INSTEADOF_DURABILITY=1` при сборке библиотеки. + +33. На **Windows** _libmdbx_ использует файловые блокировки +`LockFileEx()`, так как это позволяет размещать БД на сетевых дисках, а +также обеспечивает защиту от некомпетентных действий пользователя +([защиту от +дурака](https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D1%89%D0%B8%D1%82%D0%B0_%D0%BE%D1%82_%D0%B4%D1%83%D1%80%D0%B0%D0%BA%D0%B0)). +Поэтому _libmdbx_ может немного отставать в тестах производительность от +LMDB, где используются именованные мьютексы. + + +## Недостатки и Компромиссы + +1. Единовременно может выполняться не более одной транзакция изменения данных + (один писатель). Зато все изменения всегда последовательны, не может быть + конфликтов или логических ошибок при откате транзакций. + +2. Отсутствие [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) + обуславливает относительно большой + [WAF](https://en.wikipedia.org/wiki/Write_amplification) (Write + Amplification Factor). Поэтому фиксация изменений на диске может быть + достаточно дорогой и являться главным ограничением производительности + при интенсивном изменении данных. + > В качестве компромисса _libmdbx_ предлагает несколько режимов ленивой + > и/или периодической фиксации. В том числе режим `MAPASYNC`, при котором + > изменения происходят только в памяти и асинхронно фиксируются на диске + > ядром ОС. + > + > Однако, следует воспринимать это свойство аккуратно и взвешенно. + > Например, полная фиксация транзакции в БД с журналом потребует минимум 2 + > IOPS (скорее всего 3-4) из-за накладных расходов в файловой системе. В + > _libmdbx_ фиксация транзакции также требует от 2 IOPS. Однако, в БД с + > журналом кол-во IOPS будет меняться в зависимости от файловой системы, + > но не от кол-ва записей или их объема. Тогда как в _libmdbx_ кол-во + > будет расти логарифмически от кол-ва записей/строк в БД (по высоте + > b+tree). + +3. [COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8) + для реализации [MVCC](https://ru.wikipedia.org/wiki/MVCC) выполняется на + уровне страниц в [B+ + дереве](https://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE). + Поэтому изменение данных амортизационно требует копирования Olog(N) + страниц, что расходует [пропускную способность оперативной + памяти](https://en.wikipedia.org/wiki/Memory_bandwidth) и является + основным ограничителем производительности в режиме `MAPASYNC`. + > Этот недостаток неустраним, тем не менее следует дать некоторые пояснения. + > Дело в том, что фиксация изменений на диске потребует гораздо более + > значительного копирования данных в памяти и массы других затратных операций. + > Поэтому обусловленное этим недостатком падение производительности становится + > заметным только при отказе от фиксации изменений на диске. + > Соответственно, корректнее сказать, что _libmdbx_ позволяет + > получить персистентность ценой минимального падения производительности. + > Если же нет необходимости оперативно сохранять данные, то логичнее + > использовать `std::map`. + +4. В _LMDB_ существует проблема долгих чтений (приостановленных читателей), + которая приводит к деградации производительности и переполнению БД. + > В _libmdbx_ предложены средства для предотвращения, быстрого выхода из + > некомфортной ситуации и устранения её последствий. Подробности ниже. + +5. В _LMDB_ есть вероятность разрушения БД в режиме `WRITEMAP+MAPASYNC`. + В _libmdbx_ для `WRITEMAP+MAPASYNC` гарантируется как сохранность базы, + так и согласованность данных. + > Дополнительно, в качестве альтернативы, предложен режим `UTTERLY_NOSYNC`. + > Подробности ниже. + + +### Проблема долгих чтений +*Следует отметить*, что проблема "сборки мусора" так или иначе +существует во всех СУБД (Vacuum в PostgreSQL). Однако в случае _libmdbx_ +и LMDB она проявляется более остро, прежде всего из-за высокой +производительности, а также из-за намеренного упрощения внутренних +механизмов ради производительности. + +Понимание проблемы требует некоторых пояснений, которые +изложены ниже, но могут быть сложны для быстрого восприятия. +Поэтому, тезисно: + +* Изменение данных на фоне долгой операции чтения может + приводить к исчерпанию места в БД. + +* После чего любая попытка обновить данные будет приводить к + ошибке `MAP_FULL` до завершения долгой операции чтения. + +* Характерными примерами долгих чтений являются горячее + резервное копирования и отладка клиентского приложения при + активной транзакции чтения. + +* В оригинальной _LMDB_ после этого будет наблюдаться + устойчивая деградация производительности всех механизмов + обратной записи на диск (в I/O контроллере, в гипервизоре, + в ядре ОС). + +* В _libmdbx_ предусмотрен механизм аварийного прерывания таких + операций, а также режим `LIFO RECLAIM` устраняющий последующую + деградацию производительности. + +Операции чтения выполняются в контексте снимка данных (версии +БД), который был актуальным на момент старта транзакции чтения. Такой +читаемый снимок поддерживается неизменным до завершения операции. В свою +очередь, это не позволяет повторно использовать страницы БД в +последующих версиях (снимках БД). + +Другими словами, если обновление данных выполняется на фоне долгой +операции чтения, то вместо повторного использования "старых" ненужных +страниц будут выделяться новые, так как "старые" страницы составляют +снимок БД, который еще используется долгой операцией чтения. + +В результате, при интенсивном изменении данных и достаточно длительной +операции чтения, в БД могут быть исчерпаны свободные страницы, что не +позволит создавать новые снимки/версии БД. Такая ситуация будет +сохраняться до завершения операции чтения, которая использует старый +снимок данных и препятствует повторному использованию страниц БД. + +Однако, на этом проблемы не заканчиваются. После описанной ситуации, все +дополнительные страницы, которые были выделены пока переработка старых +была невозможна, будут участвовать в цикле выделения/освобождения до +конца жизни экземпляра БД. В оригинальной _LMDB_ этот цикл использования +страниц работает по принципу [FIFO](https://ru.wikipedia.org/wiki/FIFO). +Поэтому увеличение количества циркулирующий страниц, с точки зрения +механизмов кэширования и/или обратной записи, выглядит как увеличение +рабочего набор данных. Проще говоря, однократное попадание в ситуацию +"уснувшего читателя" приводит к устойчивому эффекту вымывания I/O кэша +при всех последующих изменениях данных. + +Для устранения описанных проблемы в _libmdbx_ сделаны существенные +доработки, подробности ниже. Иллюстрации к проблеме "долгих чтений" +можно найти в [слайдах презентации](http://www.slideshare.net/leoyuriev/lmdb). + +Там же приведен пример количественной оценки прироста производительности +за счет эффективной работы [BBWC](https://en.wikipedia.org/wiki/BBWC) +при включении `LIFO RECLAIM` в _libmdbx_. + +### Сохранность данных в режиме асинхронной фиксации +При работе в режиме `WRITEMAP+MAPSYNC` запись измененных страниц +выполняется ядром ОС, что имеет ряд преимуществ. Так например, при крахе +приложения, ядро ОС сохранит все изменения. + +Однако, при аварийном отключении питания или сбое в ядре ОС, на диске +может быть сохранена только часть измененных страниц БД. При этом с +большой вероятностью может оказаться, что будут сохранены мета-страницы +со ссылками на страницы с новыми версиями данных, но не сами новые +данные. В этом случае БД будет безвозвратна разрушена, даже если до +аварии производилась полная синхронизация данных (посредством +`mdbx_env_sync()`). + +В _libmdbx_ эта проблема устранена путем полной переработки +пути записи данных: + +* В режиме `WRITEMAP+MAPSYNC` _libmdbx_ не обновляет + мета-страницы непосредственно, а поддерживает их теневые копии + с переносом изменений после фиксации данных. + +* При завершении транзакций, в зависимости от состояния + синхронности данных между диском и оперативной памятью, + _libmdbx_ помечает точки фиксации либо как сильные (strong), + либо как слабые (weak). Так например, в режиме + `WRITEMAP+MAPSYNC` завершаемые транзакции помечаются как + слабые, а при явной синхронизации данных - как сильные. + +* В _libmdbx_ поддерживается не две, а три отдельные мета-страницы. + Это позволяет выполнять фиксацию транзакций с формированием как + сильной, так и слабой точки фиксации, без потери двух предыдущих + точек фиксации (из которых одна может быть сильной, а вторая слабой). + В результате, _libmdbx_ позволяет в произвольном порядке чередовать + сильные и слабые точки фиксации без нарушения соответствующих + гарантий в случае неожиданной системной аварии во время фиксации. + +* При открытии БД выполняется автоматический откат к последней + сильной фиксации. Этим обеспечивается гарантия сохранности БД. + +Такая гарантия надежности не дается бесплатно. Для сохранности данных, +страницы, формирующие крайний снимок с сильной фиксацией, не должны +повторно использоваться (перезаписываться) до формирования следующей +сильной точки фиксации. Таким образом, крайняя точка фиксации создает +описанный выше эффект "долгого чтения". Разница же здесь в том, что при +исчерпании свободных страниц ситуация будет автоматически исправлена, +посредством записи изменений на диск и формирования новой сильной точки +фиксации. + +Таким образом, в режиме безопасной асинхронной фиксации _libmdbx_ будет +всегда использовать новые страницы до исчерпания места в БД или до +явного формирования сильной точки фиксации посредством +`mdbx_env_sync()`. При этом суммарный трафик записи на диск будет +примерно такой же, как если бы отдельно фиксировалась каждая транзакция. + +В текущей версии _libmdbx_ вам предоставляется выбор между безопасным +режимом (по умолчанию) асинхронной фиксации, и режимом `UTTERLY_NOSYNC` +когда при системной аварии есть шанс полного разрушения БД как в LMDB. + +В последующих версиях _libmdbx_ будут предусмотрены средства для +асинхронной записи данных на диск с автоматическим формированием сильных +точек фиксации. + +-------------------------------------------------------------------------------- + +Использование +============= + +## Сборка + +Для сборки на всех платформах кроме Windows вам потребуются не-дремучие +версии: GNU Make, [bash](https://ru.wikipedia.org/wiki/Bash), компиляторы C и C++ совместимые с GCC или CLANG. + +Исторически сборка _libmdbx_ основывается на одном +[Makefile](https://ru.wikipedia.org/wiki/Makefile), что предполагает +разные рецепты сборки в зависимости от целевой платформы. В следующих +версиях планируется переход на использование +[CMake](https://ru.wikipedia.org/wiki/CMake), с отказом от поддержки +других инструментов. + +#### Выгрузка DSO/DLL и деструкторы Thread-Local-Storage объектов +При сборке _libmdbx_ в виде разделяемой библиотеки, либо использовании +статической _libmdbx_ в составе другой динамической библиотеке, +желательно убедиться, что ваша система обеспечивает корректность вызова +деструкторов Thread-Local-Storage объектов при выгрузке динамических +библиотек. + +Если это не так, то при выгрузке динамической библиотеки с _libmdbx_ +внутри возможна либо утечка ресурсов, либо падения из-за вызова +деструкторов из уже выгруженного DSO/DLL объекта. Проблема может +проявляться только в многопоточном приложении, которое производит +выгрузку разделяемых динамических библиотек с кодом _libmdbx_ внутри, +после использования _libmdbx_. Заведомо известно, что TLS-деструкторы +корректно обслуживаются: + +- На всех актуальных версиях Windows (Windows 7 и последующих). + +- На системах c функцией +[`__cxa_thread_atexit_impl()`](https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables) +в стандартной библиотеке C. В том числе на системах с GNU libc версии +2.18 и выше. + +- На системах с libpthread/ntpl из состава GNU libc с исправлением +ошибок [#21031](https://sourceware.org/bugzilla/show_bug.cgi?id=21031) и +[#21032](https://sourceware.org/bugzilla/show_bug.cgi?id=21032), либо +где нет подобных ошибок в реализации pthreads. + +### Linux и другие платформы с GNU Make +Для сборки библиотеки достаточно выполнить `make all` в директории с +исходными текстами, а для выполнения базовых тестов `make check`. + +Если установленный в система `make` не является GNU Make, то при попытке +сборки будет масса ошибок от make. В этом случае, возможно, вместо +`make` вам следует использовать `gmake`, либо даже `gnu-make` и т.п. + +### FreeBSD и родственные платформы +Как правило, на таких системах по-умолчанию используется Berkeley Make. +А GNU Make вызывается командой `gmake` или может отсутствовать. Кроме +этого может отсутствовать [`bash`](https://ru.wikipedia.org/wiki/Bash). + +Вам необходимо установить требуемые компоненты: GNU Make, bash, +компиляторы C и C++ совместимые с GCC или CLANG. После этого для сборки +библиотеки достаточно выполнить `gmake all` (или `make all`) в +директории с исходными текстами, а для выполнения базовых тестов `gmake +check` (или `make check`). + +### Windows +Для сборки libmdbx_ для ОС Windows рекомендуется использовать [Microsoft +Visual Studio](https://ru.wikipedia.org/wiki/Microsoft_Visual_Studio), +но не такие инструменты как MinGW, MSYS или Cygwin. Для этого в набор +исходных кодов _libmdbx_ входят соответствующие файлы проектов +совместимые с Visual Studio 2015, Windows SDK для Windows 8.1 и более +поздними версиями. Достаточно открыть `mdbx.sln` и выполнить сборку +библиотеки. + +Для сборки с более новыми версиями SDK или Visual Studio должно быть +достаточно выполнить "Retarget solution". Для сборки под старые версии +Windows (например Windows XP) или более старыми компиляторами вам +потребуется самостоятельно преобразовать или воссоздать файлы проектов. + +Сборка посредством MinGW, MSYS или Cygwin потенциально возможна. Однако, +эти сценарии не тестируются и вероятно потребуют от вас доработки +`Makefile`. Следует отметить, что в _libmdbx_ предприняты усилия для +устранения runtime зависимостей от CRT и других библиотек Visual Studio. +Для этого достаточно при сборке определить опцию `MDBX_AVOID_CRT`. + +Пример запуска базового сценария тестирования можно найти в +[CI-сценарии](appveyor.yml) для [AppVeyor](https://www.appveyor.com/). +Для выполнения [сценария длительного стохастического +тестирования](test/long_stochastic.sh) потребуется +[`bash`](https://ru.wikipedia.org/wiki/Bash), а само тестирование +рекомендуется выполнять с размещением тестовых данных на +[RAM-диске](https://ru.wikipedia.org/wiki/RAM-%D0%B4%D0%B8%D1%81%D0%BA). + +### MacOS X +Актуальные [нативные сборочные +инструменты](https://ru.wikipedia.org/wiki/Xcode) для MacOS X включают +GNU Make, CLANG и устаревшую версию bash. Поэтому для сборки библиотеки +достаточно выполнить `make all` в директории с исходными текстами, а для +выполнения базовых тестов `make check`. Если же что-то пойдет не так, то +рекомендуется установить [Homebrew](https://brew.sh/) и попробовать ещё +раз. + +Для выполнения [сценария длительного стохастического +тестирования](test/long_stochastic.sh) потребуется установка актуальной +(не устаревшей) версии [`bash`](https://ru.wikipedia.org/wiki/Bash). Для +этого рекомендуется установить [Homebrew](https://brew.sh/), а затем +выполнить `brew install bash`. + +## Привязки к другим языкам + + | Runtime | GitHub | Author | + | -------- | ------ | ------ | + | Java | [mdbxjni](https://github.com/castortech/mdbxjni) | [Castor Technologies](https://castortech.com/) | + | .NET | [mdbx.NET](https://github.com/wangjia184/mdbx.NET) | [Jerry Wang](https://github.com/wangjia184) | + +-------------------------------------------------------------------------------- + +Сравнение производительности +============================ + +Все представленные ниже данные получены многократным прогоном тестов на +ноутбуке Lenovo Carbon-2, i7-4600U 2.1 ГГц, 8 Гб ОЗУ, с SSD-диском +SAMSUNG MZNTD512HAGL-000L1 (DXT23L0Q) 512 Гб. + +Исходный код бенчмарка [_IOArena_](https://github.com/pmwkaa/ioarena) и +сценарии тестирования [доступны на +github](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015). + + +## Интегральная производительность + +Показана соотнесенная сумма ключевых показателей производительности в трёх +бенчмарках: + + - Чтение/Поиск на машине с 4-мя процессорами; + + - Транзакции с [CRUD](https://ru.wikipedia.org/wiki/CRUD)-операциями + (вставка, чтение, обновление, удаление) в режиме **синхронной фиксации** + данных (fdatasync при завершении каждой транзакции или аналог); + + - Транзакции с [CRUD](https://ru.wikipedia.org/wiki/CRUD)-операциями + (вставка, чтение, обновление, удаление) в режиме **отложенной фиксации** + данных (отложенная запись посредством файловой систем или аналог); + +*Бенчмарк в режиме асинхронной записи не включен по двум причинам:* + + 1. Такое сравнение не совсем правомочно, его следует делать с движками + ориентированными на хранение данных в памяти ([Tarantool](https://tarantool.io/), [Redis](https://redis.io/)). + + 2. Превосходство libmdbx становится еще более подавляющим, что мешает + восприятию информации. + +![Comparison #1: Integral Performance](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-1.png) + +-------------------------------------------------------------------------------- + +## Масштабируемость чтения + +Для каждого движка показана суммарная производительность при +одновременном выполнении запросов чтения/поиска в 1-2-4-8 потоков на +машине с 4-мя физическими процессорами. + +![Comparison #2: Read Scalability](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-2.png) + +-------------------------------------------------------------------------------- + +## Синхронная фиксация + + - Линейная шкала слева и темные прямоугольники соответствуют количеству + транзакций в секунду, усредненному за всё время теста. + + - Логарифмическая шкала справа и желтые интервальные отрезки + соответствуют времени выполнения транзакций. При этом каждый отрезок + показывает минимальное и максимальное время, затраченное на выполнение + транзакций, а крестиком отмечено среднеквадратичное значение. + +Выполняется **10.000 транзакций в режиме синхронной фиксации данных** на +диске. При этом требуется гарантия, что при аварийном выключении питания +(или другом подобном сбое) все данные будут консистентны и полностью +соответствовать последней завершенной транзакции. В _libmdbx_ в этом +режиме при фиксации каждой транзакции выполняется системный вызов +[fdatasync](https://linux.die.net/man/2/fdatasync). + +В каждой транзакции выполняется комбинированная CRUD-операция (две +вставки, одно чтение, одно обновление, одно удаление). Бенчмарк стартует +на пустой базе, а при завершении, в результате выполняемых действий, в +базе насчитывается 10.000 небольших key-value записей. + +![Comparison #3: Sync-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-3.png) + +-------------------------------------------------------------------------------- + +## Отложенная фиксация + + - Линейная шкала слева и темные прямоугольники соответствуют количеству + транзакций в секунду, усредненному за всё время теста. + + - Логарифмическая шкала справа и желтые интервальные отрезки + соответствуют времени выполнения транзакций. При этом каждый отрезок + показывает минимальное и максимальное время, затраченное на выполнение + транзакций, а крестиком отмечено среднеквадратичное значение. + +Выполняется **100.000 транзакций в режиме отложенной фиксации данных** +на диске. При этом требуется гарантия, что при аварийном выключении +питания (или другом подобном сбое) все данные будут консистентны на +момент завершения одной из транзакций, но допускается потеря изменений +из некоторого количества последних транзакций, что для многих движков +предполагает включение +[WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) (write-ahead +logging) либо журнала транзакций, который в свою очередь опирается на +гарантию упорядоченности данных в журналируемой файловой системе. +_libmdbx_ при этом не ведет WAL, а передает весь контроль файловой +системе и ядру ОС. + +В каждой транзакции выполняется комбинированная CRUD-операция (две +вставки, одно чтение, одно обновление, одно удаление). Бенчмарк стартует +на пустой базе, а при завершении, в результате выполняемых действий, в +базе насчитывается 100.000 небольших key-value записей. + +![Comparison #4: Lazy-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-4.png) + +-------------------------------------------------------------------------------- + +## Асинхронная фиксация + + - Линейная шкала слева и темные прямоугольники соответствуют количеству + транзакций в секунду, усредненному за всё время теста. + + - Логарифмическая шкала справа и желтые интервальные отрезки + соответствуют времени выполнения транзакций. При этом каждый отрезок + показывает минимальное и максимальное время, затраченное на выполнение + транзакций, а крестиком отмечено среднеквадратичное значение. + +Выполняется **1.000.000 транзакций в режиме асинхронной фиксации +данных** на диске. При этом требуется гарантия, что при аварийном +выключении питания (или другом подобном сбое) все данные будут +консистентны на момент завершения одной из транзакций, но допускается +потеря изменений из значительного количества последних транзакций. Во +всех движках при этом включался режим предполагающий минимальную +нагрузку на диск по записи, и соответственно минимальную гарантию +сохранности данных. В _libmdbx_ при этом используется режим асинхронной +записи измененных страниц на диск посредством ядра ОС и системного +вызова [msync(MS_ASYNC)](https://linux.die.net/man/2/msync). + +В каждой транзакции выполняется комбинированная CRUD-операция (две +вставки, одно чтение, одно обновление, одно удаление). Бенчмарк стартует +на пустой базе, а при завершении, в результате выполняемых действий, в +базе насчитывается 10.000 небольших key-value записей. + +![Comparison #5: Async-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-5.png) + +-------------------------------------------------------------------------------- + +## Потребление ресурсов + +Показана соотнесенная сумма использованных ресурсов в ходе бенчмарка в +режиме отложенной фиксации: + + - суммарное количество операций ввода-вывода (IOPS), как записи, так и + чтения. + + - суммарное затраченное время процессора, как в режиме пользовательских + процессов, так и в режиме ядра ОС. + + - использованное место на диске при завершении теста, после закрытия БД + из тестирующего процесса, но без ожидания всех внутренних операций + обслуживания (компактификации LSM и т.п.). + +Движок _ForestDB_ был исключен при оформлении результатов, так как +относительно конкурентов многократно превысил потребление каждого из +ресурсов (потратил процессорное время на генерацию IOPS для заполнения +диска), что не позволяло наглядно сравнить показатели остальных движков +на одной диаграмме. + +Все данные собирались посредством системного вызова +[getrusage()](http://man7.org/linux/man-pages/man2/getrusage.2.html) и +сканированием директорий с данными. + +![Comparison #6: Cost comparison](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-6.png) + +-------------------------------------------------------------------------------- + +``` +$ objdump -f -h -j .text libmdbx.so + +libmdbx.so: file format elf64-x86-64 +architecture: i386:x86-64, flags 0x00000150: +HAS_SYMS, DYNAMIC, D_PAGED +start address 0x0000000000003870 + +Sections: +Idx Name Size VMA LMA File off Algn + 11 .text 000173d4 0000000000003870 0000000000003870 00003870 2**4 + CONTENTS, ALLOC, LOAD, READONLY, CODE + +``` diff --git a/contrib/db/libmdbx/README.md b/contrib/db/libmdbx/README.md new file mode 100644 index 00000000..a5b420f3 --- /dev/null +++ b/contrib/db/libmdbx/README.md @@ -0,0 +1,701 @@ +### The [repository now only mirrored on the Github](https://abf.io/erthink/libmdbx) due to illegal discriminatory restrictions for Russian Crimea and for sovereign crimeans. + +----- + +libmdbx +====================================== +Revised and extended descendant of [Lightning Memory-Mapped Database](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database) (aka _LMDB_). +Русскоязычная версия [здесь](README-RU.md). + +_libmdbx_ is superior to LMDB in terms of features and reliability, not +inferior in performance. _libmdbx_ works on Linux, FreeBSD, MacOS X and +other systems compliant with POSIX.1-2008, but also support Windows as a +complementary platform. + +The next version is under active non-public development, which will +radically change both the API and the database format. The goal of this +revolution is to provide a clearer and more reliable API, add more +features and new database properties. + +*The Future will (be) [Positive](https://www.ptsecurity.com). Всё будет хорошо.* + +[![Build Status](https://travis-ci.org/leo-yuriev/libmdbx.svg?branch=master)](https://travis-ci.org/leo-yuriev/libmdbx) +[![Build status](https://ci.appveyor.com/api/projects/status/ue94mlopn50dqiqg/branch/master?svg=true)](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master) +[![Coverity Scan Status](https://scan.coverity.com/projects/12915/badge.svg)](https://scan.coverity.com/projects/reopen-libmdbx) + +## Table of Contents +- [Overview](#overview) + - [Comparison with other databases](#comparison-with-other-databases) + - [History & Acknowledgments](#history) +- [Description](#description) + - [Key features](#key-features) + - [Improvements over LMDB](#improvements-over-lmdb) + - [Gotchas](#gotchas) + - [Problem of long-time reading](#problem-of-long-time-reading) + - [Durability in asynchronous writing mode](#durability-in-asynchronous-writing-mode) +- [Usage](#usage) + - [Building](#building) + - [Bindings](#bindings) +- [Performance comparison](#performance-comparison) + - [Integral performance](#integral-performance) + - [Read scalability](#read-scalability) + - [Sync-write mode](#sync-write-mode) + - [Lazy-write mode](#lazy-write-mode) + - [Async-write mode](#async-write-mode) + - [Cost comparison](#cost-comparison) + +----- + +## Overview +_libmdbx_ is an embedded lightweight key-value database engine oriented +for performance. + +_libmdbx_ allows multiple processes to read and update several key-value +tables concurrently, while being +[ACID](https://en.wikipedia.org/wiki/ACID)-compliant, with minimal +overhead and Olog(N) operation cost. + +_libmdbx_ enforce +[serializability](https://en.wikipedia.org/wiki/Serializability) for +writers by single +[mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) and affords +[wait-free](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom) +for parallel readers without atomic/interlocked operations, while +writing and reading transactions do not block each other. + +_libmdbx_ can guarantee consistency after crash depending of operation +mode. + +_libmdbx_ uses [B+Trees](https://en.wikipedia.org/wiki/B%2B_tree) and +[Memory-Mapping](https://en.wikipedia.org/wiki/Memory-mapped_file), +doesn't use [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) +which might be a caveat for some workloads. + +### Comparison with other databases +For now please refer to [chapter of "BoltDB comparison with other +databases"](https://github.com/coreos/bbolt#comparison-with-other-databases) +which is also (mostly) applicable to MDBX. + +### History +The _libmdbx_ design is based on [Lightning Memory-Mapped +Database](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database). +Initial development was going in +[ReOpenLDAP](https://github.com/leo-yuriev/ReOpenLDAP) project. About a +year later libmdbx was isolated to separate project, which was +[presented at Highload++ 2015 +conference](http://www.highload.ru/2015/abstracts/1831.html). + +Since early 2017 _libmdbx_ is used in [Fast Positive Tables](https://github.com/leo-yuriev/libfpta), +and development is funded by [Positive Technologies](https://www.ptsecurity.com). + +### Acknowledgments +Howard Chu is the author of LMDB, from which +originated the MDBX in 2015. + +Martin Hedenfalk is the author of `btree.c` code, which +was used for begin development of LMDB. + +----- + +Description +=========== + +## Key features + +_libmdbx_ inherits all features and characteristics from +[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database): + +1. Key-value pairs are stored in ordered map(s), keys are always sorted, +range lookups are supported. + +2. Data is [memory-mapped](https://en.wikipedia.org/wiki/Memory-mapped_file) +into each worker DB process, and could be accessed zero-copy from transactions. + +3. Transactions are +[ACID](https://en.wikipedia.org/wiki/ACID)-compliant, through to +[MVCC](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) +and [CoW](https://en.wikipedia.org/wiki/Copy-on-write). Writes are +strongly serialized and aren't blocked by reads, transactions can't +conflict with each other. Reads are guaranteed to get only commited data +([relaxing serializability](https://en.wikipedia.org/wiki/Serializability#Relaxing_serializability)). + +4. Read transactions are +[non-blocking](https://en.wikipedia.org/wiki/Non-blocking_algorithm), +don't use [atomic operations](https://en.wikipedia.org/wiki/Linearizability#High-level_atomic_operations). +Readers don't block each other and aren't blocked by writers. Read +performance scales linearly with CPU core count. + > Nonetheless, "connect to DB" (starting the first read transaction in a thread) and + > "disconnect from DB" (closing DB or thread termination) requires a lock + > acquisition to register/unregister at the "readers table". + +5. Keys with multiple values are stored efficiently without key +duplication, sorted by value, including integers (valuable for +secondary indexes). + +6. Efficient operation on short fixed length keys, +including 32/64-bit integer types. + +7. [WAF](https://en.wikipedia.org/wiki/Write_amplification) (Write +Amplification Factor) и RAF (Read Amplification Factor) are Olog(N). + +8. No [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) and +transaction journal. In case of a crash no recovery needed. No need for +regular maintenance. Backups can be made on the fly on working DB +without freezing writers. + +9. No additional memory management, all done by basic OS services. + + +## Improvements over LMDB + +1. Automatic dynamic DB size management according to the parameters +specified by `mdbx_env_set_geometry()` function. Including +growth step and truncation threshold, as well as the choice of page +size. + +2. Automatic returning of freed pages into unallocated space at the end +of database file, with optionally automatic shrinking it. This reduces +amount of pages resides in RAM and circulated in disk I/O. In fact +_libmdbx_ constantly performs DB compactification, without spending +additional resources for that. + +3. `LIFO RECLAIM` mode: + + The newest pages are picked for reuse instead of the oldest. This allows + to minimize reclaim loop and make it execution time independent of total + page count. + + This results in OS kernel cache mechanisms working with maximum + efficiency. In case of using disk controllers or storages with + [BBWC](https://en.wikipedia.org/wiki/Disk_buffer#Write_acceleration) + this may greatly improve write performance. + +4. Fast estimation of range query result size via functions +`mdbx_estimate_range()`, `mdbx_estimate_move()` and +`mdbx_estimate_distance()`. E.g. for selection the optimal query +execution plan. + +5. `mdbx_chk` tool for DB integrity check. + +6. Support for keys and values of zero length, including multi-values +(aka sorted duplicates). + +7. Ability to assign up to 3 persistent 64-bit markers to commiting +transaction with `mdbx_canary_put()` and then get them in read +transaction by `mdbx_canary_get()`. + +8. Ability to update or delete record and get previous value via +`mdbx_replace()`. Also allows update the specific item from multi-value +with the same key. + +9. Sequence generation via `mdbx_dbi_sequence()`. + +10. `OOM-KICK` callback. + + `mdbx_env_set_oomfunc()` allows to set a callback, which will be called + in the event of DB space exhausting during long-time read transaction in + parallel with extensive updating. Callback will be invoked with PID and + pthread_id of offending thread as parameters. Callback can do any of + these things to remedy the problem: + + * wait for read transaction to finish normally; + + * kill the offending process (signal 9), if separate process is doing + long-time read; + + * abort or restart offending read transaction if it's running in sibling + thread; + + * abort current write transaction with returning error code. + +11. Ability to open DB in exclusive mode by `MDBX_EXCLUSIVE` flag. + +12. Ability to get how far current read-transaction snapshot lags +from the latest version of the DB by `mdbx_txn_straggler()`. + +13. Ability to explicitly update the existing record, not insertion +a new one. Implemented as `MDBX_CURRENT` flag for `mdbx_put()`. + +14. Fixed `mdbx_cursor_count()`, which returns correct count of +duplicated (aka multi-value) for all cases and any cursor position. + +15. `mdbx_env_info()` to getting additional info, including number of +the oldest snapshot of DB, which is used by someone of the readers. + +16. `mdbx_del()` doesn't ignore additional argument (specifier) `data` +for tables without duplicates (without flag `MDBX_DUPSORT`), if `data` +is not null then always uses it to verify record, which is being +deleted. + +17. Ability to open dbi-table with simultaneous with race-free setup +of comparators for keys and values, via `mdbx_dbi_open_ex()`. + +18. `mdbx_is_dirty()`to find out if given key or value is on dirty page, that +useful to avoid copy-out before updates. + +19. Correct update of current record in `MDBX_CURRENT` mode of +`mdbx_cursor_put()`, including sorted duplicated. + +20. Check if there is a row with data after current cursor position via +`mdbx_cursor_eof()`. + +21. Additional error code `MDBX_EMULTIVAL`, which is returned by +`mdbx_put()` and `mdbx_replace()` in case is ambiguous update or delete. + +22. Ability to get value by key and duplicates count by `mdbx_get_ex()`. + +23. Functions `mdbx_cursor_on_first()` and `mdbx_cursor_on_last()`, +which allows to check cursor is currently on first or last position +respectively. + +24. Automatic creation of steady commit-points (flushing data to the +disk) when the volume of changes reaches a threshold, which can be +set by `mdbx_env_set_syncbytes()`. + +25. Control over debugging and receiving of debugging messages via +`mdbx_setup_debug()`. + +26. Function `mdbx_env_pgwalk()` for page-walking the DB. + +27. Three meta-pages instead of two, that allows to guarantee +consistency of data when updating weak commit-points without the +risk of damaging the last steady commit-point. + +28. Guarantee of DB integrity in `WRITEMAP+MAPSYNC` mode: + > Current _libmdbx_ gives a choice of safe async-write mode (default) + > and `UTTERLY_NOSYNC` mode which may result in full + > DB corruption during system crash as with LMDB. For details see + > [Data safety in async-write mode](#data-safety-in-async-write-mode). + +29. Ability to close DB in "dirty" state (without data flush and +creation of steady synchronization point) via `mdbx_env_close_ex()`. + +30. If read transaction is aborted via `mdbx_txn_abort()` or +`mdbx_txn_reset()` then DBI-handles, which were opened during it, +will not be closed or deleted. In several cases this allows +to avoid hard-to-debug errors. + +31. All cursors in all read and write transactions can be reused by +`mdbx_cursor_renew()` and MUST be freed explicitly. + > ## Caution, please pay attention! + > + > This is the only change of API, which changes semantics of cursor management + > and can lead to memory leaks on misuse. This is a needed change as it eliminates ambiguity + > which helps to avoid such errors as: + > - use-after-free; + > - double-free; + > - memory corruption and segfaults. + + +32. On **Mac OS X** the `fcntl(F_FULLFSYNC)` syscall is used _by +default_ to synchronize data with the disk, as this is [the only way to +guarantee data +durability](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fsync.2.html) +in case of power failure. Unfortunately, in scenarios with high write +intensity, the use of `F_FULLFSYNC` significant degrades performance +compared to LMDB, where the `fsync()` syscall is used. Therefore, +_libmdbx_ allows you to override this behavior by defining the +`MDBX_OSX_SPEED_INSTEADOF_DURABILITY=1` option while build the library. + +33. On **Windows** the `LockFileEx()` syscall is used for locking, since +it allows place the database on network drives, and provides protection +against incompetent user actions (aka +[poka-yoke](https://en.wikipedia.org/wiki/Poka-yoke)). Therefore +_libmdbx_ may be a little lag in performance tests from LMDB where a +named mutexes are used. + + +## Gotchas + +1. There cannot be more than one writer at a time. This allows serialize an +updates and eliminate any possibility of conflicts, deadlocks or logical errors. + +2. No [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) means +relatively big [WAF](https://en.wikipedia.org/wiki/Write_amplification) +(Write Amplification Factor). Because of this syncing data to disk might +be quite resource intensive and be main performance bottleneck during +intensive write workload. + > As compromise _libmdbx_ allows several modes of lazy and/or periodic + > syncing, including `MAPASYNC` mode, which modificate data in memory and + > asynchronously syncs data to disk, moment to sync is picked by OS. + > + > Although this should be used with care, synchronous transactions in a DB + > with transaction journal will require 2 IOPS minimum (probably 3-4 in + > practice) because of filesystem overhead, overhead depends on + > filesystem, not on record count or record size. In _libmdbx_ IOPS count + > will grow logarithmically depending on record count in DB (height of B+ + > tree) and will require at least 2 IOPS per transaction too. + +3. [CoW](https://en.wikipedia.org/wiki/Copy-on-write) for +[MVCC](https://en.wikipedia.org/wiki/Multiversion_concurrency_control) +is done on memory page level with +[B+trees](https://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE). +Therefore altering data requires to copy about Olog(N) memory pages, +which uses [memory bandwidth](https://en.wikipedia.org/wiki/Memory_bandwidth) and is main +performance bottleneck in `MAPASYNC` mode. + > This is unavoidable, but isn't that bad. Syncing data to disk requires + > much more similar operations which will be done by OS, therefore this is + > noticeable only if data sync to persistent storage is fully disabled. + > _libmdbx_ allows to safely save data to persistent storage with minimal + > performance overhead. If there is no need to save data to persistent + > storage then it's much more preferable to use `std::map`. + + +4. _LMDB_ has a problem of long-time readers which degrades performance +and bloats DB. + > _libmdbx_ addresses that, details below. + +5. _LMDB_ is susceptible to DB corruption in `WRITEMAP+MAPASYNC` mode. +_libmdbx_ in `WRITEMAP+MAPASYNC` guarantees DB integrity and consistency +of data. + > Additionally there is an alternative: `UTTERLY_NOSYNC` mode. + > Details below. + + +### Problem of long-time reading +Garbage collection problem exists in all databases one way or another +(e.g. VACUUM in PostgreSQL). But in _libmdbx_ and LMDB it's even more +discernible because of high transaction rate and intentional internals +simplification in favor of performance. + +Understanding the problem requires some explanation, but can be +difficult for quick perception. So is is reasonable +to simplify this as follows: + +* Massive altering of data during a parallel long read operation may +exhaust the free DB space. + +* If the available space is exhausted, any attempt to update the data +will cause a "MAP_FULL" error until a long read transaction is +completed. + +* A good example of long readers is a hot backup or debugging of +a client application while retaining an active read transaction. + +* In _LMDB_ this results in degraded performance of all operations of +writing data to persistent storage. + +* _libmdbx_ has the `OOM-KICK` mechanism which allow to abort such +operations and the `LIFO RECLAIM` mode which addresses performance +degradation. + +### Durability in asynchronous writing mode +In `WRITEMAP+MAPSYNC` mode updated (aka dirty) pages are written to +persistent storage by the OS kernel. This means that if the application +fails, the OS kernel will finish writing all updated data to disk and +nothing will be lost. However, in the case of hardware malfunction or OS +kernel fatal error, only some updated data can be written to disk and +the database structure is likely to be destroyed. In such situation, DB +is completely corrupted and can't be repaired. + +_libmdbx_ addresses this by fully reimplementing write path of data: + +* In `WRITEMAP+MAPSYNC` mode meta-data pages aren't updated in place, +instead their shadow copies are used and their updates are synced after +data is flushed to disk. + +* During transaction commit _libmdbx_ marks it as a steady or weak +depending on synchronization status between RAM and persistent storage. +For instance, in the `WRITEMAP+MAPSYNC` mode committed transactions +are marked as weak by default, but as steady after explicit data flushes. + +* _libmdbx_ maintains three separate meta-pages instead of two. This +allows to commit transaction as steady or weak without losing two +previous commit points (one of them can be steady, and another +weak). Thus, after a fatal system failure, it will be possible to +rollback to the last steady commit point. + +* During DB open _libmdbx_ rollbacks to the last steady commit point, +this guarantees database integrity after a crash. However, if the +database opening in read-only mode, such rollback cannot be performed +which will cause returning the MDBX_WANNA_RECOVERY error. + +For data integrity a pages which form database snapshot with steady +commit point, must not be updated until next steady commit point. +Therefore the last steady commit point creates an effect analogues to +"long-time read". The only difference that now in case of space +exhaustion the problem will be immediately addressed by writing changes +to disk and forming the new steady commit point. + +So in async-write mode _libmdbx_ will always use new pages until the +free DB space will be exhausted or `mdbx_env_sync()` will be invoked, +and the total write traffic to the disk will be the same as in +sync-write mode. + +Currently libmdbx gives a choice between a safe async-write mode +(default) and `UTTERLY_NOSYNC` mode which may lead to DB corruption +after a system crash, i.e. like the LMDB. + +Next version of _libmdbx_ will be automatically create steady commit +points in async-write mode upon completion transfer data to the disk. + +-------------------------------------------------------------------------------- + +Usage +===== + +## Building + +To build on all platforms except Windows the prerequirements are the +same: non-obsolete versions of GNU Make, +[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)), C and C++ +compilers compatible with GCC or CLANG. On Windows you will need only : +Microsoft Visual Studio 2015 or later, Windows SDK for Windows 8 or +later. + +Historically, the libmdbx builing is based on single +[Makefile](https://en.wikipedia.org/wiki/Makefile) which assumes +different recipes depending on target platform. In the next versions, it +is planned to switch to [CMake](https://en.wikipedia.org/wiki/CMake), +with the refusal to support other tools. + +#### DSO/DLL unloading and destructors of Thread-Local-Storage objects +When building _libmdbx_ as a shared library or use static _libmdbx_ as a +part of another dynamic library, it is advisable to make sure that your +system ensures the correctness of the call destructors of +Thread-Local-Storage objects when unloading dynamic libraries'. + +If this is not the case, then unloading a dynamic-link library with +_libmdbx_ code inside, can result in either a resource leak or a crash +due to calling destructors from an already unloaded DSO/DLL object. The +problem can only manifest in a multithreaded application, which makes +the unloading of shared dynamic libraries with _libmdbx_ code inside, +after using _libmdbx_. It is known that TLS-destructors are properly +maintained in the following cases: + +- On all modern versions of Windows (Windows 7 and later). + +- On systems with the +[`__cxa_thread_atexit_impl()`](https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables) +function in the standard C library, including systems with GNU libc +version 2.18 and later. + +- On systems with libpthread/ntpl from GNU libc with bug fixes +[#21031](https://sourceware.org/bugzilla/show_bug.cgi?id=21031) and +[#21032](https://sourceware.org/bugzilla/show_bug.cgi?id=21032), or +where there are no similar bugs in the pthreads implementation. + +### Linux and other platforms with GNU Make +To build the library it is enough to execute `make all` in the directory +of source code, and `make check` for execute the basic tests. + +If the `make` installed on the system is not GNU Make, there will be a +lot of errors from make when trying to build. In this case, perhaps you +should use `gmake` instead of `make`, or even `gnu-make`, etc. + +### FreeBSD and related platforms +As a rule, in such systems, the default is to use Berkeley Make. And GNU +Make is called by the gmake command or may be missing. In addition, +[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) may be absent. + +You need to install the required components: GNU Make, bash, C and C++ +compilers compatible with GCC or CLANG. After that, to build the +library, it is enough execute `gmake all` (or `make all`) in the +directory with source code, and `gmake check` (or `make check`) to run +the basic tests. + +### Windows +For building _libmdbx_ on Windows the [Microsoft Visual +Studio](https://en.wikipedia.org/wiki/Microsoft_Visual_Studio) is +recommended, but not tools such as MinGW, MSYS, or Cygwin. To do this, +the libmdbx source code includes the set of appropriate project files +that are compatible with Visual Studio 2015, the Windows SDK for Windows +8.1, and later. Just open `mdbx.sln` in Visual Studio and build the +library. + +To build with newer versions of the SDK or Visual Studio, it should be +sufficient to execute "Retarget solution". To build for older versions +of Windows (such as Windows XP) or by older compilers, you will need to +convert or recreate the corresponding project files yourself. + +Building by MinGW, MSYS or Cygwin is potentially possible. However, +these scripts are not tested and will probably require you to modify the +Makefile. It should be noted that in _libmdbx_ was efforts to resolve +runtime dependencies from CRT and other libraries Visual Studio. +For this is enough define the `MDBX_AVOID_CRT` during build. + +An example of running a basic test script can be found in the +[CI-script](appveyor.yml) for [AppVeyor](https://www.appveyor.com/). To +run the [long stochastic test scenario](test/long_stochastic.sh), +[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)) is required, and +the such testing is recommended with place the test data on the +[RAM-disk](https://en.wikipedia.org/wiki/RAM_drive). + +### MacOS X +Current [native build tools](https://en.wikipedia.org/wiki/Xcode) for +MacOS X include GNU Make, CLANG and an outdated version of bash. +Therefore, to build the library, it is enough to run `make all` in the +directory with source code, and run `make check` to execute the base +tests. If something goes wrong, it is recommended to install +[Homebrew](https://brew.sh/) and try again. + +To run the [long stochastic test scenario](test/long_stochastic.sh), you +will need to install the current (not outdated) version of +[bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)). To do this, we +recommend that you install [Homebrew](https://brew.sh/) and then execute +`brew install bash`. + +## Bindings + + | Runtime | GitHub | Author | + | -------- | ------ | ------ | + | Java | [mdbxjni](https://github.com/castortech/mdbxjni) | [Castor Technologies](https://castortech.com/) | + | .NET | [mdbx.NET](https://github.com/wangjia184/mdbx.NET) | [Jerry Wang](https://github.com/wangjia184) | + + +-------------------------------------------------------------------------------- + +Performance comparison +====================== + +All benchmarks were done by [IOArena](https://github.com/pmwkaa/ioarena) +and multiple [scripts](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015) +runs on Lenovo Carbon-2 laptop, i7-4600U 2.1 GHz, 8 Gb RAM, +SSD SAMSUNG MZNTD512HAGL-000L1 (DXT23L0Q) 512 Gb. + +## Integral performance + +Here showed sum of performance metrics in 3 benchmarks: + + - Read/Search on 4 CPU cores machine; + + - Transactions with [CRUD](https://en.wikipedia.org/wiki/CRUD) + operations in sync-write mode (fdatasync is called after each + transaction); + + - Transactions with [CRUD](https://en.wikipedia.org/wiki/CRUD) + operations in lazy-write mode (moment to sync data to persistent storage + is decided by OS). + +*Reasons why asynchronous mode isn't benchmarked here:* + + 1. It doesn't make sense as it has to be done with DB engines, oriented + for keeping data in memory e.g. [Tarantool](https://tarantool.io/), + [Redis](https://redis.io/)), etc. + + 2. Performance gap is too high to compare in any meaningful way. + +![Comparison #1: Integral Performance](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-1.png) + +-------------------------------------------------------------------------------- + +## Read Scalability + +Summary performance with concurrent read/search queries in 1-2-4-8 +threads on 4 CPU cores machine. + +![Comparison #2: Read Scalability](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-2.png) + +-------------------------------------------------------------------------------- + +## Sync-write mode + + - Linear scale on left and dark rectangles mean arithmetic mean + transactions per second; + + - Logarithmic scale on right is in seconds and yellow intervals mean + execution time of transactions. Each interval shows minimal and maximum + execution time, cross marks standard deviation. + +**10,000 transactions in sync-write mode**. In case of a crash all data +is consistent and state is right after last successful transaction. +[fdatasync](https://linux.die.net/man/2/fdatasync) syscall is used after +each write transaction in this mode. + +In the benchmark each transaction contains combined CRUD operations (2 +inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database +and after full run the database contains 10,000 small key-value records. + +![Comparison #3: Sync-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-3.png) + +-------------------------------------------------------------------------------- + +## Lazy-write mode + + - Linear scale on left and dark rectangles mean arithmetic mean of + thousands transactions per second; + + - Logarithmic scale on right in seconds and yellow intervals mean + execution time of transactions. Each interval shows minimal and maximum + execution time, cross marks standard deviation. + +**100,000 transactions in lazy-write mode**. In case of a crash all data +is consistent and state is right after one of last transactions, but +transactions after it will be lost. Other DB engines use +[WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) or transaction +journal for that, which in turn depends on order of operations in +journaled filesystem. _libmdbx_ doesn't use WAL and hands I/O operations +to filesystem and OS kernel (mmap). + +In the benchmark each transaction contains combined CRUD operations (2 +inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database +and after full run the database contains 100,000 small key-value +records. + + +![Comparison #4: Lazy-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-4.png) + +-------------------------------------------------------------------------------- + +## Async-write mode + + - Linear scale on left and dark rectangles mean arithmetic mean of + thousands transactions per second; + + - Logarithmic scale on right in seconds and yellow intervals mean + execution time of transactions. Each interval shows minimal and maximum + execution time, cross marks standard deviation. + +**1,000,000 transactions in async-write mode**. In case of a crash all +data will be consistent and state will be right after one of last +transactions, but lost transaction count is much higher than in +lazy-write mode. All DB engines in this mode do as little writes as +possible on persistent storage. _libmdbx_ uses +[msync(MS_ASYNC)](https://linux.die.net/man/2/msync) in this mode. + +In the benchmark each transaction contains combined CRUD operations (2 +inserts, 1 read, 1 update, 1 delete). Benchmark starts on empty database +and after full run the database contains 10,000 small key-value records. + +![Comparison #5: Async-write mode](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-5.png) + +-------------------------------------------------------------------------------- + +## Cost comparison + +Summary of used resources during lazy-write mode benchmarks: + + - Read and write IOPS; + + - Sum of user CPU time and sys CPU time; + + - Used space on persistent storage after the test and closed DB, but not + waiting for the end of all internal housekeeping operations (LSM + compactification, etc). + +_ForestDB_ is excluded because benchmark showed it's resource +consumption for each resource (CPU, IOPS) much higher than other engines +which prevents to meaningfully compare it with them. + +All benchmark data is gathered by +[getrusage()](http://man7.org/linux/man-pages/man2/getrusage.2.html) +syscall and by scanning data directory. + +![Comparison #6: Cost comparison](https://raw.githubusercontent.com/wiki/leo-yuriev/libmdbx/img/perf-slide-6.png) + +-------------------------------------------------------------------------------- + +``` +$ objdump -f -h -j .text libmdbx.so + +libmdbx.so: file format elf64-x86-64 +architecture: i386:x86-64, flags 0x00000150: +HAS_SYMS, DYNAMIC, D_PAGED +start address 0x0000000000003870 + +Sections: +Idx Name Size VMA LMA File off Algn + 11 .text 000173d4 0000000000003870 0000000000003870 00003870 2**4 + CONTENTS, ALLOC, LOAD, READONLY, CODE + +``` diff --git a/contrib/db/libmdbx/appveyor.yml b/contrib/db/libmdbx/appveyor.yml new file mode 100644 index 00000000..0c0dd8a6 --- /dev/null +++ b/contrib/db/libmdbx/appveyor.yml @@ -0,0 +1,54 @@ +version: 0.3.2.{build} + +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TOOLSET: v141 +# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 +# TOOLSET: v140 +# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 +# TOOLSET: v120 + +branches: + except: + - coverity_scan + +configuration: +- Debug +- Release + +platform: +- x86 +- x64 +#- ARM + +build_script: +- ps: > + msbuild "C:\projects\libmdbx\mdbx.sln" /verbosity:minimal + /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + /property:PlatformToolset=$env:TOOLSET + /property:Configuration=$env:CONFIGURATION + /property:Platform=$env:PLATFORM + +test_script: +- ps: | + if (($env:PLATFORM -eq "x86") -and (Test-Path "C:\projects\libmdbx\Win32\$env:CONFIGURATION\mdbx_test.exe" -PathType Leaf)) { + $mdbx_test = "C:\projects\libmdbx\Win32\$env:CONFIGURATION\mdbx_test.exe" + $mdbx_chk = "C:\projects\libmdbx\Win32\$env:CONFIGURATION\mdbx_chk.exe" + } elseif (($env:PLATFORM -ne "ARM") -and ($env:PLATFORM -ne "ARM64")) { + $mdbx_test = "C:\projects\libmdbx\$env:PLATFORM\$env:CONFIGURATION\mdbx_test.exe" + $mdbx_chk = "C:\projects\libmdbx\$env:PLATFORM\$env:CONFIGURATION\mdbx_chk.exe" + } else { + $mdbx_test = "" + $mdbx_chk = "" + } + + if ($mdbx_test -ne "") { + & "$mdbx_test" --pathname=test.db --dont-cleanup-after basic | Tee-Object -file test.log | Select-Object -last 42 + & "$mdbx_chk" -nvv test.db | Tee-Object -file chk.log | Select-Object -last 42 + } + +on_failure: +- ps: Push-AppveyorArtifact test.log +- ps: Push-AppveyorArtifact test.db +- ps: Push-AppveyorArtifact chk.log diff --git a/contrib/db/libmdbx/dll.vcxproj b/contrib/db/libmdbx/dll.vcxproj new file mode 100644 index 00000000..5464c158 --- /dev/null +++ b/contrib/db/libmdbx/dll.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {6D19209B-ECE7-4B9C-941C-0AA2B484F199} + Win32Proj + 8.1 + + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + mdbx + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + PreLinkEvent + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + mdbx + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + PreLinkEvent + + + true + mdbx + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + PreLinkEvent + + + false + mdbx + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + PreLinkEvent + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + EnableAllWarnings + ProgramDatabase + Disabled + true + true + + + MachineX86 + true + Windows + ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) + + + Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) + $(IntermediateOutputPath)mdbx_ntdll_extra.lib + $(ProjectDir)src/ntdll.def + lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) + MultiThreadedDLL + EnableAllWarnings + ProgramDatabase + true + Full + AnySuitable + true + Size + true + true + true + false + All + + + MachineX86 + true + Windows + true + true + UseLinkTimeCodeGeneration + ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) + true + + + Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) + $(IntermediateOutputPath)mdbx_ntdll_extra.lib + $(ProjectDir)src/ntdll.def + lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) + + + + + ProgramDatabase + + + + + EnableAllWarnings + WIN64;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + true + true + + + ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) + + + Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) + $(IntermediateOutputPath)mdbx_ntdll_extra.lib + $(ProjectDir)src/ntdll.def + lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) + + + + + WIN64;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) + MultiThreadedDLL + true + Full + AnySuitable + true + Size + true + true + EnableAllWarnings + true + false + All + + + UseLinkTimeCodeGeneration + ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) + true + + + Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) + $(IntermediateOutputPath)mdbx_ntdll_extra.lib + $(ProjectDir)src/ntdll.def + lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) + + + + + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/libmdbx.cflags b/contrib/db/libmdbx/libmdbx.cflags new file mode 100644 index 00000000..bb8c4c33 --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.cflags @@ -0,0 +1 @@ +-std=c11 \ No newline at end of file diff --git a/contrib/db/libmdbx/libmdbx.config b/contrib/db/libmdbx/libmdbx.config new file mode 100644 index 00000000..e0284f42 --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.config @@ -0,0 +1,2 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 diff --git a/contrib/db/libmdbx/libmdbx.creator b/contrib/db/libmdbx/libmdbx.creator new file mode 100644 index 00000000..e94cbbd3 --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.creator @@ -0,0 +1 @@ +[General] diff --git a/contrib/db/libmdbx/libmdbx.cxxflags b/contrib/db/libmdbx/libmdbx.cxxflags new file mode 100644 index 00000000..6435dfce --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/contrib/db/libmdbx/libmdbx.files b/contrib/db/libmdbx/libmdbx.files new file mode 100644 index 00000000..cdea405b --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.files @@ -0,0 +1,62 @@ +AUTHORS +CMakeLists.txt +LICENSE +Makefile +README-RU.md +README.md +TODO.md +mdbx.h +src/bits.h +src/defs.h +src/lck-linux.c +src/lck-posix.c +src/lck-windows.c +src/mdbx.c +src/osal.c +src/osal.h +src/tools/CMakeLists.txt +src/tools/mdbx_chk.c +src/tools/mdbx_copy.1 +src/tools/mdbx_copy.c +src/tools/mdbx_dump.1 +src/tools/mdbx_dump.c +src/tools/mdbx_load.1 +src/tools/mdbx_load.c +src/tools/mdbx_stat.1 +src/tools/mdbx_stat.c +src/tools/wingetopt.c +src/tools/wingetopt.h +src/version.c +test/CMakeLists.txt +test/actor.cc +test/append.cc +test/base.h +test/cases.cc +test/chrono.cc +test/chrono.h +test/config.cc +test/config.h +test/copy.cc +test/dead.cc +test/hill.cc +test/jitter.cc +test/keygen.cc +test/keygen.h +test/log.cc +test/log.h +test/main.cc +test/osal-unix.cc +test/osal-windows.cc +test/osal.h +test/pcrf/CMakeLists.txt +test/test.cc +test/test.h +test/try.cc +test/ttl.cc +test/utils.cc +test/utils.h +tutorial/CMakeLists.txt +tutorial/README.md +tutorial/sample-bdb.txt +tutorial/sample-mdb.txt +tutorial/sample-mdbx.c diff --git a/contrib/db/libmdbx/libmdbx.includes b/contrib/db/libmdbx/libmdbx.includes new file mode 100644 index 00000000..eb512a01 --- /dev/null +++ b/contrib/db/libmdbx/libmdbx.includes @@ -0,0 +1,4 @@ +. +src +src/tools +test diff --git a/contrib/db/libmdbx/mdbx.h b/contrib/db/libmdbx/mdbx.h new file mode 100644 index 00000000..267b94c0 --- /dev/null +++ b/contrib/db/libmdbx/mdbx.h @@ -0,0 +1,2005 @@ +/* LICENSE AND COPYRUSTING ***************************************************** + * + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + * + * --- + * + * This code is derived from "LMDB engine" written by + * Howard Chu (Symas Corporation), which itself derived from btree.c + * written by Martin Hedenfalk. + * + * --- + * + * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + * + * --- + * + * Portions Copyright (c) 2009, 2010 Martin Hedenfalk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/* ACKNOWLEDGEMENTS ************************************************************ + * + * Howard Chu (Symas Corporation) - the author of LMDB, + * from which originated the MDBX in 2015. + * + * Martin Hedenfalk - the author of `btree.c` code, + * which was used for begin development of LMDB. */ + +#pragma once +#ifndef LIBMDBX_H +#define LIBMDBX_H + +/* IMPENDING CHANGES WARNING *************************************************** + * + * MDBX is under active non-public development, database format and API + * will be refined. New version won't be backwards compatible. Main focus + * of the rework is to provide clear and robust API and new features. + * + ******************************************************************************/ + +#ifdef _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable : 4548) /* expression before comma has no effect; \ + expected expression with side - effect */ +#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ + * semantics are not enabled. Specify /EHsc */ +#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ + * mode specified; termination on exception is \ + * not guaranteed. Specify /EHsc */ +#endif /* _MSC_VER (warnings) */ + +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) + +#include +#include +#ifndef __mode_t_defined +typedef unsigned short mode_t; +#endif +typedef HANDLE mdbx_filehandle_t; +typedef DWORD mdbx_pid_t; +typedef DWORD mdbx_tid_t; +#define MDBX_ENODATA ERROR_HANDLE_EOF +#define MDBX_EINVAL ERROR_INVALID_PARAMETER +#define MDBX_EACCESS ERROR_ACCESS_DENIED +#define MDBX_ENOMEM ERROR_OUTOFMEMORY +#define MDBX_EROFS ERROR_FILE_READ_ONLY +#define MDBX_ENOSYS ERROR_NOT_SUPPORTED +#define MDBX_EIO ERROR_WRITE_FAULT +#define MDBX_EPERM ERROR_INVALID_FUNCTION +#define MDBX_EINTR ERROR_CANCELLED +#define MDBX_ENOFILE ERROR_FILE_NOT_FOUND + +#else + +#include /* for error codes */ +#include /* for pthread_t */ +#include /* for pid_t */ +#include /* for truct iovec */ +#define HAVE_STRUCT_IOVEC 1 +typedef int mdbx_filehandle_t; +typedef pid_t mdbx_pid_t; +typedef pthread_t mdbx_tid_t; +#ifdef ENODATA +#define MDBX_ENODATA ENODATA +#else +#define MDBX_ENODATA -1 +#endif +#define MDBX_EINVAL EINVAL +#define MDBX_EACCESS EACCES +#define MDBX_ENOMEM ENOMEM +#define MDBX_EROFS EROFS +#define MDBX_ENOSYS ENOSYS +#define MDBX_EIO EIO +#define MDBX_EPERM EPERM +#define MDBX_EINTR EINTR +#define MDBX_ENOFILE ENOENT + +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/*--------------------------------------------------------------------------*/ + +#ifndef __has_attribute +#define __has_attribute(x) (0) +#endif + +#ifndef __dll_export +#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(__GNUC__) || __has_attribute(dllexport) +#define __dll_export __attribute__((dllexport)) +#elif defined(_MSC_VER) +#define __dll_export __declspec(dllexport) +#else +#define __dll_export +#endif +#elif defined(__GNUC__) || __has_attribute(__visibility__) +#define __dll_export __attribute__((__visibility__("default"))) +#else +#define __dll_export +#endif +#endif /* __dll_export */ + +#ifndef __dll_import +#if defined(_WIN32) || defined(__CYGWIN__) +#if defined(__GNUC__) || __has_attribute(dllimport) +#define __dll_import __attribute__((dllimport)) +#elif defined(_MSC_VER) +#define __dll_import __declspec(dllimport) +#else +#define __dll_import +#endif +#else +#define __dll_import +#endif +#endif /* __dll_import */ + +/*--------------------------------------------------------------------------*/ + +#define MDBX_VERSION_MAJOR 0 +#define MDBX_VERSION_MINOR 3 + +#if defined(LIBMDBX_EXPORTS) +#define LIBMDBX_API __dll_export +#elif defined(LIBMDBX_IMPORTS) +#define LIBMDBX_API __dll_import +#else +#define LIBMDBX_API +#endif /* LIBMDBX_API */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mdbx_version_info { + uint8_t major; + uint8_t minor; + uint16_t release; + uint32_t revision; + struct { + const char *datetime; + const char *tree; + const char *commit; + const char *describe; + } git; +} mdbx_version_info; + +typedef struct mdbx_build_info { + const char *datetime; + const char *target; + const char *options; + const char *compiler; + const char *flags; +} mdbx_build_info; + +extern LIBMDBX_API const mdbx_version_info mdbx_version; +extern LIBMDBX_API const mdbx_build_info mdbx_build; + +#if defined(_WIN32) || defined(_WIN64) +#ifndef MDBX_BUILD_DLL + +/* Dll initialization callback for ability to dynamically load MDBX DLL by + * LoadLibrary() on Windows versions before Windows Vista. This function MUST be + * called once from DllMain() for each reason (DLL_PROCESS_ATTACH, + * DLL_PROCESS_DETACH, DLL_THREAD_ATTACH and DLL_THREAD_DETACH). Do this + * carefully and ONLY when actual Windows version don't support initialization + * via "TLS Directory" (e.g .CRT$XL[A-Z] sections in executable or dll file). */ + +#ifndef MDBX_CONFIG_MANUAL_TLS_CALLBACK +#define MDBX_CONFIG_MANUAL_TLS_CALLBACK 0 +#endif +#if MDBX_CONFIG_MANUAL_TLS_CALLBACK +void LIBMDBX_API NTAPI mdbx_dll_callback(PVOID module, DWORD reason, + PVOID reserved); +#endif /* MDBX_CONFIG_MANUAL_TLS_CALLBACK */ +#endif /* MDBX_BUILD_DLL */ +#endif /* Windows */ + +/* The name of the lock file in the DB environment */ +#define MDBX_LOCKNAME "/mdbx.lck" +/* The name of the data file in the DB environment */ +#define MDBX_DATANAME "/mdbx.dat" +/* The suffix of the lock file when no subdir is used */ +#define MDBX_LOCK_SUFFIX "-lck" + +/* Opaque structure for a database environment. + * + * A DB environment supports multiple databases, all residing in the same + * shared-memory map. */ +typedef struct MDBX_env MDBX_env; + +/* Opaque structure for a transaction handle. + * + * All database operations require a transaction handle. Transactions may be + * read-only or read-write. */ +typedef struct MDBX_txn MDBX_txn; + +/* A handle for an individual database in the DB environment. */ +typedef uint32_t MDBX_dbi; + +/* Opaque structure for navigating through a database */ +typedef struct MDBX_cursor MDBX_cursor; + +/* Generic structure used for passing keys and data in and out + * of the database. + * + * Values returned from the database are valid only until a subsequent + * update operation, or the end of the transaction. Do not modify or + * free them, they commonly point into the database itself. + * + * Key sizes must be between 1 and mdbx_env_get_maxkeysize() inclusive. + * The same applies to data sizes in databases with the MDBX_DUPSORT flag. + * Other data items can in theory be from 0 to 0xffffffff bytes long. */ +#ifndef HAVE_STRUCT_IOVEC +struct iovec { + void *iov_base; + size_t iov_len; +}; +#define HAVE_STRUCT_IOVEC +#endif /* HAVE_STRUCT_IOVEC */ + +typedef struct iovec MDBX_val; + +/* The maximum size of a data item. + * MDBX only store a 32 bit value for node sizes. */ +#define MDBX_MAXDATASIZE INT32_MAX + +/* A callback function used to compare two keys in a database */ +typedef int(MDBX_cmp_func)(const MDBX_val *a, const MDBX_val *b); + +/* Environment Flags */ +/* no environment directory */ +#define MDBX_NOSUBDIR 0x4000u +/* don't fsync after commit */ +#define MDBX_NOSYNC 0x10000u +/* read only */ +#define MDBX_RDONLY 0x20000u +/* don't fsync metapage after commit */ +#define MDBX_NOMETASYNC 0x40000u +/* use writable mmap */ +#define MDBX_WRITEMAP 0x80000u +/* use asynchronous msync when MDBX_WRITEMAP is used */ +#define MDBX_MAPASYNC 0x100000u +/* tie reader locktable slots to MDBX_txn objects instead of to threads */ +#define MDBX_NOTLS 0x200000u +/* open DB in exclusive/monopolistic mode. */ +#define MDBX_EXCLUSIVE 0x400000u +/* don't do readahead */ +#define MDBX_NORDAHEAD 0x800000u +/* don't initialize malloc'd memory before writing to datafile */ +#define MDBX_NOMEMINIT 0x1000000u +/* aim to coalesce FreeDB records */ +#define MDBX_COALESCE 0x2000000u +/* LIFO policy for reclaiming FreeDB records */ +#define MDBX_LIFORECLAIM 0x4000000u +/* make a steady-sync only on close and explicit env-sync */ +#define MDBX_UTTERLY_NOSYNC (MDBX_NOSYNC | MDBX_MAPASYNC) +/* debuging option, fill/perturb released pages */ +#define MDBX_PAGEPERTURB 0x8000000u + +/* Database Flags */ +/* use reverse string keys */ +#define MDBX_REVERSEKEY 0x02u +/* use sorted duplicates */ +#define MDBX_DUPSORT 0x04u +/* numeric keys in native byte order, either uint32_t or uint64_t. + * The keys must all be of the same size. */ +#define MDBX_INTEGERKEY 0x08u +/* with MDBX_DUPSORT, sorted dup items have fixed size */ +#define MDBX_DUPFIXED 0x10u +/* with MDBX_DUPSORT, dups are MDBX_INTEGERKEY-style integers */ +#define MDBX_INTEGERDUP 0x20u +/* with MDBX_DUPSORT, use reverse string dups */ +#define MDBX_REVERSEDUP 0x40u +/* create DB if not already existing */ +#define MDBX_CREATE 0x40000u + +/* Write Flags */ +/* For put: Don't write if the key already exists. */ +#define MDBX_NOOVERWRITE 0x10u +/* Only for MDBX_DUPSORT + * For put: don't write if the key and data pair already exist. + * For mdbx_cursor_del: remove all duplicate data items. */ +#define MDBX_NODUPDATA 0x20u +/* For mdbx_cursor_put: overwrite the current key/data pair + * MDBX allows this flag for mdbx_put() for explicit overwrite/update without + * insertion. */ +#define MDBX_CURRENT 0x40u +/* For put: Just reserve space for data, don't copy it. Return a + * pointer to the reserved space. */ +#define MDBX_RESERVE 0x10000u +/* Data is being appended, don't split full pages. */ +#define MDBX_APPEND 0x20000u +/* Duplicate data is being appended, don't split full pages. */ +#define MDBX_APPENDDUP 0x40000u +/* Store multiple data items in one call. Only for MDBX_DUPFIXED. */ +#define MDBX_MULTIPLE 0x80000u + +/* Transaction Flags */ +/* Do not block when starting a write transaction */ +#define MDBX_TRYTXN 0x10000000u + +/* Copy Flags */ +/* Compacting copy: Omit free space from copy, and renumber all + * pages sequentially. */ +#define MDBX_CP_COMPACT 1u + +/* Cursor Get operations. + * + * This is the set of all operations for retrieving data + * using a cursor. */ +typedef enum MDBX_cursor_op { + MDBX_FIRST, /* Position at first key/data item */ + MDBX_FIRST_DUP, /* MDBX_DUPSORT-only: Position at first data item + * of current key. */ + MDBX_GET_BOTH, /* MDBX_DUPSORT-only: Position at key/data pair. */ + MDBX_GET_BOTH_RANGE, /* MDBX_DUPSORT-only: position at key, nearest data. */ + MDBX_GET_CURRENT, /* Return key/data at current cursor position */ + MDBX_GET_MULTIPLE, /* MDBX_DUPFIXED-only: Return up to a page of duplicate + * data items from current cursor position. + * Move cursor to prepare for MDBX_NEXT_MULTIPLE. */ + MDBX_LAST, /* Position at last key/data item */ + MDBX_LAST_DUP, /* MDBX_DUPSORT-only: Position at last data item + * of current key. */ + MDBX_NEXT, /* Position at next data item */ + MDBX_NEXT_DUP, /* MDBX_DUPSORT-only: Position at next data item + * of current key. */ + MDBX_NEXT_MULTIPLE, /* MDBX_DUPFIXED-only: Return up to a page of duplicate + * data items from next cursor position. + * Move cursor to prepare for MDBX_NEXT_MULTIPLE. */ + MDBX_NEXT_NODUP, /* Position at first data item of next key */ + MDBX_PREV, /* Position at previous data item */ + MDBX_PREV_DUP, /* MDBX_DUPSORT-only: Position at previous data item + * of current key. */ + MDBX_PREV_NODUP, /* Position at last data item of previous key */ + MDBX_SET, /* Position at specified key */ + MDBX_SET_KEY, /* Position at specified key, return both key and data */ + MDBX_SET_RANGE, /* Position at first key greater than or equal to + * specified key. */ + MDBX_PREV_MULTIPLE /* MDBX_DUPFIXED-only: Position at previous page and + * return up to a page of duplicate data items. */ +} MDBX_cursor_op; + +/* Return Codes + * BerkeleyDB uses -30800 to -30999, we'll go under them */ + +/* Successful result */ +#define MDBX_SUCCESS 0 +#define MDBX_RESULT_FALSE MDBX_SUCCESS +#define MDBX_RESULT_TRUE (-1) + +/* key/data pair already exists */ +#define MDBX_KEYEXIST (-30799) +/* key/data pair not found (EOF) */ +#define MDBX_NOTFOUND (-30798) +/* Requested page not found - this usually indicates corruption */ +#define MDBX_PAGE_NOTFOUND (-30797) +/* Located page was wrong type */ +#define MDBX_CORRUPTED (-30796) +/* Update of meta page failed or environment had fatal error */ +#define MDBX_PANIC (-30795) +/* DB file version mismatch with libmdbx */ +#define MDBX_VERSION_MISMATCH (-30794) +/* File is not a valid MDBX file */ +#define MDBX_INVALID (-30793) +/* Environment mapsize reached */ +#define MDBX_MAP_FULL (-30792) +/* Environment maxdbs reached */ +#define MDBX_DBS_FULL (-30791) +/* Environment maxreaders reached */ +#define MDBX_READERS_FULL (-30790) +/* Txn has too many dirty pages */ +#define MDBX_TXN_FULL (-30788) +/* Cursor stack too deep - internal error */ +#define MDBX_CURSOR_FULL (-30787) +/* Page has not enough space - internal error */ +#define MDBX_PAGE_FULL (-30786) +/* Database contents grew beyond environment mapsize */ +#define MDBX_MAP_RESIZED (-30785) +/* Operation and DB incompatible, or DB type changed. This can mean: + * - The operation expects an MDBX_DUPSORT / MDBX_DUPFIXED database. + * - Opening a named DB when the unnamed DB has MDBX_DUPSORT/MDBX_INTEGERKEY. + * - Accessing a data record as a database, or vice versa. + * - The database was dropped and recreated with different flags. */ +#define MDBX_INCOMPATIBLE (-30784) +/* Invalid reuse of reader locktable slot */ +#define MDBX_BAD_RSLOT (-30783) +/* Transaction must abort, has a child, or is invalid */ +#define MDBX_BAD_TXN (-30782) +/* Unsupported size of key/DB name/data, or wrong DUPFIXED size */ +#define MDBX_BAD_VALSIZE (-30781) +/* The specified DBI was changed unexpectedly */ +#define MDBX_BAD_DBI (-30780) +/* Unexpected problem - txn should abort */ +#define MDBX_PROBLEM (-30779) +/* Another write transaction is running */ +#define MDBX_BUSY (-30778) +/* The last defined error code */ +#define MDBX_LAST_ERRCODE MDBX_BUSY + +/* The mdbx_put() or mdbx_replace() was called for key, + that has more that one associated value. */ +#define MDBX_EMULTIVAL (-30421) + +/* Bad signature of a runtime object(s), this can mean: + * - memory corruption or double-free; + * - ABI version mismatch (rare case); */ +#define MDBX_EBADSIGN (-30420) + +/* Database should be recovered, but this could NOT be done automatically + * right now (e.g. in readonly mode and so forth). */ +#define MDBX_WANNA_RECOVERY (-30419) + +/* The given key value is mismatched to the current cursor position, + * when mdbx_cursor_put() called with MDBX_CURRENT option. */ +#define MDBX_EKEYMISMATCH (-30418) + +/* Database is too large for current system, + * e.g. could NOT be mapped into RAM. */ +#define MDBX_TOO_LARGE (-30417) + +/* A thread has attempted to use a not owned object, + * e.g. a transaction that started by another thread. */ +#define MDBX_THREAD_MISMATCH (-30416) + +/* Statistics for a database in the environment */ +typedef struct MDBX_stat { + uint32_t ms_psize; /* Size of a database page. + * This is currently the same for all databases. */ + uint32_t ms_depth; /* Depth (height) of the B-tree */ + uint64_t ms_branch_pages; /* Number of internal (non-leaf) pages */ + uint64_t ms_leaf_pages; /* Number of leaf pages */ + uint64_t ms_overflow_pages; /* Number of overflow pages */ + uint64_t ms_entries; /* Number of data items */ +} MDBX_stat; + +/* Information about the environment */ +typedef struct MDBX_envinfo { + struct { + uint64_t lower; /* lower limit for datafile size */ + uint64_t upper; /* upper limit for datafile size */ + uint64_t current; /* current datafile size */ + uint64_t shrink; /* shrink threshold for datafile */ + uint64_t grow; /* growth step for datafile */ + } mi_geo; + uint64_t mi_mapsize; /* Size of the data memory map */ + uint64_t mi_last_pgno; /* ID of the last used page */ + uint64_t mi_recent_txnid; /* ID of the last committed transaction */ + uint64_t mi_latter_reader_txnid; /* ID of the last reader transaction */ + uint64_t mi_self_latter_reader_txnid; /* ID of the last reader transaction of + caller process */ + uint64_t mi_meta0_txnid, mi_meta0_sign; + uint64_t mi_meta1_txnid, mi_meta1_sign; + uint64_t mi_meta2_txnid, mi_meta2_sign; + uint32_t mi_maxreaders; /* max reader slots in the environment */ + uint32_t mi_numreaders; /* max reader slots used in the environment */ + uint32_t mi_dxb_pagesize; /* database pagesize */ + uint32_t mi_sys_pagesize; /* system pagesize */ +} MDBX_envinfo; + +/* Return a string describing a given error code. + * + * This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3) + * function. If the error code is greater than or equal to 0, then the string + * returned by the system function strerror(3) is returned. If the error code + * is less than 0, an error string corresponding to the MDBX library error is + * returned. See errors for a list of MDBX-specific error codes. + * + * [in] err The error code + * + * Returns "error message" The description of the error */ +LIBMDBX_API const char *mdbx_strerror(int errnum); +LIBMDBX_API const char *mdbx_strerror_r(int errnum, char *buf, size_t buflen); + +/* Create an MDBX environment handle. + * + * This function allocates memory for a MDBX_env structure. To release + * the allocated memory and discard the handle, call mdbx_env_close(). + * Before the handle may be used, it must be opened using mdbx_env_open(). + * Various other options may also need to be set before opening the handle, + * e.g. mdbx_env_set_mapsize(), mdbx_env_set_maxreaders(), + * mdbx_env_set_maxdbs(), depending on usage requirements. + * + * [out] env The address where the new handle will be stored + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_create(MDBX_env **penv); + +/* Open an environment handle. + * + * If this function fails, mdbx_env_close() must be called to discard + * the MDBX_env handle. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] path The directory in which the database files reside. + * This directory must already exist and be writable. + * [in] flags Special options for this environment. This parameter + * must be set to 0 or by bitwise OR'ing together one + * or more of the values described here. + * + * Flags set by mdbx_env_set_flags() are also used: + * - MDBX_NOSUBDIR + * By default, MDBX creates its environment in a directory whose + * pathname is given in path, and creates its data and lock files + * under that directory. With this option, path is used as-is for + * the database main data file. The database lock file is the path + * with "-lock" appended. + * + * - MDBX_RDONLY + * Open the environment in read-only mode. No write operations will + * be allowed. MDBX will still modify the lock file - except on + * read-only filesystems, where MDBX does not use locks. + * + * - MDBX_WRITEMAP + * Use a writeable memory map unless MDBX_RDONLY is set. This uses fewer + * mallocs but loses protection from application bugs like wild pointer + * writes and other bad updates into the database. + * This may be slightly faster for DBs that fit entirely in RAM, + * but is slower for DBs larger than RAM. + * Incompatible with nested transactions. + * Do not mix processes with and without MDBX_WRITEMAP on the same + * environment. This can defeat durability (mdbx_env_sync etc). + * + * - MDBX_NOMETASYNC + * Flush system buffers to disk only once per transaction, omit the + * metadata flush. Defer that until the system flushes files to disk, + * or next non-MDBX_RDONLY commit or mdbx_env_sync(). This optimization + * maintains database integrity, but a system crash may undo the last + * committed transaction. I.e. it preserves the ACI (atomicity, + * consistency, isolation) but not D (durability) database property. + * This flag may be changed at any time using mdbx_env_set_flags(). + * + * - MDBX_NOSYNC + * Don't flush system buffers to disk when committing a transaction. + * This optimization means a system crash can corrupt the database or + * lose the last transactions if buffers are not yet flushed to disk. + * The risk is governed by how often the system flushes dirty buffers + * to disk and how often mdbx_env_sync() is called. However, if the + * filesystem preserves write order and the MDBX_WRITEMAP and/or + * MDBX_LIFORECLAIM flags are not used, transactions exhibit ACI + * (atomicity, consistency, isolation) properties and only lose D + * (durability). I.e. database integrity is maintained, but a system + * crash may undo the final transactions. + * + * Note that (MDBX_NOSYNC | MDBX_WRITEMAP) leaves the system with no + * hint for when to write transactions to disk. + * Therefore the (MDBX_MAPASYNC | MDBX_WRITEMAP) may be preferable. + * This flag may be changed at any time using mdbx_env_set_flags(). + * + * - MDBX_UTTERLY_NOSYNC (internally MDBX_NOSYNC | MDBX_MAPASYNC) + * FIXME: TODO + * + * - MDBX_MAPASYNC + * When using MDBX_WRITEMAP, use asynchronous flushes to disk. As with + * MDBX_NOSYNC, a system crash can then corrupt the database or lose + * the last transactions. Calling mdbx_env_sync() ensures on-disk + * database integrity until next commit. This flag may be changed at + * any time using mdbx_env_set_flags(). + * + * - MDBX_NOTLS + * Don't use Thread-Local Storage. Tie reader locktable slots to + * MDBX_txn objects instead of to threads. I.e. mdbx_txn_reset() keeps + * the slot reserved for the MDBX_txn object. A thread may use parallel + * read-only transactions. A read-only transaction may span threads if + * the user synchronizes its use. Applications that multiplex many + * user threads over individual OS threads need this option. Such an + * application must also serialize the write transactions in an OS + * thread, since MDBX's write locking is unaware of the user threads. + * + * - MDBX_NOLOCK (don't supported by MDBX) + * Don't do any locking. If concurrent access is anticipated, the + * caller must manage all concurrency itself. For proper operation + * the caller must enforce single-writer semantics, and must ensure + * that no readers are using old transactions while a writer is + * active. The simplest approach is to use an exclusive lock so that + * no readers may be active at all when a writer begins. + * + * - MDBX_NORDAHEAD + * Turn off readahead. Most operating systems perform readahead on + * read requests by default. This option turns it off if the OS + * supports it. Turning it off may help random read performance + * when the DB is larger than RAM and system RAM is full. + * + * - MDBX_NOMEMINIT + * Don't initialize malloc'd memory before writing to unused spaces + * in the data file. By default, memory for pages written to the data + * file is obtained using malloc. While these pages may be reused in + * subsequent transactions, freshly malloc'd pages will be initialized + * to zeroes before use. This avoids persisting leftover data from other + * code (that used the heap and subsequently freed the memory) into the + * data file. Note that many other system libraries may allocate and free + * memory from the heap for arbitrary uses. E.g., stdio may use the heap + * for file I/O buffers. This initialization step has a modest performance + * cost so some applications may want to disable it using this flag. This + * option can be a problem for applications which handle sensitive data + * like passwords, and it makes memory checkers like Valgrind noisy. This + * flag is not needed with MDBX_WRITEMAP, which writes directly to the + * mmap instead of using malloc for pages. The initialization is also + * skipped if MDBX_RESERVE is used; the caller is expected to overwrite + * all of the memory that was reserved in that case. This flag may be + * changed at any time using mdbx_env_set_flags(). + * + * - MDBX_COALESCE + * Aim to coalesce records while reclaiming FreeDB. This flag may be + * changed at any time using mdbx_env_set_flags(). + * FIXME: TODO + * + * - MDBX_LIFORECLAIM + * LIFO policy for reclaiming FreeDB records. This significantly reduce + * write IPOs in case MDBX_NOSYNC with periodically checkpoints. + * FIXME: TODO + * + * [in] mode The UNIX permissions to set on created files. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_VERSION_MISMATCH - the version of the MDBX library doesn't match the + * version that created the database environment. + * - MDBX_INVALID - the environment file headers are corrupted. + * - MDBX_ENOENT - the directory specified by the path parameter + * doesn't exist. + * - MDBX_EACCES - the user didn't have permission to access + * the environment files. + * - MDBX_EAGAIN - the environment was locked by another process. */ +LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *path, unsigned flags, + mode_t mode); + +/* Copy an MDBX environment to the specified path, with options. + * + * This function may be used to make a backup of an existing environment. + * No lockfile is created, since it gets recreated at need. + * NOTE: This call can trigger significant file size growth if run in + * parallel with write transactions, because it employs a read-only + * transaction. See long-lived transactions under "Caveats" section. + * + * [in] env An environment handle returned by mdbx_env_create(). It must + * have already been opened successfully. + * [in] path The directory in which the copy will reside. This directory + * must already exist and be writable but must otherwise be empty. + * [in] flags Special options for this operation. This parameter must be set + * to 0 or by bitwise OR'ing together one or more of the values + * described here: + * + * - MDBX_CP_COMPACT + * Perform compaction while copying: omit free pages and sequentially + * renumber all pages in output. This option consumes little bit more + * CPU for processing, but may running quickly than the default, on + * account skipping free pages. + * + * NOTE: Currently it fails if the environment has suffered a page leak. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_copy(MDBX_env *env, const char *dest_path, + unsigned flags); + +/* Copy an MDBX environment to the specified file descriptor, + * with options. + * + * This function may be used to make a backup of an existing environment. + * No lockfile is created, since it gets recreated at need. See + * mdbx_env_copy() for further details. + * + * NOTE: This call can trigger significant file size growth if run in + * parallel with write transactions, because it employs a read-only + * transaction. See long-lived transactions under "Caveats" section. + * + * [in] env An environment handle returned by mdbx_env_create(). It must + * have already been opened successfully. + * [in] fd The filedescriptor to write the copy to. It must have already + * been opened for Write access. + * [in] flags Special options for this operation. See mdbx_env_copy() for + * options. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd, + unsigned flags); + +/* Return statistics about the MDBX environment. + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] stat The address of an MDBX_stat structure where the statistics + * will be copied */ +LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes); +LIBMDBX_API int mdbx_env_stat2(const MDBX_env *env, const MDBX_txn *txn, + MDBX_stat *stat, size_t bytes); + +/* Return information about the MDBX environment. + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] stat The address of an MDBX_envinfo structure + * where the information will be copied */ +LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info, size_t bytes); +LIBMDBX_API int mdbx_env_info2(const MDBX_env *env, const MDBX_txn *txn, + MDBX_envinfo *info, size_t bytes); + +/* Flush the data buffers to disk. + * + * Data is always written to disk when mdbx_txn_commit() is called, + * but the operating system may keep it buffered. MDBX always flushes + * the OS buffers upon commit as well, unless the environment was + * opened with MDBX_NOSYNC or in part MDBX_NOMETASYNC. This call is + * not valid if the environment was opened with MDBX_RDONLY. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] force If non-zero, force a synchronous flush. Otherwise if the + * environment has the MDBX_NOSYNC flag set the flushes will be + * omitted, and with MDBX_MAPASYNC they will be asynchronous. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EACCES - the environment is read-only. + * - MDBX_EINVAL - an invalid parameter was specified. + * - MDBX_EIO - an error occurred during synchronization. */ +LIBMDBX_API int mdbx_env_sync(MDBX_env *env, int force); + +/* Close the environment and release the memory map. + * + * Only a single thread may call this function. All transactions, databases, + * and cursors must already be closed before calling this function. Attempts + * to use any such handles after calling this function will cause a SIGSEGV. + * The environment handle will be freed and must not be used again after this + * call. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] dont_sync A dont'sync flag, if non-zero the last checkpoint (meta-page + * update) will be kept "as is" and may be still "weak" in the + * NOSYNC/MAPASYNC modes. Such "weak" checkpoint will be + * ignored on opening next time, and transactions since the + * last non-weak checkpoint (meta-page update) will rolledback + * for consistency guarantee. */ +LIBMDBX_API int mdbx_env_close(MDBX_env *env); + +/* Set environment flags. + * + * This may be used to set some flags in addition to those from + * mdbx_env_open(), or to unset these flags. If several threads + * change the flags at the same time, the result is undefined. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] flags The flags to change, bitwise OR'ed together + * [in] onoff A non-zero value sets the flags, zero clears them. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff); + +/* Get environment flags. + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] flags The address of an integer to store the flags + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_env_get_flags(MDBX_env *env, unsigned *flags); + +/* Return the path that was used in mdbx_env_open(). + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] path Address of a string pointer to contain the path. + * This is the actual string in the environment, not a copy. + * It should not be altered in any way. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_env_get_path(MDBX_env *env, const char **path); + +/* Return the file descriptor for the given environment. + * + * NOTE: All MDBX file descriptors have FD_CLOEXEC and + * could't be used after exec() and or fork(). + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] fd Address of a int to contain the descriptor. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *fd); + +/* Set the size of the memory map to use for this environment. + * + * The size should be a multiple of the OS page size. The default is + * 10485760 bytes. The size of the memory map is also the maximum size + * of the database. The value should be chosen as large as possible, + * to accommodate future growth of the database. + * This function should be called after mdbx_env_create() and before + * mdbx_env_open(). It may be called at later times if no transactions + * are active in this process. Note that the library does not check for + * this condition, the caller must ensure it explicitly. + * + * The new size takes effect immediately for the current process but + * will not be persisted to any others until a write transaction has been + * committed by the current process. Also, only mapsize increases are + * persisted into the environment. + * + * If the mapsize is increased by another process, and data has grown + * beyond the range of the current mapsize, mdbx_txn_begin() will + * return MDBX_MAP_RESIZED. This function may be called with a size + * of zero to adopt the new size. + * + * Any attempt to set a size smaller than the space already consumed by the + * environment will be silently changed to the current size of the used space. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] size The size in bytes + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified, + * or the environment has an active write transaction. */ +LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env, size_t size); +LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, + intptr_t size_now, intptr_t size_upper, + intptr_t growth_step, + intptr_t shrink_threshold, + intptr_t pagesize); + +/* Set the maximum number of threads/reader slots for the environment. + * + * This defines the number of slots in the lock table that is used to track + * readers in the the environment. The default is 61. + * Starting a read-only transaction normally ties a lock table slot to the + * current thread until the environment closes or the thread exits. If + * MDBX_NOTLS is in use, mdbx_txn_begin() instead ties the slot to the + * MDBX_txn object until it or the MDBX_env object is destroyed. + * This function may only be called after mdbx_env_create() and before + * mdbx_env_open(). + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] readers The maximum number of reader lock table slots + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified, + * or the environment is already open. */ +LIBMDBX_API int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers); + +/* Get the maximum number of threads/reader slots for the environment. + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] readers Address of an integer to store the number of readers + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers); + +/* Set the maximum number of named databases for the environment. + * + * This function is only needed if multiple databases will be used in the + * environment. Simpler applications that use the environment as a single + * unnamed database can ignore this option. + * This function may only be called after mdbx_env_create() and before + * mdbx_env_open(). + * + * Currently a moderate number of slots are cheap but a huge number gets + * expensive: 7-120 words per transaction, and every mdbx_dbi_open() + * does a linear search of the opened slots. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] dbs The maximum number of databases + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified, + * or the environment is already open. */ +LIBMDBX_API int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs); + +/* Get the maximum size of keys and MDBX_DUPSORT data we can write. + * + * [in] env An environment handle returned by mdbx_env_create() + * + * Returns The maximum size of a key we can write. */ +LIBMDBX_API int mdbx_env_get_maxkeysize(MDBX_env *env); + +/* Set application information associated with the MDBX_env. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] ctx An arbitrary pointer for whatever the application needs. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_set_userctx(MDBX_env *env, void *ctx); + +/* Get the application information associated with the MDBX_env. + * + * [in] env An environment handle returned by mdbx_env_create() + * Returns The pointer set by mdbx_env_set_userctx(). */ +LIBMDBX_API void *mdbx_env_get_userctx(MDBX_env *env); + +/* A callback function for most MDBX assert() failures, + * called before printing the message and aborting. + * + * [in] env An environment handle returned by mdbx_env_create(). + * [in] msg The assertion message, not including newline. */ +typedef void MDBX_assert_func(const MDBX_env *env, const char *msg, + const char *function, unsigned line); + +/* Set or reset the assert() callback of the environment. + * + * Disabled if libmdbx is buillt with MDBX_DEBUG=0. + * NOTE: This hack should become obsolete as mdbx's error handling matures. + * + * [in] env An environment handle returned by mdbx_env_create(). + * [in] func An MDBX_assert_func function, or 0. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func); + +/* Create a transaction for use with the environment. + * + * The transaction handle may be discarded using mdbx_txn_abort() + * or mdbx_txn_commit(). + * NOTE: A transaction and its cursors must only be used by a single + * thread, and a thread may only have a single transaction at a time. + * If MDBX_NOTLS is in use, this does not apply to read-only transactions. + * NOTE: Cursors may not span transactions. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] parent If this parameter is non-NULL, the new transaction will be + * a nested transaction, with the transaction indicated by parent + * as its parent. Transactions may be nested to any level. + * A parent transaction and its cursors may not issue any other + * operations than mdbx_txn_commit and mdbx_txn_abort while it + * has active child transactions. + * [in] flags Special options for this transaction. This parameter + * must be set to 0 or by bitwise OR'ing together one or more + * of the values described here. + * + * - MDBX_RDONLY + * This transaction will not perform any write operations. + * + * - MDBX_TRYTXN + * Do not block when starting a write transaction + * + * [out] txn Address where the new MDBX_txn handle will be stored + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_PANIC - a fatal error occurred earlier and the environment + * must be shut down. + * - MDBX_MAP_RESIZED - another process wrote data beyond this MDBX_env's + * mapsize and this environment's map must be resized + * as well. See mdbx_env_set_mapsize(). + * - MDBX_READERS_FULL - a read-only transaction was requested and the reader + * lock table is full. See mdbx_env_set_maxreaders(). + * - MDBX_ENOMEM - out of memory. + * - MDBX_BUSY - a write transaction is already started. */ +LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags, + MDBX_txn **txn); + +/* Returns the transaction's MDBX_env + * + * [in] txn A transaction handle returned by mdbx_txn_begin() */ +LIBMDBX_API MDBX_env *mdbx_txn_env(MDBX_txn *txn); + +/* Return the transaction's flags. + * + * This returns the flags associated with this transaction. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * + * Returns A transaction flags, valid if input is an active transaction. */ +LIBMDBX_API int mdbx_txn_flags(MDBX_txn *txn); + +/* Return the transaction's ID. + * + * This returns the identifier associated with this transaction. For a + * read-only transaction, this corresponds to the snapshot being read; + * concurrent readers will frequently have the same transaction ID. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * + * Returns A transaction ID, valid if input is an active transaction. */ +LIBMDBX_API uint64_t mdbx_txn_id(MDBX_txn *txn); + +/* Commit all the operations of a transaction into the database. + * + * The transaction handle is freed. It and its cursors must not be used + * again after this call, except with mdbx_cursor_renew(). + * + * A cursor must be closed explicitly always, before + * or after its transaction ends. It can be reused with + * mdbx_cursor_renew() before finally closing it. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. + * - MDBX_ENOSPC - no more disk space. + * - MDBX_EIO - a low-level I/O error occurred while writing. + * - MDBX_ENOMEM - out of memory. */ +LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn); + +/* Abandon all the operations of the transaction instead of saving them. + * + * The transaction handle is freed. It and its cursors must not be used + * again after this call, except with mdbx_cursor_renew(). + * + * A cursor must be closed explicitly always, before or after its transaction + * ends. It can be reused with mdbx_cursor_renew() before finally closing it. + * + * [in] txn A transaction handle returned by mdbx_txn_begin(). */ +LIBMDBX_API int mdbx_txn_abort(MDBX_txn *txn); + +/* Reset a read-only transaction. + * + * Abort the transaction like mdbx_txn_abort(), but keep the transaction + * handle. Therefore mdbx_txn_renew() may reuse the handle. This saves + * allocation overhead if the process will start a new read-only transaction + * soon, and also locking overhead if MDBX_NOTLS is in use. The reader table + * lock is released, but the table slot stays tied to its thread or + * MDBX_txn. Use mdbx_txn_abort() to discard a reset handle, and to free + * its lock table slot if MDBX_NOTLS is in use. + * + * Cursors opened within the transaction must not be used + * again after this call, except with mdbx_cursor_renew(). + * + * Reader locks generally don't interfere with writers, but they keep old + * versions of database pages allocated. Thus they prevent the old pages + * from being reused when writers commit new data, and so under heavy load + * the database size may grow much more rapidly than otherwise. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() */ +LIBMDBX_API int mdbx_txn_reset(MDBX_txn *txn); + +/* Renew a read-only transaction. + * + * This acquires a new reader lock for a transaction handle that had been + * released by mdbx_txn_reset(). It must be called before a reset transaction + * may be used again. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_PANIC - a fatal error occurred earlier and the environment + * must be shut down. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_txn_renew(MDBX_txn *txn); + +/* Open a table in the environment. + * + * A table handle denotes the name and parameters of a table, independently + * of whether such a table exists. The table handle may be discarded by + * calling mdbx_dbi_close(). The old table handle is returned if the table + * was already open. The handle may only be closed once. + * + * The table handle will be private to the current transaction until + * the transaction is successfully committed. If the transaction is + * aborted the handle will be closed automatically. + * After a successful commit the handle will reside in the shared + * environment, and may be used by other transactions. + * + * This function must not be called from multiple concurrent + * transactions in the same process. A transaction that uses + * this function must finish (either commit or abort) before + * any other transaction in the process may use this function. + * + * To use named table (with name != NULL), mdbx_env_set_maxdbs() + * must be called before opening the environment. Table names are + * keys in the internal unnamed table, and may be read but not written. + * + * [in] txn transaction handle returned by mdbx_txn_begin() + * [in] name The name of the table to open. If only a single + * table is needed in the environment, this value may be NULL. + * [in] flags Special options for this table. This parameter must be set + * to 0 or by bitwise OR'ing together one or more of the values + * described here: + * - MDBX_REVERSEKEY + * Keys are strings to be compared in reverse order, from the end + * of the strings to the beginning. By default, Keys are treated as + * strings and compared from beginning to end. + * - MDBX_DUPSORT + * Duplicate keys may be used in the table. Or, from another point of + * view, keys may have multiple data items, stored in sorted order. By + * default keys must be unique and may have only a single data item. + * - MDBX_INTEGERKEY + * Keys are binary integers in native byte order, either uin32_t or + * uint64_t, and will be sorted as such. The keys must all be of the + * same size. + * - MDBX_DUPFIXED + * This flag may only be used in combination with MDBX_DUPSORT. This + * option tells the library that the data items for this database are + * all the same size, which allows further optimizations in storage and + * retrieval. When all data items are the same size, the MDBX_GET_MULTIPLE, + * MDBX_NEXT_MULTIPLE and MDBX_PREV_MULTIPLE cursor operations may be used + * to retrieve multiple items at once. + * - MDBX_INTEGERDUP + * This option specifies that duplicate data items are binary integers, + * similar to MDBX_INTEGERKEY keys. + * - MDBX_REVERSEDUP + * This option specifies that duplicate data items should be compared as + * strings in reverse order (the comparison is performed in the direction + * from the last byte to the first). + * - MDBX_CREATE + * Create the named database if it doesn't exist. This option is not + * allowed in a read-only transaction or a read-only environment. + * + * [out] dbi Address where the new MDBX_dbi handle will be stored + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - the specified database doesn't exist in the + * environment and MDBX_CREATE was not specified. + * - MDBX_DBS_FULL - too many databases have been opened. + * See mdbx_env_set_maxdbs(). */ +LIBMDBX_API int mdbx_dbi_open_ex(MDBX_txn *txn, const char *name, + unsigned flags, MDBX_dbi *dbi, + MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp); +LIBMDBX_API int mdbx_dbi_open(MDBX_txn *txn, const char *name, unsigned flags, + MDBX_dbi *dbi); + +/* Retrieve statistics for a database. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [out] stat The address of an MDBX_stat structure where the statistics + * will be copied + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *stat, + size_t bytes); + +/* Retrieve the DB flags for a database handle. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [out] flags Address where the flags will be returned. + * [out] state Address where the state will be returned. + * + * Returns A non-zero error value on failure and 0 on success. */ +#define MDBX_TBL_DIRTY 0x01 /* DB was written in this txn */ +#define MDBX_TBL_STALE 0x02 /* Named-DB record is older than txnID */ +#define MDBX_TBL_FRESH 0x04 /* Named-DB handle opened in this txn */ +#define MDBX_TBL_CREAT 0x08 /* Named-DB handle created in this txn */ +LIBMDBX_API int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, + unsigned *state); +LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags); + +/* Close a database handle. Normally unnecessary. + * + * Use with care: + * FIXME: This call is not mutex protected. Handles should only be closed by + * a single thread, and only if no other threads are going to reference + * the database handle or one of its cursors any further. Do not close + * a handle if an existing transaction has modified its database. + * Doing so can cause misbehavior from database corruption to errors + * like MDBX_BAD_VALSIZE (since the DB name is gone). + * + * Closing a database handle is not necessary, but lets mdbx_dbi_open() + * reuse the handle value. Usually it's better to set a bigger + * mdbx_env_set_maxdbs(), unless that value would be large. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] dbi A database handle returned by mdbx_dbi_open() + */ +LIBMDBX_API int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi); + +/* Empty or delete+close a database. + * + * See mdbx_dbi_close() for restrictions about closing the DB handle. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] del 0 to empty the DB, 1 to delete it from the environment + * and close the DB handle. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del); + +/* Get items from a database. + * + * This function retrieves key/data pairs from the database. The address + * and length of the data associated with the specified key are returned + * in the structure to which data refers. + * If the database supports duplicate keys (MDBX_DUPSORT) then the + * first data item for the key will be returned. Retrieval of other + * items requires the use of mdbx_cursor_get(). + * + * NOTE: The memory pointed to by the returned values is owned by the + * database. The caller need not dispose of the memory, and may not + * modify it in any way. For values returned in a read-only transaction + * any modification attempts will cause a SIGSEGV. + * + * NOTE: Values returned from the database are valid only until a + * subsequent update operation, or the end of the transaction. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] key The key to search for in the database + * [in,out] data The data corresponding to the key + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - the key was not in the database. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data); +LIBMDBX_API int mdbx_get2(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data); + +/* Store items into a database. + * + * This function stores key/data pairs in the database. The default behavior + * is to enter the new key/data pair, replacing any previously existing key + * if duplicates are disallowed, or adding a duplicate data item if + * duplicates are allowed (MDBX_DUPSORT). + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] key The key to store in the database + * [in,out] data The data to store + * [in] flags Special options for this operation. This parameter must be + * set to 0 or by bitwise OR'ing together one or more of the + * values described here. + * + * - MDBX_NODUPDATA + * Enter the new key/data pair only if it does not already appear + * in the database. This flag may only be specified if the database + * was opened with MDBX_DUPSORT. The function will return MDBX_KEYEXIST + * if the key/data pair already appears in the database. + * + * - MDBX_NOOVERWRITE + * Enter the new key/data pair only if the key does not already appear + * in the database. The function will return MDBX_KEYEXIST if the key + * already appears in the database, even if the database supports + * duplicates (MDBX_DUPSORT). The data parameter will be set to point + * to the existing item. + * + * - MDBX_CURRENT + * Update an single existing entry, but not add new ones. The function + * will return MDBX_NOTFOUND if the given key not exist in the database. + * Or the MDBX_EMULTIVAL in case duplicates for the given key. + * + * - MDBX_RESERVE + * Reserve space for data of the given size, but don't copy the given + * data. Instead, return a pointer to the reserved space, which the + * caller can fill in later - before the next update operation or the + * transaction ends. This saves an extra memcpy if the data is being + * generated later. MDBX does nothing else with this memory, the caller + * is expected to modify all of the space requested. This flag must not + * be specified if the database was opened with MDBX_DUPSORT. + * + * - MDBX_APPEND + * Append the given key/data pair to the end of the database. This option + * allows fast bulk loading when keys are already known to be in the + * correct order. Loading unsorted keys with this flag will cause + * a MDBX_EKEYMISMATCH error. + * + * - MDBX_APPENDDUP + * As above, but for sorted dup data. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_KEYEXIST + * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize(). + * - MDBX_TXN_FULL - the transaction has too many dirty pages. + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data, unsigned flags); + +/* Delete items from a database. + * + * This function removes key/data pairs from the database. + * + * The data parameter is NOT ignored regardless the database does + * support sorted duplicate data items or not. If the data parameter + * is non-NULL only the matching data item will be deleted. + * + * This function will return MDBX_NOTFOUND if the specified key/data + * pair is not in the database. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] key The key to delete from the database + * [in] data The data to delete + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data); + +/* Create a cursor handle. + * + * A cursor is associated with a specific transaction and database. + * A cursor cannot be used when its database handle is closed. Nor + * when its transaction has ended, except with mdbx_cursor_renew(). + * It can be discarded with mdbx_cursor_close(). + * + * A cursor must be closed explicitly always, before + * or after its transaction ends. It can be reused with + * mdbx_cursor_renew() before finally closing it. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [out] cursor Address where the new MDBX_cursor handle will be stored + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, + MDBX_cursor **cursor); + +/* Close a cursor handle. + * + * The cursor handle will be freed and must not be used again after this call. + * Its transaction must still be live if it is a write-transaction. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() */ +LIBMDBX_API void mdbx_cursor_close(MDBX_cursor *cursor); + +/* Renew a cursor handle. + * + * A cursor is associated with a specific transaction and database. + * Cursors that are only used in read-only transactions may be re-used, + * to avoid unnecessary malloc/free overhead. The cursor may be associated + * with a new read-only transaction, and referencing the same database handle + * as it was created with. + * + * This may be done whether the previous transaction is live or dead. + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *cursor); + +/* Return the cursor's transaction handle. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() */ +LIBMDBX_API MDBX_txn *mdbx_cursor_txn(MDBX_cursor *cursor); + +/* Return the cursor's database handle. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() */ +LIBMDBX_API MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *cursor); + +/* Retrieve by cursor. + * + * This function retrieves key/data pairs from the database. The address and + * length of the key are returned in the object to which key refers (except + * for the case of the MDBX_SET option, in which the key object is unchanged), + * and the address and length of the data are returned in the object to which + * data refers. See mdbx_get() for restrictions on using the output values. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [in,out] key The key for a retrieved item + * [in,out] data The data of a retrieved item + * [in] op A cursor operation MDBX_cursor_op + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - no matching key found. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_get(MDBX_cursor *cursor, MDBX_val *key, + MDBX_val *data, MDBX_cursor_op op); + +/* Store by cursor. + * + * This function stores key/data pairs into the database. The cursor is + * positioned at the new item, or on failure usually near it. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [in] key The key operated on. + * [in] data The data operated on. + * [in] flags Options for this operation. This parameter + * must be set to 0 or one of the values described here: + * + * - MDBX_CURRENT + * Replace the item at the current cursor position. The key parameter + * must still be provided, and must match it, otherwise the function + * return MDBX_EKEYMISMATCH. + * + * NOTE: MDBX unlike LMDB allows you to change the size of the data and + * automatically handles reordering for sorted duplicates (MDBX_DUPSORT). + * + * - MDBX_NODUPDATA + * Enter the new key/data pair only if it does not already appear in the + * database. This flag may only be specified if the database was opened + * with MDBX_DUPSORT. The function will return MDBX_KEYEXIST if the + * key/data pair already appears in the database. + * + * - MDBX_NOOVERWRITE + * Enter the new key/data pair only if the key does not already appear + * in the database. The function will return MDBX_KEYEXIST if the key + * already appears in the database, even if the database supports + * duplicates (MDBX_DUPSORT). + * + * - MDBX_RESERVE + * Reserve space for data of the given size, but don't copy the given + * data. Instead, return a pointer to the reserved space, which the + * caller can fill in later - before the next update operation or the + * transaction ends. This saves an extra memcpy if the data is being + * generated later. This flag must not be specified if the database + * was opened with MDBX_DUPSORT. + * + * - MDBX_APPEND + * Append the given key/data pair to the end of the database. No key + * comparisons are performed. This option allows fast bulk loading when + * keys are already known to be in the correct order. Loading unsorted + * keys with this flag will cause a MDBX_KEYEXIST error. + * + * - MDBX_APPENDDUP + * As above, but for sorted dup data. + * + * - MDBX_MULTIPLE + * Store multiple contiguous data elements in a single request. This flag + * may only be specified if the database was opened with MDBX_DUPFIXED. + * The data argument must be an array of two MDBX_vals. The iov_len of the + * first MDBX_val must be the size of a single data element. The iov_base + * of the first MDBX_val must point to the beginning of the array of + * contiguous data elements. The iov_len of the second MDBX_val must be + * the count of the number of data elements to store. On return this + * field will be set to the count of the number of elements actually + * written. The iov_base of the second MDBX_val is unused. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EKEYMISMATCH + * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize(). + * - MDBX_TXN_FULL - the transaction has too many dirty pages. + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_put(MDBX_cursor *cursor, MDBX_val *key, + MDBX_val *data, unsigned flags); + +/* Delete current key/data pair + * + * This function deletes the key/data pair to which the cursor refers. + * This does not invalidate the cursor, so operations such as MDBX_NEXT + * can still be used on it. Both MDBX_NEXT and MDBX_GET_CURRENT will return + * the same record after this operation. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [in] flags Options for this operation. This parameter must be set to 0 + * or one of the values described here. + * + * - MDBX_NODUPDATA + * Delete all of the data items for the current key. This flag may only + * be specified if the database was opened with MDBX_DUPSORT. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_del(MDBX_cursor *cursor, unsigned flags); + +/* Return count of duplicates for current key. + * + * This call is only valid on databases that support sorted duplicate data + * items MDBX_DUPSORT. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [out] countp Address where the count will be stored + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EINVAL - cursor is not initialized, or an invalid parameter + * was specified. */ +LIBMDBX_API int mdbx_cursor_count(MDBX_cursor *cursor, size_t *countp); + +/* Compare two data items according to a particular database. + * + * This returns a comparison as if the two data items were keys in the + * specified database. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] a The first item to compare + * [in] b The second item to compare + * + * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */ +LIBMDBX_API int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, + const MDBX_val *b); + +/* Compare two data items according to a particular database. + * + * This returns a comparison as if the two items were data items of + * the specified database. The database must have the MDBX_DUPSORT flag. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] a The first item to compare + * [in] b The second item to compare + * + * Returns < 0 if a < b, 0 if a == b, > 0 if a > b */ +LIBMDBX_API int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, + const MDBX_val *b); + +/* A callback function used to print a message from the library. + * + * [in] msg The string to be printed. + * [in] ctx An arbitrary context pointer for the callback. + * + * Returns < 0 on failure, >= 0 on success. */ +typedef int(MDBX_msg_func)(const char *msg, void *ctx); + +/* Dump the entries in the reader lock table. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] func A MDBX_msg_func function + * [in] ctx Anything the message function needs + * + * Returns < 0 on failure, >= 0 on success. */ +LIBMDBX_API int mdbx_reader_list(MDBX_env *env, MDBX_msg_func *func, void *ctx); + +/* Check for stale entries in the reader lock table. + * + * [in] env An environment handle returned by mdbx_env_create() + * [out] dead Number of stale slots that were cleared + * + * Returns 0 on success, non-zero on failure. */ +LIBMDBX_API int mdbx_reader_check(MDBX_env *env, int *dead); + +LIBMDBX_API char *mdbx_dkey(const MDBX_val *key, char *const buf, + const size_t bufsize); + +LIBMDBX_API int mdbx_env_close_ex(MDBX_env *env, int dont_sync); + +/* Sets threshold to force flush the data buffers to disk, + * even of MDBX_NOSYNC, MDBX_NOMETASYNC and MDBX_MAPASYNC flags + * in the environment. The value affects all processes which operates with given + * DB until the last process close DB or a new value will be settled. + * + * Data is always written to disk when mdbx_txn_commit() is called, + * but the operating system may keep it buffered. MDBX always flushes + * the OS buffers upon commit as well, unless the environment was + * opened with MDBX_NOSYNC, MDBX_MAPASYNC or in part MDBX_NOMETASYNC. + * + * The default is 0, than mean no any threshold checked, and no additional + * flush will be made. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] bytes The size in bytes of summary changes when a synchronous + * flush would be made. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_set_syncbytes(MDBX_env *env, size_t bytes); + +/* Sets relative period since the last unsteay commit to force flush the data + * buffers to disk, even of MDBX_NOSYNC, MDBX_NOMETASYNC and MDBX_MAPASYNC flags + * in the environment. The value affects all processes which operates with given + * DB until the last process close DB or a new value will be settled. + * + * Data is always written to disk when mdbx_txn_commit() is called, + * but the operating system may keep it buffered. MDBX always flushes + * the OS buffers upon commit as well, unless the environment was + * opened with MDBX_NOSYNC, MDBX_MAPASYNC or in part MDBX_NOMETASYNC. + * + * Settled period don't checked asynchronously, but only inside the functions. + * mdbx_txn_commit() and mdbx_env_sync(). Therefore, in cases where transactions + * are committed infrequently and/or irregularly, polling by mdbx_env_sync() may + * be a reasonable solution to timeout enforcement. + * + * The default is 0, than mean no any timeout checked, and no additional + * flush will be made. + * + * [in] env An environment handle returned by mdbx_env_create() + * [in] seconds_16dot16 The period in 1/65536 of second when a synchronous + * flush would be made since the last unsteay commit. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_set_syncperiod(MDBX_env *env, + unsigned seconds_16dot16); + +/* Returns a lag of the reading for the given transaction. + * + * Returns an information for estimate how much given read-only + * transaction is lagging relative the to actual head. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [out] percent Percentage of page allocation in the database. + * + * Returns Number of transactions committed after the given was started for + * read, or negative value on failure. */ +LIBMDBX_API int mdbx_txn_straggler(MDBX_txn *txn, int *percent); + +/* A callback function for killing a laggard readers, + * but also could waiting ones. Called in case of MDBX_MAP_FULL error. + * + * [in] env An environment handle returned by mdbx_env_create(). + * [in] pid pid of the reader process. + * [in] tid thread_id of the reader thread. + * [in] txn Transaction number on which stalled. + * [in] gap A lag from the last commited txn. + * [in] retry A retry number, less that zero for notify end of OOM-loop. + * + * Returns -1 on failure (reader is not killed), + * 0 should wait or retry, + * 1 drop reader txn-lock (reading-txn was aborted), + * >1 drop reader registration (reader process was killed). */ +typedef int(MDBX_oom_func)(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn, + unsigned gap, int retry); + +/* Set the OOM callback. + * + * Callback will be called only on out-of-pages case for killing + * a laggard readers to allowing reclaiming of freeDB. + * + * [in] env An environment handle returned by mdbx_env_create(). + * [in] oomfunc A MDBX_oom_func function or NULL to disable. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oom_func); + +/* Get the current oom_func callback. + * + * Callback will be called only on out-of-pages case for killing + * a laggard readers to allowing reclaiming of freeDB. + * + * [in] env An environment handle returned by mdbx_env_create(). + * + * Returns A MDBX_oom_func function or NULL if disabled. */ +LIBMDBX_API MDBX_oom_func *mdbx_env_get_oomfunc(MDBX_env *env); + +#define MDBX_DBG_ASSERT 1 +#define MDBX_DBG_PRINT 2 +#define MDBX_DBG_TRACE 4 +#define MDBX_DBG_EXTRA 8 +#define MDBX_DBG_AUDIT 16 +#define MDBX_DBG_JITTER 32 +#define MDBX_DBG_DUMP 64 +#define MDBX_DBG_LEGACY_MULTIOPEN 128 + +typedef void MDBX_debug_func(int type, const char *function, int line, + const char *msg, va_list args); + +LIBMDBX_API int mdbx_setup_debug(int flags, MDBX_debug_func *logger); + +typedef enum { + MDBX_page_void, + MDBX_page_meta, + MDBX_page_large, + MDBX_page_branch, + MDBX_page_leaf, + MDBX_page_dupfixed_leaf, + MDBX_subpage_leaf, + MDBX_subpage_dupfixed_leaf +} MDBX_page_type_t; + +#define MDBX_PGWALK_MAIN ((const char *)((ptrdiff_t)0)) +#define MDBX_PGWALK_GC ((const char *)((ptrdiff_t)-1)) +#define MDBX_PGWALK_META ((const char *)((ptrdiff_t)-2)) + +typedef int +MDBX_pgvisitor_func(const uint64_t pgno, const unsigned number, void *const ctx, + const int deep, const char *const dbi, + const size_t page_size, const MDBX_page_type_t type, + const size_t nentries, const size_t payload_bytes, + const size_t header_bytes, const size_t unused_bytes); +LIBMDBX_API int mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor, + void *ctx); + +typedef struct mdbx_canary { + uint64_t x, y, z, v; +} mdbx_canary; + +LIBMDBX_API int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary); +LIBMDBX_API int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary); + +/* Returns: + * - MDBX_RESULT_TRUE + * when no more data available or cursor not positioned; + * - MDBX_RESULT_FALSE + * when data available; + * - Otherwise the error code. */ +LIBMDBX_API int mdbx_cursor_eof(MDBX_cursor *mc); + +/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */ +LIBMDBX_API int mdbx_cursor_on_first(MDBX_cursor *mc); + +/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */ +LIBMDBX_API int mdbx_cursor_on_last(MDBX_cursor *mc); + +/* Estimates the distance between cursors as the number of elements. + * Both cursors must be initialized for the same DBI. + * + * [in] cursor_a The first cursor for estimation. + * [in] cursor_b The second cursor for estimation. + * [out] distance_items A pointer to store estimated distance value, + * i.e. *distance_items = distance(a - b). + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_estimate_distance(const MDBX_cursor *first, + const MDBX_cursor *last, + ptrdiff_t *distance_items); + +/* Estimates the move distance, i.e. between the current cursor position and + * next position after the specified move-operation with given key and data. + * Current cursor position and state are preserved. + * + * [in] cursor Cursor for estimation. + * [in,out] key The key for a retrieved item. + * [in,out] data The data of a retrieved item. + * [in] op A cursor operation MDBX_cursor_op. + * [out] distance_items A pointer to store estimated move distance + * as the number of elements. + * + * Returns A non-zero error value on failure and 0 on success. */ +LIBMDBX_API int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, + MDBX_val *data, MDBX_cursor_op move_op, + ptrdiff_t *distance_items); + +/* Estimates the size of a range in the number of elements. + * + * [in] txn A transaction handle returned by mdbx_txn_begin(). + * [in] dbi A database handle returned by mdbx_dbi_open(). + * [in] begin_key The key of range beginning or NULL for explicit FIRST. + * [in] begin_data Optional additional data to seeking among sorted + * duplicates. Only for MDBX_DUPSORT, NULL otherwise. + * [in] end_key The key of range ending or NULL for explicit LAST. + * [in] end_data Optional additional data to seeking among sorted + * duplicates. Only for MDBX_DUPSORT, NULL otherwise. + * [out] distance_items A pointer to store range estimation result. + * + * Returns A non-zero error value on failure and 0 on success. */ +#define MDBX_EPSILON ((MDBX_val *)((ptrdiff_t)-1)) +LIBMDBX_API int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, + MDBX_val *begin_key, MDBX_val *begin_data, + MDBX_val *end_key, MDBX_val *end_data, + ptrdiff_t *size_items); + +LIBMDBX_API int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *new_data, MDBX_val *old_data, + unsigned flags); +/* Same as mdbx_get(), but: + * 1) if values_count is not NULL, then returns the count + * of multi-values/duplicates for a given key. + * 2) updates the key for pointing to the actual key's data inside DB. */ +LIBMDBX_API int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data, size_t *values_count); + +LIBMDBX_API int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr); + +LIBMDBX_API int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, + uint64_t increment); + +LIBMDBX_API int mdbx_limits_pgsize_min(void); +LIBMDBX_API int mdbx_limits_pgsize_max(void); +LIBMDBX_API intptr_t mdbx_limits_dbsize_min(intptr_t pagesize); +LIBMDBX_API intptr_t mdbx_limits_dbsize_max(intptr_t pagesize); +LIBMDBX_API intptr_t mdbx_limits_keysize_max(intptr_t pagesize); +LIBMDBX_API intptr_t mdbx_limits_txnsize_max(intptr_t pagesize); + +/*----------------------------------------------------------------------------*/ +/* attribute support functions for Nexenta */ +typedef uint_fast64_t mdbx_attr_t; + +/* Store by cursor with attribute. + * + * This function stores key/data pairs into the database. The cursor is + * positioned at the new item, or on failure usually near it. + * + * NOTE: Internally based on MDBX_RESERVE feature, + * therefore doesn't support MDBX_DUPSORT. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [in] key The key operated on. + * [in] data The data operated on. + * [in] attr The attribute. + * [in] flags Options for this operation. This parameter must be set to 0 + * or one of the values described here: + * + * - MDBX_CURRENT + * Replace the item at the current cursor position. The key parameter + * must still be provided, and must match it, otherwise the function + * return MDBX_EKEYMISMATCH. + * + * - MDBX_APPEND + * Append the given key/data pair to the end of the database. No key + * comparisons are performed. This option allows fast bulk loading when + * keys are already known to be in the correct order. Loading unsorted + * keys with this flag will cause a MDBX_KEYEXIST error. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_EKEYMISMATCH + * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize(). + * - MDBX_TXN_FULL - the transaction has too many dirty pages. + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key, + MDBX_val *data, mdbx_attr_t attr, + unsigned flags); + +/* Store items and attributes into a database. + * + * This function stores key/data pairs in the database. The default behavior + * is to enter the new key/data pair, replacing any previously existing key + * if duplicates are disallowed. + * + * NOTE: Internally based on MDBX_RESERVE feature, + * therefore doesn't support MDBX_DUPSORT. + * + * [in] txn A transaction handle returned by mdbx_txn_begin(). + * [in] dbi A database handle returned by mdbx_dbi_open(). + * [in] key The key to store in the database. + * [in] attr The attribute to store in the database. + * [in,out] data The data to store. + * [in] flags Special options for this operation. This parameter must be + * set to 0 or by bitwise OR'ing together one or more of the + * values described here: + * + * - MDBX_NOOVERWRITE + * Enter the new key/data pair only if the key does not already appear + * in the database. The function will return MDBX_KEYEXIST if the key + * already appears in the database. The data parameter will be set to + * point to the existing item. + * + * - MDBX_CURRENT + * Update an single existing entry, but not add new ones. The function + * will return MDBX_NOTFOUND if the given key not exist in the database. + * Or the MDBX_EMULTIVAL in case duplicates for the given key. + * + * - MDBX_APPEND + * Append the given key/data pair to the end of the database. This option + * allows fast bulk loading when keys are already known to be in the + * correct order. Loading unsorted keys with this flag will cause + * a MDBX_EKEYMISMATCH error. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_KEYEXIST + * - MDBX_MAP_FULL - the database is full, see mdbx_env_set_mapsize(). + * - MDBX_TXN_FULL - the transaction has too many dirty pages. + * - MDBX_EACCES - an attempt was made to write in a read-only transaction. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data, mdbx_attr_t attr, unsigned flags); + +/* Set items attribute from a database. + * + * This function stores key/data pairs attribute to the database. + * + * NOTE: Internally based on MDBX_RESERVE feature, + * therefore doesn't support MDBX_DUPSORT. + * + * [in] txn A transaction handle returned by mdbx_txn_begin(). + * [in] dbi A database handle returned by mdbx_dbi_open(). + * [in] key The key to search for in the database. + * [in] data The data to be stored or NULL to save previous value. + * [in] attr The attribute to be stored. + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - the key-value pair was not in the database. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data, mdbx_attr_t attr); + +/* Get items attribute from a database cursor. + * + * This function retrieves key/data pairs from the database. The address and + * length of the key are returned in the object to which key refers (except + * for the case of the MDBX_SET option, in which the key object is unchanged), + * and the address and length of the data are returned in the object to which + * data refers. See mdbx_get() for restrictions on using the output values. + * + * [in] cursor A cursor handle returned by mdbx_cursor_open() + * [in,out] key The key for a retrieved item + * [in,out] data The data of a retrieved item + * [in] op A cursor operation MDBX_cursor_op + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - no matching key found. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data, mdbx_attr_t *attrptr, + MDBX_cursor_op op); + +/* Get items attribute from a database. + * + * This function retrieves key/data pairs from the database. The address + * and length of the data associated with the specified key are returned + * in the structure to which data refers. + * If the database supports duplicate keys (MDBX_DUPSORT) then the + * first data item for the key will be returned. Retrieval of other + * items requires the use of mdbx_cursor_get(). + * + * NOTE: The memory pointed to by the returned values is owned by the + * database. The caller need not dispose of the memory, and may not + * modify it in any way. For values returned in a read-only transaction + * any modification attempts will cause a SIGSEGV. + * + * NOTE: Values returned from the database are valid only until a + * subsequent update operation, or the end of the transaction. + * + * [in] txn A transaction handle returned by mdbx_txn_begin() + * [in] dbi A database handle returned by mdbx_dbi_open() + * [in] key The key to search for in the database + * [in,out] data The data corresponding to the key + * + * Returns A non-zero error value on failure and 0 on success, some + * possible errors are: + * - MDBX_NOTFOUND - the key was not in the database. + * - MDBX_EINVAL - an invalid parameter was specified. */ +LIBMDBX_API int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, + MDBX_val *data, mdbx_attr_t *attrptr); + +/*----------------------------------------------------------------------------*/ +/* LY: temporary workaround for Elbrus's memcmp() bug. */ +#ifndef __GLIBC_PREREQ +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +#define __GLIBC_PREREQ(maj, min) \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GLIBC_PREREQ(maj, min) (0) +#endif +#endif /* __GLIBC_PREREQ */ +#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) +LIBMDBX_API int mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, + size_t n); +LIBMDBX_API int mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2); +LIBMDBX_API int mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, + size_t n); +LIBMDBX_API size_t mdbx_e2k_strlen_bug_workaround(const char *s); +LIBMDBX_API size_t mdbx_e2k_strnlen_bug_workaround(const char *s, + size_t maxlen); +#include +#include +#undef memcmp +#define memcmp mdbx_e2k_memcmp_bug_workaround +#undef bcmp +#define bcmp mdbx_e2k_memcmp_bug_workaround +#undef strcmp +#define strcmp mdbx_e2k_strcmp_bug_workaround +#undef strncmp +#define strncmp mdbx_e2k_strncmp_bug_workaround +#undef strlen +#define strlen mdbx_e2k_strlen_bug_workaround +#undef strnlen +#define strnlen mdbx_e2k_strnlen_bug_workaround + +#endif /* Elbrus's memcmp() bug. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBMDBX_H */ diff --git a/contrib/db/libmdbx/mdbx.sln b/contrib/db/libmdbx/mdbx.sln new file mode 100644 index 00000000..f1462ab8 --- /dev/null +++ b/contrib/db/libmdbx/mdbx.sln @@ -0,0 +1,97 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcxproj", "{6D19209B-ECE7-4B9C-941C-0AA2B484F199}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0A147F9F-22D5-44E6-B389-218CFFB0C524}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_load", "src\tools\mdbx_load.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_dump", "src\tools\mdbx_dump.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_copy", "src\tools\mdbx_copy.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_chk", "src\tools\mdbx_chk.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_stat", "src\tools\mdbx_stat.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x64.ActiveCfg = Debug|x64 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x64.Build.0 = Debug|x64 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x86.ActiveCfg = Debug|Win32 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x86.Build.0 = Debug|Win32 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x64.ActiveCfg = Release|x64 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x64.Build.0 = Release|x64 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x86.ActiveCfg = Release|Win32 + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x86.Build.0 = Release|Win32 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x64.ActiveCfg = Debug|x64 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x64.Build.0 = Debug|x64 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x86.ActiveCfg = Debug|Win32 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x86.Build.0 = Debug|Win32 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.ActiveCfg = Release|x64 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.Build.0 = Release|x64 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x86.ActiveCfg = Release|Win32 + {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x86.Build.0 = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x64.ActiveCfg = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x64.Build.0 = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x86.ActiveCfg = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x86.Build.0 = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x64.ActiveCfg = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x64.Build.0 = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x86.ActiveCfg = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x86.Build.0 = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x64.ActiveCfg = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x64.Build.0 = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x86.ActiveCfg = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x86.Build.0 = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x64.ActiveCfg = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x64.Build.0 = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x86.ActiveCfg = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x86.Build.0 = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x64.ActiveCfg = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x64.Build.0 = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x86.ActiveCfg = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x86.Build.0 = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x64.ActiveCfg = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x64.Build.0 = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x86.ActiveCfg = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x86.Build.0 = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x64.ActiveCfg = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x64.Build.0 = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x86.ActiveCfg = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x86.Build.0 = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x64.ActiveCfg = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x64.Build.0 = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x86.ActiveCfg = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x86.Build.0 = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x64.ActiveCfg = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x64.Build.0 = Debug|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x86.ActiveCfg = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x86.Build.0 = Debug|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x64.ActiveCfg = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x64.Build.0 = Release|x64 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x86.ActiveCfg = Release|Win32 + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} + EndGlobalSection +EndGlobal diff --git a/contrib/db/libmdbx/packages/rpm/CMakeLists.txt b/contrib/db/libmdbx/packages/rpm/CMakeLists.txt new file mode 100644 index 00000000..5949e9f0 --- /dev/null +++ b/contrib/db/libmdbx/packages/rpm/CMakeLists.txt @@ -0,0 +1,184 @@ +cmake_minimum_required(VERSION 2.8.7) +set(TARGET mdbx) +project(${TARGET}) + +set(MDBX_VERSION_MAJOR 0) +set(MDBX_VERSION_MINOR 3) +set(MDBX_VERSION_RELEASE 1) +set(MDBX_VERSION_REVISION 0) + +set(MDBX_VERSION_STRING ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR}.${MDBX_VERSION_RELEASE}) + +enable_language(C) +enable_language(CXX) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED on) + +add_definitions(-DNDEBUG=1 -DMDBX_DEBUG=0 -DLIBMDBX_EXPORTS=1 -D_GNU_SOURCE=1) + +find_package(Threads REQUIRED) + +get_directory_property(hasParent PARENT_DIRECTORY) +if(hasParent) + set(STANDALONE_BUILD 0) +else() + set(STANDALONE_BUILD 1) + enable_testing() + + if (CMAKE_C_COMPILER_ID MATCHES GNU) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") + endif() + + if (CMAKE_CXX_COMPILER_ID MATCHES GNU) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpointer-arith") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat-security") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wwrite-strings") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=20") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wunused-function -Wunused-variable -Wunused-value -Wmissing-declarations") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-field-initializers") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-qual") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-functions-called-once") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-packed-bitfield-compat") + + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g3") + endif() + + if (COVERAGE) + if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + message(FATAL_ERROR "Coverage requires -DCMAKE_BUILD_TYPE=Debug Current value=${CMAKE_BUILD_TYPE}") + endif() + + message(STATUS "Setting coverage compiler flags") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb3 -O0 --coverage -fprofile-arcs -ftest-coverage") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -ggdb3 -O0 --coverage -fprofile-arcs -ftest-coverage") + add_definitions(-DCOVERAGE_TEST) + endif() + + if (NOT TRAVIS) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=leak -fstack-protector-strong -static-libasan") + endif() +endif() + +set(${TARGET}_SRC + mdbx.h + src/bits.h + src/defs.h + src/lck-linux.c + src/mdbx.c + src/osal.c + src/osal.h + src/version.c + ) + +add_library(${TARGET}_STATIC STATIC + ${${TARGET}_SRC} + ) + +add_library(${TARGET} ALIAS ${TARGET}_STATIC) + +add_library(${TARGET}_SHARED SHARED + ${${TARGET}_SRC} + ) + +set_target_properties(${TARGET}_SHARED PROPERTIES + VERSION ${MDBX_VERSION_STRING} + SOVERSION ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR} + OUTPUT_NAME ${TARGET} + CLEAN_DIRECT_OUTPUT 1 + ) + +set_target_properties(${TARGET}_STATIC PROPERTIES + VERSION ${MDBX_VERSION_STRING} + SOVERSION ${MDBX_VERSION_MAJOR}.${MDBX_VERSION_MINOR} + OUTPUT_NAME ${TARGET} + CLEAN_DIRECT_OUTPUT 1 + ) + +target_include_directories(${TARGET}_STATIC PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(${TARGET}_SHARED PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(${TARGET}_STATIC ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(${TARGET}_SHARED ${CMAKE_THREAD_LIBS_INIT}) +if(UNIX AND NOT APPLE) + target_link_libraries(${TARGET}_STATIC rt) + target_link_libraries(${TARGET}_SHARED rt) +endif() + +install(TARGETS ${TARGET}_STATIC DESTINATION ${CMAKE_INSTALL_PREFIX}/lib64 COMPONENT mdbx) +install(TARGETS ${TARGET}_SHARED DESTINATION ${CMAKE_INSTALL_PREFIX}/lib64 COMPONENT mdbx) +install(FILES mdbx.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include COMPONENT mdbx-devel) + +add_subdirectory(src/tools) +add_subdirectory(test) +add_subdirectory(test/pcrf) +add_subdirectory(tutorial) + +############################################################################## + +set(CPACK_GENERATOR "RPM") +set(CPACK_RPM_COMPONENT_INSTALL ON) + +# Version +if (NOT "$ENV{BUILD_NUMBER}" STREQUAL "") + set(CPACK_PACKAGE_RELEASE $ENV{BUILD_NUMBER}) +else() + if (NOT "$ENV{CI_PIPELINE_ID}" STREQUAL "") + set(CPACK_PACKAGE_RELEASE $ENV{CI_PIPELINE_ID}) + else() + set(CPACK_PACKAGE_RELEASE 1) + endif() +endif() +set(CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE}) + +set(CPACK_PACKAGE_VERSION ${MDBX_VERSION_STRING}) +set(CPACK_PACKAGE_VERSION_FULL ${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}) + +set(CPACK_RPM_mdbx-devel_PACKAGE_REQUIRES "mdbx = ${CPACK_PACKAGE_VERSION}") + +set(CPACK_RPM_SPEC_INSTALL_POST "/bin/true") +set(CPACK_RPM_mdbx_PACKAGE_NAME mdbx) +set(CPACK_RPM_mdbx-devel_PACKAGE_NAME mdbx-devel) +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The revised and extended descendant of Symas LMDB") + +set(CPACK_PACKAGE_VENDOR "???") +set(CPACK_PACKAGE_CONTACT "Vladimir Romanov") +set(CPACK_PACKAGE_RELOCATABLE false) +set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") +set(CPACK_RPM_PACKAGE_REQUIRES "") +set(CPACK_RPM_PACKAGE_GROUP "Applications/Database") + +set(CPACK_RPM_mdbx_FILE_NAME "${CPACK_RPM_mdbx_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_FULL}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") +set(CPACK_RPM_mdbx-devel_FILE_NAME "${CPACK_RPM_mdbx-devel_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION_FULL}.${CPACK_RPM_PACKAGE_ARCHITECTURE}.rpm") + +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION + /usr/local + /usr/local/bin + /usr/local/lib64 + /usr/local/include + /usr/local/man + /usr/local/man/man1 + ) + +include(CPack) diff --git a/contrib/db/libmdbx/packages/rpm/build.sh b/contrib/db/libmdbx/packages/rpm/build.sh new file mode 100644 index 00000000..51708822 --- /dev/null +++ b/contrib/db/libmdbx/packages/rpm/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e +CONFIG=$1 + +if [[ -z "${CONFIG}" ]]; then + CONFIG=Debug +fi +if [[ -r /opt/rh/devtoolset-6/enable ]]; then + source /opt/rh/devtoolset-6/enable +fi +#rm -f -r build || true +mkdir -p cmake-build-${CONFIG} +pushd cmake-build-${CONFIG} &> /dev/null +if [[ ! -r Makefile ]]; then + cmake .. -DCMAKE_BUILD_TYPE=${CONFIG} +fi +make -j8 || exit 1 +popd &> /dev/null diff --git a/contrib/db/libmdbx/packages/rpm/package.sh b/contrib/db/libmdbx/packages/rpm/package.sh new file mode 100644 index 00000000..d7f9ab29 --- /dev/null +++ b/contrib/db/libmdbx/packages/rpm/package.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +CONFIG=$1 + +if [[ -z "${CONFIG}" ]]; then + CONFIG=Debug +fi + +DIRNAME=`dirname ${BASH_SOURCE[0]}` +DIRNAME=`readlink --canonicalize ${DIRNAME}` + +if [[ -r /opt/rh/devtoolset-6/enable ]]; then + source /opt/rh/devtoolset-6/enable +fi + +mkdir -p cmake-build-${CONFIG} +pushd cmake-build-${CONFIG} &> /dev/null +if [[ ! -r Makefile ]]; then + cmake .. -DCMAKE_BUILD_TYPE=${CONFIG} +fi +rm -f *.rpm +make -j8 package || exit 1 +rm -f *-Unspecified.rpm +popd &> /dev/null diff --git a/contrib/db/libmdbx/src/bits.h b/contrib/db/libmdbx/src/bits.h new file mode 100644 index 00000000..fd36cac9 --- /dev/null +++ b/contrib/db/libmdbx/src/bits.h @@ -0,0 +1,1252 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#pragma once +/* *INDENT-OFF* */ +/* clang-format off */ + +/* In case the MDBX_DEBUG is undefined set it corresponding to NDEBUG */ +#ifndef MDBX_DEBUG +#ifdef NDEBUG +# define MDBX_DEBUG 0 +#else +# define MDBX_DEBUG 1 +#endif +#endif + +/* Undefine the NDEBUG if debugging is enforced by MDBX_DEBUG */ +#if MDBX_DEBUG +# undef NDEBUG +#endif + +#define MDBX_OSX_WANNA_DURABILITY 0 /* using fcntl(F_FULLFSYNC) with 5-10 times slowdown */ +#define MDBX_OSX_WANNA_SPEED 1 /* using fsync() with chance of data lost on power failure */ +#ifndef MDBX_OSX_SPEED_INSTEADOF_DURABILITY +#define MDBX_OSX_SPEED_INSTEADOF_DURABILITY MDBX_OSX_WANNA_DURABILITY +#endif + +/*----------------------------------------------------------------------------*/ + +/* Should be defined before any includes */ +#ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +#endif + +#ifdef __APPLE__ +#define _DARWIN_C_SOURCE +#endif + +#ifdef _MSC_VER +# if _MSC_VER < 1400 +# error "Microsoft Visual C++ 8.0 (Visual Studio 2005) or later version is required" +# endif +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +#if _MSC_VER > 1800 +# pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#if _MSC_VER > 1913 +# pragma warning(disable : 5045) /* Compiler will insert Spectre mitigation... */ +#endif +#pragma warning(disable : 4710) /* 'xyz': function not inlined */ +#pragma warning(disable : 4711) /* function 'xyz' selected for automatic inline expansion */ +#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct / union */ +#pragma warning(disable : 4702) /* unreachable code */ +#pragma warning(disable : 4706) /* assignment within conditional expression */ +#pragma warning(disable : 4127) /* conditional expression is constant */ +#pragma warning(disable : 4324) /* 'xyz': structure was padded due to alignment specifier */ +#pragma warning(disable : 4310) /* cast truncates constant value */ +#pragma warning(disable : 4820) /* bytes padding added after data member for aligment */ +#pragma warning(disable : 4548) /* expression before comma has no effect; expected expression with side - effect */ +#pragma warning(disable : 4366) /* the result of the unary '&' operator may be unaligned */ +#endif /* _MSC_VER (warnings) */ + +#include "../mdbx.h" +#include "./defs.h" + +#if defined(__GNUC__) && !__GNUC_PREREQ(4,2) + /* Actualy libmdbx was not tested with compilers older than GCC from RHEL6. + * But you could remove this #error and try to continue at your own risk. + * In such case please don't rise up an issues related ONLY to old compilers. + */ +# warning "libmdbx required GCC >= 4.2" +#endif + +#if defined(__clang__) && !__CLANG_PREREQ(3,8) + /* Actualy libmdbx was not tested with CLANG older than 3.8. + * But you could remove this #error and try to continue at your own risk. + * In such case please don't rise up an issues related ONLY to old compilers. + */ +# warning "libmdbx required CLANG >= 3.8" +#endif + +#if defined(__GLIBC__) && !__GLIBC_PREREQ(2,12) + /* Actualy libmdbx was not tested with something older than glibc 2.12 (from RHEL6). + * But you could remove this #error and try to continue at your own risk. + * In such case please don't rise up an issues related ONLY to old systems. + */ +# warning "libmdbx required at least GLIBC 2.12." +#endif + +#ifdef __SANITIZE_THREAD__ +# warning "libmdbx don't compatible with ThreadSanitizer, you will get a lot of false-positive issues." +#endif /* __SANITIZE_THREAD__ */ + +#if __has_warning("-Wconstant-logical-operand") +# if defined(__clang__) +# pragma clang diagnostic ignored "-Wconstant-logical-operand" +# elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wconstant-logical-operand" +# else +# pragma warning disable "constant-logical-operand" +# endif +#endif /* -Wconstant-logical-operand */ + +#if defined(__LCC__) && (__LCC__ <= 121) + /* bug #2798 */ +# pragma diag_suppress alignment_reduction_ignored +#elif defined(__ICC) +# pragma warning(disable: 3453 1366) +#elif __has_warning("-Walignment-reduction-ignored") +# if defined(__clang__) +# pragma clang diagnostic ignored "-Walignment-reduction-ignored" +# elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Walignment-reduction-ignored" +# else +# pragma warning disable "alignment-reduction-ignored" +# endif +#endif /* -Walignment-reduction-ignored */ + +#include "./osal.h" + +/* *INDENT-ON* */ +/* clang-format on */ + +#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul +#define MDBX_WORDBITS 64 +#else +#define MDBX_WORDBITS 32 +#endif /* MDBX_WORDBITS */ + +/*----------------------------------------------------------------------------*/ +/* Basic constants and types */ + +/* The minimum number of keys required in a database page. + * Setting this to a larger value will place a smaller bound on the + * maximum size of a data item. Data items larger than this size will + * be pushed into overflow pages instead of being stored directly in + * the B-tree node. This value used to default to 4. With a page size + * of 4096 bytes that meant that any item larger than 1024 bytes would + * go into an overflow page. That also meant that on average 2-3KB of + * each overflow page was wasted space. The value cannot be lower than + * 2 because then there would no longer be a tree structure. With this + * value, items larger than 2KB will go into overflow pages, and on + * average only 1KB will be wasted. */ +#define MDBX_MINKEYS 2 + +/* A stamp that identifies a file as an MDBX file. + * There's nothing special about this value other than that it is easily + * recognizable, and it will reflect any byte order mismatches. */ +#define MDBX_MAGIC UINT64_C(/* 56-bit prime */ 0x59659DBDEF4C11) + +/* The version number for a database's datafile format. */ +#define MDBX_DATA_VERSION 2 +/* The version number for a database's lockfile format. */ +#define MDBX_LOCK_VERSION 3 + +/* handle for the DB used to track free pages. */ +#define FREE_DBI 0 +/* handle for the default DB. */ +#define MAIN_DBI 1 +/* Number of DBs in metapage (free and main) - also hardcoded elsewhere */ +#define CORE_DBS 2 +#define MAX_DBI (INT16_MAX - CORE_DBS) + +/* Number of meta pages - also hardcoded elsewhere */ +#define NUM_METAS 3 + +/* A page number in the database. + * + * MDBX uses 32 bit for page numbers. This limits database + * size up to 2^44 bytes, in case of 4K pages. */ +typedef uint32_t pgno_t; +#define PRIaPGNO PRIu32 +#define MAX_PAGENO UINT32_C(0x7FFFffff) +#define MIN_PAGENO NUM_METAS + +/* A transaction ID. */ +typedef uint64_t txnid_t; +#define PRIaTXN PRIi64 +#if MDBX_DEBUG +#define MIN_TXNID UINT64_C(0x100000000) +#else +#define MIN_TXNID UINT64_C(1) +#endif /* MIN_TXNID */ + +/* Used for offsets within a single page. + * Since memory pages are typically 4 or 8KB in size, 12-13 bits, + * this is plenty. */ +typedef uint16_t indx_t; + +#define MEGABYTE ((size_t)1 << 20) + +/*----------------------------------------------------------------------------*/ +/* Core structures for database and shared memory (i.e. format definition) */ +#pragma pack(push, 1) + +/* Information about a single database in the environment. */ +typedef struct MDBX_db { + uint16_t md_flags; /* see mdbx_dbi_open */ + uint16_t md_depth; /* depth of this tree */ + uint32_t md_xsize; /* also ksize for LEAF2 pages */ + pgno_t md_root; /* the root page of this tree */ + pgno_t md_branch_pages; /* number of internal pages */ + pgno_t md_leaf_pages; /* number of leaf pages */ + pgno_t md_overflow_pages; /* number of overflow pages */ + uint64_t md_seq; /* table sequence counter */ + uint64_t md_entries; /* number of data items */ + uint64_t md_merkle; /* Merkle tree checksum */ +} MDBX_db; + +/* Meta page content. + * A meta page is the start point for accessing a database snapshot. + * Pages 0-1 are meta pages. Transaction N writes meta page (N % 2). */ +typedef struct MDBX_meta { + /* Stamp identifying this as an MDBX file. + * It must be set to MDBX_MAGIC with MDBX_DATA_VERSION. */ + uint64_t mm_magic_and_version; + + /* txnid that committed this page, the first of a two-phase-update pair */ + volatile txnid_t mm_txnid_a; + + uint16_t mm_extra_flags; /* extra DB flags, zero (nothing) for now */ + uint8_t mm_validator_id; /* ID of checksum and page validation method, + * zero (nothing) for now */ + uint8_t mm_extra_pagehdr; /* extra bytes in the page header, + * zero (nothing) for now */ + + struct { + uint16_t grow; /* datafile growth step in pages */ + uint16_t shrink; /* datafile shrink threshold in pages */ + pgno_t lower; /* minimal size of datafile in pages */ + pgno_t upper; /* maximal size of datafile in pages */ + pgno_t now; /* current size of datafile in pages */ + pgno_t next; /* first unused page in the datafile, + * but actually the file may be shorter. */ + } mm_geo; + + MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ + /* The size of pages used in this DB */ +#define mm_psize mm_dbs[FREE_DBI].md_xsize +/* Any persistent environment flags, see mdbx_env */ +#define mm_flags mm_dbs[FREE_DBI].md_flags + mdbx_canary mm_canary; + +#define MDBX_DATASIGN_NONE 0u +#define MDBX_DATASIGN_WEAK 1u +#define SIGN_IS_WEAK(sign) ((sign) == MDBX_DATASIGN_WEAK) +#define SIGN_IS_STEADY(sign) ((sign) > MDBX_DATASIGN_WEAK) +#define META_IS_WEAK(meta) SIGN_IS_WEAK((meta)->mm_datasync_sign) +#define META_IS_STEADY(meta) SIGN_IS_STEADY((meta)->mm_datasync_sign) + volatile uint64_t mm_datasync_sign; + + /* txnid that committed this page, the second of a two-phase-update pair */ + volatile txnid_t mm_txnid_b; + + /* Number of non-meta pages which were put in GC after COW. May be 0 in case + * DB was previously handled by libmdbx without corresponding feature. + * This value in couple with mr_snapshot_pages_retired allows fast estimation + * of "how much reader is restraining GC recycling". */ + uint64_t mm_pages_retired; +} MDBX_meta; + +/* Common header for all page types. The page type depends on mp_flags. + * + * P_BRANCH and P_LEAF pages have unsorted 'MDBX_node's at the end, with + * sorted mp_ptrs[] entries referring to them. Exception: P_LEAF2 pages + * omit mp_ptrs and pack sorted MDBX_DUPFIXED values after the page header. + * + * P_OVERFLOW records occupy one or more contiguous pages where only the + * first has a page header. They hold the real data of F_BIGDATA nodes. + * + * P_SUBP sub-pages are small leaf "pages" with duplicate data. + * A node with flag F_DUPDATA but not F_SUBDATA contains a sub-page. + * (Duplicate data can also go in sub-databases, which use normal pages.) + * + * P_META pages contain MDBX_meta, the start point of an MDBX snapshot. + * + * Each non-metapage up to MDBX_meta.mm_last_pg is reachable exactly once + * in the snapshot: Either used by a database or listed in a freeDB record. */ +typedef struct MDBX_page { + union { + struct MDBX_page *mp_next; /* for in-memory list of freed pages, + * must be first field, see NEXT_LOOSE_PAGE */ + uint64_t mp_validator; /* checksum of page content or a txnid during + * which the page has been updated */ + }; + uint16_t mp_leaf2_ksize; /* key size if this is a LEAF2 page */ +#define P_BRANCH 0x01 /* branch page */ +#define P_LEAF 0x02 /* leaf page */ +#define P_OVERFLOW 0x04 /* overflow page */ +#define P_META 0x08 /* meta page */ +#define P_DIRTY 0x10 /* dirty page, also set for P_SUBP pages */ +#define P_LEAF2 0x20 /* for MDBX_DUPFIXED records */ +#define P_SUBP 0x40 /* for MDBX_DUPSORT sub-pages */ +#define P_LOOSE 0x4000 /* page was dirtied then freed, can be reused */ +#define P_KEEP 0x8000 /* leave this page alone during spill */ + uint16_t mp_flags; + union { + struct { + indx_t mp_lower; /* lower bound of free space */ + indx_t mp_upper; /* upper bound of free space */ + }; + uint32_t mp_pages; /* number of overflow pages */ + }; + pgno_t mp_pgno; /* page number */ + + /* dynamic size */ + union { + indx_t mp_ptrs[1]; + MDBX_meta mp_meta; + uint8_t mp_data[1]; + }; +} MDBX_page; + +/* Size of the page header, excluding dynamic data at the end */ +#define PAGEHDRSZ ((unsigned)offsetof(MDBX_page, mp_data)) + +/* The maximum size of a database page. + * + * It is 64K, but value-PAGEHDRSZ must fit in MDBX_page.mp_upper. + * + * MDBX will use database pages < OS pages if needed. + * That causes more I/O in write transactions: The OS must + * know (read) the whole page before writing a partial page. + * + * Note that we don't currently support Huge pages. On Linux, + * regular data files cannot use Huge pages, and in general + * Huge pages aren't actually pageable. We rely on the OS + * demand-pager to read our data and page it out when memory + * pressure from other processes is high. So until OSs have + * actual paging support for Huge pages, they're not viable. */ +#define MAX_PAGESIZE 0x10000u +#define MIN_PAGESIZE 512u + +#define MIN_MAPSIZE (MIN_PAGESIZE * MIN_PAGENO) +#if defined(_WIN32) || defined(_WIN64) +#define MAX_MAPSIZE32 UINT32_C(0x38000000) +#else +#define MAX_MAPSIZE32 UINT32_C(0x7ff80000) +#endif +#define MAX_MAPSIZE64 (MAX_PAGENO * (uint64_t)MAX_PAGESIZE) + +#if MDBX_WORDBITS >= 64 +#define MAX_MAPSIZE MAX_MAPSIZE64 +#else +#define MAX_MAPSIZE MAX_MAPSIZE32 +#endif /* MDBX_WORDBITS */ + +#pragma pack(pop) + +/* Reader Lock Table + * + * Readers don't acquire any locks for their data access. Instead, they + * simply record their transaction ID in the reader table. The reader + * mutex is needed just to find an empty slot in the reader table. The + * slot's address is saved in thread-specific data so that subsequent + * read transactions started by the same thread need no further locking to + * proceed. + * + * If MDBX_NOTLS is set, the slot address is not saved in thread-specific data. + * No reader table is used if the database is on a read-only filesystem. + * + * Since the database uses multi-version concurrency control, readers don't + * actually need any locking. This table is used to keep track of which + * readers are using data from which old transactions, so that we'll know + * when a particular old transaction is no longer in use. Old transactions + * that have discarded any data pages can then have those pages reclaimed + * for use by a later write transaction. + * + * The lock table is constructed such that reader slots are aligned with the + * processor's cache line size. Any slot is only ever used by one thread. + * This alignment guarantees that there will be no contention or cache + * thrashing as threads update their own slot info, and also eliminates + * any need for locking when accessing a slot. + * + * A writer thread will scan every slot in the table to determine the oldest + * outstanding reader transaction. Any freed pages older than this will be + * reclaimed by the writer. The writer doesn't use any locks when scanning + * this table. This means that there's no guarantee that the writer will + * see the most up-to-date reader info, but that's not required for correct + * operation - all we need is to know the upper bound on the oldest reader, + * we don't care at all about the newest reader. So the only consequence of + * reading stale information here is that old pages might hang around a + * while longer before being reclaimed. That's actually good anyway, because + * the longer we delay reclaiming old pages, the more likely it is that a + * string of contiguous pages can be found after coalescing old pages from + * many old transactions together. */ + +/* The actual reader record, with cacheline padding. */ +typedef struct MDBX_reader { + /* Current Transaction ID when this transaction began, or (txnid_t)-1. + * Multiple readers that start at the same time will probably have the + * same ID here. Again, it's not important to exclude them from + * anything; all we need to know is which version of the DB they + * started from so we can avoid overwriting any data used in that + * particular version. */ + volatile txnid_t mr_txnid; + + /* The information we store in a single slot of the reader table. + * In addition to a transaction ID, we also record the process and + * thread ID that owns a slot, so that we can detect stale information, + * e.g. threads or processes that went away without cleaning up. + * + * NOTE: We currently don't check for stale records. + * We simply re-init the table when we know that we're the only process + * opening the lock file. */ + + /* The thread ID of the thread owning this txn. */ + union { + volatile mdbx_tid_t mr_tid; + volatile uint64_t mr_tid_u64; + }; + /* The process ID of the process owning this reader txn. */ + union { + volatile mdbx_pid_t mr_pid; + volatile uint32_t mr_pid_u32; + }; + /* The number of pages used in the reader's MVCC snapshot, + * i.e. the value of meta->mm_geo.next and txn->mt_next_pgno */ + volatile pgno_t mr_snapshot_pages_used; + /* Number of retired pages at the time this reader starts transaction. So, + * at any time the difference mm_pages_retired - mr_snapshot_pages_retired + * will give the number of pages which this reader restraining from reuse. */ + volatile uint64_t mr_snapshot_pages_retired; +} MDBX_reader; + +/* The header for the reader table (a memory-mapped lock file). */ +typedef struct MDBX_lockinfo { + /* Stamp identifying this as an MDBX file. + * It must be set to MDBX_MAGIC with with MDBX_LOCK_VERSION. */ + uint64_t mti_magic_and_version; + + /* Format of this lock file. Must be set to MDBX_LOCK_FORMAT. */ + uint32_t mti_os_and_format; + + /* Flags which environment was opened. */ + volatile uint32_t mti_envmode; + + /* Threshold of un-synced-with-disk pages for auto-sync feature, + * zero means no-threshold, i.e. auto-sync is disabled. */ + volatile pgno_t mti_autosync_threshold; + /* Period for timed auto-sync feature, i.e. at the every steady checkpoint + * the mti_unsynced_timeout sets to the current_time + mti_autosync_period. + * The time value is represented in a suitable system-dependent form, for + * example clock_gettime(CLOCK_BOOTTIME) or clock_gettime(CLOCK_MONOTONIC). + * Zero means timed auto-sync is disabled. */ + volatile uint64_t mti_autosync_period; + + alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ +#ifdef MDBX_OSAL_LOCK + /* Mutex protecting write-txn. */ + MDBX_OSAL_LOCK mti_wmutex; +#endif + + volatile txnid_t mti_oldest_reader; + + /* Timestamp for auto-sync feature, i.e. the steady checkpoint should be + * created at the first commit that will be not early this timestamp. + * The time value is represented in a suitable system-dependent form, for + * example clock_gettime(CLOCK_BOOTTIME) or clock_gettime(CLOCK_MONOTONIC). + * Zero means timed auto-sync is not pending. */ + volatile uint64_t mti_unsynced_timeout; + + /* Number un-synced-with-disk pages for auto-sync feature. */ + volatile pgno_t mti_unsynced_pages; + + alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ + +#ifdef MDBX_OSAL_LOCK + /* Mutex protecting readers registration access to this table. */ + MDBX_OSAL_LOCK mti_rmutex; +#endif + + /* The number of slots that have been used in the reader table. + * This always records the maximum count, it is not decremented + * when readers release their slots. */ + volatile unsigned mti_numreaders; + volatile unsigned mti_readers_refresh_flag; + + alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ + MDBX_reader mti_readers[1]; +} MDBX_lockinfo; + +/* Lockfile format signature: version, features and field layout */ +#define MDBX_LOCK_FORMAT \ + (MDBX_OSAL_LOCK_SIGN * 27733 + (unsigned)sizeof(MDBX_reader) * 13 + \ + (unsigned)offsetof(MDBX_reader, mr_snapshot_pages_used) * 251 + \ + (unsigned)offsetof(MDBX_lockinfo, mti_oldest_reader) * 83 + \ + (unsigned)offsetof(MDBX_lockinfo, mti_numreaders) * 29) + +#define MDBX_DATA_MAGIC ((MDBX_MAGIC << 8) + MDBX_DATA_VERSION) +#define MDBX_DATA_MAGIC_DEVEL ((MDBX_MAGIC << 8) + 255) + +#define MDBX_LOCK_MAGIC ((MDBX_MAGIC << 8) + MDBX_LOCK_VERSION) + +#ifndef MDBX_ASSUME_MALLOC_OVERHEAD +#define MDBX_ASSUME_MALLOC_OVERHEAD (sizeof(void *) * 2u) +#endif /* MDBX_ASSUME_MALLOC_OVERHEAD */ + +/*----------------------------------------------------------------------------*/ +/* Two kind lists of pages (aka PNL) */ + +/* An PNL is an Page Number List, a sorted array of IDs. The first element of + * the array is a counter for how many actual page-numbers are in the list. + * PNLs are sorted in descending order, this allow cut off a page with lowest + * pgno (at the tail) just truncating the list */ +#define MDBX_PNL_ASCENDING 0 +typedef pgno_t *MDBX_PNL; + +#if MDBX_PNL_ASCENDING +#define MDBX_PNL_ORDERED(first, last) ((first) < (last)) +#define MDBX_PNL_DISORDERED(first, last) ((first) >= (last)) +#else +#define MDBX_PNL_ORDERED(first, last) ((first) > (last)) +#define MDBX_PNL_DISORDERED(first, last) ((first) <= (last)) +#endif + +/* List of txnid, only for MDBX_env.mt_lifo_reclaimed */ +typedef txnid_t *MDBX_TXL; + +/* An Dirty-Page list item is an pgno/pointer pair. */ +typedef union MDBX_DP { + struct { + pgno_t pgno; + void *ptr; + }; + struct { + pgno_t unused; + unsigned length; + }; +} MDBX_DP; + +/* An DPL (dirty-page list) is a sorted array of MDBX_DPs. + * The first element's length member is a count of how many actual + * elements are in the array. */ +typedef MDBX_DP *MDBX_DPL; + +/* PNL sizes - likely should be even bigger */ +#define MDBX_PNL_GRANULATE 1024 +#define MDBX_PNL_INITIAL \ + (MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t)) +#define MDBX_PNL_MAX \ + ((1u << 24) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t)) +#define MDBX_DPL_TXNFULL (MDBX_PNL_MAX / 4) + +#define MDBX_TXL_GRANULATE 32 +#define MDBX_TXL_INITIAL \ + (MDBX_TXL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t)) +#define MDBX_TXL_MAX \ + ((1u << 17) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t)) + +#define MDBX_PNL_ALLOCLEN(pl) ((pl)[-1]) +#define MDBX_PNL_SIZE(pl) ((pl)[0]) +#define MDBX_PNL_FIRST(pl) ((pl)[1]) +#define MDBX_PNL_LAST(pl) ((pl)[MDBX_PNL_SIZE(pl)]) +#define MDBX_PNL_BEGIN(pl) (&(pl)[1]) +#define MDBX_PNL_END(pl) (&(pl)[MDBX_PNL_SIZE(pl) + 1]) + +#define MDBX_PNL_SIZEOF(pl) ((MDBX_PNL_SIZE(pl) + 1) * sizeof(pgno_t)) +#define MDBX_PNL_IS_EMPTY(pl) (MDBX_PNL_SIZE(pl) == 0) + +/*----------------------------------------------------------------------------*/ +/* Internal structures */ + +/* Auxiliary DB info. + * The information here is mostly static/read-only. There is + * only a single copy of this record in the environment. */ +typedef struct MDBX_dbx { + MDBX_val md_name; /* name of the database */ + MDBX_cmp_func *md_cmp; /* function for comparing keys */ + MDBX_cmp_func *md_dcmp; /* function for comparing data items */ +} MDBX_dbx; + +/* A database transaction. + * Every operation requires a transaction handle. */ +struct MDBX_txn { +#define MDBX_MT_SIGNATURE UINT32_C(0x93D53A31) + size_t mt_signature; + MDBX_txn *mt_parent; /* parent of a nested txn */ + /* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */ + MDBX_txn *mt_child; + pgno_t mt_next_pgno; /* next unallocated page */ + pgno_t mt_end_pgno; /* corresponding to the current size of datafile */ + /* The ID of this transaction. IDs are integers incrementing from 1. + * Only committed write transactions increment the ID. If a transaction + * aborts, the ID may be re-used by the next writer. */ + txnid_t mt_txnid; + MDBX_env *mt_env; /* the DB environment */ + /* The list of reclaimed txns from freeDB */ + MDBX_TXL mt_lifo_reclaimed; + /* The list of pages that became unused during this transaction. */ + MDBX_PNL mt_befree_pages; + /* The list of loose pages that became unused and may be reused + * in this transaction, linked through NEXT_LOOSE_PAGE(page). */ + MDBX_page *mt_loose_pages; + /* Number of loose pages (mt_loose_pages) */ + unsigned mt_loose_count; + /* The sorted list of dirty pages we temporarily wrote to disk + * because the dirty list was full. page numbers in here are + * shifted left by 1, deleted slots have the LSB set. */ + MDBX_PNL mt_spill_pages; + union { + /* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */ + MDBX_DPL mt_rw_dirtylist; + /* For read txns: This thread/txn's reader table slot, or NULL. */ + MDBX_reader *mt_ro_reader; + }; + /* Array of records for each DB known in the environment. */ + MDBX_dbx *mt_dbxs; + /* Array of MDBX_db records for each known DB */ + MDBX_db *mt_dbs; + /* Array of sequence numbers for each DB handle */ + unsigned *mt_dbiseqs; + +/* Transaction DB Flags */ +#define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */ +#define DB_STALE MDBX_TBL_STALE /* Named-DB record is older than txnID */ +#define DB_FRESH MDBX_TBL_FRESH /* Named-DB handle opened in this txn */ +#define DB_CREAT MDBX_TBL_CREAT /* Named-DB handle created in this txn */ +#define DB_VALID 0x10 /* DB handle is valid, see also MDBX_VALID */ +#define DB_USRVALID 0x20 /* As DB_VALID, but not set for FREE_DBI */ +#define DB_DUPDATA 0x40 /* DB is MDBX_DUPSORT data */ + /* In write txns, array of cursors for each DB */ + MDBX_cursor **mt_cursors; + /* Array of flags for each DB */ + uint8_t *mt_dbflags; + /* Number of DB records in use, or 0 when the txn is finished. + * This number only ever increments until the txn finishes; we + * don't decrement it when individual DB handles are closed. */ + MDBX_dbi mt_numdbs; + +/* Transaction Flags */ +/* mdbx_txn_begin() flags */ +#define MDBX_TXN_BEGIN_FLAGS \ + (MDBX_NOMETASYNC | MDBX_NOSYNC | MDBX_RDONLY | MDBX_TRYTXN) +#define MDBX_TXN_NOMETASYNC \ + MDBX_NOMETASYNC /* don't sync meta for this txn on commit */ +#define MDBX_TXN_NOSYNC MDBX_NOSYNC /* don't sync this txn on commit */ +#define MDBX_TXN_RDONLY MDBX_RDONLY /* read-only transaction */ + /* internal txn flags */ +#define MDBX_TXN_WRITEMAP MDBX_WRITEMAP /* copy of MDBX_env flag in writers */ +#define MDBX_TXN_FINISHED 0x01 /* txn is finished or never began */ +#define MDBX_TXN_ERROR 0x02 /* txn is unusable after an error */ +#define MDBX_TXN_DIRTY 0x04 /* must write, even if dirty list is empty */ +#define MDBX_TXN_SPILLS 0x08 /* txn or a parent has spilled pages */ +#define MDBX_TXN_HAS_CHILD 0x10 /* txn has an MDBX_txn.mt_child */ +/* most operations on the txn are currently illegal */ +#define MDBX_TXN_BLOCKED \ + (MDBX_TXN_FINISHED | MDBX_TXN_ERROR | MDBX_TXN_HAS_CHILD) + unsigned mt_flags; + /* dirtylist room: Array size - dirty pages visible to this txn. + * Includes ancestor txns' dirty pages not hidden by other txns' + * dirty/spilled pages. Thus commit(nested txn) has room to merge + * dirtylist into mt_parent after freeing hidden mt_parent pages. */ + unsigned mt_dirtyroom; + mdbx_tid_t mt_owner; /* thread ID that owns this transaction */ + mdbx_canary mt_canary; +}; + +/* Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. + * At 4 keys per node, enough for 2^64 nodes, so there's probably no need to + * raise this on a 64 bit machine. */ +#define CURSOR_STACK 32 + +struct MDBX_xcursor; + +/* Cursors are used for all DB operations. + * A cursor holds a path of (page pointer, key index) from the DB + * root to a position in the DB, plus other state. MDBX_DUPSORT + * cursors include an xcursor to the current data item. Write txns + * track their cursors and keep them up to date when data moves. + * Exception: An xcursor's pointer to a P_SUBP page can be stale. + * (A node with F_DUPDATA but no F_SUBDATA contains a subpage). */ +struct MDBX_cursor { +#define MDBX_MC_SIGNATURE UINT32_C(0xFE05D5B1) +#define MDBX_MC_READY4CLOSE UINT32_C(0x2817A047) +#define MDBX_MC_WAIT4EOT UINT32_C(0x90E297A7) + uint32_t mc_signature; + /* The database handle this cursor operates on */ + MDBX_dbi mc_dbi; + /* Next cursor on this DB in this txn */ + MDBX_cursor *mc_next; + /* Backup of the original cursor if this cursor is a shadow */ + MDBX_cursor *mc_backup; + /* Context used for databases with MDBX_DUPSORT, otherwise NULL */ + struct MDBX_xcursor *mc_xcursor; + /* The transaction that owns this cursor */ + MDBX_txn *mc_txn; + /* The database record for this cursor */ + MDBX_db *mc_db; + /* The database auxiliary record for this cursor */ + MDBX_dbx *mc_dbx; + /* The mt_dbflag for this database */ + uint8_t *mc_dbflag; + uint16_t mc_snum; /* number of pushed pages */ + uint16_t mc_top; /* index of top page, normally mc_snum-1 */ + /* Cursor state flags. */ +#define C_INITIALIZED 0x01 /* cursor has been initialized and is valid */ +#define C_EOF 0x02 /* No more data */ +#define C_SUB 0x04 /* Cursor is a sub-cursor */ +#define C_DEL 0x08 /* last op was a cursor_del */ +#define C_UNTRACK 0x10 /* Un-track cursor when closing */ +#define C_RECLAIMING 0x20 /* FreeDB lookup is prohibited */ +#define C_GCFREEZE 0x40 /* me_reclaimed_pglist must not be updated */ + unsigned mc_flags; /* see mdbx_cursor */ + MDBX_page *mc_pg[CURSOR_STACK]; /* stack of pushed pages */ + indx_t mc_ki[CURSOR_STACK]; /* stack of page indices */ +}; + +/* Context for sorted-dup records. + * We could have gone to a fully recursive design, with arbitrarily + * deep nesting of sub-databases. But for now we only handle these + * levels - main DB, optional sub-DB, sorted-duplicate DB. */ +typedef struct MDBX_xcursor { + /* A sub-cursor for traversing the Dup DB */ + MDBX_cursor mx_cursor; + /* The database record for this Dup DB */ + MDBX_db mx_db; + /* The auxiliary DB record for this Dup DB */ + MDBX_dbx mx_dbx; + /* The mt_dbflag for this Dup DB */ + uint8_t mx_dbflag; +} MDBX_xcursor; + +typedef struct MDBX_cursor_couple { + MDBX_cursor outer; + MDBX_xcursor inner; +} MDBX_cursor_couple; + +/* Check if there is an inited xcursor, so XCURSOR_REFRESH() is proper */ +#define XCURSOR_INITED(mc) \ + ((mc)->mc_xcursor && ((mc)->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) + +/* Update sub-page pointer, if any, in mc->mc_xcursor. + * Needed when the node which contains the sub-page may have moved. + * Called with mp = mc->mc_pg[mc->mc_top], ki = mc->mc_ki[mc->mc_top]. */ +#define XCURSOR_REFRESH(mc, mp, ki) \ + do { \ + MDBX_page *xr_pg = (mp); \ + MDBX_node *xr_node = NODEPTR(xr_pg, ki); \ + if ((xr_node->mn_flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) \ + (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node); \ + } while (0) + +/* State of FreeDB old pages, stored in the MDBX_env */ +typedef struct MDBX_pgstate { + pgno_t *mf_reclaimed_pglist; /* Reclaimed freeDB pages, or NULL before use */ + txnid_t mf_last_reclaimed; /* ID of last used record, or 0 if + !mf_reclaimed_pglist */ +} MDBX_pgstate; + +/* The database environment. */ +struct MDBX_env { +#define MDBX_ME_SIGNATURE UINT32_C(0x9A899641) + size_t me_signature; + mdbx_mmap_t me_dxb_mmap; /* The main data file */ +#define me_map me_dxb_mmap.dxb +#define me_fd me_dxb_mmap.fd +#define me_mapsize me_dxb_mmap.length + mdbx_mmap_t me_lck_mmap; /* The lock file */ +#define me_lfd me_lck_mmap.fd +#define me_lck me_lck_mmap.lck + +/* Failed to update the meta page. Probably an I/O error. */ +#define MDBX_FATAL_ERROR UINT32_C(0x80000000) +/* Additional flag for mdbx_sync_locked() */ +#define MDBX_SHRINK_ALLOWED UINT32_C(0x40000000) +/* Some fields are initialized. */ +#define MDBX_ENV_ACTIVE UINT32_C(0x20000000) +/* me_txkey is set */ +#define MDBX_ENV_TXKEY UINT32_C(0x10000000) + uint32_t me_flags; /* see mdbx_env */ + unsigned me_psize; /* DB page size, inited from me_os_psize */ + unsigned me_psize2log; /* log2 of DB page size */ + unsigned me_os_psize; /* OS page size, from mdbx_syspagesize() */ + unsigned me_maxreaders; /* size of the reader table */ + mdbx_fastmutex_t me_dbi_lock; + MDBX_dbi me_numdbs; /* number of DBs opened */ + MDBX_dbi me_maxdbs; /* size of the DB table */ + mdbx_pid_t me_pid; /* process ID of this env */ + mdbx_thread_key_t me_txkey; /* thread-key for readers */ + char *me_path; /* path to the DB files */ + void *me_pbuf; /* scratch area for DUPSORT put() */ + MDBX_txn *me_txn; /* current write transaction */ + MDBX_txn *me_txn0; /* prealloc'd write transaction */ +#ifdef MDBX_OSAL_LOCK + MDBX_OSAL_LOCK *me_wmutex; /* write-txn mutex */ +#endif + MDBX_dbx *me_dbxs; /* array of static DB info */ + uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */ + unsigned *me_dbiseqs; /* array of dbi sequence numbers */ + volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */ + MDBX_pgstate me_pgstate; /* state of old pages from freeDB */ +#define me_last_reclaimed me_pgstate.mf_last_reclaimed +#define me_reclaimed_pglist me_pgstate.mf_reclaimed_pglist + MDBX_page *me_dpages; /* list of malloc'd blocks for re-use */ + /* PNL of pages that became unused in a write txn */ + MDBX_PNL me_free_pgs; + /* MDBX_DP of pages written during a write txn. Length MDBX_DPL_TXNFULL. */ + MDBX_DPL me_dirtylist; + /* Number of freelist items that can fit in a single overflow page */ + unsigned me_maxgc_ov1page; + /* Max size of a node on a page */ + unsigned me_nodemax; + unsigned me_maxkey_limit; /* max size of a key */ + mdbx_pid_t me_live_reader; /* have liveness lock in reader table */ + void *me_userctx; /* User-settable context */ + volatile uint64_t *me_unsynced_timeout; + volatile uint64_t *me_autosync_period; + volatile pgno_t *me_unsynced_pages; + volatile pgno_t *me_autosync_threshold; + MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */ + struct { +#ifdef MDBX_OSAL_LOCK + MDBX_OSAL_LOCK wmutex; +#endif + txnid_t oldest; + uint64_t unsynced_timeout; + uint64_t autosync_period; + pgno_t autosync_pending; + pgno_t autosync_threshold; + } me_lckless_stub; +#if MDBX_DEBUG + MDBX_assert_func *me_assert_func; /* Callback for assertion failures */ +#endif +#ifdef USE_VALGRIND + int me_valgrind_handle; +#endif + + struct { + size_t lower; /* minimal size of datafile */ + size_t upper; /* maximal size of datafile */ + size_t now; /* current size of datafile */ + size_t grow; /* step to grow datafile */ + size_t shrink; /* threshold to shrink datafile */ + } me_dbgeo; /* */ + +#if defined(_WIN32) || defined(_WIN64) + MDBX_srwlock me_remap_guard; + /* Workaround for LockFileEx and WriteFile multithread bug */ + CRITICAL_SECTION me_windowsbug_lock; +#else + mdbx_fastmutex_t me_remap_guard; +#endif +}; + +/* Nested transaction */ +typedef struct MDBX_ntxn { + MDBX_txn mnt_txn; /* the transaction */ + MDBX_pgstate mnt_pgstate; /* parent transaction's saved freestate */ +} MDBX_ntxn; + +/*----------------------------------------------------------------------------*/ +/* Debug and Logging stuff */ + +#ifndef mdbx_runtime_flags /* avoid override from tools */ +extern int mdbx_runtime_flags; +#endif +extern MDBX_debug_func *mdbx_debug_logger; +extern txnid_t mdbx_debug_edge; + +void mdbx_debug_log(int type, const char *function, int line, const char *fmt, + ...) __printf_args(4, 5); + +void mdbx_panic(const char *fmt, ...) __printf_args(1, 2); + +#if MDBX_DEBUG + +#define mdbx_assert_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_ASSERT) + +#define mdbx_audit_enabled() unlikely(mdbx_runtime_flags &MDBX_DBG_AUDIT) + +#define mdbx_debug_enabled(type) \ + unlikely(mdbx_runtime_flags &(type & (MDBX_DBG_TRACE | MDBX_DBG_EXTRA))) + +#else +#define mdbx_debug_enabled(type) (0) +#define mdbx_audit_enabled() (0) +#if !defined(NDEBUG) || defined(MDBX_FORCE_ASSERT) +#define mdbx_assert_enabled() (1) +#else +#define mdbx_assert_enabled() (0) +#endif /* NDEBUG */ +#endif /* MDBX_DEBUG */ + +LIBMDBX_API void mdbx_assert_fail(const MDBX_env *env, const char *msg, + const char *func, int line); + +#define mdbx_print(fmt, ...) \ + mdbx_debug_log(MDBX_DBG_PRINT, NULL, 0, fmt, ##__VA_ARGS__) + +#define mdbx_trace(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \ + mdbx_debug_log(MDBX_DBG_TRACE, __FUNCTION__, __LINE__, fmt "\n", \ + ##__VA_ARGS__); \ + } while (0) + +#define mdbx_verbose(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_info(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_notice(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_warning(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_error(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_fatal(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE /* FIXME */)) \ + mdbx_debug_log(MDBX_DBG_TRACE /* FIXME */, __FUNCTION__, __LINE__, \ + fmt "\n", ##__VA_ARGS__); \ + } while (0) + +#define mdbx_debug(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \ + mdbx_debug_log(MDBX_DBG_TRACE, __FUNCTION__, __LINE__, fmt "\n", \ + ##__VA_ARGS__); \ + } while (0) + +#define mdbx_debug_print(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_TRACE)) \ + mdbx_debug_log(MDBX_DBG_TRACE, NULL, 0, fmt, ##__VA_ARGS__); \ + } while (0) + +#define mdbx_debug_extra(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) \ + mdbx_debug_log(MDBX_DBG_EXTRA, __FUNCTION__, __LINE__, fmt, \ + ##__VA_ARGS__); \ + } while (0) + +#define mdbx_debug_extra_print(fmt, ...) \ + do { \ + if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) \ + mdbx_debug_log(MDBX_DBG_EXTRA, NULL, 0, fmt, ##__VA_ARGS__); \ + } while (0) + +#define mdbx_ensure_msg(env, expr, msg) \ + do { \ + if (unlikely(!(expr))) \ + mdbx_assert_fail(env, msg, __FUNCTION__, __LINE__); \ + } while (0) + +#define mdbx_ensure(env, expr) mdbx_ensure_msg(env, expr, #expr) + +/* assert(3) variant in environment context */ +#define mdbx_assert(env, expr) \ + do { \ + if (mdbx_assert_enabled()) \ + mdbx_ensure(env, expr); \ + } while (0) + +/* assert(3) variant in cursor context */ +#define mdbx_cassert(mc, expr) mdbx_assert((mc)->mc_txn->mt_env, expr) + +/* assert(3) variant in transaction context */ +#define mdbx_tassert(txn, expr) mdbx_assert((txn)->mt_env, expr) + +#undef assert +#define assert(expr) mdbx_assert(NULL, expr) + +/*----------------------------------------------------------------------------*/ +/* Internal prototypes */ + +int mdbx_reader_check0(MDBX_env *env, int rlocked, int *dead); +int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin, + MDBX_reader *end); +void mdbx_rthc_remove(const mdbx_thread_key_t key); + +void mdbx_rthc_global_init(void); +void mdbx_rthc_global_dtor(void); +void mdbx_rthc_thread_dtor(void *ptr); + +#define MDBX_IS_ERROR(rc) \ + ((rc) != MDBX_RESULT_TRUE && (rc) != MDBX_RESULT_FALSE) + +/* Internal error codes, not exposed outside libmdbx */ +#define MDBX_NO_ROOT (MDBX_LAST_ERRCODE + 10) + +/* Debuging output value of a cursor DBI: Negative in a sub-cursor. */ +#define DDBI(mc) \ + (((mc)->mc_flags & C_SUB) ? -(int)(mc)->mc_dbi : (int)(mc)->mc_dbi) + +/* Key size which fits in a DKBUF. */ +#define DKBUF_MAXKEYSIZE 511 /* FIXME */ + +#if MDBX_DEBUG +#define DKBUF char _kbuf[DKBUF_MAXKEYSIZE * 4 + 2] +#define DKEY(x) mdbx_dkey(x, _kbuf, DKBUF_MAXKEYSIZE * 2 + 1) +#define DVAL(x) \ + mdbx_dkey(x, _kbuf + DKBUF_MAXKEYSIZE * 2 + 1, DKBUF_MAXKEYSIZE * 2 + 1) +#else +#define DKBUF ((void)(0)) +#define DKEY(x) ("-") +#define DVAL(x) ("-") +#endif + +/* An invalid page number. + * Mainly used to denote an empty tree. */ +#define P_INVALID (~(pgno_t)0) + +/* Test if the flags f are set in a flag word w. */ +#define F_ISSET(w, f) (((w) & (f)) == (f)) + +/* Round n up to an even number. */ +#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */ + +/* Default size of memory map. + * This is certainly too small for any actual applications. Apps should + * always set the size explicitly using mdbx_env_set_mapsize(). */ +#define DEFAULT_MAPSIZE 1048576 + +/* Number of slots in the reader table. + * This value was chosen somewhat arbitrarily. The 61 is a prime number, + * and such readers plus a couple mutexes fit into single 4KB page. + * Applications should set the table size using mdbx_env_set_maxreaders(). */ +#define DEFAULT_READERS 61 + +/* Address of first usable data byte in a page, after the header */ +#define PAGEDATA(p) ((void *)((char *)(p) + PAGEHDRSZ)) + +/* Number of nodes on a page */ +#define NUMKEYS(p) ((unsigned)(p)->mp_lower >> 1) + +/* The amount of space remaining in the page */ +#define SIZELEFT(p) ((indx_t)((p)->mp_upper - (p)->mp_lower)) + +/* The percentage of space used in the page, in tenths of a percent. */ +#define PAGEFILL(env, p) \ + (1024UL * ((env)->me_psize - PAGEHDRSZ - SIZELEFT(p)) / \ + ((env)->me_psize - PAGEHDRSZ)) +/* The minimum page fill factor, in tenths of a percent. + * Pages emptier than this are candidates for merging. */ +#define FILL_THRESHOLD 256 + +/* Test if a page is a leaf page */ +#define IS_LEAF(p) (((p)->mp_flags & P_LEAF) != 0) +/* Test if a page is a LEAF2 page */ +#define IS_LEAF2(p) unlikely(((p)->mp_flags & P_LEAF2) != 0) +/* Test if a page is a branch page */ +#define IS_BRANCH(p) (((p)->mp_flags & P_BRANCH) != 0) +/* Test if a page is an overflow page */ +#define IS_OVERFLOW(p) unlikely(((p)->mp_flags & P_OVERFLOW) != 0) +/* Test if a page is a sub page */ +#define IS_SUBP(p) (((p)->mp_flags & P_SUBP) != 0) +/* Test if a page is dirty */ +#define IS_DIRTY(p) (((p)->mp_flags & P_DIRTY) != 0) + +#define PAGETYPE(p) ((p)->mp_flags & (P_BRANCH | P_LEAF | P_LEAF2 | P_OVERFLOW)) + +/* The number of overflow pages needed to store the given size. */ +#define OVPAGES(env, size) (bytes2pgno(env, PAGEHDRSZ - 1 + (size)) + 1) + +/* Link in MDBX_txn.mt_loose_pages list. + * Kept outside the page header, which is needed when reusing the page. */ +#define NEXT_LOOSE_PAGE(p) (*(MDBX_page **)((p) + 2)) + +/* Header for a single key/data pair within a page. + * Used in pages of type P_BRANCH and P_LEAF without P_LEAF2. + * We guarantee 2-byte alignment for 'MDBX_node's. + * + * mn_lo and mn_hi are used for data size on leaf nodes, and for child + * pgno on branch nodes. On 64 bit platforms, mn_flags is also used + * for pgno. (Branch nodes have no flags). Lo and hi are in host byte + * order in case some accesses can be optimized to 32-bit word access. + * + * Leaf node flags describe node contents. F_BIGDATA says the node's + * data part is the page number of an overflow page with actual data. + * F_DUPDATA and F_SUBDATA can be combined giving duplicate data in + * a sub-page/sub-database, and named databases (just F_SUBDATA). */ +typedef struct MDBX_node { + union { + struct { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + union { + struct { + uint16_t mn_lo, mn_hi; /* part of data size or pgno */ + }; + uint32_t mn_dsize; + }; + uint16_t mn_flags; /* see mdbx_node */ + uint16_t mn_ksize; /* key size */ +#else + uint16_t mn_ksize; /* key size */ + uint16_t mn_flags; /* see mdbx_node */ + union { + struct { + uint16_t mn_hi, mn_lo; /* part of data size or pgno */ + }; + uint32_t mn_dsize; + }; +#endif + }; + pgno_t mn_ksize_and_pgno; + }; + +/* mdbx_node Flags */ +#define F_BIGDATA 0x01 /* data put on overflow page */ +#define F_SUBDATA 0x02 /* data is a sub-database */ +#define F_DUPDATA 0x04 /* data has duplicates */ + +/* valid flags for mdbx_node_add() */ +#define NODE_ADD_FLAGS (F_DUPDATA | F_SUBDATA | MDBX_RESERVE | MDBX_APPEND) + uint8_t mn_data[1]; /* key and data are appended here */ +} MDBX_node; + +/* Size of the node header, excluding dynamic data at the end */ +#define NODESIZE offsetof(MDBX_node, mn_data) + +/* Bit position of top word in page number, for shifting mn_flags */ +#define PGNO_TOPWORD ((pgno_t)-1 > 0xffffffffu ? 32 : 0) + +/* Size of a node in a branch page with a given key. + * This is just the node header plus the key, there is no data. */ +#define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->iov_len)) + +/* Size of a node in a leaf page with a given key and data. + * This is node header plus key plus data size. */ +#define LEAFSIZE(k, d) (NODESIZE + (k)->iov_len + (d)->iov_len) + +/* Address of the key for the node */ +#define NODEKEY(node) (void *)((node)->mn_data) + +/* Address of the data for a node */ +#define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) + +/* The size of a key in a node */ +#define NODEKSZ(node) ((node)->mn_ksize) + +/* The address of a key in a LEAF2 page. + * LEAF2 pages are used for MDBX_DUPFIXED sorted-duplicate sub-DBs. + * There are no node headers, keys are stored contiguously. */ +#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i) * (ks))) + +/* Set the node's key into keyptr, if requested. */ +#define MDBX_GET_MAYNULL_KEYPTR(node, keyptr) \ + do { \ + if ((keyptr) != NULL) { \ + (keyptr)->iov_len = NODEKSZ(node); \ + (keyptr)->iov_base = NODEKEY(node); \ + } \ + } while (0) + +/* Set the node's key into key. */ +#define MDBX_GET_KEYVALUE(node, key) \ + do { \ + key.iov_len = NODEKSZ(node); \ + key.iov_base = NODEKEY(node); \ + } while (0) + +#define MDBX_VALID 0x8000 /* DB handle is valid, for me_dbflags */ +#define PERSISTENT_FLAGS (0xffff & ~(MDBX_VALID)) +/* mdbx_dbi_open() flags */ +#define VALID_FLAGS \ + (MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_INTEGERKEY | MDBX_DUPFIXED | \ + MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_CREATE) + +/* max number of pages to commit in one writev() call */ +#define MDBX_COMMIT_PAGES 64 +#if defined(IOV_MAX) && IOV_MAX < MDBX_COMMIT_PAGES /* sysconf(_SC_IOV_MAX) */ +#undef MDBX_COMMIT_PAGES +#define MDBX_COMMIT_PAGES IOV_MAX +#endif + +/* LY: fast enough on most systems + * + * / + * | -1, a < b + * cmp2int(a,b) = < 0, a == b + * | 1, a > b + * \ + */ +#if 1 +#define mdbx_cmp2int(a, b) (((b) > (a)) ? -1 : (a) > (b)) +#else +#define mdbx_cmp2int(a, b) (((a) > (b)) - ((b) > (a))) +#endif + +/* Do not spill pages to disk if txn is getting full, may fail instead */ +#define MDBX_NOSPILL 0x8000 + +static __inline pgno_t pgno_add(pgno_t base, pgno_t augend) { + assert(base <= MAX_PAGENO); + return (augend < MAX_PAGENO - base) ? base + augend : MAX_PAGENO; +} + +static __inline pgno_t pgno_sub(pgno_t base, pgno_t subtrahend) { + assert(base >= MIN_PAGENO); + return (subtrahend < base - MIN_PAGENO) ? base - subtrahend : MIN_PAGENO; +} + +static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + +/* Controls checking PID against reuse DB environment after the fork() */ +#ifndef MDBX_TXN_CHECKPID +#if defined(MADV_DONTFORK) || defined(_WIN32) || defined(_WIN64) +/* PID check could be ommited: + * - on Linux when madvise(MADV_DONTFORK) is available. i.e. after the fork() + * mapped pages will not be available for child process. + * - in Windows where fork() not available. */ +#define MDBX_TXN_CHECKPID 0 +#else +#define MDBX_TXN_CHECKPID 1 +#endif +#endif /* MDBX_TXN_CHECKPID */ diff --git a/contrib/db/libmdbx/src/defs.h b/contrib/db/libmdbx/src/defs.h new file mode 100644 index 00000000..622f1c13 --- /dev/null +++ b/contrib/db/libmdbx/src/defs.h @@ -0,0 +1,447 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once +/* *INDENT-OFF* */ +/* clang-format off */ + +#ifndef __GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) (0) +# endif +#endif /* __GNUC_PREREQ */ + +#ifndef __CLANG_PREREQ +# ifdef __clang__ +# define __CLANG_PREREQ(maj,min) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) +# else +# define __CLANG_PREREQ(maj,min) (0) +# endif +#endif /* __CLANG_PREREQ */ + +#ifndef __GLIBC_PREREQ +# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define __GLIBC_PREREQ(maj, min) \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GLIBC_PREREQ(maj, min) (0) +# endif +#endif /* __GLIBC_PREREQ */ + +#ifndef __has_attribute +# define __has_attribute(x) (0) +#endif + +#ifndef __has_feature +# define __has_feature(x) (0) +#endif + +#ifndef __has_extension +# define __has_extension(x) (0) +#endif + +#ifndef __has_builtin +# define __has_builtin(x) (0) +#endif + +#ifndef __has_warning +# define __has_warning(x) (0) +#endif + +#ifndef __has_include +# define __has_include(x) (0) +#endif + +#if __has_feature(thread_sanitizer) +# define __SANITIZE_THREAD__ 1 +#endif + +#if __has_feature(address_sanitizer) +# define __SANITIZE_ADDRESS__ 1 +#endif + +/*----------------------------------------------------------------------------*/ + +#ifndef __extern_C +# ifdef __cplusplus +# define __extern_C extern "C" +# else +# define __extern_C +# endif +#endif /* __extern_C */ + +#ifndef __cplusplus +# ifndef bool +# define bool _Bool +# endif +# ifndef true +# define true (1) +# endif +# ifndef false +# define false (0) +# endif +#endif + +#if !defined(nullptr) && !defined(__cplusplus) || (__cplusplus < 201103L && !defined(_MSC_VER)) +# define nullptr NULL +#endif + +/*----------------------------------------------------------------------------*/ + +#ifndef __always_inline +# if defined(__GNUC__) || __has_attribute(__always_inline__) +# define __always_inline __inline __attribute__((__always_inline__)) +# elif defined(_MSC_VER) +# define __always_inline __forceinline +# else +# define __always_inline +# endif +#endif /* __always_inline */ + +#ifndef __noinline +# if defined(__GNUC__) || __has_attribute(__noinline__) +# define __noinline __attribute__((__noinline__)) +# elif defined(_MSC_VER) +# define __noinline __declspec(noinline) +# elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) +# define __noinline inline +# elif !defined(__INTEL_COMPILER) +# define __noinline /* FIXME ? */ +# endif +#endif /* __noinline */ + +#ifndef __must_check_result +# if defined(__GNUC__) || __has_attribute(__warn_unused_result__) +# define __must_check_result __attribute__((__warn_unused_result__)) +# else +# define __must_check_result +# endif +#endif /* __must_check_result */ + +#ifndef __deprecated +# if defined(__GNUC__) || __has_attribute(__deprecated__) +# define __deprecated __attribute__((__deprecated__)) +# elif defined(_MSC_VER) +# define __deprecated __declspec(deprecated) +# else +# define __deprecated +# endif +#endif /* __deprecated */ + +#if !defined(__noop) && !defined(_MSC_VER) +# ifdef __cplusplus + static inline void __noop_consume_args() {} + template + static inline void + __noop_consume_args(const First &first, const Rest &... rest) { + (void) first; __noop_consume_args(rest...); + } +# define __noop(...) __noop_consume_args(__VA_ARGS__) +# elif defined(__GNUC__) && (!defined(__STRICT_ANSI__) || !__STRICT_ANSI__) + static __inline void __noop_consume_args(void* anchor, ...) { + (void) anchor; + } +# define __noop(...) __noop_consume_args(0, ##__VA_ARGS__) +# else +# define __noop(...) do {} while(0) +# endif +#endif /* __noop */ + +#ifndef __fallthrough +# if __GNUC_PREREQ(7, 0) || __has_attribute(__fallthrough__) +# define __fallthrough __attribute__((__fallthrough__)) +# else +# define __fallthrough __noop() +# endif +#endif /* __fallthrough */ + +#ifndef __unreachable +# if __GNUC_PREREQ(4,5) +# define __unreachable() __builtin_unreachable() +# elif defined(_MSC_VER) +# define __unreachable() __assume(0) +# else +# define __unreachable() __noop() +# endif +#endif /* __unreachable */ + +#ifndef __prefetch +# if defined(__GNUC__) || defined(__clang__) +# define __prefetch(ptr) __builtin_prefetch(ptr) +# else +# define __prefetch(ptr) __noop(ptr) +# endif +#endif /* __prefetch */ + +#ifndef __noreturn +# if defined(__GNUC__) || __has_attribute(__noreturn__) +# define __noreturn __attribute__((__noreturn__)) +# elif defined(_MSC_VER) +# define __noreturn __declspec(noreturn) +# else +# define __noreturn +# endif +#endif /* __noreturn */ + +#ifndef __nothrow +# if defined(__cplusplus) +# if __cplusplus < 201703L +# define __nothrow throw() +# else +# define __nothrow noexcept(true) +# endif /* __cplusplus */ +# elif defined(__GNUC__) || __has_attribute(__nothrow__) +# define __nothrow __attribute__((__nothrow__)) +# elif defined(_MSC_VER) && defined(__cplusplus) +# define __nothrow __declspec(nothrow) +# else +# define __nothrow +# endif +#endif /* __nothrow */ + +#ifndef __pure_function + /* Many functions have no effects except the return value and their + * return value depends only on the parameters and/or global variables. + * Such a function can be subject to common subexpression elimination + * and loop optimization just as an arithmetic operator would be. + * These functions should be declared with the attribute pure. */ +# if defined(__GNUC__) || __has_attribute(__pure__) +# define __pure_function __attribute__((__pure__)) +# else +# define __pure_function +# endif +#endif /* __pure_function */ + +#ifndef __const_function + /* Many functions do not examine any values except their arguments, + * and have no effects except the return value. Basically this is just + * slightly more strict class than the PURE attribute, since function + * is not allowed to read global memory. + * + * Note that a function that has pointer arguments and examines the + * data pointed to must not be declared const. Likewise, a function + * that calls a non-const function usually must not be const. + * It does not make sense for a const function to return void. */ +# if defined(__GNUC__) || __has_attribute(__const__) +# define __const_function __attribute__((__const__)) +# else +# define __const_function +# endif +#endif /* __const_function */ + +#ifndef __hidden +# if defined(__GNUC__) || __has_attribute(__visibility__) +# define __hidden __attribute__((__visibility__("hidden"))) +# else +# define __hidden +# endif +#endif /* __hidden */ + +#ifndef __optimize +# if defined(__OPTIMIZE__) +# if defined(__clang__) && !__has_attribute(__optimize__) +# define __optimize(ops) +# elif defined(__GNUC__) || __has_attribute(__optimize__) +# define __optimize(ops) __attribute__((__optimize__(ops))) +# else +# define __optimize(ops) +# endif +# else +# define __optimize(ops) +# endif +#endif /* __optimize */ + +#ifndef __hot +# if defined(__OPTIMIZE__) +# if defined(__e2k__) +# define __hot __attribute__((__hot__)) __optimize(3) +# elif defined(__clang__) && !__has_attribute(__hot_) \ + && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__)) + /* just put frequently used functions in separate section */ +# define __hot __attribute__((__section__("text.hot"))) __optimize("O3") +# elif defined(__GNUC__) || __has_attribute(__hot__) +# define __hot __attribute__((__hot__)) __optimize("O3") +# else +# define __hot __optimize("O3") +# endif +# else +# define __hot +# endif +#endif /* __hot */ + +#ifndef __cold +# if defined(__OPTIMIZE__) +# if defined(__e2k__) +# define __cold __attribute__((__cold__)) __optimize(1) +# elif defined(__clang__) && !__has_attribute(cold) \ + && __has_attribute(__section__) && (defined(__linux__) || defined(__gnu_linux__)) + /* just put infrequently used functions in separate section */ +# define __cold __attribute__((__section__("text.unlikely"))) __optimize("Os") +# elif defined(__GNUC__) || __has_attribute(cold) +# define __cold __attribute__((__cold__)) __optimize("Os") +# else +# define __cold __optimize("Os") +# endif +# else +# define __cold +# endif +#endif /* __cold */ + +#ifndef __flatten +# if defined(__OPTIMIZE__) && (defined(__GNUC__) || __has_attribute(__flatten__)) +# define __flatten __attribute__((__flatten__)) +# else +# define __flatten +# endif +#endif /* __flatten */ + +#ifndef likely +# if (defined(__GNUC__) || defined(__clang__)) && !defined(__COVERITY__) +# define likely(cond) __builtin_expect(!!(cond), 1) +# else +# define likely(x) (x) +# endif +#endif /* likely */ + +#ifndef unlikely +# if (defined(__GNUC__) || defined(__clang__)) && !defined(__COVERITY__) +# define unlikely(cond) __builtin_expect(!!(cond), 0) +# else +# define unlikely(x) (x) +# endif +#endif /* unlikely */ + +/* Workaround for Coverity Scan */ +#if defined(__COVERITY__) && __GNUC_PREREQ(7, 0) && !defined(__cplusplus) +typedef float _Float32; +typedef double _Float32x; +typedef double _Float64; +typedef long double _Float64x; +typedef float _Float128 __attribute__((__mode__(__TF__))); +typedef __complex__ float __cfloat128 __attribute__ ((__mode__ (__TC__))); +typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); +#endif /* Workaround for Coverity Scan */ + +/* Wrapper around __func__, which is a C99 feature */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define mdbx_func_ __func__ +#elif (defined(__GNUC__) && __GNUC__ >= 2) || defined(__clang__) || defined(_MSC_VER) +# define mdbx_func_ __FUNCTION__ +#else +# define mdbx_func_ "" +#endif + +#if defined(__GNUC__) || __has_attribute(__format__) +#define __printf_args(format_index, first_arg) \ + __attribute__((__format__(printf, format_index, first_arg))) +#else +#define __printf_args(format_index, first_arg) +#endif + +/*----------------------------------------------------------------------------*/ + +#if defined(USE_VALGRIND) +# include +# ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE + /* LY: available since Valgrind 3.10 */ +# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# endif +#elif !defined(RUNNING_ON_VALGRIND) +# define VALGRIND_CREATE_MEMPOOL(h,r,z) +# define VALGRIND_DESTROY_MEMPOOL(h) +# define VALGRIND_MEMPOOL_TRIM(h,a,s) +# define VALGRIND_MEMPOOL_ALLOC(h,a,s) +# define VALGRIND_MEMPOOL_FREE(h,a) +# define VALGRIND_MEMPOOL_CHANGE(h,a,b,s) +# define VALGRIND_MAKE_MEM_NOACCESS(a,s) +# define VALGRIND_MAKE_MEM_DEFINED(a,s) +# define VALGRIND_MAKE_MEM_UNDEFINED(a,s) +# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,s) +# define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,s) (0) +# define VALGRIND_CHECK_MEM_IS_DEFINED(a,s) (0) +# define RUNNING_ON_VALGRIND (0) +#endif /* USE_VALGRIND */ + +#ifdef __SANITIZE_ADDRESS__ +# include +#elif !defined(ASAN_POISON_MEMORY_REGION) +# define ASAN_POISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ + ((void)(addr), (void)(size)) +#endif /* __SANITIZE_ADDRESS__ */ + +/*----------------------------------------------------------------------------*/ + +#ifndef ARRAY_LENGTH +# ifdef __cplusplus + template + char (&__ArraySizeHelper(T (&array)[N]))[N]; +# define ARRAY_LENGTH(array) (sizeof(::__ArraySizeHelper(array))) +# else +# define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) +# endif +#endif /* ARRAY_LENGTH */ + +#ifndef ARRAY_END +# define ARRAY_END(array) (&array[ARRAY_LENGTH(array)]) +#endif /* ARRAY_END */ + +#ifndef STRINGIFY +# define STRINGIFY_HELPER(x) #x +# define STRINGIFY(x) STRINGIFY_HELPER(x) +#endif /* STRINGIFY */ + +#ifndef offsetof +# define offsetof(type, member) __builtin_offsetof(type, member) +#endif /* offsetof */ + +#ifndef container_of +# define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) +#endif /* container_of */ + +#define MDBX_TETRAD(a, b, c, d) \ + ((uint32_t)(a) << 24 | (uint32_t)(b) << 16 | (uint32_t)(c) << 8 | (d)) + +#define MDBX_STRING_TETRAD(str) MDBX_TETRAD(str[0], str[1], str[2], str[3]) + +#define FIXME "FIXME: " __FILE__ ", " STRINGIFY(__LINE__) + +#ifndef STATIC_ASSERT_MSG +# if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ + || __has_feature(c_static_assert) +# define STATIC_ASSERT_MSG(expr, msg) _Static_assert(expr, msg) +# elif defined(static_assert) +# define STATIC_ASSERT_MSG(expr, msg) static_assert(expr, msg) +# elif defined(_MSC_VER) +# include +# define STATIC_ASSERT_MSG(expr, msg) _STATIC_ASSERT(expr) +# else +# define STATIC_ASSERT_MSG(expr, msg) switch (0) {case 0:case (expr):;} +# endif +#endif /* STATIC_ASSERT */ + +#ifndef STATIC_ASSERT +# define STATIC_ASSERT(expr) STATIC_ASSERT_MSG(expr, #expr) +#endif + +/* *INDENT-ON* */ +/* clang-format on */ diff --git a/contrib/db/libmdbx/src/lck-linux.c b/contrib/db/libmdbx/src/lck-linux.c new file mode 100644 index 00000000..925941b2 --- /dev/null +++ b/contrib/db/libmdbx/src/lck-linux.c @@ -0,0 +1,428 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#if !(defined(__linux__) || defined(__gnu_linux__)) +#error "This implementation of locking only supports Linux,\ + where is no interaction between the types of lock placed\ + by flock() and fcntl()." +#endif + +#include "./bits.h" +#include + +/* Some platforms define the EOWNERDEAD error code + * even though they don't support Robust Mutexes. + * Compile with -DMDBX_USE_ROBUST=0. */ +#ifndef MDBX_USE_ROBUST +/* Howard Chu: Android currently lacks Robust Mutex support */ +#if defined(EOWNERDEAD) && \ + !defined(__ANDROID__) /* LY: glibc before 2.10 has a troubles \ + with Robust Mutex too. */ \ + && (!defined(__GLIBC__) || __GLIBC_PREREQ(2, 10) || \ + _POSIX_C_SOURCE >= 200809L) +#define MDBX_USE_ROBUST 1 +#else +#define MDBX_USE_ROBUST 0 +#endif +#endif /* MDBX_USE_ROBUST */ + +/*----------------------------------------------------------------------------*/ +/* global constructor/destructor */ + +uint32_t mdbx_linux_kernel_version; +static __cold __attribute__((__constructor__)) void +mdbx_global_constructor(void) { + struct utsname buffer; + if (uname(&buffer) == 0) { + int i = 0; + char *p = buffer.release; + while (*p && i < 4) { + if (*p >= '0' && *p <= '9') { + long number = strtol(p, &p, 10); + if (number > 0) { + if (number > 255) + number = 255; + mdbx_linux_kernel_version += number << (24 - i * 8); + } + ++i; + } else { + ++p; + } + } + } + + mdbx_rthc_global_init(); +} + +static __cold __attribute__((__destructor__)) void +mdbx_global_destructor(void) { + mdbx_rthc_global_dtor(); +} + +/*----------------------------------------------------------------------------*/ +/* lck */ + +/* Описание реализации блокировок для Linux: + * + * lck-файл отображается в память, в нём организуется таблица читателей и + * размещаются совместно используемые posix-мьютексы (futex). Посредством + * этих мьютексов (см struct MDBX_lockinfo) реализуются: + * - Блокировка таблицы читателей для регистрации, + * т.е. функции mdbx_rdt_lock() и mdbx_rdt_unlock(). + * - Блокировка БД для пишущих транзакций, + * т.е. функции mdbx_txn_lock() и mdbx_txn_unlock(). + * + * Остальной функционал реализуется отдельно посредством файловых блокировок: + * - Первоначальный захват БД в режиме exclusive/shared и последующий перевод + * в операционный режим, функции mdbx_lck_seize() и mdbx_lck_downgrade(). + * - Проверка присутствие процессов-читателей, + * т.е. функции mdbx_rpid_set(), mdbx_rpid_clear() и mdbx_rpid_check(). + * + * Используется два вида файловых блокировок flock() и fcntl(F_SETLK), + * как для lck-файла, так и для основного файла БД: + * - Для контроля процессов-читателей используются однобайтовые + * range-блокировки lck-файла посредством fcntl(F_SETLK). При этом + * в качестве позиции используется pid процесса-читателя. + * - Для первоначального захвата и shared/exclusive блокировок используется + * комбинация flock() и fcntl(F_SETLK) блокировки одного байта lck-файла + * в нулевой позиции (нулевая позиция не используется механизмом контроля + * процессов-читателей, так как pid пользовательского процесса в Linux + * всегда больше 0). + * - Кроме этого, flock() блокировка основного файла БД используется при работе + * в режимах без lck-файла, как в в read-only, так и в эксклюзивном. + * - Блокировки flock() и fcntl(F_SETLK) в Linux работают независимо. Поэтому + * их комбинирование позволяет предотвратить совместное использование БД + * через NFS, что позволяет fcntl(F_SETLK), одновременно защитившись + * от проблем не-аторманости flock() при переходе между эксклюзивным + * и атомарным режимами блокировок. + */ + +static int op_setlk, op_setlkw, op_getlk; +static void __cold choice_fcntl() { + assert(!op_setlk && !op_setlkw && !op_getlk); +#if defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && defined(F_OFD_GETLK) + if (mdbx_linux_kernel_version > + 0x030f0000 /* OFD locks are available since 3.15, but engages here + only for 3.16 and larer kernels (LTS) for reliability reasons */ + && (mdbx_runtime_flags & MDBX_DBG_LEGACY_MULTIOPEN) == 0) { + op_setlk = F_OFD_SETLK; + op_setlkw = F_OFD_SETLKW; + op_getlk = F_OFD_GETLK; + return; + } +#endif /* OFD locks */ + op_setlk = F_SETLK; + op_setlkw = F_SETLKW; + op_getlk = F_GETLK; +} + +#ifndef OFF_T_MAX +#define OFF_T_MAX \ + ((sizeof(off_t) > 4 ? INT64_MAX : INT32_MAX) & ~(size_t)0xffff) +#endif +#define LCK_WHOLE OFF_T_MAX + +static int mdbx_lck_op(mdbx_filehandle_t fd, int cmd, short lck, off_t offset, + off_t len) { + for (;;) { + struct flock lock_op; + memset(&lock_op, 0, sizeof(lock_op)); + lock_op.l_type = lck; + lock_op.l_whence = SEEK_SET; + lock_op.l_start = offset; + lock_op.l_len = len; + if (fcntl(fd, cmd, &lock_op) == 0) { + if (cmd == op_getlk) { + /* Checks reader by pid. Returns: + * MDBX_RESULT_TRUE - if pid is live (unable to acquire lock) + * MDBX_RESULT_FALSE - if pid is dead (lock acquired). */ + return (lock_op.l_type == F_UNLCK) ? MDBX_RESULT_FALSE + : MDBX_RESULT_TRUE; + } + return 0; + } + int rc = errno; + if (rc != EINTR || cmd == op_setlkw) + return rc; + } +} + +static __inline int mdbx_lck_exclusive(int lfd, bool fallback2shared) { + assert(lfd != INVALID_HANDLE_VALUE); + if (flock(lfd, LOCK_EX | LOCK_NB)) + return errno; + int rc = mdbx_lck_op(lfd, op_setlk, F_WRLCK, 0, 1); + if (rc != 0 && fallback2shared) { + while (flock(lfd, LOCK_SH)) { + int rc = errno; + if (rc != EINTR) + return rc; + } + } + return rc; +} + +static __inline int mdbx_lck_shared(int lfd) { + assert(lfd != INVALID_HANDLE_VALUE); + while (flock(lfd, LOCK_SH)) { + int rc = errno; + if (rc != EINTR) + return rc; + } + return mdbx_lck_op(lfd, op_setlkw, F_RDLCK, 0, 1); +} + +int mdbx_lck_downgrade(MDBX_env *env, bool complete) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + return complete ? mdbx_lck_shared(env->me_lfd) : MDBX_SUCCESS; +} + +int mdbx_rpid_set(MDBX_env *env) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(env->me_pid > 0); + return mdbx_lck_op(env->me_lfd, op_setlk, F_WRLCK, env->me_pid, 1); +} + +int mdbx_rpid_clear(MDBX_env *env) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(env->me_pid > 0); + return mdbx_lck_op(env->me_lfd, op_setlkw, F_UNLCK, env->me_pid, 1); +} + +int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(pid > 0); + return mdbx_lck_op(env->me_lfd, op_getlk, F_WRLCK, pid, 1); +} + +/*---------------------------------------------------------------------------*/ + +static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, + const int rc); + +int __cold mdbx_lck_init(MDBX_env *env) { + pthread_mutexattr_t ma; + int rc = pthread_mutexattr_init(&ma); + if (rc) + return rc; + + rc = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + if (rc) + goto bailout; + +#if MDBX_USE_ROBUST +#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ + !defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L + rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP); +#else + rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); +#endif + if (rc) + goto bailout; +#endif /* MDBX_USE_ROBUST */ + +#if _POSIX_C_SOURCE >= 199506L && !defined(MDBX_SAFE4QEMU) + rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT); + if (rc == ENOTSUP) + rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE); + if (rc) + goto bailout; +#endif /* PTHREAD_PRIO_INHERIT */ + + rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + if (rc) + goto bailout; + + rc = pthread_mutex_init(&env->me_lck->mti_rmutex, &ma); + if (rc) + goto bailout; + rc = pthread_mutex_init(&env->me_lck->mti_wmutex, &ma); + +bailout: + pthread_mutexattr_destroy(&ma); + return rc; +} + +void __cold mdbx_lck_destroy(MDBX_env *env) { + if (env->me_lfd != INVALID_HANDLE_VALUE) { + /* try get exclusive access */ + if (env->me_lck && mdbx_lck_exclusive(env->me_lfd, false) == 0) { + mdbx_info("%s: got exclusive, drown mutexes", mdbx_func_); + int rc = pthread_mutex_destroy(&env->me_lck->mti_rmutex); + if (rc == 0) + rc = pthread_mutex_destroy(&env->me_lck->mti_wmutex); + assert(rc == 0); + (void)rc; + /* file locks would be released (by kernel) + * while the me_lfd will be closed */ + } + } +} + +static int mdbx_robust_lock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_lock(mutex); + if (unlikely(rc != 0)) + rc = mdbx_mutex_failed(env, mutex, rc); + return rc; +} + +static int mdbx_robust_trylock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_trylock(mutex); + if (unlikely(rc != 0 && rc != EBUSY)) + rc = mdbx_mutex_failed(env, mutex, rc); + return (rc != EBUSY) ? rc : MDBX_BUSY; +} + +static int mdbx_robust_unlock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_unlock(mutex); + if (unlikely(rc != 0)) + rc = mdbx_mutex_failed(env, mutex, rc); + return rc; +} + +int mdbx_rdt_lock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_lock(env, &env->me_lck->mti_rmutex); + mdbx_trace("<< rc %d", rc); + return rc; +} + +void mdbx_rdt_unlock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_unlock(env, &env->me_lck->mti_rmutex); + mdbx_trace("<< rc %d", rc); + if (unlikely(MDBX_IS_ERROR(rc))) + mdbx_panic("%s() failed: errcode %d\n", mdbx_func_, rc); +} + +int mdbx_txn_lock(MDBX_env *env, bool dontwait) { + mdbx_trace(">>"); + int rc = dontwait ? mdbx_robust_trylock(env, env->me_wmutex) + : mdbx_robust_lock(env, env->me_wmutex); + mdbx_trace("<< rc %d", rc); + return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS; +} + +void mdbx_txn_unlock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_unlock(env, env->me_wmutex); + mdbx_trace("<< rc %d", rc); + if (unlikely(MDBX_IS_ERROR(rc))) + mdbx_panic("%s() failed: errcode %d\n", mdbx_func_, rc); +} + +static int __cold internal_seize_lck(int lfd) { + assert(lfd != INVALID_HANDLE_VALUE); + + /* try exclusive access */ + int rc = mdbx_lck_exclusive(lfd, false); + if (rc == 0) + /* got exclusive */ + return MDBX_RESULT_TRUE; + if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK) { + /* get shared access */ + rc = mdbx_lck_shared(lfd); + if (rc == 0) { + /* got shared, try exclusive again */ + rc = mdbx_lck_exclusive(lfd, true); + if (rc == 0) + /* now got exclusive */ + return MDBX_RESULT_TRUE; + if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK) + /* unable exclusive, but stay shared */ + return MDBX_RESULT_FALSE; + } + } + assert(MDBX_IS_ERROR(rc)); + return rc; +} + +int __cold mdbx_lck_seize(MDBX_env *env) { + assert(env->me_fd != INVALID_HANDLE_VALUE); + if (unlikely(op_setlk == 0)) + choice_fcntl(); + + if (env->me_lfd == INVALID_HANDLE_VALUE) { + /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ + int rc = mdbx_lck_op(env->me_fd, op_setlk, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, + LCK_WHOLE); + if (rc != 0) { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc); + return rc; + } + return MDBX_RESULT_TRUE; + } + + if ((env->me_flags & MDBX_RDONLY) == 0) { + /* Check that another process don't operates in without-lck mode. */ + int rc = mdbx_lck_op(env->me_fd, op_setlk, F_WRLCK, env->me_pid, 1); + if (rc != 0) { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "lock-against-without-lck", rc); + return rc; + } + } + + return internal_seize_lck(env->me_lfd); +} + +static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, + const int err) { + int rc = err; +#if MDBX_USE_ROBUST + if (err == EOWNERDEAD) { + /* We own the mutex. Clean up after dead previous owner. */ + + int rlocked = (env->me_lck && mutex == &env->me_lck->mti_rmutex); + rc = MDBX_SUCCESS; + if (!rlocked) { + if (unlikely(env->me_txn)) { + /* env is hosed if the dead thread was ours */ + env->me_flags |= MDBX_FATAL_ERROR; + env->me_txn = NULL; + rc = MDBX_PANIC; + } + } + mdbx_notice("%cmutex owner died, %s", (rlocked ? 'r' : 'w'), + (rc ? "this process' env is hosed" : "recovering")); + + int check_rc = mdbx_reader_check0(env, rlocked, NULL); + check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc; + +#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ + !defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L + int mreco_rc = pthread_mutex_consistent_np(mutex); +#else + int mreco_rc = pthread_mutex_consistent(mutex); +#endif + check_rc = (mreco_rc == 0) ? check_rc : mreco_rc; + + if (unlikely(mreco_rc)) + mdbx_error("mutex recovery failed, %s", mdbx_strerror(mreco_rc)); + + rc = (rc == MDBX_SUCCESS) ? check_rc : rc; + if (MDBX_IS_ERROR(rc)) + pthread_mutex_unlock(mutex); + return rc; + } +#else + (void)mutex; +#endif /* MDBX_USE_ROBUST */ + + mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err)); + if (rc != EDEADLK) + env->me_flags |= MDBX_FATAL_ERROR; + return rc; +} diff --git a/contrib/db/libmdbx/src/lck-posix.c b/contrib/db/libmdbx/src/lck-posix.c new file mode 100644 index 00000000..3b931579 --- /dev/null +++ b/contrib/db/libmdbx/src/lck-posix.c @@ -0,0 +1,389 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "./bits.h" + +/* Some platforms define the EOWNERDEAD error code + * even though they don't support Robust Mutexes. + * Compile with -DMDBX_USE_ROBUST=0. */ +#ifndef MDBX_USE_ROBUST +#if (defined(EOWNERDEAD) || _POSIX_C_SOURCE >= 200809L) && !defined(__APPLE__) +#define MDBX_USE_ROBUST 1 +#else +#define MDBX_USE_ROBUST 0 +#endif +#endif /* MDBX_USE_ROBUST */ + +/*----------------------------------------------------------------------------*/ +/* rthc */ + +static __cold __attribute__((__constructor__)) void +mdbx_global_constructor(void) { + mdbx_rthc_global_init(); +} + +static __cold __attribute__((__destructor__)) void +mdbx_global_destructor(void) { + mdbx_rthc_global_dtor(); +} + +/*----------------------------------------------------------------------------*/ +/* lck */ + +/* Описание реализации блокировок для POSIX: + * + * lck-файл отображается в память, в нём организуется таблица читателей и + * размещаются совместно используемые posix-мьютексы (futex). Посредством + * этих мьютексов (см struct MDBX_lockinfo) реализуются: + * - Блокировка таблицы читателей для регистрации, + * т.е. функции mdbx_rdt_lock() и mdbx_rdt_unlock(). + * - Блокировка БД для пишущих транзакций, + * т.е. функции mdbx_txn_lock() и mdbx_txn_unlock(). + * + * Остальной функционал реализуется отдельно посредством файловых блокировок: + * - Первоначальный захват БД в режиме exclusive/shared и последующий перевод + * в операционный режим, функции mdbx_lck_seize() и mdbx_lck_downgrade(). + * - Проверка присутствие процессов-читателей, + * т.е. функции mdbx_rpid_set(), mdbx_rpid_clear() и mdbx_rpid_check(). + * + * Для блокировки файлов Используется только fcntl(F_SETLK), так как: + * - lockf() оперирует только эксклюзивной блокировкой и требует + * открытия файла в RW-режиме. + * - flock() не гарантирует атомарности при смене блокировок + * и оперирует только всем файлом целиком. + * - Для контроля процессов-читателей используются однобайтовые + * range-блокировки lck-файла посредством fcntl(F_SETLK). При этом + * в качестве позиции используется pid процесса-читателя. + * - Для первоначального захвата и shared/exclusive выполняется блокировка + * основного файла БД и при успехе lck-файла. + */ + +#ifndef OFF_T_MAX +#define OFF_T_MAX \ + ((sizeof(off_t) > 4 ? INT64_MAX : INT32_MAX) & ~(size_t)0xffff) +#endif +#ifndef PID_T_MAX +#define PID_T_MAX INT_MAX +#endif + +#if defined(F_OFD_SETLK) && defined(F_OFD_SETLKW) && defined(F_OFD_GETLK) +#define OP_SETLK F_OFD_SETLK +#define OP_SETLKW F_OFD_SETLKW +#define OP_GETLK F_OFD_GETLK +#else +#define OP_SETLK F_SETLK +#define OP_SETLKW F_SETLKW +#define OP_GETLK F_GETLK +#endif /* OFD locks */ + +static int mdbx_lck_op(mdbx_filehandle_t fd, int cmd, short lck, off_t offset, + off_t len) { + for (;;) { + struct flock lock_op; + memset(&lock_op, 0, sizeof(lock_op)); + lock_op.l_type = lck; + lock_op.l_whence = SEEK_SET; + lock_op.l_start = offset; + lock_op.l_len = len; + if (fcntl(fd, cmd, &lock_op) == 0) { + if (cmd == OP_GETLK) { + /* Checks reader by pid. Returns: + * MDBX_RESULT_TRUE - if pid is live (unable to acquire lock) + * MDBX_RESULT_FALSE - if pid is dead (lock acquired). */ + return (lock_op.l_type == F_UNLCK) ? MDBX_RESULT_FALSE + : MDBX_RESULT_TRUE; + } + return 0; + } + int rc = errno; + if (rc != EINTR || cmd == F_SETLKW) + return rc; + } +} + +int mdbx_rpid_set(MDBX_env *env) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(env->me_pid > 0 && env->me_pid <= PID_T_MAX); + return mdbx_lck_op(env->me_lfd, OP_SETLK, F_WRLCK, env->me_pid, 1); +} + +int mdbx_rpid_clear(MDBX_env *env) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(env->me_pid > 0 && env->me_pid <= PID_T_MAX); + return mdbx_lck_op(env->me_lfd, OP_SETLKW, F_UNLCK, env->me_pid, 1); +} + +int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + assert(pid > 0 && pid <= PID_T_MAX); + assert(PID_T_MAX < OFF_T_MAX); + return mdbx_lck_op(env->me_lfd, OP_GETLK, F_WRLCK, pid, 1); +} + +int __cold mdbx_lck_seize(MDBX_env *env) { + assert(env->me_fd != INVALID_HANDLE_VALUE); + assert(env->me_pid > 0 && env->me_pid <= PID_T_MAX); + + if (env->me_lfd == INVALID_HANDLE_VALUE) { + /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ + int rc = mdbx_lck_op(env->me_fd, OP_SETLK, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, + OFF_T_MAX); + if (rc != 0) { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc); + return rc; + } + return MDBX_RESULT_TRUE; + } + + /* try exclusive access */ + int rc = mdbx_lck_op(env->me_fd, OP_SETLK, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, + OFF_T_MAX); + if (rc == 0) { + continue_exclusive: + /* got dxb-exclusive, continue lck-exclusive */ + rc = mdbx_lck_op(env->me_lfd, OP_SETLKW, F_WRLCK, 0, OFF_T_MAX); + if (rc == 0) { + /* got both exclusive */ + return MDBX_RESULT_TRUE; + } + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "lck-after-dxb-exclusive", rc); + assert(MDBX_IS_ERROR(rc)); + goto bailout; + } + + if (rc == EAGAIN || rc == EACCES || rc == EBUSY || rc == EWOULDBLOCK) { + rc = mdbx_lck_op(env->me_fd, OP_SETLKW, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, + env->me_pid, 1); + if (rc == 0) { + /* got dxb-shared, try again dxb-exclusive */ + rc = mdbx_lck_op(env->me_fd, OP_SETLK, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, + OFF_T_MAX); + if (rc == 0) + goto continue_exclusive; + + /* continue lck-shared */ + rc = mdbx_lck_op(env->me_lfd, OP_SETLKW, F_RDLCK, 0, 1); + if (rc == 0) { + /* got both dxb and lck shared lock */ + return MDBX_RESULT_FALSE; + } + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "lck-shared", rc); + } else { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "dxb-shared", rc); + } + assert(MDBX_IS_ERROR(rc)); + } + +bailout: + (void)mdbx_lck_op(env->me_lfd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); + (void)mdbx_lck_op(env->me_fd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); + assert(MDBX_IS_ERROR(rc)); + return rc; +} + +int mdbx_lck_downgrade(MDBX_env *env, bool complete) { + assert(env->me_lfd != INVALID_HANDLE_VALUE); + int rc = mdbx_lck_op(env->me_lfd, OP_SETLK, F_UNLCK, 1, OFF_T_MAX - 1); + if (rc == 0) + rc = mdbx_lck_op(env->me_lfd, OP_SETLKW, F_RDLCK, 0, 1); + if (unlikely(rc != 0)) { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "lck", rc); + goto bailout; + } + if (complete) { + rc = mdbx_lck_op(env->me_fd, OP_SETLK, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, + env->me_pid, 1); + if (unlikely(rc != 0)) { + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "dxb", rc); + goto bailout; + } + } + return MDBX_SUCCESS; + +bailout: + (void)mdbx_lck_op(env->me_lfd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); + (void)mdbx_lck_op(env->me_fd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); + assert(MDBX_IS_ERROR(rc)); + return rc; +} + +/*---------------------------------------------------------------------------*/ + +static int mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, + const int rc); + +int __cold mdbx_lck_init(MDBX_env *env) { + pthread_mutexattr_t ma; + int rc = pthread_mutexattr_init(&ma); + if (rc) + return rc; + + rc = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); + if (rc) + goto bailout; + +#if MDBX_USE_ROBUST + rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); + if (rc) + goto bailout; +#endif /* MDBX_USE_ROBUST */ + +#if _POSIX_C_SOURCE >= 199506L && !defined(MDBX_SAFE4QEMU) + rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT); + if (rc == ENOTSUP) + rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE); + if (rc) + goto bailout; +#endif /* PTHREAD_PRIO_INHERIT */ + + rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + if (rc) + goto bailout; + + rc = pthread_mutex_init(&env->me_lck->mti_rmutex, &ma); + if (rc) + goto bailout; + rc = pthread_mutex_init(&env->me_lck->mti_wmutex, &ma); + +bailout: + pthread_mutexattr_destroy(&ma); + return rc; +} + +void __cold mdbx_lck_destroy(MDBX_env *env) { + /* File locks would be released (by kernel) while the file-descriptors + * will be closed. But to avoid false-positive EDEADLK from the kernel, + * locks should be released here explicitly with properly order. */ + if (env->me_lfd != INVALID_HANDLE_VALUE) { + /* try get exclusive access */ + if (env->me_lck && + mdbx_lck_op(env->me_fd, OP_SETLK, + (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, + OFF_T_MAX) == 0 && + mdbx_lck_op(env->me_lfd, OP_SETLK, F_WRLCK, 0, OFF_T_MAX) == 0) { + mdbx_info("%s: got exclusive, drown mutexes", mdbx_func_); + int rc = pthread_mutex_destroy(&env->me_lck->mti_rmutex); + if (rc == 0) + rc = pthread_mutex_destroy(&env->me_lck->mti_wmutex); + assert(rc == 0); + (void)rc; + msync(env->me_lck, env->me_os_psize, MS_ASYNC); + } + (void)mdbx_lck_op(env->me_lfd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); + } + if (env->me_fd != INVALID_HANDLE_VALUE) + (void)mdbx_lck_op(env->me_fd, OP_SETLK, F_UNLCK, 0, OFF_T_MAX); +} + +static int mdbx_robust_lock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_lock(mutex); + if (unlikely(rc != 0)) + rc = mdbx_mutex_failed(env, mutex, rc); + return rc; +} + +static int mdbx_robust_trylock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_trylock(mutex); + if (unlikely(rc != 0 && rc != EBUSY)) + rc = mdbx_mutex_failed(env, mutex, rc); + return (rc != EBUSY) ? rc : MDBX_BUSY; +} + +static int mdbx_robust_unlock(MDBX_env *env, pthread_mutex_t *mutex) { + int rc = pthread_mutex_unlock(mutex); + if (unlikely(rc != 0)) + rc = mdbx_mutex_failed(env, mutex, rc); + return rc; +} + +int mdbx_rdt_lock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_lock(env, &env->me_lck->mti_rmutex); + mdbx_trace("<< rc %d", rc); + return rc; +} + +void mdbx_rdt_unlock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_unlock(env, &env->me_lck->mti_rmutex); + mdbx_trace("<< rc %d", rc); + if (unlikely(MDBX_IS_ERROR(rc))) + mdbx_panic("%s() failed: errcode %d\n", mdbx_func_, rc); +} + +int mdbx_txn_lock(MDBX_env *env, bool dontwait) { + mdbx_trace(">>"); + int rc = dontwait ? mdbx_robust_trylock(env, env->me_wmutex) + : mdbx_robust_lock(env, env->me_wmutex); + mdbx_trace("<< rc %d", rc); + return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS; +} + +void mdbx_txn_unlock(MDBX_env *env) { + mdbx_trace(">>"); + int rc = mdbx_robust_unlock(env, env->me_wmutex); + mdbx_trace("<< rc %d", rc); + if (unlikely(MDBX_IS_ERROR(rc))) + mdbx_panic("%s() failed: errcode %d\n", mdbx_func_, rc); +} + +static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, + const int err) { + int rc = err; +#if MDBX_USE_ROBUST + if (err == EOWNERDEAD) { + /* We own the mutex. Clean up after dead previous owner. */ + + int rlocked = (env->me_lck && mutex == &env->me_lck->mti_rmutex); + rc = MDBX_SUCCESS; + if (!rlocked) { + if (unlikely(env->me_txn)) { + /* env is hosed if the dead thread was ours */ + env->me_flags |= MDBX_FATAL_ERROR; + env->me_txn = NULL; + rc = MDBX_PANIC; + } + } + mdbx_notice("%cmutex owner died, %s", (rlocked ? 'r' : 'w'), + (rc ? "this process' env is hosed" : "recovering")); + + int check_rc = mdbx_reader_check0(env, rlocked, NULL); + check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc; + + int mreco_rc = pthread_mutex_consistent(mutex); + check_rc = (mreco_rc == 0) ? check_rc : mreco_rc; + + if (unlikely(mreco_rc)) + mdbx_error("mutex recovery failed, %s", mdbx_strerror(mreco_rc)); + + rc = (rc == MDBX_SUCCESS) ? check_rc : rc; + if (MDBX_IS_ERROR(rc)) + pthread_mutex_unlock(mutex); + return rc; + } +#else + (void)mutex; +#endif /* MDBX_USE_ROBUST */ + + mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err)); + if (rc != EDEADLK) + env->me_flags |= MDBX_FATAL_ERROR; + return rc; +} diff --git a/contrib/db/libmdbx/src/lck-windows.c b/contrib/db/libmdbx/src/lck-windows.c new file mode 100644 index 00000000..34a6e5a5 --- /dev/null +++ b/contrib/db/libmdbx/src/lck-windows.c @@ -0,0 +1,707 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "./bits.h" + +/* PREAMBLE FOR WINDOWS: + * + * We are not concerned for performance here. + * If you are running Windows a performance could NOT be the goal. + * Otherwise please use Linux. + * + * Regards, + * LY + */ + +static void mdbx_winnt_import(void); + +#ifdef MDBX_BUILD_DLL +/* DEBUG/CHECKED builds still require MSVC's CRT for runtime checks. + * + * Therefore we don't define dll's entry point for debug/checked builds by MSVC. + * In this case MSVC's will automatically use DllMainCRTStartup() from CRT + * library, which also automatically call DllMain() from our mdbx.dll + * + * On the other side, for RELEASE builds + * we explicitly define DllMain() as the entry point and don't linking with + * any CRT libraries (IgnoreAllDefaultLibraries = Yes). */ +#if !defined(_MSC_VER) || defined(NDEBUG) +#pragma comment(linker, "/ENTRY:DllMain") +#endif + +BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID reserved) +#else +#if !MDBX_CONFIG_MANUAL_TLS_CALLBACK +static +#endif /* !MDBX_CONFIG_MANUAL_TLS_CALLBACK */ + void NTAPI + mdbx_dll_callback(PVOID module, DWORD reason, PVOID reserved) +#endif /* MDBX_BUILD_DLL */ +{ + (void)reserved; + switch (reason) { + case DLL_PROCESS_ATTACH: + mdbx_winnt_import(); + mdbx_rthc_global_init(); + break; + case DLL_PROCESS_DETACH: + mdbx_rthc_global_dtor(); + break; + + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + mdbx_rthc_thread_dtor(module); + break; + } +#ifdef MDBX_BUILD_DLL + return TRUE; +#endif +} + +#if !defined(MDBX_BUILD_DLL) && !MDBX_CONFIG_MANUAL_TLS_CALLBACK +/* *INDENT-OFF* */ +/* clang-format off */ +#if defined(_MSC_VER) +# pragma const_seg(push) +# pragma data_seg(push) + +# ifdef _WIN64 + /* kick a linker to create the TLS directory if not already done */ +# pragma comment(linker, "/INCLUDE:_tls_used") + /* Force some symbol references. */ +# pragma comment(linker, "/INCLUDE:mdbx_tls_anchor") + /* specific const-segment for WIN64 */ +# pragma const_seg(".CRT$XLB") + const +# else + /* kick a linker to create the TLS directory if not already done */ +# pragma comment(linker, "/INCLUDE:__tls_used") + /* Force some symbol references. */ +# pragma comment(linker, "/INCLUDE:_mdbx_tls_anchor") + /* specific data-segment for WIN32 */ +# pragma data_seg(".CRT$XLB") +# endif + + __declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK mdbx_tls_anchor = mdbx_dll_callback; +# pragma data_seg(pop) +# pragma const_seg(pop) + +#elif defined(__GNUC__) +# ifdef _WIN64 + const +# endif + PIMAGE_TLS_CALLBACK mdbx_tls_anchor __attribute__((__section__(".CRT$XLB"), used)) = mdbx_dll_callback; +#else +# error FIXME +#endif +/* *INDENT-ON* */ +/* clang-format on */ +#endif /* !defined(MDBX_BUILD_DLL) && !MDBX_CONFIG_MANUAL_TLS_CALLBACK */ + +/*----------------------------------------------------------------------------*/ + +#define LCK_SHARED 0 +#define LCK_EXCLUSIVE LOCKFILE_EXCLUSIVE_LOCK +#define LCK_WAITFOR 0 +#define LCK_DONTWAIT LOCKFILE_FAIL_IMMEDIATELY + +static __inline BOOL flock(mdbx_filehandle_t fd, DWORD flags, uint64_t offset, + size_t bytes) { + OVERLAPPED ov; + ov.hEvent = 0; + ov.Offset = (DWORD)offset; + ov.OffsetHigh = HIGH_DWORD(offset); + return LockFileEx(fd, flags, 0, (DWORD)bytes, HIGH_DWORD(bytes), &ov); +} + +static __inline BOOL funlock(mdbx_filehandle_t fd, uint64_t offset, + size_t bytes) { + return UnlockFile(fd, (DWORD)offset, HIGH_DWORD(offset), (DWORD)bytes, + HIGH_DWORD(bytes)); +} + +/*----------------------------------------------------------------------------*/ +/* global `write` lock for write-txt processing, + * exclusive locking both meta-pages) */ + +#define LCK_MAXLEN (1u + (size_t)(MAXSSIZE_T)) +#define LCK_META_OFFSET 0 +#define LCK_META_LEN 0x10000u +#define LCK_BODY_OFFSET LCK_META_LEN +#define LCK_BODY_LEN (LCK_MAXLEN - LCK_BODY_OFFSET) +#define LCK_META LCK_META_OFFSET, LCK_META_LEN +#define LCK_BODY LCK_BODY_OFFSET, LCK_BODY_LEN +#define LCK_WHOLE 0, LCK_MAXLEN + +int mdbx_txn_lock(MDBX_env *env, bool dontwait) { + if (dontwait) { + if (!TryEnterCriticalSection(&env->me_windowsbug_lock)) + return MDBX_BUSY; + } else { + EnterCriticalSection(&env->me_windowsbug_lock); + } + + if ((env->me_flags & MDBX_EXCLUSIVE) || + flock(env->me_fd, + dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT) + : (LCK_EXCLUSIVE | LCK_WAITFOR), + LCK_BODY)) + return MDBX_SUCCESS; + int rc = GetLastError(); + LeaveCriticalSection(&env->me_windowsbug_lock); + return (!dontwait || rc != ERROR_LOCK_VIOLATION) ? rc : MDBX_BUSY; +} + +void mdbx_txn_unlock(MDBX_env *env) { + int rc = + (env->me_flags & MDBX_EXCLUSIVE) ? TRUE : funlock(env->me_fd, LCK_BODY); + LeaveCriticalSection(&env->me_windowsbug_lock); + if (!rc) + mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError()); +} + +/*----------------------------------------------------------------------------*/ +/* global `read` lock for readers registration, + * exclusive locking `mti_numreaders` (second) cacheline */ + +#define LCK_LO_OFFSET 0 +#define LCK_LO_LEN offsetof(MDBX_lockinfo, mti_numreaders) +#define LCK_UP_OFFSET LCK_LO_LEN +#define LCK_UP_LEN (sizeof(MDBX_lockinfo) - LCK_UP_OFFSET) +#define LCK_LOWER LCK_LO_OFFSET, LCK_LO_LEN +#define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN + +int mdbx_rdt_lock(MDBX_env *env) { + mdbx_srwlock_AcquireShared(&env->me_remap_guard); + if (env->me_lfd == INVALID_HANDLE_VALUE) + return MDBX_SUCCESS; /* readonly database in readonly filesystem */ + + /* transite from S-? (used) to S-E (locked), e.g. exclusive lock upper-part */ + if ((env->me_flags & MDBX_EXCLUSIVE) || + flock(env->me_lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) + return MDBX_SUCCESS; + + int rc = GetLastError(); + mdbx_srwlock_ReleaseShared(&env->me_remap_guard); + return rc; +} + +void mdbx_rdt_unlock(MDBX_env *env) { + if (env->me_lfd != INVALID_HANDLE_VALUE) { + /* transite from S-E (locked) to S-? (used), e.g. unlock upper-part */ + if ((env->me_flags & MDBX_EXCLUSIVE) == 0 && + !funlock(env->me_lfd, LCK_UPPER)) + mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError()); + } + mdbx_srwlock_ReleaseShared(&env->me_remap_guard); +} + +static int suspend_and_append(mdbx_handle_array_t **array, + const DWORD ThreadId) { + const unsigned limit = (*array)->limit; + if ((*array)->count == limit) { + void *ptr = mdbx_realloc( + (limit > ARRAY_LENGTH((*array)->handles)) + ? *array + : /* don't free initial array on the stack */ NULL, + sizeof(mdbx_handle_array_t) + + sizeof(HANDLE) * (limit * 2 - ARRAY_LENGTH((*array)->handles))); + if (!ptr) + return MDBX_ENOMEM; + if (limit == ARRAY_LENGTH((*array)->handles)) + memcpy(ptr, *array, sizeof(mdbx_handle_array_t)); + *array = (mdbx_handle_array_t *)ptr; + (*array)->limit = limit * 2; + } + + HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, + FALSE, ThreadId); + if (hThread == NULL) + return GetLastError(); + + if (SuspendThread(hThread) == -1) { + int err = GetLastError(); + DWORD ExitCode; + if (err == /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED || + !GetExitCodeThread(hThread, &ExitCode) || ExitCode != STILL_ACTIVE) + err = MDBX_SUCCESS; + CloseHandle(hThread); + return err; + } + + (*array)->handles[(*array)->count++] = hThread; + return MDBX_SUCCESS; +} + +int mdbx_suspend_threads_before_remap(MDBX_env *env, + mdbx_handle_array_t **array) { + const mdbx_pid_t CurrentTid = GetCurrentThreadId(); + int rc; + if (env->me_lck) { + /* Scan LCK for threads of the current process */ + const MDBX_reader *const begin = env->me_lck->mti_readers; + const MDBX_reader *const end = begin + env->me_lck->mti_numreaders; + const mdbx_tid_t WriteTxnOwner = env->me_txn0 ? env->me_txn0->mt_owner : 0; + for (const MDBX_reader *reader = begin; reader < end; ++reader) { + if (reader->mr_pid != env->me_pid || !reader->mr_tid) { + skip_lck: + continue; + } + if (reader->mr_tid == CurrentTid || reader->mr_tid == WriteTxnOwner) + goto skip_lck; + if (env->me_flags & MDBX_NOTLS) { + /* Skip duplicates in no-tls mode */ + for (const MDBX_reader *scan = reader; --scan >= begin;) + if (scan->mr_tid == reader->mr_tid) + goto skip_lck; + } + + rc = suspend_and_append(array, reader->mr_tid); + if (rc != MDBX_SUCCESS) { + bailout_lck: + (void)mdbx_resume_threads_after_remap(*array); + return rc; + } + } + if (WriteTxnOwner && WriteTxnOwner != CurrentTid) { + rc = suspend_and_append(array, WriteTxnOwner); + if (rc != MDBX_SUCCESS) + goto bailout_lck; + } + } else { + /* Without LCK (i.e. read-only mode). + * Walk thougth a snapshot of all running threads */ + mdbx_assert(env, + env->me_txn0 == NULL || (env->me_flags & MDBX_EXCLUSIVE) != 0); + const HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) + return GetLastError(); + + THREADENTRY32 entry; + entry.dwSize = sizeof(THREADENTRY32); + + if (!Thread32First(hSnapshot, &entry)) { + rc = GetLastError(); + bailout_toolhelp: + CloseHandle(hSnapshot); + (void)mdbx_resume_threads_after_remap(*array); + return rc; + } + + do { + if (entry.th32OwnerProcessID != env->me_pid || + entry.th32ThreadID == CurrentTid) + continue; + + rc = suspend_and_append(array, entry.th32ThreadID); + if (rc != MDBX_SUCCESS) + goto bailout_toolhelp; + + } while (Thread32Next(hSnapshot, &entry)); + + rc = GetLastError(); + if (rc != ERROR_NO_MORE_FILES) + goto bailout_toolhelp; + CloseHandle(hSnapshot); + } + + return MDBX_SUCCESS; +} + +int mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) { + int rc = MDBX_SUCCESS; + for (unsigned i = 0; i < array->count; ++i) { + const HANDLE hThread = array->handles[i]; + if (ResumeThread(hThread) == -1) { + const int err = GetLastError(); + DWORD ExitCode; + if (err != /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED && + GetExitCodeThread(hThread, &ExitCode) && ExitCode == STILL_ACTIVE) + rc = err; + } + CloseHandle(hThread); + } + return rc; +} + +/*----------------------------------------------------------------------------*/ +/* global `initial` lock for lockfile initialization, + * exclusive/shared locking first cacheline */ + +/* FIXME: locking schema/algo descritpion. + ?-? = free + S-? = used + E-? = exclusive-read + ?-S + ?-E = middle + S-S + S-E = locked + E-S + E-E = exclusive-write +*/ + +int mdbx_lck_init(MDBX_env *env) { + (void)env; + return MDBX_SUCCESS; +} + +/* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE) + * or as 'used' (S-? and returns MDBX_RESULT_FALSE), otherwise returns an error + */ +static int internal_seize_lck(HANDLE lfd) { + int rc; + assert(lfd != INVALID_HANDLE_VALUE); + + /* 1) now on ?-? (free), get ?-E (middle) */ + mdbx_jitter4testing(false); + if (!flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) { + rc = GetLastError() /* 2) something went wrong, give up */; + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "?-?(free) >> ?-E(middle)", rc); + return rc; + } + + /* 3) now on ?-E (middle), try E-E (exclusive-write) */ + mdbx_jitter4testing(false); + if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER)) + return MDBX_RESULT_TRUE /* 4) got E-E (exclusive-write), done */; + + /* 5) still on ?-E (middle) */ + rc = GetLastError(); + mdbx_jitter4testing(false); + if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) { + /* 6) something went wrong, give up */ + if (!funlock(lfd, LCK_UPPER)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "?-E(middle) >> ?-?(free)", GetLastError()); + return rc; + } + + /* 7) still on ?-E (middle), try S-E (locked) */ + mdbx_jitter4testing(false); + rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER) ? MDBX_RESULT_FALSE + : GetLastError(); + + mdbx_jitter4testing(false); + if (rc != MDBX_RESULT_FALSE) + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "?-E(middle) >> S-E(locked)", rc); + + /* 8) now on S-E (locked) or still on ?-E (middle), + * transite to S-? (used) or ?-? (free) */ + if (!funlock(lfd, LCK_UPPER)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "X-E(locked/middle) >> X-?(used/free)", GetLastError()); + + /* 9) now on S-? (used, DONE) or ?-? (free, FAILURE) */ + return rc; +} + +int mdbx_lck_seize(MDBX_env *env) { + int rc; + + assert(env->me_fd != INVALID_HANDLE_VALUE); + if (env->me_flags & MDBX_EXCLUSIVE) + return MDBX_RESULT_TRUE /* nope since files were must be opened + non-shareable */ + ; + + if (env->me_lfd == INVALID_HANDLE_VALUE) { + /* LY: without-lck mode (e.g. on read-only filesystem) */ + mdbx_jitter4testing(false); + if (!flock(env->me_fd, LCK_SHARED | LCK_DONTWAIT, LCK_WHOLE)) { + rc = GetLastError(); + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc); + return rc; + } + return MDBX_RESULT_FALSE; + } + + rc = internal_seize_lck(env->me_lfd); + mdbx_jitter4testing(false); + if (rc == MDBX_RESULT_TRUE && (env->me_flags & MDBX_RDONLY) == 0) { + /* Check that another process don't operates in without-lck mode. + * Doing such check by exclusive locking the body-part of db. Should be + * noted: + * - we need an exclusive lock for do so; + * - we can't lock meta-pages, otherwise other process could get an error + * while opening db in valid (non-conflict) mode. */ + if (!flock(env->me_fd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_BODY)) { + rc = GetLastError(); + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "lock-against-without-lck", rc); + mdbx_jitter4testing(false); + mdbx_lck_destroy(env); + } else { + mdbx_jitter4testing(false); + if (!funlock(env->me_fd, LCK_BODY)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "unlock-against-without-lck", GetLastError()); + } + } + + return rc; +} + +int mdbx_lck_downgrade(MDBX_env *env, bool complete) { + /* Transite from exclusive state (E-?) to used (S-?) */ + assert(env->me_fd != INVALID_HANDLE_VALUE); + assert(env->me_lfd != INVALID_HANDLE_VALUE); + + if (env->me_flags & MDBX_EXCLUSIVE) + return MDBX_SUCCESS /* nope since files were must be opened non-shareable */ + ; + + /* 1) must be at E-E (exclusive-write) */ + if (!complete) { + /* transite from E-E to E_? (exclusive-read) */ + if (!funlock(env->me_lfd, LCK_UPPER)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "E-E(exclusive-write) >> E-?(exclusive-read)", GetLastError()); + return MDBX_SUCCESS /* 2) now at E-? (exclusive-read), done */; + } + + /* 3) now at E-E (exclusive-write), transite to ?_E (middle) */ + if (!funlock(env->me_lfd, LCK_LOWER)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "E-E(exclusive-write) >> ?-E(middle)", GetLastError()); + + /* 4) now at ?-E (middle), transite to S-E (locked) */ + if (!flock(env->me_lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER)) { + int rc = GetLastError() /* 5) something went wrong, give up */; + mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, + "?-E(middle) >> S-E(locked)", rc); + return rc; + } + + /* 6) got S-E (locked), continue transition to S-? (used) */ + if (!funlock(env->me_lfd, LCK_UPPER)) + mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_, + "S-E(locked) >> S-?(used)", GetLastError()); + + return MDBX_SUCCESS /* 7) now at S-? (used), done */; +} + +void mdbx_lck_destroy(MDBX_env *env) { + int rc; + + if (env->me_lfd != INVALID_HANDLE_VALUE) { + /* double `unlock` for robustly remove overlapped shared/exclusive locks */ + while (funlock(env->me_lfd, LCK_LOWER)) + ; + rc = GetLastError(); + assert(rc == ERROR_NOT_LOCKED); + (void)rc; + SetLastError(ERROR_SUCCESS); + + while (funlock(env->me_lfd, LCK_UPPER)) + ; + rc = GetLastError(); + assert(rc == ERROR_NOT_LOCKED); + (void)rc; + SetLastError(ERROR_SUCCESS); + } + + if (env->me_fd != INVALID_HANDLE_VALUE) { + /* explicitly unlock to avoid latency for other processes (windows kernel + * releases such locks via deferred queues) */ + while (funlock(env->me_fd, LCK_BODY)) + ; + rc = GetLastError(); + assert(rc == ERROR_NOT_LOCKED); + (void)rc; + SetLastError(ERROR_SUCCESS); + + while (funlock(env->me_fd, LCK_META)) + ; + rc = GetLastError(); + assert(rc == ERROR_NOT_LOCKED); + (void)rc; + SetLastError(ERROR_SUCCESS); + + while (funlock(env->me_fd, LCK_WHOLE)) + ; + rc = GetLastError(); + assert(rc == ERROR_NOT_LOCKED); + (void)rc; + SetLastError(ERROR_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/* reader checking (by pid) */ + +int mdbx_rpid_set(MDBX_env *env) { + (void)env; + return MDBX_SUCCESS; +} + +int mdbx_rpid_clear(MDBX_env *env) { + (void)env; + return MDBX_SUCCESS; +} + +/* Checks reader by pid. + * + * Returns: + * MDBX_RESULT_TRUE, if pid is live (unable to acquire lock) + * MDBX_RESULT_FALSE, if pid is dead (lock acquired) + * or otherwise the errcode. */ +int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { + (void)env; + HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); + int rc; + if (likely(hProcess)) { + rc = WaitForSingleObject(hProcess, 0); + if (unlikely(rc == WAIT_FAILED)) + rc = GetLastError(); + CloseHandle(hProcess); + } else { + rc = GetLastError(); + } + + switch (rc) { + case ERROR_INVALID_PARAMETER: + /* pid seem invalid */ + return MDBX_RESULT_FALSE; + case WAIT_OBJECT_0: + /* process just exited */ + return MDBX_RESULT_FALSE; + case WAIT_TIMEOUT: + /* pid running */ + return MDBX_RESULT_TRUE; + default: + /* failure */ + return rc; + } +} + +//---------------------------------------------------------------------------- +// Stub for slim read-write lock +// Copyright (C) 1995-2002 Brad Wilson + +static void WINAPI stub_srwlock_Init(MDBX_srwlock *srwl) { + srwl->readerCount = srwl->writerCount = 0; +} + +static void WINAPI stub_srwlock_AcquireShared(MDBX_srwlock *srwl) { + while (true) { + assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); + + // If there's a writer already, spin without unnecessarily + // interlocking the CPUs + if (srwl->writerCount != 0) { + YieldProcessor(); + continue; + } + + // Add to the readers list + _InterlockedIncrement(&srwl->readerCount); + + // Check for writers again (we may have been pre-empted). If + // there are no writers writing or waiting, then we're done. + if (srwl->writerCount == 0) + break; + + // Remove from the readers list, spin, try again + _InterlockedDecrement(&srwl->readerCount); + YieldProcessor(); + } +} + +static void WINAPI stub_srwlock_ReleaseShared(MDBX_srwlock *srwl) { + assert(srwl->readerCount > 0); + _InterlockedDecrement(&srwl->readerCount); +} + +static void WINAPI stub_srwlock_AcquireExclusive(MDBX_srwlock *srwl) { + while (true) { + assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); + + // If there's a writer already, spin without unnecessarily + // interlocking the CPUs + if (srwl->writerCount != 0) { + YieldProcessor(); + continue; + } + + // See if we can become the writer (expensive, because it inter- + // locks the CPUs, so writing should be an infrequent process) + if (_InterlockedExchange(&srwl->writerCount, 1) == 0) + break; + } + + // Now we're the writer, but there may be outstanding readers. + // Spin until there aren't any more; new readers will wait now + // that we're the writer. + while (srwl->readerCount != 0) { + assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); + YieldProcessor(); + } +} + +static void WINAPI stub_srwlock_ReleaseExclusive(MDBX_srwlock *srwl) { + assert(srwl->writerCount == 1 && srwl->readerCount >= 0); + srwl->writerCount = 0; +} + +MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared, + mdbx_srwlock_ReleaseShared, mdbx_srwlock_AcquireExclusive, + mdbx_srwlock_ReleaseExclusive; + +/*----------------------------------------------------------------------------*/ + +MDBX_GetFileInformationByHandleEx mdbx_GetFileInformationByHandleEx; +MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW; +MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW; +MDBX_SetFileInformationByHandle mdbx_SetFileInformationByHandle; +MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory; +MDBX_NtFsControlFile mdbx_NtFsControlFile; + +static void mdbx_winnt_import(void) { + const HINSTANCE hKernel32dll = GetModuleHandleA("kernel32.dll"); + const MDBX_srwlock_function init = + (MDBX_srwlock_function)GetProcAddress(hKernel32dll, "InitializeSRWLock"); + if (init != NULL) { + mdbx_srwlock_Init = init; + mdbx_srwlock_AcquireShared = (MDBX_srwlock_function)GetProcAddress( + hKernel32dll, "AcquireSRWLockShared"); + mdbx_srwlock_ReleaseShared = (MDBX_srwlock_function)GetProcAddress( + hKernel32dll, "ReleaseSRWLockShared"); + mdbx_srwlock_AcquireExclusive = (MDBX_srwlock_function)GetProcAddress( + hKernel32dll, "AcquireSRWLockExclusive"); + mdbx_srwlock_ReleaseExclusive = (MDBX_srwlock_function)GetProcAddress( + hKernel32dll, "ReleaseSRWLockExclusive"); + } else { + mdbx_srwlock_Init = stub_srwlock_Init; + mdbx_srwlock_AcquireShared = stub_srwlock_AcquireShared; + mdbx_srwlock_ReleaseShared = stub_srwlock_ReleaseShared; + mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive; + mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive; + } + +#define GET_KERNEL32_PROC(ENTRY) \ + mdbx_##ENTRY = (MDBX_##ENTRY)GetProcAddress(hKernel32dll, #ENTRY) + + GET_KERNEL32_PROC(GetFileInformationByHandleEx); + GET_KERNEL32_PROC(GetVolumeInformationByHandleW); + GET_KERNEL32_PROC(GetFinalPathNameByHandleW); + GET_KERNEL32_PROC(SetFileInformationByHandle); + GET_KERNEL32_PROC(PrefetchVirtualMemory); + + const HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll"); + mdbx_NtFsControlFile = + (MDBX_NtFsControlFile)GetProcAddress(hNtdll, "NtFsControlFile"); +} diff --git a/contrib/db/libmdbx/src/mdbx.c b/contrib/db/libmdbx/src/mdbx.c new file mode 100644 index 00000000..a8edbc64 --- /dev/null +++ b/contrib/db/libmdbx/src/mdbx.c @@ -0,0 +1,14492 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * This code is derived from "LMDB engine" written by + * Howard Chu (Symas Corporation), which itself derived from btree.c + * written by Martin Hedenfalk. + * + * --- + * + * Portions Copyright 2011-2015 Howard Chu, Symas Corp. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + * + * --- + * + * Portions Copyright (c) 2009, 2010 Martin Hedenfalk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include "./bits.h" + +/*----------------------------------------------------------------------------*/ +/* Internal inlines */ + +static __inline bool mdbx_is_power2(size_t x) { return (x & (x - 1)) == 0; } + +static __inline size_t mdbx_roundup2(size_t value, size_t granularity) { + assert(mdbx_is_power2(granularity)); + return (value + granularity - 1) & ~(granularity - 1); +} + +static __inline unsigned mdbx_log2(size_t value) { + assert(mdbx_is_power2(value)); + + unsigned log = 0; + while (value > 1) { + log += 1; + value >>= 1; + } + return log; +} + +/* Address of node i in page p */ +static __inline MDBX_node *NODEPTR(MDBX_page *p, unsigned i) { + assert(NUMKEYS(p) > (unsigned)(i)); + return (MDBX_node *)((char *)(p) + (p)->mp_ptrs[i] + PAGEHDRSZ); +} + +/* Get the page number pointed to by a branch node */ +static __inline pgno_t NODEPGNO(const MDBX_node *node) { + pgno_t pgno; + if (UNALIGNED_OK) { + pgno = node->mn_ksize_and_pgno; + if (sizeof(pgno_t) > 4) + pgno &= MAX_PAGENO; + } else { + pgno = node->mn_lo | ((pgno_t)node->mn_hi << 16); + if (sizeof(pgno_t) > 4) + pgno |= ((uint64_t)node->mn_flags) << 32; + } + return pgno; +} + +/* Set the page number in a branch node */ +static __inline void SETPGNO(MDBX_node *node, pgno_t pgno) { + assert(pgno <= MAX_PAGENO); + + if (UNALIGNED_OK) { + if (sizeof(pgno_t) > 4) + pgno |= ((uint64_t)node->mn_ksize) << 48; + node->mn_ksize_and_pgno = pgno; + } else { + node->mn_lo = (uint16_t)pgno; + node->mn_hi = (uint16_t)(pgno >> 16); + if (sizeof(pgno_t) > 4) + node->mn_flags = (uint16_t)((uint64_t)pgno >> 32); + } +} + +/* Get the size of the data in a leaf node */ +static __inline size_t NODEDSZ(const MDBX_node *node) { + size_t size; + if (UNALIGNED_OK) { + size = node->mn_dsize; + } else { + size = node->mn_lo | ((size_t)node->mn_hi << 16); + } + return size; +} + +/* Set the size of the data for a leaf node */ +static __inline void SETDSZ(MDBX_node *node, size_t size) { + assert(size < INT_MAX); + if (UNALIGNED_OK) { + node->mn_dsize = (uint32_t)size; + } else { + node->mn_lo = (uint16_t)size; + node->mn_hi = (uint16_t)(size >> 16); + } +} + +static __inline size_t pgno2bytes(const MDBX_env *env, pgno_t pgno) { + mdbx_assert(env, (1u << env->me_psize2log) == env->me_psize); + return ((size_t)pgno) << env->me_psize2log; +} + +static __inline MDBX_page *pgno2page(const MDBX_env *env, pgno_t pgno) { + return (MDBX_page *)(env->me_map + pgno2bytes(env, pgno)); +} + +static __inline pgno_t bytes2pgno(const MDBX_env *env, size_t bytes) { + mdbx_assert(env, (env->me_psize >> env->me_psize2log) == 1); + return (pgno_t)(bytes >> env->me_psize2log); +} + +static __inline size_t pgno_align2os_bytes(const MDBX_env *env, pgno_t pgno) { + return mdbx_roundup2(pgno2bytes(env, pgno), env->me_os_psize); +} + +static __inline pgno_t pgno_align2os_pgno(const MDBX_env *env, pgno_t pgno) { + return bytes2pgno(env, pgno_align2os_bytes(env, pgno)); +} + +/* Perform act while tracking temporary cursor mn */ +#define WITH_CURSOR_TRACKING(mn, act) \ + do { \ + mdbx_cassert(&(mn), \ + mn.mc_txn->mt_cursors != NULL /* must be not rdonly txt */); \ + MDBX_cursor mc_dummy, *tracked, \ + **tp = &(mn).mc_txn->mt_cursors[mn.mc_dbi]; \ + if ((mn).mc_flags & C_SUB) { \ + mc_dummy.mc_flags = C_INITIALIZED; \ + mc_dummy.mc_xcursor = (MDBX_xcursor *)&(mn); \ + tracked = &mc_dummy; \ + } else { \ + tracked = &(mn); \ + } \ + tracked->mc_next = *tp; \ + *tp = tracked; \ + { act; } \ + *tp = tracked->mc_next; \ + } while (0) + +/*----------------------------------------------------------------------------*/ +/* LY: temporary workaround for Elbrus's memcmp() bug. */ + +#if defined(__e2k__) && !__GLIBC_PREREQ(2, 24) +int __hot mdbx_e2k_memcmp_bug_workaround(const void *s1, const void *s2, + size_t n) { + if (unlikely(n > 42 + /* LY: align followed access if reasonable possible */ + && (((uintptr_t)s1) & 7) != 0 && + (((uintptr_t)s1) & 7) == (((uintptr_t)s2) & 7))) { + if (((uintptr_t)s1) & 1) { + const int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (diff) + return diff; + s1 = (char *)s1 + 1; + s2 = (char *)s2 + 1; + n -= 1; + } + + if (((uintptr_t)s1) & 2) { + const uint16_t a = *(uint16_t *)s1; + const uint16_t b = *(uint16_t *)s2; + if (likely(a != b)) + return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; + s1 = (char *)s1 + 2; + s2 = (char *)s2 + 2; + n -= 2; + } + + if (((uintptr_t)s1) & 4) { + const uint32_t a = *(uint32_t *)s1; + const uint32_t b = *(uint32_t *)s2; + if (likely(a != b)) + return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; + s1 = (char *)s1 + 4; + s2 = (char *)s2 + 4; + n -= 4; + } + } + + while (n >= 8) { + const uint64_t a = *(uint64_t *)s1; + const uint64_t b = *(uint64_t *)s2; + if (likely(a != b)) + return (__builtin_bswap64(a) > __builtin_bswap64(b)) ? 1 : -1; + s1 = (char *)s1 + 8; + s2 = (char *)s2 + 8; + n -= 8; + } + + if (n & 4) { + const uint32_t a = *(uint32_t *)s1; + const uint32_t b = *(uint32_t *)s2; + if (likely(a != b)) + return (__builtin_bswap32(a) > __builtin_bswap32(b)) ? 1 : -1; + s1 = (char *)s1 + 4; + s2 = (char *)s2 + 4; + } + + if (n & 2) { + const uint16_t a = *(uint16_t *)s1; + const uint16_t b = *(uint16_t *)s2; + if (likely(a != b)) + return (__builtin_bswap16(a) > __builtin_bswap16(b)) ? 1 : -1; + s1 = (char *)s1 + 2; + s2 = (char *)s2 + 2; + } + + return (n & 1) ? *(uint8_t *)s1 - *(uint8_t *)s2 : 0; +} + +int __hot mdbx_e2k_strcmp_bug_workaround(const char *s1, const char *s2) { + while (true) { + int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (likely(diff != 0) || *s1 == '\0') + return diff; + s1 += 1; + s2 += 1; + } +} + +int __hot mdbx_e2k_strncmp_bug_workaround(const char *s1, const char *s2, + size_t n) { + while (n > 0) { + int diff = *(uint8_t *)s1 - *(uint8_t *)s2; + if (likely(diff != 0) || *s1 == '\0') + return diff; + s1 += 1; + s2 += 1; + n -= 1; + } + return 0; +} + +size_t __hot mdbx_e2k_strlen_bug_workaround(const char *s) { + size_t n = 0; + while (*s) { + s += 1; + n += 1; + } + return n; +} + +size_t __hot mdbx_e2k_strnlen_bug_workaround(const char *s, size_t maxlen) { + size_t n = 0; + while (maxlen > n && *s) { + s += 1; + n += 1; + } + return n; +} +#endif /* Elbrus's memcmp() bug. */ + +/*----------------------------------------------------------------------------*/ +/* rthc (tls keys and destructors) */ + +typedef struct rthc_entry_t { + MDBX_reader *begin; + MDBX_reader *end; + mdbx_thread_key_t key; +} rthc_entry_t; + +#if MDBX_DEBUG +#define RTHC_INITIAL_LIMIT 1 +#else +#define RTHC_INITIAL_LIMIT 16 +#endif + +#if defined(_WIN32) || defined(_WIN64) +static CRITICAL_SECTION rthc_critical_section; +#else +int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, void *dso_symbol) + __attribute__((__weak__)); +#ifdef __APPLE__ /* FIXME: Thread-Local Storage destructors & DSO-unloading */ +int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, + void *dso_symbol) { + (void)dtor; + (void)obj; + (void)dso_symbol; + return -1; +} +#endif /* __APPLE__ */ + +static pthread_mutex_t mdbx_rthc_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t mdbx_rthc_cond = PTHREAD_COND_INITIALIZER; +static mdbx_thread_key_t mdbx_rthc_key; +static volatile uint32_t mdbx_rthc_pending; + +static void __cold mdbx_workaround_glibc_bug21031(void) { + /* Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=21031 + * + * Due race between pthread_key_delete() and __nptl_deallocate_tsd() + * The destructor(s) of thread-local-storate object(s) may be running + * in another thread(s) and be blocked or not finished yet. + * In such case we get a SEGFAULT after unload this library DSO. + * + * So just by yielding a few timeslices we give a chance + * to such destructor(s) for completion and avoids segfault. */ + sched_yield(); + sched_yield(); + sched_yield(); +} +#endif + +static unsigned rthc_count, rthc_limit; +static rthc_entry_t *rthc_table; +static rthc_entry_t rthc_table_static[RTHC_INITIAL_LIMIT]; + +static __cold void mdbx_rthc_lock(void) { +#if defined(_WIN32) || defined(_WIN64) + EnterCriticalSection(&rthc_critical_section); +#else + mdbx_ensure(nullptr, pthread_mutex_lock(&mdbx_rthc_mutex) == 0); +#endif +} + +static __cold void mdbx_rthc_unlock(void) { +#if defined(_WIN32) || defined(_WIN64) + LeaveCriticalSection(&rthc_critical_section); +#else + mdbx_ensure(nullptr, pthread_mutex_unlock(&mdbx_rthc_mutex) == 0); +#endif +} + +static __inline int mdbx_thread_key_create(mdbx_thread_key_t *key) { + int rc; +#if defined(_WIN32) || defined(_WIN64) + *key = TlsAlloc(); + rc = (*key != TLS_OUT_OF_INDEXES) ? MDBX_SUCCESS : GetLastError(); +#else + rc = pthread_key_create(key, nullptr); +#endif + mdbx_trace("&key = %p, value 0x%x, rc %d", key, (unsigned)*key, rc); + return rc; +} + +static __inline void mdbx_thread_key_delete(mdbx_thread_key_t key) { + mdbx_trace("key = 0x%x", (unsigned)key); +#if defined(_WIN32) || defined(_WIN64) + mdbx_ensure(nullptr, TlsFree(key)); +#else + mdbx_ensure(nullptr, pthread_key_delete(key) == 0); + mdbx_workaround_glibc_bug21031(); +#endif +} + +static __inline void *mdbx_thread_rthc_get(mdbx_thread_key_t key) { +#if defined(_WIN32) || defined(_WIN64) + return TlsGetValue(key); +#else + return pthread_getspecific(key); +#endif +} + +static void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value) { +#if defined(_WIN32) || defined(_WIN64) + mdbx_ensure(nullptr, TlsSetValue(key, (void *)value)); +#else +#define MDBX_THREAD_RTHC_ZERO 0 +#define MDBX_THREAD_RTHC_REGISTERD 1 +#define MDBX_THREAD_RTHC_COUNTED 2 + static __thread uint32_t thread_registration_state; + if (value && unlikely(thread_registration_state == MDBX_THREAD_RTHC_ZERO)) { + thread_registration_state = MDBX_THREAD_RTHC_REGISTERD; + mdbx_trace("thread registered 0x%" PRIxPTR, (uintptr_t)mdbx_thread_self()); + if (&__cxa_thread_atexit_impl == nullptr || + __cxa_thread_atexit_impl(mdbx_rthc_thread_dtor, + &thread_registration_state, + (void *)&mdbx_version /* dso_anchor */)) { + mdbx_ensure(nullptr, pthread_setspecific( + mdbx_rthc_key, &thread_registration_state) == 0); + thread_registration_state = MDBX_THREAD_RTHC_COUNTED; + const unsigned count_before = mdbx_atomic_add32(&mdbx_rthc_pending, 1); + mdbx_ensure(nullptr, count_before < INT_MAX); + mdbx_trace("fallback to pthreads' tsd, key 0x%x, count %u", + (unsigned)mdbx_rthc_key, count_before); + (void)count_before; + } + } + mdbx_ensure(nullptr, pthread_setspecific(key, value) == 0); +#endif +} + +__cold void mdbx_rthc_global_init(void) { + rthc_limit = RTHC_INITIAL_LIMIT; + rthc_table = rthc_table_static; +#if defined(_WIN32) || defined(_WIN64) + InitializeCriticalSection(&rthc_critical_section); +#else + mdbx_ensure(nullptr, + pthread_key_create(&mdbx_rthc_key, mdbx_rthc_thread_dtor) == 0); + mdbx_trace("pid %d, &mdbx_rthc_key = %p, value 0x%x", mdbx_getpid(), + &mdbx_rthc_key, (unsigned)mdbx_rthc_key); +#endif +} + +/* dtor called for thread, i.e. for all mdbx's environment objects */ +__cold void mdbx_rthc_thread_dtor(void *ptr) { + mdbx_rthc_lock(); + mdbx_trace(">> pid %d, thread 0x%" PRIxPTR ", rthc %p", mdbx_getpid(), + (uintptr_t)mdbx_thread_self(), ptr); + + const mdbx_pid_t self_pid = mdbx_getpid(); + for (unsigned i = 0; i < rthc_count; ++i) { + const mdbx_thread_key_t key = rthc_table[i].key; + MDBX_reader *const rthc = mdbx_thread_rthc_get(key); + if (rthc < rthc_table[i].begin || rthc >= rthc_table[i].end) + continue; +#if !defined(_WIN32) && !defined(_WIN64) + if (pthread_setspecific(key, nullptr) != 0) { + mdbx_trace("== thread 0x%" PRIxPTR + ", rthc %p: ignore race with tsd-key deletion", + (uintptr_t)mdbx_thread_self(), ptr); + continue /* ignore race with tsd-key deletion by mdbx_env_close() */; + } +#endif + + mdbx_trace("== thread 0x%" PRIxPTR + ", rthc %p, [%i], %p ... %p (%+i), rtch-pid %i, " + "current-pid %i", + (uintptr_t)mdbx_thread_self(), rthc, i, rthc_table[i].begin, + rthc_table[i].end, (int)(rthc - rthc_table[i].begin), + rthc->mr_pid, self_pid); + if (rthc->mr_pid == self_pid) { + mdbx_trace("==== thread 0x%" PRIxPTR ", rthc %p, cleanup", + (uintptr_t)mdbx_thread_self(), rthc); + rthc->mr_pid = 0; + } + } + +#if defined(_WIN32) || defined(_WIN64) + mdbx_trace("<< thread 0x%" PRIxPTR ", rthc %p", (uintptr_t)mdbx_thread_self(), + ptr); + mdbx_rthc_unlock(); +#else + const char self_registration = *(char *)ptr; + *(char *)ptr = MDBX_THREAD_RTHC_ZERO; + mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d", + (uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid(), + self_registration); + if (self_registration == MDBX_THREAD_RTHC_COUNTED) + mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0); + + if (mdbx_rthc_pending == 0) { + mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, wake", + (uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid()); + mdbx_ensure(nullptr, pthread_cond_broadcast(&mdbx_rthc_cond) == 0); + } + + mdbx_trace("<< thread 0x%" PRIxPTR ", rthc %p", (uintptr_t)mdbx_thread_self(), + ptr); + /* Allow tail call optimization, i.e. gcc should generate the jmp instruction + * instead of a call for pthread_mutex_unlock() and therefore CPU could not + * return to current DSO's code section, which may be unloaded immediately + * after the mutex got released. */ + pthread_mutex_unlock(&mdbx_rthc_mutex); +#endif +} + +__cold void mdbx_rthc_global_dtor(void) { + mdbx_trace( + ">> pid %d, &mdbx_rthc_global_dtor %p, &mdbx_rthc_thread_dtor = %p, " + "&mdbx_rthc_remove = %p", + mdbx_getpid(), &mdbx_rthc_global_dtor, &mdbx_rthc_thread_dtor, + &mdbx_rthc_remove); + + mdbx_rthc_lock(); +#if !defined(_WIN32) && !defined(_WIN64) + char *rthc = (char *)pthread_getspecific(mdbx_rthc_key); + mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d", + (uintptr_t)mdbx_thread_self(), rthc, mdbx_getpid(), + rthc ? *rthc : -1); + if (rthc) { + const char self_registration = *(char *)rthc; + *rthc = MDBX_THREAD_RTHC_ZERO; + if (self_registration == MDBX_THREAD_RTHC_COUNTED) + mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0); + } + + struct timespec abstime; + mdbx_ensure(nullptr, clock_gettime(CLOCK_REALTIME, &abstime) == 0); + abstime.tv_nsec += 1000000000l / 10; + if (abstime.tv_nsec >= 1000000000l) { + abstime.tv_nsec -= 1000000000l; + abstime.tv_sec += 1; + } +#if MDBX_DEBUG > 0 + abstime.tv_sec += 600; +#endif + + for (unsigned left; (left = mdbx_rthc_pending) > 0;) { + mdbx_trace("pid %d, pending %u, wait for...", mdbx_getpid(), left); + const int rc = + pthread_cond_timedwait(&mdbx_rthc_cond, &mdbx_rthc_mutex, &abstime); + if (rc && rc != EINTR) + break; + } + mdbx_thread_key_delete(mdbx_rthc_key); +#endif + + const mdbx_pid_t self_pid = mdbx_getpid(); + for (unsigned i = 0; i < rthc_count; ++i) { + const mdbx_thread_key_t key = rthc_table[i].key; + mdbx_thread_key_delete(key); + for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end; + ++rthc) { + mdbx_trace("== [%i] = key %zu, %p ... %p, rthc %p (%+i), " + "rthc-pid %i, current-pid %i", + i, (size_t)key, rthc_table[i].begin, rthc_table[i].end, rthc, + (int)(rthc - rthc_table[i].begin), rthc->mr_pid, self_pid); + if (rthc->mr_pid == self_pid) { + rthc->mr_pid = 0; + mdbx_trace("== cleanup %p", rthc); + } + } + } + + rthc_limit = rthc_count = 0; + if (rthc_table != rthc_table_static) + mdbx_free(rthc_table); + rthc_table = nullptr; + mdbx_rthc_unlock(); + +#if defined(_WIN32) || defined(_WIN64) + DeleteCriticalSection(&rthc_critical_section); +#else + /* LY: yielding a few timeslices to give a more chance + * to racing destructor(s) for completion. */ + mdbx_workaround_glibc_bug21031(); +#endif + + mdbx_trace("<< pid %d\n", mdbx_getpid()); +} + +__cold int mdbx_rthc_alloc(mdbx_thread_key_t *key, MDBX_reader *begin, + MDBX_reader *end) { +#ifndef NDEBUG + *key = (mdbx_thread_key_t)0xBADBADBAD; +#endif /* NDEBUG */ + int rc = mdbx_thread_key_create(key); + if (rc != MDBX_SUCCESS) + return rc; + + mdbx_rthc_lock(); + mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)*key, + rthc_count, rthc_limit); + if (rthc_count == rthc_limit) { + rthc_entry_t *new_table = + mdbx_realloc((rthc_table == rthc_table_static) ? nullptr : rthc_table, + sizeof(rthc_entry_t) * rthc_limit * 2); + if (new_table == nullptr) { + rc = MDBX_ENOMEM; + goto bailout; + } + if (rthc_table == rthc_table_static) + memcpy(new_table, rthc_table_static, sizeof(rthc_table_static)); + rthc_table = new_table; + rthc_limit *= 2; + } + mdbx_trace("== [%i] = key %zu, %p ... %p", rthc_count, (size_t)*key, begin, + end); + rthc_table[rthc_count].key = *key; + rthc_table[rthc_count].begin = begin; + rthc_table[rthc_count].end = end; + ++rthc_count; + mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)*key, + rthc_count, rthc_limit); + mdbx_rthc_unlock(); + return MDBX_SUCCESS; + +bailout: + mdbx_thread_key_delete(*key); + mdbx_rthc_unlock(); + return rc; +} + +__cold void mdbx_rthc_remove(const mdbx_thread_key_t key) { + mdbx_thread_key_delete(key); + mdbx_rthc_lock(); + mdbx_trace(">> key %zu, rthc_count %u, rthc_limit %u", (size_t)key, + rthc_count, rthc_limit); + + for (unsigned i = 0; i < rthc_count; ++i) { + if (key == rthc_table[i].key) { + const mdbx_pid_t self_pid = mdbx_getpid(); + mdbx_trace("== [%i], %p ...%p, current-pid %d", i, rthc_table[i].begin, + rthc_table[i].end, self_pid); + + for (MDBX_reader *rthc = rthc_table[i].begin; rthc < rthc_table[i].end; + ++rthc) { + if (rthc->mr_pid == self_pid) { + rthc->mr_pid = 0; + mdbx_trace("== cleanup %p", rthc); + } + } + if (--rthc_count > 0) + rthc_table[i] = rthc_table[rthc_count]; + else if (rthc_table != rthc_table_static) { + mdbx_free(rthc_table); + rthc_table = rthc_table_static; + rthc_limit = RTHC_INITIAL_LIMIT; + } + break; + } + } + + mdbx_trace("<< key %zu, rthc_count %u, rthc_limit %u", (size_t)key, + rthc_count, rthc_limit); + mdbx_rthc_unlock(); +} + +/*----------------------------------------------------------------------------*/ + +static __inline size_t pnl2bytes(const size_t size) { + assert(size > 0 && size <= MDBX_PNL_MAX * 2); + size_t bytes = + mdbx_roundup2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(pgno_t) * (size + 2), + MDBX_PNL_GRANULATE * sizeof(pgno_t)) - + MDBX_ASSUME_MALLOC_OVERHEAD; + return bytes; +} + +static __inline pgno_t bytes2pnl(const size_t bytes) { + size_t size = bytes / sizeof(pgno_t); + assert(size > 2 && size <= MDBX_PNL_MAX * 2); + return (pgno_t)size - 2; +} + +static MDBX_PNL mdbx_pnl_alloc(size_t size) { + const size_t bytes = pnl2bytes(size); + MDBX_PNL pl = mdbx_malloc(bytes); + if (likely(pl)) { +#if __GLIBC_PREREQ(2, 12) + const size_t bytes = malloc_usable_size(pl); +#endif + pl[0] = bytes2pnl(bytes); + assert(pl[0] >= size); + pl[1] = 0; + pl += 1; + } + return pl; +} + +static void mdbx_pnl_free(MDBX_PNL pl) { + if (likely(pl)) + mdbx_free(pl - 1); +} + +/* Shrink the PNL to the default size if it has grown larger */ +static void mdbx_pnl_shrink(MDBX_PNL *ppl) { + assert(bytes2pnl(pnl2bytes(MDBX_PNL_INITIAL)) == MDBX_PNL_INITIAL); + assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && + MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); + MDBX_PNL_SIZE(*ppl) = 0; + if (unlikely(MDBX_PNL_ALLOCLEN(*ppl) > + MDBX_PNL_INITIAL + MDBX_CACHELINE_SIZE / sizeof(pgno_t))) { + const size_t bytes = pnl2bytes(MDBX_PNL_INITIAL); + MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes); + if (likely(pl)) { +#if __GLIBC_PREREQ(2, 12) + const size_t bytes = malloc_usable_size(pl); +#endif + *pl = bytes2pnl(bytes); + *ppl = pl + 1; + } + } +} + +/* Grow the PNL to the size growed to at least given size */ +static int mdbx_pnl_reserve(MDBX_PNL *ppl, const size_t wanna) { + const size_t allocated = MDBX_PNL_ALLOCLEN(*ppl); + assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && + MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); + if (likely(allocated >= wanna)) + return MDBX_SUCCESS; + + if (unlikely(wanna > /* paranoia */ MDBX_PNL_MAX)) + return MDBX_TXN_FULL; + + const size_t size = (wanna + wanna - allocated < MDBX_PNL_MAX) + ? wanna + wanna - allocated + : MDBX_PNL_MAX; + const size_t bytes = pnl2bytes(size); + MDBX_PNL pl = mdbx_realloc(*ppl - 1, bytes); + if (likely(pl)) { +#if __GLIBC_PREREQ(2, 12) + const size_t bytes = malloc_usable_size(pl); +#endif + *pl = bytes2pnl(bytes); + assert(*pl >= wanna); + *ppl = pl + 1; + return MDBX_SUCCESS; + } + return MDBX_ENOMEM; +} + +/* Make room for num additional elements in an PNL */ +static __inline int __must_check_result mdbx_pnl_need(MDBX_PNL *ppl, + size_t num) { + assert(MDBX_PNL_SIZE(*ppl) <= MDBX_PNL_MAX && + MDBX_PNL_ALLOCLEN(*ppl) >= MDBX_PNL_SIZE(*ppl)); + assert(num <= MDBX_PNL_MAX); + const size_t wanna = MDBX_PNL_SIZE(*ppl) + num; + return likely(MDBX_PNL_ALLOCLEN(*ppl) >= wanna) + ? MDBX_SUCCESS + : mdbx_pnl_reserve(ppl, wanna); +} + +static __inline void mdbx_pnl_xappend(MDBX_PNL pl, pgno_t id) { + assert(MDBX_PNL_SIZE(pl) < MDBX_PNL_ALLOCLEN(pl)); + MDBX_PNL_SIZE(pl) += 1; + MDBX_PNL_LAST(pl) = id; +} + +/* Append an ID onto an PNL */ +static int __must_check_result mdbx_pnl_append(MDBX_PNL *ppl, pgno_t id) { + /* Too big? */ + if (unlikely(MDBX_PNL_SIZE(*ppl) == MDBX_PNL_ALLOCLEN(*ppl))) { + int rc = mdbx_pnl_need(ppl, MDBX_PNL_GRANULATE); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + mdbx_pnl_xappend(*ppl, id); + return MDBX_SUCCESS; +} + +/* Append an PNL onto an PNL */ +static int __must_check_result mdbx_pnl_append_list(MDBX_PNL *ppl, + MDBX_PNL append) { + int rc = mdbx_pnl_need(ppl, MDBX_PNL_SIZE(append)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + memcpy(MDBX_PNL_END(*ppl), MDBX_PNL_BEGIN(append), + MDBX_PNL_SIZE(append) * sizeof(pgno_t)); + MDBX_PNL_SIZE(*ppl) += MDBX_PNL_SIZE(append); + return MDBX_SUCCESS; +} + +/* Append an ID range onto an PNL */ +static int __must_check_result mdbx_pnl_append_range(MDBX_PNL *ppl, pgno_t id, + size_t n) { + int rc = mdbx_pnl_need(ppl, n); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + pgno_t *ap = MDBX_PNL_END(*ppl); + MDBX_PNL_SIZE(*ppl) += (unsigned)n; + for (pgno_t *const end = MDBX_PNL_END(*ppl); ap < end;) + *ap++ = id++; + return MDBX_SUCCESS; +} + +static bool mdbx_pnl_check(MDBX_PNL pl, bool allocated) { + if (pl) { + assert(MDBX_PNL_SIZE(pl) <= MDBX_PNL_MAX); + if (allocated) { + assert(MDBX_PNL_ALLOCLEN(pl) >= MDBX_PNL_SIZE(pl)); + } + for (const pgno_t *scan = &MDBX_PNL_LAST(pl); --scan > pl;) { + assert(MDBX_PNL_ORDERED(scan[0], scan[1])); + assert(scan[0] >= NUM_METAS); + if (unlikely(MDBX_PNL_DISORDERED(scan[0], scan[1]) || + scan[0] < NUM_METAS)) + return false; + } + } + return true; +} + +/* Merge an PNL onto an PNL. The destination PNL must be big enough */ +static void __hot mdbx_pnl_xmerge(MDBX_PNL pnl, MDBX_PNL merge) { + assert(mdbx_pnl_check(pnl, true)); + assert(mdbx_pnl_check(merge, false)); + pgno_t old_id, merge_id, i = MDBX_PNL_SIZE(merge), j = MDBX_PNL_SIZE(pnl), + k = i + j, total = k; + pnl[0] = + MDBX_PNL_ASCENDING ? 0 : ~(pgno_t)0; /* delimiter for pl scan below */ + old_id = pnl[j]; + while (i) { + merge_id = merge[i--]; + for (; MDBX_PNL_ORDERED(merge_id, old_id); old_id = pnl[--j]) + pnl[k--] = old_id; + pnl[k--] = merge_id; + } + MDBX_PNL_SIZE(pnl) = total; + assert(mdbx_pnl_check(pnl, true)); +} + +/* Sort an PNL */ +static void __hot mdbx_pnl_sort(MDBX_PNL pnl) { + /* Max possible depth of int-indexed tree * 2 items/level */ + int istack[sizeof(int) * CHAR_BIT * 2]; + int i, j, k, l, ir, jstack; + pgno_t a; + +/* Quicksort + Insertion sort for small arrays */ +#define PNL_SMALL 8 +#define PNL_SWAP(a, b) \ + do { \ + pgno_t tmp_pgno = (a); \ + (a) = (b); \ + (b) = tmp_pgno; \ + } while (0) + + ir = (int)MDBX_PNL_SIZE(pnl); + l = 1; + jstack = 0; + while (1) { + if (ir - l < PNL_SMALL) { /* Insertion sort */ + for (j = l + 1; j <= ir; j++) { + a = pnl[j]; + for (i = j - 1; i >= 1; i--) { + if (MDBX_PNL_DISORDERED(a, pnl[i])) + break; + pnl[i + 1] = pnl[i]; + } + pnl[i + 1] = a; + } + if (jstack == 0) + break; + ir = istack[jstack--]; + l = istack[jstack--]; + } else { + k = (l + ir) >> 1; /* Choose median of left, center, right */ + PNL_SWAP(pnl[k], pnl[l + 1]); + if (MDBX_PNL_ORDERED(pnl[ir], pnl[l])) + PNL_SWAP(pnl[l], pnl[ir]); + + if (MDBX_PNL_ORDERED(pnl[ir], pnl[l + 1])) + PNL_SWAP(pnl[l + 1], pnl[ir]); + + if (MDBX_PNL_ORDERED(pnl[l + 1], pnl[l])) + PNL_SWAP(pnl[l], pnl[l + 1]); + + i = l + 1; + j = ir; + a = pnl[l + 1]; + while (1) { + do + i++; + while (MDBX_PNL_ORDERED(pnl[i], a)); + do + j--; + while (MDBX_PNL_ORDERED(a, pnl[j])); + if (j < i) + break; + PNL_SWAP(pnl[i], pnl[j]); + } + pnl[l + 1] = pnl[j]; + pnl[j] = a; + jstack += 2; + if (ir - i + 1 >= j - l) { + istack[jstack] = ir; + istack[jstack - 1] = i; + ir = j - 1; + } else { + istack[jstack] = j - 1; + istack[jstack - 1] = l; + l = i; + } + } + } +#undef PNL_SMALL +#undef PNL_SWAP + assert(mdbx_pnl_check(pnl, false)); +} + +/* Search for an ID in an PNL. + * [in] pl The PNL to search. + * [in] id The ID to search for. + * Returns The index of the first ID greater than or equal to id. */ +static unsigned __hot mdbx_pnl_search(MDBX_PNL pnl, pgno_t id) { + assert(mdbx_pnl_check(pnl, true)); + + /* binary search of id in pl + * if found, returns position of id + * if not found, returns first position greater than id */ + unsigned base = 0; + unsigned cursor = 1; + int val = 0; + unsigned n = MDBX_PNL_SIZE(pnl); + + while (n > 0) { + unsigned pivot = n >> 1; + cursor = base + pivot + 1; + val = MDBX_PNL_ASCENDING ? mdbx_cmp2int(id, pnl[cursor]) + : mdbx_cmp2int(pnl[cursor], id); + + if (val < 0) { + n = pivot; + } else if (val > 0) { + base = cursor; + n -= pivot + 1; + } else { + return cursor; + } + } + + if (val > 0) + ++cursor; + + return cursor; +} + +/*----------------------------------------------------------------------------*/ + +static __inline size_t txl2bytes(const size_t size) { + assert(size > 0 && size <= MDBX_TXL_MAX * 2); + size_t bytes = + mdbx_roundup2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(txnid_t) * (size + 2), + MDBX_TXL_GRANULATE * sizeof(txnid_t)) - + MDBX_ASSUME_MALLOC_OVERHEAD; + return bytes; +} + +static __inline size_t bytes2txl(const size_t bytes) { + size_t size = bytes / sizeof(txnid_t); + assert(size > 2 && size <= MDBX_TXL_MAX * 2); + return size - 2; +} + +static MDBX_TXL mdbx_txl_alloc(void) { + const size_t bytes = txl2bytes(MDBX_TXL_INITIAL); + MDBX_TXL tl = mdbx_malloc(bytes); + if (likely(tl)) { +#if __GLIBC_PREREQ(2, 12) + const size_t bytes = malloc_usable_size(tl); +#endif + tl[0] = bytes2txl(bytes); + assert(tl[0] >= MDBX_TXL_INITIAL); + tl[1] = 0; + tl += 1; + } + return tl; +} + +static void mdbx_txl_free(MDBX_TXL tl) { + if (likely(tl)) + mdbx_free(tl - 1); +} + +static int mdbx_txl_reserve(MDBX_TXL *ptl, const size_t wanna) { + const size_t allocated = (size_t)MDBX_PNL_ALLOCLEN(*ptl); + assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX && + MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl)); + if (likely(allocated >= wanna)) + return MDBX_SUCCESS; + + if (unlikely(wanna > /* paranoia */ MDBX_TXL_MAX)) + return MDBX_TXN_FULL; + + const size_t size = (wanna + wanna - allocated < MDBX_TXL_MAX) + ? wanna + wanna - allocated + : MDBX_TXL_MAX; + const size_t bytes = txl2bytes(size); + MDBX_TXL tl = mdbx_realloc(*ptl - 1, bytes); + if (likely(tl)) { +#if __GLIBC_PREREQ(2, 12) + const size_t bytes = malloc_usable_size(tl); +#endif + *tl = bytes2txl(bytes); + assert(*tl >= wanna); + *ptl = tl + 1; + return MDBX_SUCCESS; + } + return MDBX_ENOMEM; +} + +static __inline int __must_check_result mdbx_txl_need(MDBX_TXL *ptl, + size_t num) { + assert(MDBX_PNL_SIZE(*ptl) <= MDBX_TXL_MAX && + MDBX_PNL_ALLOCLEN(*ptl) >= MDBX_PNL_SIZE(*ptl)); + assert(num <= MDBX_PNL_MAX); + const size_t wanna = (size_t)MDBX_PNL_SIZE(*ptl) + num; + return likely(MDBX_PNL_ALLOCLEN(*ptl) >= wanna) + ? MDBX_SUCCESS + : mdbx_txl_reserve(ptl, wanna); +} + +static __inline void mdbx_txl_xappend(MDBX_TXL tl, txnid_t id) { + assert(MDBX_PNL_SIZE(tl) < MDBX_PNL_ALLOCLEN(tl)); + MDBX_PNL_SIZE(tl) += 1; + MDBX_PNL_LAST(tl) = id; +} + +static int mdbx_txl_cmp(const void *pa, const void *pb) { + const txnid_t a = *(MDBX_TXL)pa; + const txnid_t b = *(MDBX_TXL)pb; + return mdbx_cmp2int(b, a); +} + +static void mdbx_txl_sort(MDBX_TXL ptr) { + /* LY: temporary */ + qsort(ptr + 1, (size_t)ptr[0], sizeof(*ptr), mdbx_txl_cmp); +} + +static int __must_check_result mdbx_txl_append(MDBX_TXL *ptl, txnid_t id) { + if (unlikely(MDBX_PNL_SIZE(*ptl) == MDBX_PNL_ALLOCLEN(*ptl))) { + int rc = mdbx_txl_need(ptl, MDBX_TXL_GRANULATE); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + mdbx_txl_xappend(*ptl, id); + return MDBX_SUCCESS; +} + +static int __must_check_result mdbx_txl_append_list(MDBX_TXL *ptl, + MDBX_TXL append) { + int rc = mdbx_txl_need(ptl, (size_t)MDBX_PNL_SIZE(append)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + memcpy(MDBX_PNL_END(*ptl), MDBX_PNL_BEGIN(append), + (size_t)MDBX_PNL_SIZE(append) * sizeof(txnid_t)); + MDBX_PNL_SIZE(*ptl) += MDBX_PNL_SIZE(append); + return MDBX_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +/* Returns the index of the first dirty-page whose pgno + * member is greater than or equal to id. */ +static unsigned __hot mdbx_dpl_search(MDBX_DPL dl, pgno_t id) { + /* binary search of id in array + * if found, returns position of id + * if not found, returns first position greater than id */ + unsigned base = 0; + unsigned cursor = 1; + int val = 0; + unsigned n = dl->length; + +#if MDBX_DEBUG + for (const MDBX_DP *ptr = dl + dl->length; --ptr > dl;) { + assert(ptr[0].pgno < ptr[1].pgno); + assert(ptr[0].pgno >= NUM_METAS); + } +#endif + + while (n > 0) { + unsigned pivot = n >> 1; + cursor = base + pivot + 1; + val = mdbx_cmp2int(id, dl[cursor].pgno); + + if (val < 0) { + n = pivot; + } else if (val > 0) { + base = cursor; + n -= pivot + 1; + } else { + return cursor; + } + } + + if (val > 0) + ++cursor; + + return cursor; +} + +static int mdbx_dpl_cmp(const void *pa, const void *pb) { + const MDBX_DP a = *(MDBX_DPL)pa; + const MDBX_DP b = *(MDBX_DPL)pb; + return mdbx_cmp2int(a.pgno, b.pgno); +} + +static void mdbx_dpl_sort(MDBX_DPL dl) { + assert(dl->length <= MDBX_DPL_TXNFULL); + /* LY: temporary */ + qsort(dl + 1, dl->length, sizeof(*dl), mdbx_dpl_cmp); +} + +static int __must_check_result mdbx_dpl_insert(MDBX_DPL dl, pgno_t pgno, + MDBX_page *page) { + assert(dl->length <= MDBX_DPL_TXNFULL); + unsigned x = mdbx_dpl_search(dl, pgno); + assert((int)x > 0); + if (unlikely(dl[x].pgno == pgno && x <= dl->length)) + return /* duplicate */ MDBX_PROBLEM; + + if (unlikely(dl->length == MDBX_DPL_TXNFULL)) + return MDBX_TXN_FULL; + + /* insert page */ + for (unsigned i = dl->length += 1; i > x; --i) + dl[i] = dl[i - 1]; + + dl[x].pgno = pgno; + dl[x].ptr = page; + return MDBX_SUCCESS; +} + +static int __must_check_result mdbx_dpl_append(MDBX_DPL dl, pgno_t pgno, + MDBX_page *page) { + assert(dl->length <= MDBX_DPL_TXNFULL); +#if MDBX_DEBUG + for (unsigned i = dl->length; i > 0; --i) { + assert(dl[i].pgno != pgno); + if (unlikely(dl[i].pgno == pgno)) + return MDBX_PROBLEM; + } +#endif + + if (unlikely(dl->length == MDBX_DPL_TXNFULL)) + return MDBX_TXN_FULL; + + /* append page */ + const unsigned i = dl->length += 1; + dl[i].pgno = pgno; + dl[i].ptr = page; + return MDBX_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +int mdbx_runtime_flags = MDBX_DBG_PRINT +#if MDBX_DEBUG + | MDBX_DBG_ASSERT +#endif +#if MDBX_DEBUG > 1 + | MDBX_DBG_TRACE +#endif +#if MDBX_DEBUG > 2 + | MDBX_DBG_AUDIT +#endif +#if MDBX_DEBUG > 3 + | MDBX_DBG_EXTRA +#endif + ; + +MDBX_debug_func *mdbx_debug_logger; + +static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, + int flags); +static int mdbx_page_new(MDBX_cursor *mc, uint32_t flags, unsigned num, + MDBX_page **mp); +static int mdbx_page_touch(MDBX_cursor *mc); +static int mdbx_cursor_touch(MDBX_cursor *mc); + +#define MDBX_END_NAMES \ + { \ + "committed", "empty-commit", "abort", "reset", "reset-tmp", "fail-begin", \ + "fail-beginchild" \ + } +enum { + /* mdbx_txn_end operation number, for logging */ + MDBX_END_COMMITTED, + MDBX_END_EMPTY_COMMIT, + MDBX_END_ABORT, + MDBX_END_RESET, + MDBX_END_RESET_TMP, + MDBX_END_FAIL_BEGIN, + MDBX_END_FAIL_BEGINCHILD +}; +#define MDBX_END_OPMASK 0x0F /* mask for mdbx_txn_end() operation number */ +#define MDBX_END_UPDATE 0x10 /* update env state (DBIs) */ +#define MDBX_END_FREE 0x20 /* free txn unless it is MDBX_env.me_txn0 */ +#define MDBX_END_EOTDONE 0x40 /* txn's cursors already closed */ +#define MDBX_END_SLOT 0x80 /* release any reader slot if MDBX_NOTLS */ +static int mdbx_txn_end(MDBX_txn *txn, unsigned mode); + +static int __must_check_result mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, + MDBX_page **mp, int *lvl); +static int __must_check_result mdbx_page_search_root(MDBX_cursor *mc, + MDBX_val *key, int modify); + +#define MDBX_PS_MODIFY 1 +#define MDBX_PS_ROOTONLY 2 +#define MDBX_PS_FIRST 4 +#define MDBX_PS_LAST 8 +static int __must_check_result mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, + int flags); +static int __must_check_result mdbx_page_merge(MDBX_cursor *csrc, + MDBX_cursor *cdst); + +#define MDBX_SPLIT_REPLACE MDBX_APPENDDUP /* newkey is not new */ +static int __must_check_result mdbx_page_split(MDBX_cursor *mc, + const MDBX_val *newkey, + MDBX_val *newdata, + pgno_t newpgno, unsigned nflags); + +static int __must_check_result mdbx_read_header(MDBX_env *env, MDBX_meta *meta, + uint64_t *filesize); +static int __must_check_result mdbx_sync_locked(MDBX_env *env, unsigned flags, + MDBX_meta *const pending); +static void mdbx_env_close0(MDBX_env *env); + +static MDBX_node *mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, int *exactp); + +static int __must_check_result mdbx_node_add_branch(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key, + pgno_t pgno); +static int __must_check_result mdbx_node_add_leaf(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key, + MDBX_val *data, + unsigned flags); +static int __must_check_result mdbx_node_add_leaf2(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key); + +static void mdbx_node_del(MDBX_cursor *mc, size_t ksize); +static void mdbx_node_shrink(MDBX_page *mp, unsigned indx); +static int __must_check_result mdbx_node_move(MDBX_cursor *csrc, + MDBX_cursor *cdst, int fromleft); +static int __must_check_result mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf, + MDBX_val *data); +static size_t mdbx_leaf_size(MDBX_env *env, const MDBX_val *key, + const MDBX_val *data); +static size_t mdbx_branch_size(MDBX_env *env, const MDBX_val *key); + +static int __must_check_result mdbx_rebalance(MDBX_cursor *mc); +static int __must_check_result mdbx_update_key(MDBX_cursor *mc, + const MDBX_val *key); + +static void mdbx_cursor_pop(MDBX_cursor *mc); +static int __must_check_result mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp); + +static int __must_check_result mdbx_cursor_check(MDBX_cursor *mc, bool pending); +static int __must_check_result mdbx_cursor_del0(MDBX_cursor *mc); +static int __must_check_result mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, + MDBX_val *key, MDBX_val *data, + unsigned flags); +static int __must_check_result mdbx_cursor_sibling(MDBX_cursor *mc, + int move_right); +static int __must_check_result mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data, + MDBX_cursor_op op); +static int __must_check_result mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data, + MDBX_cursor_op op); +static int __must_check_result mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data, + MDBX_cursor_op op, int *exactp); +static int __must_check_result mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data); +static int __must_check_result mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, + MDBX_val *data); + +static int __must_check_result mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, + MDBX_dbi dbi); +static int __must_check_result mdbx_xcursor_init0(MDBX_cursor *mc); +static int __must_check_result mdbx_xcursor_init1(MDBX_cursor *mc, + MDBX_node *node); +static int __must_check_result mdbx_xcursor_init2(MDBX_cursor *mc, + MDBX_xcursor *src_mx, + int force); + +static int __must_check_result mdbx_drop0(MDBX_cursor *mc, int subs); + +static MDBX_cmp_func mdbx_cmp_memn, mdbx_cmp_memnr, mdbx_cmp_int_ai, + mdbx_cmp_int_a2, mdbx_cmp_int_ua; + +static const char *__mdbx_strerr(int errnum) { + /* Table of descriptions for MDBX errors */ + static const char *const tbl[] = { + "MDBX_KEYEXIST: Key/data pair already exists", + "MDBX_NOTFOUND: No matching key/data pair found", + "MDBX_PAGE_NOTFOUND: Requested page not found", + "MDBX_CORRUPTED: Database is corrupted", + "MDBX_PANIC: Update of meta page failed or environment had fatal error", + "MDBX_VERSION_MISMATCH: DB version mismatch libmdbx", + "MDBX_INVALID: File is not an MDBX file", + "MDBX_MAP_FULL: Environment mapsize limit reached", + "MDBX_DBS_FULL: Too may DBI (maxdbs reached)", + "MDBX_READERS_FULL: Too many readers (maxreaders reached)", + NULL /* MDBX_TLS_FULL (-30789): unused in MDBX */, + "MDBX_TXN_FULL: Transaction has too many dirty pages - transaction too " + "big", + "MDBX_CURSOR_FULL: Internal error - cursor stack limit reached", + "MDBX_PAGE_FULL: Internal error - page has no more space", + "MDBX_MAP_RESIZED: Database contents grew beyond environment mapsize", + "MDBX_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed", + "MDBX_BAD_RSLOT: Invalid reuse of reader locktable slot", + "MDBX_BAD_TXN: Transaction must abort, has a child, or is invalid", + "MDBX_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong " + "DUPFIXED size", + "MDBX_BAD_DBI: The specified DBI handle was closed/changed unexpectedly", + "MDBX_PROBLEM: Unexpected problem - txn should abort", + "MDBX_BUSY: Another write transaction is started", + }; + + if (errnum >= MDBX_KEYEXIST && errnum <= MDBX_LAST_ERRCODE) { + int i = errnum - MDBX_KEYEXIST; + return tbl[i]; + } + + switch (errnum) { + case MDBX_SUCCESS: + return "MDBX_SUCCESS: Successful"; + case MDBX_EMULTIVAL: + return "MDBX_EMULTIVAL: Unable to update multi-value for the given key"; + case MDBX_EBADSIGN: + return "MDBX_EBADSIGN: Wrong signature of a runtime object(s)"; + case MDBX_WANNA_RECOVERY: + return "MDBX_WANNA_RECOVERY: Database should be recovered, but this could " + "NOT be done in a read-only mode"; + case MDBX_EKEYMISMATCH: + return "MDBX_EKEYMISMATCH: The given key value is mismatched to the " + "current cursor position"; + case MDBX_TOO_LARGE: + return "MDBX_TOO_LARGE: Database is too large for current system, " + "e.g. could NOT be mapped into RAM"; + case MDBX_THREAD_MISMATCH: + return "MDBX_THREAD_MISMATCH: A thread has attempted to use a not " + "owned object, e.g. a transaction that started by another thread"; + default: + return NULL; + } +} + +const char *__cold mdbx_strerror_r(int errnum, char *buf, size_t buflen) { + const char *msg = __mdbx_strerr(errnum); + if (!msg) { + if (!buflen || buflen > INT_MAX) + return NULL; +#if defined(_WIN32) || defined(_WIN64) + size_t size = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (DWORD)buflen, + NULL); + return size ? buf : NULL; +#elif defined(_GNU_SOURCE) && defined(__GLIBC__) + /* GNU-specific */ + msg = strerror_r(errnum, buf, buflen); +#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) + /* XSI-compliant */ + int rc = strerror_r(errnum, buf, buflen); + if (rc) { + rc = snprintf(buf, buflen, "error %d", errnum); + assert(rc > 0); + } + return buf; +#else + strncpy(buf, strerror(errnum), buflen); + buf[buflen - 1] = '\0'; + return buf; +#endif + } + return msg; +} + +const char *__cold mdbx_strerror(int errnum) { + const char *msg = __mdbx_strerr(errnum); + if (!msg) { +#if defined(_WIN32) || defined(_WIN64) + static char buffer[1024]; + size_t size = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, + sizeof(buffer), NULL); + if (size) + msg = buffer; +#else + if (errnum < 0) { + static char buffer[32]; + int rc = snprintf(buffer, sizeof(buffer) - 1, "unknown error %d", errnum); + assert(rc > 0); + (void)rc; + return buffer; + } + msg = strerror(errnum); +#endif + } + return msg; +} + +static txnid_t mdbx_oomkick(MDBX_env *env, const txnid_t laggard); + +void __cold mdbx_debug_log(int type, const char *function, int line, + const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + if (mdbx_debug_logger) + mdbx_debug_logger(type, function, line, fmt, args); + else { +#if defined(_WIN32) || defined(_WIN64) + if (IsDebuggerPresent()) { + int prefix_len = 0; + char *prefix = nullptr; + if (function && line > 0) + prefix_len = mdbx_asprintf(&prefix, "%s:%d ", function, line); + else if (function) + prefix_len = mdbx_asprintf(&prefix, "%s: ", function); + else if (line > 0) + prefix_len = mdbx_asprintf(&prefix, "%d: ", line); + if (prefix_len > 0 && prefix) { + OutputDebugStringA(prefix); + mdbx_free(prefix); + } + char *msg = nullptr; + int msg_len = mdbx_vasprintf(&msg, fmt, args); + if (msg_len > 0 && msg) { + OutputDebugStringA(msg); + mdbx_free(msg); + } + } +#else + if (function && line > 0) + fprintf(stderr, "%s:%d ", function, line); + else if (function) + fprintf(stderr, "%s: ", function); + else if (line > 0) + fprintf(stderr, "%d: ", line); + vfprintf(stderr, fmt, args); + fflush(stderr); +#endif + } + va_end(args); +} + +/* Dump a key in ascii or hexadecimal. */ +char *mdbx_dkey(const MDBX_val *key, char *const buf, const size_t bufsize) { + if (!key) + return ""; + if (!buf || bufsize < 4) + return nullptr; + if (!key->iov_len) + return ""; + + const uint8_t *const data = key->iov_base; + bool is_ascii = true; + unsigned i; + for (i = 0; is_ascii && i < key->iov_len; i++) + if (data[i] < ' ' || data[i] > 127) + is_ascii = false; + + if (is_ascii) { + int len = + snprintf(buf, bufsize, "%.*s", + (key->iov_len > INT_MAX) ? INT_MAX : (int)key->iov_len, data); + assert(len > 0 && (unsigned)len < bufsize); + (void)len; + } else { + char *const detent = buf + bufsize - 2; + char *ptr = buf; + *ptr++ = '<'; + for (i = 0; i < key->iov_len; i++) { + const ptrdiff_t left = detent - ptr; + assert(left > 0); + int len = snprintf(ptr, left, "%02x", data[i]); + if (len < 0 || len >= left) + break; + ptr += len; + } + if (ptr < detent) { + ptr[0] = '>'; + ptr[1] = '\0'; + } + } + return buf; +} + +#if 0 /* LY: debug stuff */ +static const char *mdbx_leafnode_type(MDBX_node *n) { + static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}}; + return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" + : tp[F_ISSET(n->mn_flags, F_DUPDATA)] + [F_ISSET(n->mn_flags, F_SUBDATA)]; +} + +/* Display all the keys in the page. */ +static void mdbx_page_list(MDBX_page *mp) { + pgno_t pgno = mp->mp_pgno; + const char *type, *state = IS_DIRTY(mp) ? ", dirty" : ""; + MDBX_node *node; + unsigned i, nkeys, nsize, total = 0; + MDBX_val key; + DKBUF; + + switch (mp->mp_flags & + (P_BRANCH | P_LEAF | P_LEAF2 | P_META | P_OVERFLOW | P_SUBP)) { + case P_BRANCH: + type = "Branch page"; + break; + case P_LEAF: + type = "Leaf page"; + break; + case P_LEAF | P_SUBP: + type = "Leaf sub-page"; + break; + case P_LEAF | P_LEAF2: + type = "Leaf2 page"; + break; + case P_LEAF | P_LEAF2 | P_SUBP: + type = "Leaf2 sub-page"; + break; + case P_OVERFLOW: + mdbx_print("Overflow page %" PRIu64 " pages %u%s\n", pgno, mp->mp_pages, + state); + return; + case P_META: + mdbx_print("Meta-page %" PRIu64 " txnid %" PRIu64 "\n", pgno, + ((MDBX_meta *)PAGEDATA(mp))->mm_txnid); + return; + default: + mdbx_print("Bad page %" PRIu64 " flags 0x%X\n", pgno, mp->mp_flags); + return; + } + + nkeys = NUMKEYS(mp); + mdbx_print("%s %" PRIu64 " numkeys %u%s\n", type, pgno, nkeys, state); + + for (i = 0; i < nkeys; i++) { + if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */ + key.iov_len = nsize = mp->mp_leaf2_ksize; + key.iov_base = LEAF2KEY(mp, i, nsize); + total += nsize; + mdbx_print("key %u: nsize %u, %s\n", i, nsize, DKEY(&key)); + continue; + } + node = NODEPTR(mp, i); + key.iov_len = node->mn_ksize; + key.iov_base = node->mn_data; + nsize = NODESIZE + key.iov_len; + if (IS_BRANCH(mp)) { + mdbx_print("key %u: page %" PRIu64 ", %s\n", i, NODEPGNO(node), + DKEY(&key)); + total += nsize; + } else { + if (F_ISSET(node->mn_flags, F_BIGDATA)) + nsize += sizeof(pgno_t); + else + nsize += NODEDSZ(node); + total += nsize; + nsize += sizeof(indx_t); + mdbx_print("key %u: nsize %u, %s%s\n", i, nsize, DKEY(&key), + mdbx_leafnode_type(node)); + } + total = EVEN(total); + } + mdbx_print("Total: header %u + contents %u + unused %u\n", + IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower, total, + SIZELEFT(mp)); +} + +static void mdbx_cursor_chk(MDBX_cursor *mc) { + unsigned i; + MDBX_node *node; + MDBX_page *mp; + + if (!mc->mc_snum || !(mc->mc_flags & C_INITIALIZED)) + return; + for (i = 0; i < mc->mc_top; i++) { + mp = mc->mc_pg[i]; + node = NODEPTR(mp, mc->mc_ki[i]); + if (unlikely(NODEPGNO(node) != mc->mc_pg[i + 1]->mp_pgno)) + mdbx_print("oops!\n"); + } + if (unlikely(mc->mc_ki[i] >= NUMKEYS(mc->mc_pg[i]))) + mdbx_print("ack!\n"); + if (XCURSOR_INITED(mc)) { + node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (((node->mn_flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) && + mc->mc_xcursor->mx_cursor.mc_pg[0] != NODEDATA(node)) { + mdbx_print("blah!\n"); + } + } +} +#endif /* 0 */ + +int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, + const MDBX_val *b) { + mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); + return txn->mt_dbxs[dbi].md_cmp(a, b); +} + +int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, + const MDBX_val *b) { + mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); + return txn->mt_dbxs[dbi].md_dcmp(a, b); +} + +/* Allocate memory for a page. + * Re-use old malloc'd pages first for singletons, otherwise just malloc. + * Set MDBX_TXN_ERROR on failure. */ +static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) { + MDBX_env *env = txn->mt_env; + MDBX_page *np = env->me_dpages; + size_t size = env->me_psize; + if (likely(num == 1 && np)) { + ASAN_UNPOISON_MEMORY_REGION(np, size); + VALGRIND_MEMPOOL_ALLOC(env, np, size); + VALGRIND_MAKE_MEM_DEFINED(&np->mp_next, sizeof(np->mp_next)); + env->me_dpages = np->mp_next; + } else { + size = pgno2bytes(env, num); + np = mdbx_malloc(size); + if (unlikely(!np)) { + txn->mt_flags |= MDBX_TXN_ERROR; + return np; + } + VALGRIND_MEMPOOL_ALLOC(env, np, size); + } + + if ((env->me_flags & MDBX_NOMEMINIT) == 0) { + /* For a single page alloc, we init everything after the page header. + * For multi-page, we init the final page; if the caller needed that + * many pages they will be filling in at least up to the last page. */ + size_t skip = PAGEHDRSZ; + if (num > 1) + skip += pgno2bytes(env, num - 1); + memset((char *)np + skip, 0, size - skip); + } +#if MDBX_DEBUG + np->mp_pgno = 0; +#endif + VALGRIND_MAKE_MEM_UNDEFINED(np, size); + np->mp_flags = 0; + np->mp_pages = num; + return np; +} + +/* Free a dirty page */ +static void mdbx_dpage_free(MDBX_env *env, MDBX_page *dp, unsigned pages) { +#if MDBX_DEBUG + dp->mp_pgno = MAX_PAGENO; +#endif + if (pages == 1) { + dp->mp_next = env->me_dpages; + VALGRIND_MEMPOOL_FREE(env, dp); + env->me_dpages = dp; + } else { + /* large pages just get freed directly */ + VALGRIND_MEMPOOL_FREE(env, dp); + mdbx_free(dp); + } +} + +/* Return all dirty pages to dpage list */ +static void mdbx_dlist_free(MDBX_txn *txn) { + MDBX_env *env = txn->mt_env; + MDBX_DPL dl = txn->mt_rw_dirtylist; + size_t i, n = dl->length; + + for (i = 1; i <= n; i++) { + MDBX_page *dp = dl[i].ptr; + mdbx_dpage_free(env, dp, IS_OVERFLOW(dp) ? dp->mp_pages : 1); + } + + dl->length = 0; +} + +static size_t bytes_align2os_bytes(const MDBX_env *env, size_t bytes) { + return mdbx_roundup2(mdbx_roundup2(bytes, env->me_psize), env->me_os_psize); +} + +static void __cold mdbx_kill_page(MDBX_env *env, MDBX_page *mp) { + const size_t len = env->me_psize - PAGEHDRSZ; + void *ptr = (env->me_flags & MDBX_WRITEMAP) + ? &mp->mp_data + : (void *)((uint8_t *)env->me_pbuf + env->me_psize); + memset(ptr, 0x6F /* 'o', 111 */, len); + if (ptr != &mp->mp_data) + (void)mdbx_pwrite(env->me_fd, ptr, len, + pgno2bytes(env, mp->mp_pgno) + PAGEHDRSZ); + + VALGRIND_MAKE_MEM_NOACCESS(&mp->mp_data, len); + ASAN_POISON_MEMORY_REGION(&mp->mp_data, len); +} + +static __inline MDBX_db *mdbx_outer_db(MDBX_cursor *mc) { + mdbx_cassert(mc, (mc->mc_flags & C_SUB) != 0); + MDBX_xcursor *mx = container_of(mc->mc_db, MDBX_xcursor, mx_db); + MDBX_cursor_couple *couple = container_of(mx, MDBX_cursor_couple, inner); + mdbx_cassert(mc, mc->mc_db == &couple->outer.mc_xcursor->mx_db); + mdbx_cassert(mc, mc->mc_dbx == &couple->outer.mc_xcursor->mx_dbx); + return couple->outer.mc_db; +} + +static int mdbx_page_befree(MDBX_cursor *mc, MDBX_page *mp) { + MDBX_txn *txn = mc->mc_txn; + + mdbx_cassert(mc, (mc->mc_flags & C_SUB) == 0); + if (IS_BRANCH(mp)) { + mc->mc_db->md_branch_pages--; + } else if (IS_LEAF(mp)) { + mc->mc_db->md_leaf_pages--; + } else { + mdbx_cassert(mc, IS_OVERFLOW(mp)); + mc->mc_db->md_overflow_pages -= mp->mp_pages; + return mdbx_pnl_append_range(&txn->mt_befree_pages, mp->mp_pgno, + mp->mp_pages); + } + + return mdbx_pnl_append(&txn->mt_befree_pages, mp->mp_pgno); +} + +/* Loosen or free a single page. + * + * Saves single pages to a list for future reuse + * in this same txn. It has been pulled from the freeDB + * and already resides on the dirty list, but has been + * deleted. Use these pages first before pulling again + * from the freeDB. + * + * If the page wasn't dirtied in this txn, just add it + * to this txn's free list. */ +static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) { + int loose = 0; + const pgno_t pgno = mp->mp_pgno; + MDBX_txn *txn = mc->mc_txn; + + if (unlikely(mc->mc_flags & C_SUB)) { + MDBX_db *outer = mdbx_outer_db(mc); + if (IS_BRANCH(mp)) + outer->md_branch_pages--; + else { + mdbx_cassert(mc, IS_LEAF(mp)); + outer->md_leaf_pages--; + } + } + + if (IS_BRANCH(mp)) + mc->mc_db->md_branch_pages--; + else { + mdbx_cassert(mc, IS_LEAF(mp)); + mc->mc_db->md_leaf_pages--; + } + + if (IS_DIRTY(mp)) { + if (txn->mt_parent) { + /* LY: TODO: use dedicated flag for tracking parent's dirty pages */ + mdbx_cassert(mc, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0); + MDBX_DP *dl = txn->mt_rw_dirtylist; + /* If txn has a parent, + * make sure the page is in our dirty list. */ + if (dl->length) { + unsigned x = mdbx_dpl_search(dl, pgno); + if (x <= dl->length && dl[x].pgno == pgno) { + if (unlikely(mp != dl[x].ptr)) { /* bad cursor? */ + mdbx_error("wrong page 0x%p #%" PRIaPGNO + " in the dirtylist[%d], expecting %p", + dl[x].ptr, pgno, x, mp); + mc->mc_flags &= ~(C_INITIALIZED | C_EOF); + txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PROBLEM; + } + /* ok, it's ours */ + loose = 1; + } + } + } else { + /* no parent txn, so it's just ours */ + loose = 1; + } + } + + if (loose) { + mdbx_debug("loosen db %d page %" PRIaPGNO, DDBI(mc), mp->mp_pgno); + MDBX_page **link = &NEXT_LOOSE_PAGE(mp); + if (unlikely(txn->mt_env->me_flags & MDBX_PAGEPERTURB)) + mdbx_kill_page(txn->mt_env, mp); + mp->mp_flags = P_LOOSE | P_DIRTY; + VALGRIND_MAKE_MEM_UNDEFINED(mp, PAGEHDRSZ); + ASAN_UNPOISON_MEMORY_REGION(link, sizeof(*link)); + *link = txn->mt_loose_pages; + txn->mt_loose_pages = mp; + txn->mt_loose_count++; + } else { + int rc = mdbx_pnl_append(&txn->mt_befree_pages, pgno); + mdbx_tassert(txn, rc == MDBX_SUCCESS); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + return MDBX_SUCCESS; +} + +/* Set or clear P_KEEP in dirty, non-overflow, non-sub pages watched by txn. + * + * [in] mc A cursor handle for the current operation. + * [in] pflags Flags of the pages to update: + * - P_DIRTY to set P_KEEP, + * - P_DIRTY|P_KEEP to clear it. + * [in] all No shortcuts. Needed except after a full mdbx_page_flush(). + * + * Returns 0 on success, non-zero on failure. */ +static int mdbx_pages_xkeep(MDBX_cursor *mc, unsigned pflags, bool all) { + const unsigned Mask = P_SUBP | P_DIRTY | P_LOOSE | P_KEEP; + MDBX_txn *txn = mc->mc_txn; + MDBX_cursor *m3, *m0 = mc; + MDBX_xcursor *mx; + MDBX_page *dp, *mp; + MDBX_node *leaf; + unsigned i, j; + int rc = MDBX_SUCCESS, level; + + /* Mark pages seen by cursors: First m0, then tracked cursors */ + for (i = txn->mt_numdbs;;) { + if (mc->mc_flags & C_INITIALIZED) { + for (m3 = mc;; m3 = &mx->mx_cursor) { + mp = NULL; + for (j = 0; j < m3->mc_snum; j++) { + mp = m3->mc_pg[j]; + if ((mp->mp_flags & Mask) == pflags) + mp->mp_flags ^= P_KEEP; + } + mx = m3->mc_xcursor; + /* Proceed to mx if it is at a sub-database */ + if (!(mx && (mx->mx_cursor.mc_flags & C_INITIALIZED))) + break; + if (!(mp && IS_LEAF(mp))) + break; + leaf = NODEPTR(mp, m3->mc_ki[j - 1]); + if (!(leaf->mn_flags & F_SUBDATA)) + break; + } + } + mc = mc->mc_next; + for (; !mc || mc == m0; mc = txn->mt_cursors[--i]) + if (i == 0) + goto mark_done; + } + +mark_done: + if (all) { + /* Mark dirty root pages */ + for (i = 0; i < txn->mt_numdbs; i++) { + if (txn->mt_dbflags[i] & DB_DIRTY) { + pgno_t pgno = txn->mt_dbs[i].md_root; + if (pgno == P_INVALID) + continue; + if (unlikely((rc = mdbx_page_get(m0, pgno, &dp, &level)) != + MDBX_SUCCESS)) + break; + if ((dp->mp_flags & Mask) == pflags && level <= 1) + dp->mp_flags ^= P_KEEP; + } + } + } + + return rc; +} + +static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep); + +/* Spill pages from the dirty list back to disk. + * This is intended to prevent running into MDBX_TXN_FULL situations, + * but note that they may still occur in a few cases: + * + * 1) our estimate of the txn size could be too small. Currently this + * seems unlikely, except with a large number of MDBX_MULTIPLE items. + * + * 2) child txns may run out of space if their parents dirtied a + * lot of pages and never spilled them. TODO: we probably should do + * a preemptive spill during mdbx_txn_begin() of a child txn, if + * the parent's dirtyroom is below a given threshold. + * + * Otherwise, if not using nested txns, it is expected that apps will + * not run into MDBX_TXN_FULL any more. The pages are flushed to disk + * the same way as for a txn commit, e.g. their P_DIRTY flag is cleared. + * If the txn never references them again, they can be left alone. + * If the txn only reads them, they can be used without any fuss. + * If the txn writes them again, they can be dirtied immediately without + * going thru all of the work of mdbx_page_touch(). Such references are + * handled by mdbx_page_unspill(). + * + * Also note, we never spill DB root pages, nor pages of active cursors, + * because we'll need these back again soon anyway. And in nested txns, + * we can't spill a page in a child txn if it was already spilled in a + * parent txn. That would alter the parent txns' data even though + * the child hasn't committed yet, and we'd have no way to undo it if + * the child aborted. + * + * [in] m0 cursor A cursor handle identifying the transaction and + * database for which we are checking space. + * [in] key For a put operation, the key being stored. + * [in] data For a put operation, the data being stored. + * + * Returns 0 on success, non-zero on failure. */ +static int mdbx_page_spill(MDBX_cursor *m0, MDBX_val *key, MDBX_val *data) { + MDBX_txn *txn = m0->mc_txn; + MDBX_DPL dl = txn->mt_rw_dirtylist; + + if (m0->mc_flags & C_SUB) + return MDBX_SUCCESS; + + /* Estimate how much space this op will take */ + pgno_t i = m0->mc_db->md_depth; + /* Named DBs also dirty the main DB */ + if (m0->mc_dbi >= CORE_DBS) + i += txn->mt_dbs[MAIN_DBI].md_depth; + /* For puts, roughly factor in the key+data size */ + if (key) + i += bytes2pgno(txn->mt_env, LEAFSIZE(key, data) + txn->mt_env->me_psize); + i += i; /* double it for good measure */ + pgno_t need = i; + + if (txn->mt_dirtyroom > i) + return MDBX_SUCCESS; + + if (!txn->mt_spill_pages) { + txn->mt_spill_pages = mdbx_pnl_alloc(MDBX_DPL_TXNFULL); + if (unlikely(!txn->mt_spill_pages)) + return MDBX_ENOMEM; + } else { + /* purge deleted slots */ + MDBX_PNL sl = txn->mt_spill_pages; + pgno_t num = MDBX_PNL_SIZE(sl), j = 0; + for (i = 1; i <= num; i++) { + if ((sl[i] & 1) == 0) + sl[++j] = sl[i]; + } + MDBX_PNL_SIZE(sl) = j; + } + + /* Preserve pages which may soon be dirtied again */ + int rc = mdbx_pages_xkeep(m0, P_DIRTY, true); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + /* Less aggressive spill - we originally spilled the entire dirty list, + * with a few exceptions for cursor pages and DB root pages. But this + * turns out to be a lot of wasted effort because in a large txn many + * of those pages will need to be used again. So now we spill only 1/8th + * of the dirty pages. Testing revealed this to be a good tradeoff, + * better than 1/2, 1/4, or 1/10. */ + if (need < MDBX_DPL_TXNFULL / 8) + need = MDBX_DPL_TXNFULL / 8; + + /* Save the page IDs of all the pages we're flushing */ + /* flush from the tail forward, this saves a lot of shifting later on. */ + for (i = dl->length; i && need; i--) { + pgno_t pn = dl[i].pgno << 1; + MDBX_page *dp = dl[i].ptr; + if (dp->mp_flags & (P_LOOSE | P_KEEP)) + continue; + /* Can't spill twice, + * make sure it's not already in a parent's spill list. */ + if (txn->mt_parent) { + MDBX_txn *tx2; + for (tx2 = txn->mt_parent; tx2; tx2 = tx2->mt_parent) { + if (tx2->mt_spill_pages) { + unsigned j = mdbx_pnl_search(tx2->mt_spill_pages, pn); + if (j <= MDBX_PNL_SIZE(tx2->mt_spill_pages) && + tx2->mt_spill_pages[j] == pn) { + dp->mp_flags |= P_KEEP; + break; + } + } + } + if (tx2) + continue; + } + rc = mdbx_pnl_append(&txn->mt_spill_pages, pn); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + need--; + } + mdbx_pnl_sort(txn->mt_spill_pages); + + /* Flush the spilled part of dirty list */ + rc = mdbx_page_flush(txn, i); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + /* Reset any dirty pages we kept that page_flush didn't see */ + rc = mdbx_pages_xkeep(m0, P_DIRTY | P_KEEP, i != 0); + +bailout: + txn->mt_flags |= rc ? MDBX_TXN_ERROR : MDBX_TXN_SPILLS; + return rc; +} + +/*----------------------------------------------------------------------------*/ + +#define METAPAGE(env, n) (&pgno2page(env, n)->mp_meta) + +#define METAPAGE_END(env) METAPAGE(env, NUM_METAS) + +static __inline txnid_t meta_txnid(const MDBX_env *env, const MDBX_meta *meta, + bool allow_volatile) { + mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); + txnid_t a = meta->mm_txnid_a; + txnid_t b = meta->mm_txnid_b; + if (allow_volatile) + return (a == b) ? a : 0; + mdbx_assert(env, a == b); + return a; +} + +static __inline txnid_t mdbx_meta_txnid_stable(const MDBX_env *env, + const MDBX_meta *meta) { + return meta_txnid(env, meta, false); +} + +static __inline txnid_t mdbx_meta_txnid_fluid(const MDBX_env *env, + const MDBX_meta *meta) { + return meta_txnid(env, meta, true); +} + +static __inline void mdbx_meta_update_begin(const MDBX_env *env, + MDBX_meta *meta, txnid_t txnid) { + mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); + mdbx_assert(env, meta->mm_txnid_a < txnid && meta->mm_txnid_b < txnid); + meta->mm_txnid_a = txnid; + (void)env; + mdbx_flush_noncoherent_cpu_writeback(); +} + +static __inline void mdbx_meta_update_end(const MDBX_env *env, MDBX_meta *meta, + txnid_t txnid) { + mdbx_assert(env, meta >= METAPAGE(env, 0) || meta < METAPAGE_END(env)); + mdbx_assert(env, meta->mm_txnid_a == txnid); + mdbx_assert(env, meta->mm_txnid_b < txnid); + + mdbx_jitter4testing(true); + meta->mm_txnid_b = txnid; + mdbx_flush_noncoherent_cpu_writeback(); +} + +static __inline void mdbx_meta_set_txnid(const MDBX_env *env, MDBX_meta *meta, + txnid_t txnid) { + mdbx_assert(env, meta < METAPAGE(env, 0) || meta > METAPAGE_END(env)); + meta->mm_txnid_a = txnid; + meta->mm_txnid_b = txnid; +} + +static __inline uint64_t mdbx_meta_sign(const MDBX_meta *meta) { + uint64_t sign = MDBX_DATASIGN_NONE; +#if 0 /* TODO */ + sign = hippeus_hash64(...); +#else + (void)meta; +#endif + /* LY: newer returns MDBX_DATASIGN_NONE or MDBX_DATASIGN_WEAK */ + return (sign > MDBX_DATASIGN_WEAK) ? sign : ~sign; +} + +enum meta_choise_mode { prefer_last, prefer_noweak, prefer_steady }; + +static __inline bool mdbx_meta_ot(const enum meta_choise_mode mode, + const MDBX_env *env, const MDBX_meta *a, + const MDBX_meta *b) { + mdbx_jitter4testing(true); + txnid_t txnid_a = mdbx_meta_txnid_fluid(env, a); + txnid_t txnid_b = mdbx_meta_txnid_fluid(env, b); + + mdbx_jitter4testing(true); + switch (mode) { + default: + assert(false); + __unreachable(); + /* fall through */ + __fallthrough; + case prefer_steady: + if (META_IS_STEADY(a) != META_IS_STEADY(b)) + return META_IS_STEADY(b); + /* fall through */ + __fallthrough; + case prefer_noweak: + if (META_IS_WEAK(a) != META_IS_WEAK(b)) + return !META_IS_WEAK(b); + /* fall through */ + __fallthrough; + case prefer_last: + mdbx_jitter4testing(true); + if (txnid_a == txnid_b) + return META_IS_STEADY(b) || (META_IS_WEAK(a) && !META_IS_WEAK(b)); + return txnid_a < txnid_b; + } +} + +static __inline bool mdbx_meta_eq(const MDBX_env *env, const MDBX_meta *a, + const MDBX_meta *b) { + mdbx_jitter4testing(true); + const txnid_t txnid = mdbx_meta_txnid_fluid(env, a); + if (!txnid || txnid != mdbx_meta_txnid_fluid(env, b)) + return false; + + mdbx_jitter4testing(true); + if (META_IS_STEADY(a) != META_IS_STEADY(b)) + return false; + + mdbx_jitter4testing(true); + return true; +} + +static int mdbx_meta_eq_mask(const MDBX_env *env) { + MDBX_meta *m0 = METAPAGE(env, 0); + MDBX_meta *m1 = METAPAGE(env, 1); + MDBX_meta *m2 = METAPAGE(env, 2); + + int rc = mdbx_meta_eq(env, m0, m1) ? 1 : 0; + if (mdbx_meta_eq(env, m1, m2)) + rc += 2; + if (mdbx_meta_eq(env, m2, m0)) + rc += 4; + return rc; +} + +static __inline MDBX_meta *mdbx_meta_recent(const enum meta_choise_mode mode, + const MDBX_env *env, MDBX_meta *a, + MDBX_meta *b) { + const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b); + mdbx_assert(env, !mdbx_meta_eq(env, a, b)); + return a_older_that_b ? b : a; +} + +static __inline MDBX_meta *mdbx_meta_ancient(const enum meta_choise_mode mode, + const MDBX_env *env, MDBX_meta *a, + MDBX_meta *b) { + const bool a_older_that_b = mdbx_meta_ot(mode, env, a, b); + mdbx_assert(env, !mdbx_meta_eq(env, a, b)); + return a_older_that_b ? a : b; +} + +static __inline MDBX_meta * +mdbx_meta_mostrecent(const enum meta_choise_mode mode, const MDBX_env *env) { + MDBX_meta *m0 = METAPAGE(env, 0); + MDBX_meta *m1 = METAPAGE(env, 1); + MDBX_meta *m2 = METAPAGE(env, 2); + + MDBX_meta *head = mdbx_meta_recent(mode, env, m0, m1); + head = mdbx_meta_recent(mode, env, head, m2); + return head; +} + +static __hot MDBX_meta *mdbx_meta_steady(const MDBX_env *env) { + return mdbx_meta_mostrecent(prefer_steady, env); +} + +static __hot MDBX_meta *mdbx_meta_head(const MDBX_env *env) { + return mdbx_meta_mostrecent(prefer_last, env); +} + +static __hot txnid_t mdbx_reclaiming_detent(const MDBX_env *env) { + if (F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC)) + return likely(env->me_txn0->mt_owner == mdbx_thread_self()) + ? env->me_txn0->mt_txnid - 1 + : mdbx_meta_txnid_fluid(env, mdbx_meta_head(env)); + + return mdbx_meta_txnid_stable(env, mdbx_meta_steady(env)); +} + +static const char *mdbx_durable_str(const MDBX_meta *const meta) { + if (META_IS_WEAK(meta)) + return "Weak"; + if (META_IS_STEADY(meta)) + return (meta->mm_datasync_sign == mdbx_meta_sign(meta)) ? "Steady" + : "Tainted"; + return "Legacy"; +} + +/*----------------------------------------------------------------------------*/ + +/* Find oldest txnid still referenced. */ +static txnid_t mdbx_find_oldest(MDBX_txn *txn) { + mdbx_tassert(txn, (txn->mt_flags & MDBX_RDONLY) == 0); + MDBX_env *env = txn->mt_env; + const txnid_t edge = mdbx_reclaiming_detent(env); + mdbx_tassert(txn, edge <= txn->mt_txnid); + + MDBX_lockinfo *const lck = env->me_lck; + if (unlikely(lck == NULL /* exclusive mode */)) + return env->me_lckless_stub.oldest = edge; + + const txnid_t last_oldest = lck->mti_oldest_reader; + mdbx_tassert(txn, edge >= last_oldest); + if (likely(last_oldest == edge)) + return edge; + + const uint32_t nothing_changed = MDBX_STRING_TETRAD("None"); + const uint32_t snap_readers_refresh_flag = lck->mti_readers_refresh_flag; + mdbx_jitter4testing(false); + if (snap_readers_refresh_flag == nothing_changed) + return last_oldest; + + txnid_t oldest = edge; + lck->mti_readers_refresh_flag = nothing_changed; + mdbx_flush_noncoherent_cpu_writeback(); + const unsigned snap_nreaders = lck->mti_numreaders; + for (unsigned i = 0; i < snap_nreaders; ++i) { + if (lck->mti_readers[i].mr_pid) { + /* mdbx_jitter4testing(true); */ + const txnid_t snap = lck->mti_readers[i].mr_txnid; + if (oldest > snap && last_oldest <= /* ignore pending updates */ snap) { + oldest = snap; + if (oldest == last_oldest) + return oldest; + } + } + } + + if (oldest != last_oldest) { + mdbx_notice("update oldest %" PRIaTXN " -> %" PRIaTXN, last_oldest, oldest); + mdbx_tassert(txn, oldest >= lck->mti_oldest_reader); + lck->mti_oldest_reader = oldest; + } + return oldest; +} + +/* Find largest mvcc-snapshot still referenced. */ +static __cold pgno_t mdbx_find_largest(MDBX_env *env, pgno_t largest) { + MDBX_lockinfo *const lck = env->me_lck; + if (likely(lck != NULL /* exclusive mode */)) { + const unsigned snap_nreaders = lck->mti_numreaders; + for (unsigned i = 0; i < snap_nreaders; ++i) { + retry: + if (lck->mti_readers[i].mr_pid) { + /* mdbx_jitter4testing(true); */ + const pgno_t snap_pages = lck->mti_readers[i].mr_snapshot_pages_used; + const txnid_t snap_txnid = lck->mti_readers[i].mr_txnid; + mdbx_memory_barrier(); + if (unlikely(snap_pages != lck->mti_readers[i].mr_snapshot_pages_used || + snap_txnid != lck->mti_readers[i].mr_txnid)) + goto retry; + if (largest < snap_pages && + lck->mti_oldest_reader <= /* ignore pending updates */ snap_txnid && + snap_txnid <= env->me_txn0->mt_txnid) + largest = snap_pages; + } + } + } + + return largest; +} + +/* Add a page to the txn's dirty list */ +static int __must_check_result mdbx_page_dirty(MDBX_txn *txn, MDBX_page *mp) { + int (*const adder)(MDBX_DPL, pgno_t pgno, MDBX_page * page) = + (txn->mt_flags & MDBX_TXN_WRITEMAP) ? mdbx_dpl_append : mdbx_dpl_insert; + const int rc = adder(txn->mt_rw_dirtylist, mp->mp_pgno, mp); + if (unlikely(rc != MDBX_SUCCESS)) { + txn->mt_flags |= MDBX_TXN_ERROR; + return rc; + } + txn->mt_dirtyroom--; + return MDBX_SUCCESS; +} + +__cold static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno, + const pgno_t limit_pgno) { +#ifdef USE_VALGRIND + const size_t prev_mapsize = env->me_mapsize; + void *const prev_mapaddr = env->me_map; +#endif + + const size_t limit_bytes = pgno_align2os_bytes(env, limit_pgno); + const size_t size_bytes = pgno_align2os_bytes(env, size_pgno); + + mdbx_info("resize datafile/mapping: " + "present %" PRIuPTR " -> %" PRIuPTR ", " + "limit %" PRIuPTR " -> %" PRIuPTR, + env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes); + + mdbx_assert(env, limit_bytes >= size_bytes); + mdbx_assert(env, bytes2pgno(env, size_bytes) == size_pgno); + mdbx_assert(env, bytes2pgno(env, limit_bytes) == limit_pgno); + +#if defined(_WIN32) || defined(_WIN64) + /* Acquire guard in exclusive mode for: + * - to avoid collision between read and write txns around env->me_dbgeo; + * - to avoid attachment of new reading threads (see mdbx_rdt_lock); */ + mdbx_srwlock_AcquireExclusive(&env->me_remap_guard); + mdbx_handle_array_t *suspended = NULL; + mdbx_handle_array_t array_onstack; + int rc = MDBX_SUCCESS; + if (limit_bytes == env->me_dxb_mmap.length && + size_bytes == env->me_dxb_mmap.current && + env->me_dxb_mmap.current == env->me_dxb_mmap.filesize) + goto bailout; + + /* 1) Windows allows only extending a read-write section, but not a + * corresponing mapped view. Therefore in other cases we must suspend + * the local threads for safe remap. + * 2) At least on Windows 10 1803 the entire mapped section is unavailable + * for short time during NtExtendSection() or VirtualAlloc() execution. + * + * THEREFORE LOCAL THREADS SUSPENDING IS ALWAYS REQUIRED! */ + array_onstack.limit = ARRAY_LENGTH(array_onstack.handles); + array_onstack.count = 0; + suspended = &array_onstack; + rc = mdbx_suspend_threads_before_remap(env, &suspended); + if (rc != MDBX_SUCCESS) { + mdbx_error("failed suspend-for-remap: errcode %d", rc); + goto bailout; + } +#else + /* Acquire guard to avoid collision between read and write txns + * around env->me_dbgeo */ + int rc = mdbx_fastmutex_acquire(&env->me_remap_guard); + if (rc != MDBX_SUCCESS) + return rc; + if (limit_bytes == env->me_dxb_mmap.length && + bytes2pgno(env, size_bytes) == env->me_dbgeo.now) + goto bailout; +#endif /* Windows */ + + rc = mdbx_mresize(env->me_flags, &env->me_dxb_mmap, size_bytes, limit_bytes); + +bailout: + if (rc == MDBX_SUCCESS) { +#if defined(_WIN32) || defined(_WIN64) + mdbx_assert(env, size_bytes == env->me_dxb_mmap.current); + mdbx_assert(env, size_bytes <= env->me_dxb_mmap.filesize); + mdbx_assert(env, limit_bytes == env->me_dxb_mmap.length); +#endif + env->me_dbgeo.now = size_bytes; + env->me_dbgeo.upper = limit_bytes; + if (env->me_txn) { + mdbx_tassert(env->me_txn, size_pgno >= env->me_txn->mt_next_pgno); + env->me_txn->mt_end_pgno = env->me_txn0->mt_end_pgno = size_pgno; + } +#ifdef USE_VALGRIND + if (prev_mapsize != env->me_mapsize || prev_mapaddr != env->me_map) { + VALGRIND_DISCARD(env->me_valgrind_handle); + env->me_valgrind_handle = 0; + if (env->me_mapsize) + env->me_valgrind_handle = + VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx"); + } +#endif + } else { + if (rc != MDBX_RESULT_TRUE) { + mdbx_error("failed resize datafile/mapping: " + "present %" PRIuPTR " -> %" PRIuPTR ", " + "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d", + env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, + limit_bytes, rc); + } else { + mdbx_notice("unable resize datafile/mapping: " + "present %" PRIuPTR " -> %" PRIuPTR ", " + "limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d", + env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, + limit_bytes, rc); + } + if (!env->me_dxb_mmap.address) { + env->me_flags |= MDBX_FATAL_ERROR; + if (env->me_txn) + env->me_txn->mt_flags |= MDBX_TXN_ERROR; + rc = MDBX_PANIC; + } + } + +#if defined(_WIN32) || defined(_WIN64) + int err = MDBX_SUCCESS; + mdbx_srwlock_ReleaseExclusive(&env->me_remap_guard); + if (suspended) { + err = mdbx_resume_threads_after_remap(suspended); + if (suspended != &array_onstack) + mdbx_free(suspended); + } +#else + int err = mdbx_fastmutex_release(&env->me_remap_guard); +#endif /* Windows */ + if (err != MDBX_SUCCESS) { + mdbx_fatal("failed resume-after-remap: errcode %d", err); + return MDBX_PANIC; + } + return rc; +} + +/* Allocate page numbers and memory for writing. Maintain me_last_reclaimed, + * me_reclaimed_pglist and mt_next_pgno. Set MDBX_TXN_ERROR on failure. + * + * If there are free pages available from older transactions, they + * are re-used first. Otherwise allocate a new page at mt_next_pgno. + * Do not modify the freedB, just merge freeDB records into me_reclaimed_pglist + * and move me_last_reclaimed to say which records were consumed. Only this + * function can create me_reclaimed_pglist and move + * me_last_reclaimed/mt_next_pgno. + * + * [in] mc cursor A cursor handle identifying the transaction and + * database for which we are allocating. + * [in] num the number of pages to allocate. + * [out] mp Address of the allocated page(s). Requests for multiple pages + * will always be satisfied by a single contiguous chunk of memory. + * + * Returns 0 on success, non-zero on failure.*/ + +#define MDBX_ALLOC_CACHE 1 +#define MDBX_ALLOC_GC 2 +#define MDBX_ALLOC_NEW 4 +#define MDBX_ALLOC_KICK 8 +#define MDBX_ALLOC_ALL \ + (MDBX_ALLOC_CACHE | MDBX_ALLOC_GC | MDBX_ALLOC_NEW | MDBX_ALLOC_KICK) + +static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp, + int flags) { + int rc; + MDBX_txn *txn = mc->mc_txn; + MDBX_env *env = txn->mt_env; + MDBX_page *np; + + if (likely(flags & MDBX_ALLOC_GC)) { + flags |= env->me_flags & (MDBX_COALESCE | MDBX_LIFORECLAIM); + if (unlikely(mc->mc_flags & C_RECLAIMING)) { + /* If mc is updating the freeDB, then the befree-list cannot play + * catch-up with itself by growing while trying to save it. */ + flags &= + ~(MDBX_ALLOC_GC | MDBX_ALLOC_KICK | MDBX_COALESCE | MDBX_LIFORECLAIM); + } else if (unlikely(txn->mt_dbs[FREE_DBI].md_entries == 0)) { + /* avoid (recursive) search inside empty tree and while tree is updating, + * https://github.com/leo-yuriev/libmdbx/issues/31 */ + flags &= ~MDBX_ALLOC_GC; + } + } + + if (likely(flags & MDBX_ALLOC_CACHE)) { + /* If there are any loose pages, just use them */ + mdbx_assert(env, mp && num); + if (likely(num == 1 && txn->mt_loose_pages)) { + np = txn->mt_loose_pages; + txn->mt_loose_pages = NEXT_LOOSE_PAGE(np); + txn->mt_loose_count--; + mdbx_debug("db %d use loose page %" PRIaPGNO, DDBI(mc), np->mp_pgno); + ASAN_UNPOISON_MEMORY_REGION(np, env->me_psize); + mdbx_tassert(txn, np->mp_pgno < txn->mt_next_pgno); + mdbx_ensure(env, np->mp_pgno >= NUM_METAS); + *mp = np; + return MDBX_SUCCESS; + } + } + + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + pgno_t pgno, *repg_list = env->me_reclaimed_pglist; + unsigned repg_pos = 0, repg_len = repg_list ? MDBX_PNL_SIZE(repg_list) : 0; + txnid_t oldest = 0, last = 0; + const unsigned wanna_range = num - 1; + + while (1) { /* oom-kick retry loop */ + /* If our dirty list is already full, we can't do anything */ + if (unlikely(txn->mt_dirtyroom == 0)) { + rc = MDBX_TXN_FULL; + goto fail; + } + + MDBX_cursor recur; + for (MDBX_cursor_op op = MDBX_FIRST;; + op = (flags & MDBX_LIFORECLAIM) ? MDBX_PREV : MDBX_NEXT) { + MDBX_val key, data; + + /* Seek a big enough contiguous page range. + * Prefer pages with lower pgno. */ + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (likely(flags & MDBX_ALLOC_CACHE) && repg_len > wanna_range && + (!(flags & MDBX_COALESCE) || op == MDBX_FIRST)) { +#if MDBX_PNL_ASCENDING + for (repg_pos = 1; repg_pos <= repg_len - wanna_range; ++repg_pos) { + pgno = repg_list[repg_pos]; + if (likely(repg_list[repg_pos + wanna_range - 1] == + pgno + wanna_range - 1)) + goto done; + } +#else + repg_pos = repg_len; + do { + pgno = repg_list[repg_pos]; + if (likely(repg_list[repg_pos - wanna_range] == pgno + wanna_range)) + goto done; + } while (--repg_pos > wanna_range); +#endif /* MDBX_PNL sort-order */ + } + + if (op == MDBX_FIRST) { /* 1st iteration, setup cursor, etc */ + if (unlikely(!(flags & MDBX_ALLOC_GC))) + break /* reclaiming is prohibited for now */; + + /* Prepare to fetch more and coalesce */ + oldest = (flags & MDBX_LIFORECLAIM) ? mdbx_find_oldest(txn) + : *env->me_oldest; + rc = mdbx_cursor_init(&recur, txn, FREE_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + if (flags & MDBX_LIFORECLAIM) { + /* Begin from oldest reader if any */ + if (oldest > 2) { + last = oldest - 1; + op = MDBX_SET_RANGE; + } + } else if (env->me_last_reclaimed) { + /* Continue lookup from env->me_last_reclaimed to oldest reader */ + last = env->me_last_reclaimed; + op = MDBX_SET_RANGE; + } + + key.iov_base = &last; + key.iov_len = sizeof(last); + } + + if (!(flags & MDBX_LIFORECLAIM)) { + /* Do not try fetch more if the record will be too recent */ + if (op != MDBX_FIRST && ++last >= oldest) { + oldest = mdbx_find_oldest(txn); + if (oldest <= last) + break; + } + } + + rc = mdbx_cursor_get(&recur, &key, NULL, op); + if (rc == MDBX_NOTFOUND && (flags & MDBX_LIFORECLAIM)) { + if (op == MDBX_SET_RANGE) + continue; + if (oldest < mdbx_find_oldest(txn)) { + oldest = *env->me_oldest; + last = oldest - 1; + key.iov_base = &last; + key.iov_len = sizeof(last); + op = MDBX_SET_RANGE; + rc = mdbx_cursor_get(&recur, &key, NULL, op); + } + } + if (unlikely(rc)) { + if (rc == MDBX_NOTFOUND) + break; + goto fail; + } + + last = *(txnid_t *)key.iov_base; + if (oldest <= last) { + oldest = mdbx_find_oldest(txn); + if (oldest <= last) { + if (flags & MDBX_LIFORECLAIM) + continue; + break; + } + } + + if (flags & MDBX_LIFORECLAIM) { + /* skip IDs of records that already reclaimed */ + if (txn->mt_lifo_reclaimed) { + unsigned i; + for (i = (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed); i > 0; --i) + if (txn->mt_lifo_reclaimed[i] == last) + break; + if (i) + continue; + } + } + + /* Reading next FreeDB record */ + np = recur.mc_pg[recur.mc_top]; + MDBX_node *leaf = NODEPTR(np, recur.mc_ki[recur.mc_top]); + if (unlikely((rc = mdbx_node_read(&recur, leaf, &data)) != MDBX_SUCCESS)) + goto fail; + + if ((flags & MDBX_LIFORECLAIM) && !txn->mt_lifo_reclaimed) { + txn->mt_lifo_reclaimed = mdbx_txl_alloc(); + if (unlikely(!txn->mt_lifo_reclaimed)) { + rc = MDBX_ENOMEM; + goto fail; + } + } + + /* Append PNL from FreeDB record to me_reclaimed_pglist */ + mdbx_cassert(mc, (mc->mc_flags & C_GCFREEZE) == 0); + pgno_t *re_pnl = (pgno_t *)data.iov_base; + mdbx_tassert(txn, data.iov_len >= MDBX_PNL_SIZEOF(re_pnl)); + mdbx_tassert(txn, mdbx_pnl_check(re_pnl, false)); + repg_pos = MDBX_PNL_SIZE(re_pnl); + if (!repg_list) { + if (unlikely(!(env->me_reclaimed_pglist = repg_list = + mdbx_pnl_alloc(repg_pos)))) { + rc = MDBX_ENOMEM; + goto fail; + } + } else { + if (unlikely( + (rc = mdbx_pnl_need(&env->me_reclaimed_pglist, repg_pos)) != 0)) + goto fail; + repg_list = env->me_reclaimed_pglist; + } + + /* Remember ID of FreeDB record */ + if (flags & MDBX_LIFORECLAIM) { + if ((rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, last)) != 0) + goto fail; + } + env->me_last_reclaimed = last; + + if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) { + mdbx_debug_extra("PNL read txn %" PRIaTXN " root %" PRIaPGNO + " num %u, PNL", + last, txn->mt_dbs[FREE_DBI].md_root, repg_pos); + unsigned i; + for (i = repg_pos; i; i--) + mdbx_debug_extra_print(" %" PRIaPGNO, re_pnl[i]); + mdbx_debug_extra_print("\n"); + } + + /* Merge in descending sorted order */ + mdbx_pnl_xmerge(repg_list, re_pnl); + repg_len = MDBX_PNL_SIZE(repg_list); + if (unlikely((flags & MDBX_ALLOC_CACHE) == 0)) { + /* Done for a kick-reclaim mode, actually no page needed */ + return MDBX_SUCCESS; + } + + mdbx_tassert(txn, + repg_len == 0 || repg_list[repg_len] < txn->mt_next_pgno); + if (repg_len) { + /* Refund suitable pages into "unallocated" space */ + pgno_t tail = txn->mt_next_pgno; + pgno_t *const begin = repg_list + 1; + pgno_t *const end = begin + repg_len; + pgno_t *higest; +#if MDBX_PNL_ASCENDING + for (higest = end; --higest >= begin;) { +#else + for (higest = begin; higest < end; ++higest) { +#endif /* MDBX_PNL sort-order */ + mdbx_tassert(txn, *higest >= NUM_METAS && *higest < tail); + if (*higest != tail - 1) + break; + tail -= 1; + } + if (tail != txn->mt_next_pgno) { +#if MDBX_PNL_ASCENDING + repg_len = (unsigned)(higest + 1 - begin); +#else + repg_len -= (unsigned)(higest - begin); + for (pgno_t *move = begin; higest < end; ++move, ++higest) + *move = *higest; +#endif /* MDBX_PNL sort-order */ + MDBX_PNL_SIZE(repg_list) = repg_len; + mdbx_info("refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO, + tail - txn->mt_next_pgno, tail, txn->mt_next_pgno); + txn->mt_next_pgno = tail; + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + } + } + + /* Don't try to coalesce too much. */ + if (unlikely(repg_len > MDBX_DPL_TXNFULL / 4)) + break; + if (repg_len /* current size */ >= env->me_maxgc_ov1page || + repg_pos /* prev size */ >= env->me_maxgc_ov1page / 2) + flags &= ~MDBX_COALESCE; + } + + if ((flags & (MDBX_COALESCE | MDBX_ALLOC_CACHE)) == + (MDBX_COALESCE | MDBX_ALLOC_CACHE) && + repg_len > wanna_range) { +#if MDBX_PNL_ASCENDING + for (repg_pos = 1; repg_pos <= repg_len - wanna_range; ++repg_pos) { + pgno = repg_list[repg_pos]; + if (likely(repg_list[repg_pos + wanna_range - 1] == + pgno + wanna_range - 1)) + goto done; + } +#else + repg_pos = repg_len; + do { + pgno = repg_list[repg_pos]; + if (likely(repg_list[repg_pos - wanna_range] == pgno + wanna_range)) + goto done; + } while (--repg_pos > wanna_range); +#endif /* MDBX_PNL sort-order */ + } + + /* Use new pages from the map when nothing suitable in the freeDB */ + repg_pos = 0; + pgno = txn->mt_next_pgno; + rc = MDBX_MAP_FULL; + const pgno_t next = pgno_add(pgno, num); + if (likely(next <= txn->mt_end_pgno)) { + rc = MDBX_NOTFOUND; + if (likely(flags & MDBX_ALLOC_NEW)) + goto done; + } + + const MDBX_meta *head = mdbx_meta_head(env); + if ((flags & MDBX_ALLOC_GC) && + ((flags & MDBX_ALLOC_KICK) || rc == MDBX_MAP_FULL)) { + MDBX_meta *steady = mdbx_meta_steady(env); + + if (oldest == mdbx_meta_txnid_stable(env, steady) && + !META_IS_STEADY(head) && META_IS_STEADY(steady)) { + /* LY: Here an oom was happened: + * - all pages had allocated; + * - reclaiming was stopped at the last steady-sync; + * - the head-sync is weak. + * Now we need make a sync to resume reclaiming. If both + * MDBX_NOSYNC and MDBX_MAPASYNC flags are set, then assume that + * utterly no-sync write mode was requested. In such case + * don't make a steady-sync, but only a legacy-mode checkpoint, + * just for resume reclaiming only, not for data consistency. */ + + mdbx_debug("kick-gc: head %" PRIaTXN "-%s, tail %" PRIaTXN + "-%s, oldest %" PRIaTXN, + mdbx_meta_txnid_stable(env, head), mdbx_durable_str(head), + mdbx_meta_txnid_stable(env, steady), + mdbx_durable_str(steady), oldest); + + const unsigned syncflags = F_ISSET(env->me_flags, MDBX_UTTERLY_NOSYNC) + ? env->me_flags + : env->me_flags & MDBX_WRITEMAP; + MDBX_meta meta = *head; + if (mdbx_sync_locked(env, syncflags, &meta) == MDBX_SUCCESS) { + txnid_t snap = mdbx_find_oldest(txn); + if (snap > oldest) + continue; + } + } + + if (rc == MDBX_MAP_FULL && oldest < txn->mt_txnid - 1) { + if (mdbx_oomkick(env, oldest) > oldest) + continue; + } + } + + if (rc == MDBX_MAP_FULL && next < head->mm_geo.upper) { + mdbx_assert(env, next > txn->mt_end_pgno); + pgno_t aligned = pgno_align2os_pgno( + env, pgno_add(next, head->mm_geo.grow - next % head->mm_geo.grow)); + + if (aligned > head->mm_geo.upper) + aligned = head->mm_geo.upper; + mdbx_assert(env, aligned > txn->mt_end_pgno); + + mdbx_info("try growth datafile to %" PRIaPGNO " pages (+%" PRIaPGNO ")", + aligned, aligned - txn->mt_end_pgno); + rc = mdbx_mapresize(env, aligned, head->mm_geo.upper); + if (rc == MDBX_SUCCESS) { + mdbx_tassert(env->me_txn, txn->mt_end_pgno >= next); + if (!mp) + return rc; + goto done; + } + + mdbx_warning("unable growth datafile to %" PRIaPGNO "pages (+%" PRIaPGNO + "), errcode %d", + aligned, aligned - txn->mt_end_pgno, rc); + } + + fail: + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (mp) { + *mp = NULL; + txn->mt_flags |= MDBX_TXN_ERROR; + } + mdbx_assert(env, rc != MDBX_SUCCESS); + return rc; + } + +done: + mdbx_tassert(txn, mp && num); + mdbx_ensure(env, pgno >= NUM_METAS); + if (env->me_flags & MDBX_WRITEMAP) { + np = pgno2page(env, pgno); + /* LY: reset no-access flag from mdbx_kill_page() */ + VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num)); + ASAN_UNPOISON_MEMORY_REGION(np, pgno2bytes(env, num)); + } else { + if (unlikely(!(np = mdbx_page_malloc(txn, num)))) { + rc = MDBX_ENOMEM; + goto fail; + } + } + + if (repg_pos) { + mdbx_cassert(mc, (mc->mc_flags & C_GCFREEZE) == 0); + mdbx_tassert(txn, pgno < txn->mt_next_pgno); + mdbx_tassert(txn, pgno == repg_list[repg_pos]); + /* Cutoff allocated pages from me_reclaimed_pglist */ + MDBX_PNL_SIZE(repg_list) = repg_len -= num; + for (unsigned i = repg_pos - num; i < repg_len;) + repg_list[++i] = repg_list[++repg_pos]; + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + } else { + txn->mt_next_pgno = pgno + num; + mdbx_assert(env, txn->mt_next_pgno <= txn->mt_end_pgno); + } + + if (env->me_flags & MDBX_PAGEPERTURB) + memset(np, 0x71 /* 'q', 113 */, pgno2bytes(env, num)); + VALGRIND_MAKE_MEM_UNDEFINED(np, pgno2bytes(env, num)); + + np->mp_pgno = pgno; + np->mp_leaf2_ksize = 0; + np->mp_flags = 0; + np->mp_pages = num; + rc = mdbx_page_dirty(txn, np); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + *mp = np; + + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + return MDBX_SUCCESS; +} + +/* Copy the used portions of a non-overflow page. + * [in] dst page to copy into + * [in] src page to copy from + * [in] psize size of a page */ +__hot static void mdbx_page_copy(MDBX_page *dst, MDBX_page *src, + unsigned psize) { + STATIC_ASSERT(UINT16_MAX > MAX_PAGESIZE - PAGEHDRSZ); + STATIC_ASSERT(MIN_PAGESIZE > PAGEHDRSZ + NODESIZE * 42); + enum { Align = sizeof(pgno_t) }; + indx_t upper = src->mp_upper, lower = src->mp_lower, unused = upper - lower; + + /* If page isn't full, just copy the used portion. Adjust + * alignment so memcpy may copy words instead of bytes. */ + if ((unused &= -Align) && !IS_LEAF2(src)) { + upper = (upper + PAGEHDRSZ) & -Align; + memcpy(dst, src, (lower + PAGEHDRSZ + (Align - 1)) & -Align); + memcpy((pgno_t *)((char *)dst + upper), (pgno_t *)((char *)src + upper), + psize - upper); + } else { + memcpy(dst, src, psize - unused); + } +} + +/* Pull a page off the txn's spill list, if present. + * + * If a page being referenced was spilled to disk in this txn, bring + * it back and make it dirty/writable again. + * + * [in] txn the transaction handle. + * [in] mp the page being referenced. It must not be dirty. + * [out] ret the writable page, if any. + * ret is unchanged if mp wasn't spilled. */ +__hot static int __must_check_result mdbx_page_unspill(MDBX_txn *txn, + MDBX_page *mp, + MDBX_page **ret) { + MDBX_env *env = txn->mt_env; + const MDBX_txn *tx2; + unsigned x; + pgno_t pgno = mp->mp_pgno, pn = pgno << 1; + + for (tx2 = txn; tx2; tx2 = tx2->mt_parent) { + if (!tx2->mt_spill_pages) + continue; + x = mdbx_pnl_search(tx2->mt_spill_pages, pn); + if (x <= MDBX_PNL_SIZE(tx2->mt_spill_pages) && + tx2->mt_spill_pages[x] == pn) { + MDBX_page *np; + int num; + if (txn->mt_dirtyroom == 0) + return MDBX_TXN_FULL; + num = IS_OVERFLOW(mp) ? mp->mp_pages : 1; + if (env->me_flags & MDBX_WRITEMAP) { + np = mp; + } else { + np = mdbx_page_malloc(txn, num); + if (unlikely(!np)) + return MDBX_ENOMEM; + if (unlikely(num > 1)) + memcpy(np, mp, pgno2bytes(env, num)); + else + mdbx_page_copy(np, mp, env->me_psize); + } + mdbx_debug("unspill page %" PRIaPGNO, mp->mp_pgno); + if (tx2 == txn) { + /* If in current txn, this page is no longer spilled. + * If it happens to be the last page, truncate the spill list. + * Otherwise mark it as deleted by setting the LSB. */ + if (x == MDBX_PNL_SIZE(txn->mt_spill_pages)) + MDBX_PNL_SIZE(txn->mt_spill_pages)--; + else + txn->mt_spill_pages[x] |= 1; + } /* otherwise, if belonging to a parent txn, the + * page remains spilled until child commits */ + + int rc = mdbx_page_dirty(txn, np); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + np->mp_flags |= P_DIRTY; + *ret = np; + break; + } + } + return MDBX_SUCCESS; +} + +/* Touch a page: make it dirty and re-insert into tree with updated pgno. + * Set MDBX_TXN_ERROR on failure. + * + * [in] mc cursor pointing to the page to be touched + * + * Returns 0 on success, non-zero on failure. */ +__hot static int mdbx_page_touch(MDBX_cursor *mc) { + MDBX_page *mp = mc->mc_pg[mc->mc_top], *np; + MDBX_txn *txn = mc->mc_txn; + MDBX_cursor *m2, *m3; + pgno_t pgno; + int rc; + + mdbx_cassert(mc, !IS_OVERFLOW(mp)); + if (!F_ISSET(mp->mp_flags, P_DIRTY)) { + if (txn->mt_flags & MDBX_TXN_SPILLS) { + np = NULL; + rc = mdbx_page_unspill(txn, mp, &np); + if (unlikely(rc)) + goto fail; + if (likely(np)) + goto done; + } + + if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages, 1)) || + (rc = mdbx_page_alloc(mc, 1, &np, MDBX_ALLOC_ALL)))) + goto fail; + pgno = np->mp_pgno; + mdbx_debug("touched db %d page %" PRIaPGNO " -> %" PRIaPGNO, DDBI(mc), + mp->mp_pgno, pgno); + mdbx_cassert(mc, mp->mp_pgno != pgno); + mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno); + /* Update the parent page, if any, to point to the new page */ + if (mc->mc_top) { + MDBX_page *parent = mc->mc_pg[mc->mc_top - 1]; + MDBX_node *node = NODEPTR(parent, mc->mc_ki[mc->mc_top - 1]); + SETPGNO(node, pgno); + } else { + mc->mc_db->md_root = pgno; + } + } else if (txn->mt_parent && !IS_SUBP(mp)) { + mdbx_tassert(txn, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0); + MDBX_DP *dl = txn->mt_rw_dirtylist; + pgno = mp->mp_pgno; + /* If txn has a parent, make sure the page is in our dirty list. */ + if (dl->length) { + unsigned x = mdbx_dpl_search(dl, pgno); + if (x <= dl->length && dl[x].pgno == pgno) { + if (unlikely(mp != dl[x].ptr)) { /* bad cursor? */ + mdbx_error("wrong page 0x%p #%" PRIaPGNO + " in the dirtylist[%d], expecting %p", + dl[x].ptr, pgno, x, mp); + mc->mc_flags &= ~(C_INITIALIZED | C_EOF); + rc = MDBX_PROBLEM; + goto fail; + } + return MDBX_SUCCESS; + } + } + + mdbx_debug("clone db %d page %" PRIaPGNO, DDBI(mc), mp->mp_pgno); + mdbx_cassert(mc, dl->length <= MDBX_DPL_TXNFULL); + /* No - copy it */ + np = mdbx_page_malloc(txn, 1); + if (unlikely(!np)) { + rc = MDBX_ENOMEM; + goto fail; + } + rc = mdbx_dpl_insert(dl, pgno, np); + if (unlikely(rc)) { + mdbx_dpage_free(txn->mt_env, np, 1); + goto fail; + } + } else { + return MDBX_SUCCESS; + } + + mdbx_page_copy(np, mp, txn->mt_env->me_psize); + np->mp_pgno = pgno; + np->mp_flags |= P_DIRTY; + +done: + /* Adjust cursors pointing to mp */ + mc->mc_pg[mc->mc_top] = np; + m2 = txn->mt_cursors[mc->mc_dbi]; + if (mc->mc_flags & C_SUB) { + for (; m2; m2 = m2->mc_next) { + m3 = &m2->mc_xcursor->mx_cursor; + if (m3->mc_snum < mc->mc_snum) + continue; + if (m3->mc_pg[mc->mc_top] == mp) + m3->mc_pg[mc->mc_top] = np; + } + } else { + for (; m2; m2 = m2->mc_next) { + if (m2->mc_snum < mc->mc_snum) + continue; + if (m2 == mc) + continue; + if (m2->mc_pg[mc->mc_top] == mp) { + m2->mc_pg[mc->mc_top] = np; + if (XCURSOR_INITED(m2) && IS_LEAF(np)) + XCURSOR_REFRESH(m2, np, m2->mc_ki[mc->mc_top]); + } + } + } + return MDBX_SUCCESS; + +fail: + txn->mt_flags |= MDBX_TXN_ERROR; + return rc; +} + +__cold static int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + unsigned flags = env->me_flags & ~MDBX_NOMETASYNC; + if (unlikely(flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) + return MDBX_EACCESS; + + const bool outside_txn = + (!env->me_txn0 || env->me_txn0->mt_owner != mdbx_thread_self()); + + if (outside_txn) { + int rc = mdbx_txn_lock(env, nonblock); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + const MDBX_meta *head = mdbx_meta_head(env); + pgno_t unsynced_pages = *env->me_unsynced_pages; + if (!META_IS_STEADY(head) || unsynced_pages) { + const pgno_t autosync_threshold = *env->me_autosync_threshold; + const uint64_t unsynced_timeout = *env->me_unsynced_timeout; + if (force || (autosync_threshold && unsynced_pages >= autosync_threshold) || + (unsynced_timeout && mdbx_osal_monotime() >= unsynced_timeout)) + flags &= MDBX_WRITEMAP /* clear flags for full steady sync */; + + if (outside_txn) { + if (unsynced_pages > /* FIXME: define threshold */ 16 && + (flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) == 0) { + mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); + const size_t usedbytes = pgno_align2os_bytes(env, head->mm_geo.next); + + mdbx_txn_unlock(env); + + /* LY: pre-sync without holding lock to reduce latency for writer(s) */ + int rc = (flags & MDBX_WRITEMAP) + ? mdbx_msync(&env->me_dxb_mmap, 0, usedbytes, false) + : mdbx_filesync(env->me_fd, MDBX_SYNC_DATA); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + rc = mdbx_txn_lock(env, nonblock); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + /* LY: head and unsynced_pages may be changed. */ + head = mdbx_meta_head(env); + unsynced_pages = *env->me_unsynced_pages; + } + env->me_txn0->mt_txnid = meta_txnid(env, head, false); + mdbx_find_oldest(env->me_txn0); + } + + if (!META_IS_STEADY(head) || + ((flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) == 0 && unsynced_pages)) { + mdbx_debug("meta-head %" PRIaPGNO ", %s, sync_pending %" PRIaPGNO, + container_of(head, MDBX_page, mp_data)->mp_pgno, + mdbx_durable_str(head), unsynced_pages); + MDBX_meta meta = *head; + int rc = mdbx_sync_locked(env, flags | MDBX_SHRINK_ALLOWED, &meta); + if (unlikely(rc != MDBX_SUCCESS)) { + if (outside_txn) + mdbx_txn_unlock(env); + return rc; + } + } + } + + if (outside_txn) + mdbx_txn_unlock(env); + return MDBX_SUCCESS; +} + +__cold int mdbx_env_sync(MDBX_env *env, int force) { + return mdbx_env_sync_ex(env, force, false); +} + +/* Back up parent txn's cursors, then grab the originals for tracking */ +static int mdbx_cursor_shadow(MDBX_txn *src, MDBX_txn *dst) { + MDBX_cursor *mc, *bk; + MDBX_xcursor *mx; + size_t size; + int i; + + for (i = src->mt_numdbs; --i >= 0;) { + if ((mc = src->mt_cursors[i]) != NULL) { + size = sizeof(MDBX_cursor); + if (mc->mc_xcursor) + size += sizeof(MDBX_xcursor); + for (; mc; mc = bk->mc_next) { + bk = mdbx_malloc(size); + if (unlikely(!bk)) + return MDBX_ENOMEM; + *bk = *mc; + mc->mc_backup = bk; + mc->mc_db = &dst->mt_dbs[i]; + /* Kill pointers into src to reduce abuse: The + * user may not use mc until dst ends. But we need a valid + * txn pointer here for cursor fixups to keep working. */ + mc->mc_txn = dst; + mc->mc_dbflag = &dst->mt_dbflags[i]; + if ((mx = mc->mc_xcursor) != NULL) { + *(MDBX_xcursor *)(bk + 1) = *mx; + mx->mx_cursor.mc_txn = dst; + } + mc->mc_next = dst->mt_cursors[i]; + dst->mt_cursors[i] = mc; + } + } + } + return MDBX_SUCCESS; +} + +/* Close this write txn's cursors, give parent txn's cursors back to parent. + * + * [in] txn the transaction handle. + * [in] merge true to keep changes to parent cursors, false to revert. + * + * Returns 0 on success, non-zero on failure. */ +static void mdbx_cursors_eot(MDBX_txn *txn, unsigned merge) { + MDBX_cursor **cursors = txn->mt_cursors, *mc, *next, *bk; + MDBX_xcursor *mx; + int i; + + for (i = txn->mt_numdbs; --i >= 0;) { + for (mc = cursors[i]; mc; mc = next) { + unsigned stage = mc->mc_signature; + mdbx_ensure(NULL, + stage == MDBX_MC_SIGNATURE || stage == MDBX_MC_WAIT4EOT); + next = mc->mc_next; + if ((bk = mc->mc_backup) != NULL) { + if (merge) { + /* Commit changes to parent txn */ + mc->mc_next = bk->mc_next; + mc->mc_backup = bk->mc_backup; + mc->mc_txn = bk->mc_txn; + mc->mc_db = bk->mc_db; + mc->mc_dbflag = bk->mc_dbflag; + if ((mx = mc->mc_xcursor) != NULL) + mx->mx_cursor.mc_txn = bk->mc_txn; + } else { + /* Abort nested txn */ + *mc = *bk; + if ((mx = mc->mc_xcursor) != NULL) + *mx = *(MDBX_xcursor *)(bk + 1); + } + bk->mc_signature = 0; + mdbx_free(bk); + } + if (stage == MDBX_MC_WAIT4EOT) { + mc->mc_signature = 0; + mdbx_free(mc); + } else { + mc->mc_signature = MDBX_MC_READY4CLOSE; + mc->mc_flags = 0 /* reset C_UNTRACK */; + } + } + cursors[i] = NULL; + } +} + +/* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */ +static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { + MDBX_env *env = txn->mt_env; + int rc; + +#if MDBX_TXN_CHECKPID + if (unlikely(env->me_pid != mdbx_getpid())) { + env->me_flags |= MDBX_FATAL_ERROR; + return MDBX_PANIC; + } +#endif /* MDBX_TXN_CHECKPID */ + + STATIC_ASSERT(sizeof(MDBX_reader) == 32); +#ifdef MDBX_OSAL_LOCK + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_wmutex) % MDBX_CACHELINE_SIZE == 0); + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_rmutex) % MDBX_CACHELINE_SIZE == 0); +#else + STATIC_ASSERT( + offsetof(MDBX_lockinfo, mti_oldest_reader) % MDBX_CACHELINE_SIZE == 0); + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE == + 0); +#endif + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == + 0); + + pgno_t upper_limit_pgno = 0; + if (flags & MDBX_TXN_RDONLY) { + txn->mt_flags = MDBX_TXN_RDONLY; + MDBX_reader *r = txn->mt_ro_reader; + if (likely(env->me_flags & MDBX_ENV_TXKEY)) { + mdbx_assert(env, !(env->me_flags & MDBX_NOTLS)); + r = mdbx_thread_rthc_get(env->me_txkey); + if (likely(r)) { + mdbx_assert(env, r->mr_pid == env->me_pid); + mdbx_assert(env, r->mr_tid == mdbx_thread_self()); + } + } else { + mdbx_assert(env, !env->me_lck || (env->me_flags & MDBX_NOTLS)); + } + + if (likely(r)) { + if (unlikely(r->mr_pid != env->me_pid || r->mr_txnid != ~(txnid_t)0)) + return MDBX_BAD_RSLOT; + } else if (env->me_lck) { + unsigned slot, nreaders; + const mdbx_tid_t tid = mdbx_thread_self(); + mdbx_assert(env, env->me_lck->mti_magic_and_version == MDBX_LOCK_MAGIC); + mdbx_assert(env, env->me_lck->mti_os_and_format == MDBX_LOCK_FORMAT); + + rc = mdbx_rdt_lock(env); + if (unlikely(MDBX_IS_ERROR(rc))) + return rc; + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { + mdbx_rdt_unlock(env); + return MDBX_PANIC; + } +#if defined(_WIN32) || defined(_WIN64) + if (unlikely(!env->me_map)) { + mdbx_rdt_unlock(env); + return MDBX_EPERM; + } +#endif /* Windows */ + rc = MDBX_SUCCESS; + + if (unlikely(env->me_live_reader != env->me_pid)) { + rc = mdbx_rpid_set(env); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_rdt_unlock(env); + return rc; + } + env->me_live_reader = env->me_pid; + } + + while (1) { + nreaders = env->me_lck->mti_numreaders; + for (slot = 0; slot < nreaders; slot++) + if (env->me_lck->mti_readers[slot].mr_pid == 0) + break; + + if (likely(slot < env->me_maxreaders)) + break; + + rc = mdbx_reader_check0(env, true, NULL); + if (rc != MDBX_RESULT_TRUE) { + mdbx_rdt_unlock(env); + return (rc == MDBX_SUCCESS) ? MDBX_READERS_FULL : rc; + } + } + + r = &env->me_lck->mti_readers[slot]; + /* Claim the reader slot, carefully since other code + * uses the reader table un-mutexed: First reset the + * slot, next publish it in lck->mti_numreaders. After + * that, it is safe for mdbx_env_close() to touch it. + * When it will be closed, we can finally claim it. */ + r->mr_pid = 0; + r->mr_txnid = ~(txnid_t)0; + r->mr_tid = tid; + mdbx_flush_noncoherent_cpu_writeback(); + if (slot == nreaders) + env->me_lck->mti_numreaders = ++nreaders; + r->mr_pid = env->me_pid; + mdbx_rdt_unlock(env); + + if (likely(env->me_flags & MDBX_ENV_TXKEY)) { + mdbx_assert(env, env->me_live_reader == env->me_pid); + mdbx_thread_rthc_set(env->me_txkey, r); + } + } + + while (1) { + MDBX_meta *const meta = mdbx_meta_head(env); + mdbx_jitter4testing(false); + const txnid_t snap = mdbx_meta_txnid_fluid(env, meta); + mdbx_jitter4testing(false); + if (likely(r)) { + r->mr_snapshot_pages_used = meta->mm_geo.next; + r->mr_txnid = snap; + mdbx_jitter4testing(false); + mdbx_assert(env, r->mr_pid == mdbx_getpid()); + mdbx_assert(env, r->mr_tid == mdbx_thread_self()); + mdbx_assert(env, r->mr_txnid == snap); + mdbx_compiler_barrier(); + env->me_lck->mti_readers_refresh_flag = true; + mdbx_flush_noncoherent_cpu_writeback(); + } + mdbx_jitter4testing(true); + + /* Snap the state from current meta-head */ + txn->mt_txnid = snap; + txn->mt_next_pgno = meta->mm_geo.next; + txn->mt_end_pgno = meta->mm_geo.now; + upper_limit_pgno = meta->mm_geo.upper; + memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db)); + txn->mt_canary = meta->mm_canary; + + /* LY: Retry on a race, ITS#7970. */ + mdbx_compiler_barrier(); + if (likely(meta == mdbx_meta_head(env) && + snap == mdbx_meta_txnid_fluid(env, meta) && + snap >= *env->me_oldest)) { + mdbx_jitter4testing(false); + break; + } + } + + if (unlikely(txn->mt_txnid == 0)) { + mdbx_error("environment corrupted by died writer, must shutdown!"); + rc = MDBX_WANNA_RECOVERY; + goto bailout; + } + mdbx_assert(env, txn->mt_txnid >= *env->me_oldest); + txn->mt_ro_reader = r; + txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */ + mdbx_ensure(env, txn->mt_txnid >= + /* paranoia is appropriate here */ *env->me_oldest); + } else { + /* Not yet touching txn == env->me_txn0, it may be active */ + mdbx_jitter4testing(false); + rc = mdbx_txn_lock(env, F_ISSET(flags, MDBX_TRYTXN)); + if (unlikely(rc)) + return rc; + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { + mdbx_txn_unlock(env); + return MDBX_PANIC; + } +#if defined(_WIN32) || defined(_WIN64) + if (unlikely(!env->me_map)) { + mdbx_txn_unlock(env); + return MDBX_EPERM; + } +#endif /* Windows */ + + mdbx_jitter4testing(false); + MDBX_meta *meta = mdbx_meta_head(env); + mdbx_jitter4testing(false); + txn->mt_canary = meta->mm_canary; + const txnid_t snap = mdbx_meta_txnid_stable(env, meta); + txn->mt_txnid = snap + 1; + if (unlikely(txn->mt_txnid < snap)) { + mdbx_debug("txnid overflow!"); + rc = MDBX_TXN_FULL; + goto bailout; + } + + txn->mt_flags = flags; + txn->mt_child = NULL; + txn->mt_loose_pages = NULL; + txn->mt_loose_count = 0; + txn->mt_dirtyroom = MDBX_DPL_TXNFULL; + txn->mt_rw_dirtylist = env->me_dirtylist; + txn->mt_rw_dirtylist->length = 0; + txn->mt_befree_pages = env->me_free_pgs; + MDBX_PNL_SIZE(txn->mt_befree_pages) = 0; + txn->mt_spill_pages = NULL; + if (txn->mt_lifo_reclaimed) + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) = 0; + env->me_txn = txn; + memcpy(txn->mt_dbiseqs, env->me_dbiseqs, env->me_maxdbs * sizeof(unsigned)); + /* Copy the DB info and flags */ + memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db)); + /* Moved to here to avoid a data race in read TXNs */ + txn->mt_next_pgno = meta->mm_geo.next; + txn->mt_end_pgno = meta->mm_geo.now; + upper_limit_pgno = meta->mm_geo.upper; + } + + /* Setup db info */ + txn->mt_numdbs = env->me_numdbs; + mdbx_compiler_barrier(); + for (unsigned i = CORE_DBS; i < txn->mt_numdbs; i++) { + unsigned x = env->me_dbflags[i]; + txn->mt_dbs[i].md_flags = x & PERSISTENT_FLAGS; + txn->mt_dbflags[i] = + (x & MDBX_VALID) ? DB_VALID | DB_USRVALID | DB_STALE : 0; + } + txn->mt_dbflags[MAIN_DBI] = DB_VALID | DB_USRVALID; + txn->mt_dbflags[FREE_DBI] = DB_VALID; + + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) { + mdbx_warning("environment had fatal error, must shutdown!"); + rc = MDBX_PANIC; + } else { + const size_t size = pgno2bytes(env, txn->mt_end_pgno); + if (unlikely(size > env->me_mapsize)) { + if (upper_limit_pgno > MAX_PAGENO || + bytes2pgno(env, pgno2bytes(env, upper_limit_pgno)) != + upper_limit_pgno) { + rc = MDBX_MAP_RESIZED; + goto bailout; + } + rc = mdbx_mapresize(env, txn->mt_end_pgno, upper_limit_pgno); + if (rc != MDBX_SUCCESS) { + if (rc == MDBX_RESULT_TRUE) + rc = MDBX_MAP_RESIZED; + goto bailout; + } + } + txn->mt_owner = mdbx_thread_self(); +#if defined(_WIN32) || defined(_WIN64) + if ((txn->mt_flags & MDBX_TXN_RDONLY) != 0 && size > env->me_dbgeo.lower && + env->me_dbgeo.shrink) { + txn->mt_flags |= MDBX_SHRINK_ALLOWED; + mdbx_srwlock_AcquireShared(&env->me_remap_guard); + } +#endif + return MDBX_SUCCESS; + } +bailout: + mdbx_tassert(txn, rc != MDBX_SUCCESS); + mdbx_txn_end(txn, MDBX_END_SLOT | MDBX_END_FAIL_BEGIN); + return rc; +} + +int mdbx_txn_renew(MDBX_txn *txn) { + int rc; + + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely((txn->mt_flags & MDBX_TXN_RDONLY) == 0)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_owner != 0)) + return MDBX_THREAD_MISMATCH; + + rc = mdbx_txn_renew0(txn, MDBX_TXN_RDONLY); + if (rc == MDBX_SUCCESS) { + txn->mt_owner = mdbx_thread_self(); + mdbx_debug("renew txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO + "/%" PRIaPGNO, + txn->mt_txnid, (txn->mt_flags & MDBX_TXN_RDONLY) ? 'r' : 'w', + (void *)txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root, + txn->mt_dbs[FREE_DBI].md_root); + } + return rc; +} + +int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags, + MDBX_txn **ret) { + MDBX_txn *txn; + MDBX_ntxn *ntxn; + int rc; + unsigned size, tsize; + + if (unlikely(!env || !ret)) + return MDBX_EINVAL; + + *ret = NULL; + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + +#if MDBX_TXN_CHECKPID + if (unlikely(env->me_pid != mdbx_getpid())) + env->me_flags |= MDBX_FATAL_ERROR; +#endif /* MDBX_TXN_CHECKPID */ + + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) + return MDBX_PANIC; + +#if !defined(_WIN32) && !defined(_WIN64) + /* Don't check env->me_map until lock to avoid race with re-mapping for + * shrinking */ + if (unlikely(!env->me_map)) + return MDBX_EPERM; +#endif /* Windows */ + + flags &= MDBX_TXN_BEGIN_FLAGS; + flags |= env->me_flags & MDBX_WRITEMAP; + + if (unlikely(env->me_flags & MDBX_RDONLY & + ~flags)) /* write txn in RDONLY env */ + return MDBX_EACCESS; + + if (parent) { + if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(parent->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + +#if defined(_WIN32) || defined(_WIN64) + if (unlikely(!env->me_map)) + return MDBX_EPERM; +#endif /* Windows */ + + /* Nested transactions: Max 1 child, write txns only, no writemap */ + flags |= parent->mt_flags; + if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) + return (parent->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EINVAL : MDBX_BAD_TXN; + + /* Child txns save MDBX_pgstate and use own copy of cursors */ + size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1); + size += tsize = sizeof(MDBX_ntxn); + } else if (flags & MDBX_RDONLY) { + if (env->me_txn0 && unlikely(env->me_txn0->mt_owner == mdbx_thread_self())) + return MDBX_BUSY; + size = env->me_maxdbs * (sizeof(MDBX_db) + 1); + size += tsize = sizeof(MDBX_txn); + } else { + /* Reuse preallocated write txn. However, do not touch it until + * mdbx_txn_renew0() succeeds, since it currently may be active. */ + txn = env->me_txn0; + if (unlikely(txn->mt_owner == mdbx_thread_self())) + return MDBX_BUSY; + goto renew; + } + if (unlikely((txn = mdbx_malloc(size)) == NULL)) { + mdbx_debug("calloc: %s", "failed"); + return MDBX_ENOMEM; + } + memset(txn, 0, tsize); + txn->mt_dbxs = env->me_dbxs; /* static */ + txn->mt_dbs = (MDBX_db *)((char *)txn + tsize); + txn->mt_dbflags = (uint8_t *)txn + size - env->me_maxdbs; + txn->mt_flags = flags; + txn->mt_env = env; + + if (parent) { + unsigned i; + txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs); + txn->mt_dbiseqs = parent->mt_dbiseqs; + txn->mt_rw_dirtylist = + mdbx_malloc(sizeof(MDBX_DP) * (MDBX_DPL_TXNFULL + 1)); + if (!txn->mt_rw_dirtylist || + !(txn->mt_befree_pages = mdbx_pnl_alloc(MDBX_PNL_INITIAL))) { + mdbx_free(txn->mt_rw_dirtylist); + mdbx_free(txn); + return MDBX_ENOMEM; + } + txn->mt_txnid = parent->mt_txnid; + txn->mt_dirtyroom = parent->mt_dirtyroom; + txn->mt_rw_dirtylist->length = 0; + txn->mt_spill_pages = NULL; + txn->mt_next_pgno = parent->mt_next_pgno; + txn->mt_end_pgno = parent->mt_end_pgno; + parent->mt_flags |= MDBX_TXN_HAS_CHILD; + parent->mt_child = txn; + txn->mt_parent = parent; + txn->mt_numdbs = parent->mt_numdbs; + memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db)); + /* Copy parent's mt_dbflags, but clear DB_NEW */ + for (i = 0; i < txn->mt_numdbs; i++) + txn->mt_dbflags[i] = parent->mt_dbflags[i] & ~(DB_FRESH | DB_CREAT); + rc = 0; + ntxn = (MDBX_ntxn *)txn; + ntxn->mnt_pgstate = + env->me_pgstate; /* save parent me_reclaimed_pglist & co */ + if (env->me_reclaimed_pglist) { + size = MDBX_PNL_SIZEOF(env->me_reclaimed_pglist); + env->me_reclaimed_pglist = + mdbx_pnl_alloc(MDBX_PNL_SIZE(env->me_reclaimed_pglist)); + if (likely(env->me_reclaimed_pglist)) + memcpy(env->me_reclaimed_pglist, ntxn->mnt_pgstate.mf_reclaimed_pglist, + size); + else + rc = MDBX_ENOMEM; + } + if (likely(!rc)) + rc = mdbx_cursor_shadow(parent, txn); + if (unlikely(rc)) + mdbx_txn_end(txn, MDBX_END_FAIL_BEGINCHILD); + } else { /* MDBX_RDONLY */ + txn->mt_dbiseqs = env->me_dbiseqs; + renew: + rc = mdbx_txn_renew0(txn, flags); + } + + if (unlikely(rc != MDBX_SUCCESS)) { + if (txn != env->me_txn0) + mdbx_free(txn); + } else { + mdbx_assert(env, (txn->mt_flags & ~(MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP | + MDBX_SHRINK_ALLOWED)) == 0); + txn->mt_signature = MDBX_MT_SIGNATURE; + *ret = txn; + mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO + "/%" PRIaPGNO, + txn->mt_txnid, (flags & MDBX_RDONLY) ? 'r' : 'w', (void *)txn, + (void *)env, txn->mt_dbs[MAIN_DBI].md_root, + txn->mt_dbs[FREE_DBI].md_root); + } + + return rc; +} + +MDBX_env *mdbx_txn_env(MDBX_txn *txn) { + if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return NULL; + return txn->mt_env; +} + +uint64_t mdbx_txn_id(MDBX_txn *txn) { + if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return ~(txnid_t)0; + return txn->mt_txnid; +} + +int mdbx_txn_flags(MDBX_txn *txn) { + if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return -1; + + return txn->mt_flags; +} + +/* Export or close DBI handles opened in this txn. */ +static void mdbx_dbis_update(MDBX_txn *txn, int keep) { + MDBX_dbi n = txn->mt_numdbs; + if (n) { + bool locked = false; + MDBX_env *env = txn->mt_env; + uint8_t *tdbflags = txn->mt_dbflags; + + for (unsigned i = n; --i >= CORE_DBS;) { + if (likely((tdbflags[i] & DB_CREAT) == 0)) + continue; + if (!locked) { + mdbx_ensure(env, + mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS); + locked = true; + } + if (keep) { + env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDBX_VALID; + mdbx_compiler_barrier(); + if (env->me_numdbs <= i) + env->me_numdbs = i + 1; + } else { + char *ptr = env->me_dbxs[i].md_name.iov_base; + if (ptr) { + env->me_dbxs[i].md_name.iov_len = 0; + mdbx_compiler_barrier(); + mdbx_assert(env, env->me_dbflags[i] == 0); + env->me_dbiseqs[i]++; + env->me_dbxs[i].md_name.iov_base = NULL; + mdbx_free(ptr); + } + } + } + + if (unlikely(locked)) + mdbx_ensure(env, + mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); + } +} + +/* End a transaction, except successful commit of a nested transaction. + * May be called twice for readonly txns: First reset it, then abort. + * [in] txn the transaction handle to end + * [in] mode why and how to end the transaction */ +static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) { + MDBX_env *env = txn->mt_env; + static const char *const names[] = MDBX_END_NAMES; + +#if MDBX_TXN_CHECKPID + if (unlikely(txn->mt_env->me_pid != mdbx_getpid())) { + env->me_flags |= MDBX_FATAL_ERROR; + return MDBX_PANIC; + } +#endif /* MDBX_TXN_CHECKPID */ + + mdbx_debug("%s txn %" PRIaTXN "%c %p on mdbenv %p, root page %" PRIaPGNO + "/%" PRIaPGNO, + names[mode & MDBX_END_OPMASK], txn->mt_txnid, + (txn->mt_flags & MDBX_TXN_RDONLY) ? 'r' : 'w', (void *)txn, + (void *)env, txn->mt_dbs[MAIN_DBI].md_root, + txn->mt_dbs[FREE_DBI].md_root); + + mdbx_ensure(env, txn->mt_txnid >= + /* paranoia is appropriate here */ *env->me_oldest); + if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) { +#if defined(_WIN32) || defined(_WIN64) + if (txn->mt_flags & MDBX_SHRINK_ALLOWED) + mdbx_srwlock_ReleaseShared(&env->me_remap_guard); +#endif + if (txn->mt_ro_reader) { + mdbx_ensure(env, /* paranoia is appropriate here */ + txn->mt_txnid == txn->mt_ro_reader->mr_txnid && + txn->mt_ro_reader->mr_txnid >= + env->me_lck->mti_oldest_reader); + txn->mt_ro_reader->mr_snapshot_pages_used = 0; + txn->mt_ro_reader->mr_txnid = ~(txnid_t)0; + mdbx_memory_barrier(); + env->me_lck->mti_readers_refresh_flag = true; + if (mode & MDBX_END_SLOT) { + if ((env->me_flags & MDBX_ENV_TXKEY) == 0) + txn->mt_ro_reader->mr_pid = 0; + txn->mt_ro_reader = NULL; + } + } + mdbx_flush_noncoherent_cpu_writeback(); + txn->mt_numdbs = 0; /* prevent further DBI activity */ + txn->mt_flags = MDBX_TXN_RDONLY | MDBX_TXN_FINISHED; + txn->mt_owner = 0; + } else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) { + /* Export or close DBI handles created in this txn */ + mdbx_dbis_update(txn, mode & MDBX_END_UPDATE); + + pgno_t *pghead = env->me_reclaimed_pglist; + + if (!(mode & MDBX_END_EOTDONE)) /* !(already closed cursors) */ + mdbx_cursors_eot(txn, 0); + if (!(env->me_flags & MDBX_WRITEMAP)) { + mdbx_dlist_free(txn); + } + + if (txn->mt_lifo_reclaimed) { + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) = 0; + if (txn != env->me_txn0) { + mdbx_txl_free(txn->mt_lifo_reclaimed); + txn->mt_lifo_reclaimed = NULL; + } + } + txn->mt_numdbs = 0; + txn->mt_flags = MDBX_TXN_FINISHED; + txn->mt_owner = 0; + + if (!txn->mt_parent) { + mdbx_pnl_shrink(&txn->mt_befree_pages); + env->me_free_pgs = txn->mt_befree_pages; + /* me_pgstate: */ + env->me_reclaimed_pglist = NULL; + env->me_last_reclaimed = 0; + + env->me_txn = NULL; + + /* The writer mutex was locked in mdbx_txn_begin. */ + mdbx_txn_unlock(env); + } else { + txn->mt_parent->mt_child = NULL; + txn->mt_parent->mt_flags &= ~MDBX_TXN_HAS_CHILD; + env->me_pgstate = ((MDBX_ntxn *)txn)->mnt_pgstate; + mdbx_pnl_free(txn->mt_befree_pages); + mdbx_pnl_free(txn->mt_spill_pages); + mdbx_free(txn->mt_rw_dirtylist); + } + + mdbx_pnl_free(pghead); + } + + mdbx_assert(env, txn == env->me_txn0 || txn->mt_owner == 0); + if ((mode & MDBX_END_FREE) != 0 && txn != env->me_txn0) { + txn->mt_signature = 0; + mdbx_free(txn); + } + + return MDBX_SUCCESS; +} + +int mdbx_txn_reset(MDBX_txn *txn) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + /* This call is only valid for read-only txns */ + if (unlikely(!(txn->mt_flags & MDBX_TXN_RDONLY))) + return MDBX_EINVAL; + + /* LY: don't close DBI-handles in MDBX mode */ + int rc = mdbx_txn_end(txn, MDBX_END_RESET | MDBX_END_UPDATE); + if (rc == MDBX_SUCCESS) { + mdbx_tassert(txn, txn->mt_signature == MDBX_MT_SIGNATURE); + mdbx_tassert(txn, txn->mt_owner == 0); + } + return rc; +} + +int mdbx_txn_abort(MDBX_txn *txn) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) + /* LY: don't close DBI-handles in MDBX mode */ + return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_UPDATE | MDBX_END_SLOT | + MDBX_END_FREE); + + if (txn->mt_child) + mdbx_txn_abort(txn->mt_child); + + return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_SLOT | MDBX_END_FREE); +} + +static __inline int mdbx_backlog_size(MDBX_txn *txn) { + int reclaimed_and_loose = + txn->mt_env->me_reclaimed_pglist + ? MDBX_PNL_SIZE(txn->mt_env->me_reclaimed_pglist) + + txn->mt_loose_count + : 0; + return reclaimed_and_loose; +} + +static __inline int mdbx_backlog_extragap(MDBX_env *env) { + /* LY: extra page(s) for b-tree rebalancing */ + return (env->me_flags & MDBX_LIFORECLAIM) ? 2 : 1; +} + +/* LY: Prepare a backlog of pages to modify FreeDB itself, + * while reclaiming is prohibited. It should be enough to prevent search + * in mdbx_page_alloc() during a deleting, when freeDB tree is unbalanced. */ +static int mdbx_prep_backlog(MDBX_txn *txn, MDBX_cursor *mc) { + /* LY: extra page(s) for b-tree rebalancing */ + const int extra = + mdbx_backlog_extragap(txn->mt_env) + + MDBX_PNL_SIZEOF(txn->mt_befree_pages) / txn->mt_env->me_maxkey_limit; + + if (mdbx_backlog_size(txn) < mc->mc_db->md_depth + extra) { + mc->mc_flags &= ~C_RECLAIMING; + int rc = mdbx_cursor_touch(mc); + if (unlikely(rc)) + return rc; + + while (unlikely(mdbx_backlog_size(txn) < extra)) { + rc = mdbx_page_alloc(mc, 1, NULL, MDBX_ALLOC_GC); + if (unlikely(rc)) { + if (rc != MDBX_NOTFOUND) + return rc; + break; + } + } + mc->mc_flags |= C_RECLAIMING; + } + + return MDBX_SUCCESS; +} + +static void mdbx_prep_backlog_data(MDBX_txn *txn, MDBX_cursor *mc, + size_t bytes) { + const int wanna = + (int)OVPAGES(txn->mt_env, bytes) + mdbx_backlog_extragap(txn->mt_env); + if (unlikely(wanna > mdbx_backlog_size(txn))) { + mc->mc_flags &= ~C_RECLAIMING; + do { + if (mdbx_page_alloc(mc, 1, NULL, MDBX_ALLOC_GC) != MDBX_SUCCESS) + break; + } while (wanna > mdbx_backlog_size(txn)); + mc->mc_flags |= C_RECLAIMING; + } +} + +/* Count all the pages in each DB and in the freelist and make sure + * it matches the actual number of pages being used. + * All named DBs must be open for a correct count. */ +static __cold int mdbx_audit(MDBX_txn *txn, unsigned befree_stored) { + MDBX_val key, data; + + const pgno_t pending = + (txn->mt_flags & MDBX_RDONLY) + ? 0 + : txn->mt_loose_count + + (txn->mt_env->me_reclaimed_pglist + ? MDBX_PNL_SIZE(txn->mt_env->me_reclaimed_pglist) + : 0) + + (txn->mt_befree_pages + ? MDBX_PNL_SIZE(txn->mt_befree_pages) - befree_stored + : 0); + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, FREE_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + pgno_t freecount = 0; + while ((rc = mdbx_cursor_get(&cx.outer, &key, &data, MDBX_NEXT)) == 0) + freecount += *(pgno_t *)data.iov_base; + mdbx_tassert(txn, rc == MDBX_NOTFOUND); + + pgno_t count = 0; + for (MDBX_dbi i = FREE_DBI; i <= MAIN_DBI; i++) { + if (!(txn->mt_dbflags[i] & DB_VALID)) + continue; + rc = mdbx_cursor_init(&cx.outer, txn, i); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (txn->mt_dbs[i].md_root == P_INVALID) + continue; + count += txn->mt_dbs[i].md_branch_pages + txn->mt_dbs[i].md_leaf_pages + + txn->mt_dbs[i].md_overflow_pages; + + rc = mdbx_page_search(&cx.outer, NULL, MDBX_PS_FIRST); + while (rc == MDBX_SUCCESS) { + MDBX_page *mp = cx.outer.mc_pg[cx.outer.mc_top]; + for (unsigned j = 0; j < NUMKEYS(mp); j++) { + MDBX_node *leaf = NODEPTR(mp, j); + if ((leaf->mn_flags & (F_DUPDATA | F_SUBDATA)) == F_SUBDATA) { + MDBX_db db_copy, *db; + memcpy(db = &db_copy, NODEDATA(leaf), sizeof(db_copy)); + if ((txn->mt_flags & MDBX_RDONLY) == 0) { + for (MDBX_dbi k = txn->mt_numdbs; --k > MAIN_DBI;) { + if ((txn->mt_dbflags[k] & MDBX_TBL_DIRTY) && + /* txn->mt_dbxs[k].md_name.iov_len > 0 && */ + NODEKSZ(leaf) == txn->mt_dbxs[k].md_name.iov_len && + memcmp(NODEKEY(leaf), txn->mt_dbxs[k].md_name.iov_base, + NODEKSZ(leaf)) == 0) { + db = txn->mt_dbs + k; + break; + } + } + } + count += + db->md_branch_pages + db->md_leaf_pages + db->md_overflow_pages; + } + } + rc = mdbx_cursor_sibling(&cx.outer, 1); + } + mdbx_tassert(txn, rc == MDBX_NOTFOUND); + } + + if (pending + freecount + count + NUM_METAS == txn->mt_next_pgno) + return MDBX_SUCCESS; + + if ((txn->mt_flags & MDBX_RDONLY) == 0) + mdbx_error("audit @%" PRIaTXN ": %u(pending) = %u(loose-count) + " + "%u(reclaimed-list) + %u(befree-pending) - %u(befree-stored)", + txn->mt_txnid, pending, txn->mt_loose_count, + txn->mt_env->me_reclaimed_pglist + ? MDBX_PNL_SIZE(txn->mt_env->me_reclaimed_pglist) + : 0, + txn->mt_befree_pages ? MDBX_PNL_SIZE(txn->mt_befree_pages) : 0, + befree_stored); + mdbx_error("audit @%" PRIaTXN ": %" PRIaPGNO "(pending) + %" PRIaPGNO + "(free) + %" PRIaPGNO "(count) = %" PRIaPGNO + "(total) <> %" PRIaPGNO "(next-pgno)", + txn->mt_txnid, pending, freecount, count + NUM_METAS, + pending + freecount + count + NUM_METAS, txn->mt_next_pgno); + return MDBX_PROBLEM; +} + +/* Cleanup reclaimed GC records, than save the befree-list as of this + * transaction to GC (aka freeDB). This recursive changes the reclaimed-list + * loose-list and befree-list. Keep trying until it stabilizes. */ +static int mdbx_update_gc(MDBX_txn *txn) { + /* env->me_reclaimed_pglist[] can grow and shrink during this call. + * env->me_last_reclaimed and txn->mt_befree_pages[] can only grow. + * Page numbers cannot disappear from txn->mt_befree_pages[]. */ + MDBX_env *const env = txn->mt_env; + const bool lifo = (env->me_flags & MDBX_LIFORECLAIM) != 0; + const char *dbg_prefix_mode = lifo ? " lifo" : " fifo"; + (void)dbg_prefix_mode; + mdbx_trace("\n>>> @%" PRIaTXN, txn->mt_txnid); + + unsigned befree_stored = 0, loop = 0; + MDBX_cursor mc; + int rc = mdbx_cursor_init(&mc, txn, FREE_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout_notracking; + + mc.mc_flags |= C_RECLAIMING; + mc.mc_next = txn->mt_cursors[FREE_DBI]; + txn->mt_cursors[FREE_DBI] = &mc; + +retry: + mdbx_trace(" >> restart"); + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (unlikely(/* paranoia */ ++loop > 42)) { + mdbx_error("too more loops %u, bailout", loop); + rc = MDBX_PROBLEM; + goto bailout; + } + + unsigned settled = 0, cleaned_gc_slot = 0, reused_gc_slot = 0, + filled_gc_slot = ~0u; + txnid_t cleaned_gc_id = 0, head_gc_id = env->me_last_reclaimed; + while (1) { + /* Come back here after each Put() in case befree-list changed */ + MDBX_val key, data; + mdbx_trace(" >> continue"); + + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (txn->mt_lifo_reclaimed) { + if (cleaned_gc_slot < MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)) { + settled = 0; + cleaned_gc_slot = 0; + reused_gc_slot = 0; + filled_gc_slot = ~0u; + /* LY: cleanup reclaimed records. */ + do { + cleaned_gc_id = txn->mt_lifo_reclaimed[++cleaned_gc_slot]; + mdbx_tassert(txn, + cleaned_gc_slot > 0 && cleaned_gc_id < *env->me_oldest); + key.iov_base = &cleaned_gc_id; + key.iov_len = sizeof(cleaned_gc_id); + rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET); + if (rc == MDBX_NOTFOUND) + continue; + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + rc = mdbx_prep_backlog(txn, &mc); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + mdbx_tassert(txn, cleaned_gc_id < *env->me_oldest); + mdbx_trace("%s.cleanup-reclaimed-id [%u]%" PRIaTXN, dbg_prefix_mode, + cleaned_gc_slot, cleaned_gc_id); + rc = mdbx_cursor_del(&mc, 0); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } while (cleaned_gc_slot < MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + mdbx_txl_sort(txn->mt_lifo_reclaimed); + head_gc_id = MDBX_PNL_LAST(txn->mt_lifo_reclaimed); + } + } else { + /* If using records from freeDB which we have not yet deleted, + * now delete them and any we reserved for me_reclaimed_pglist. */ + while (cleaned_gc_id < env->me_last_reclaimed) { + rc = mdbx_cursor_first(&mc, &key, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + rc = mdbx_prep_backlog(txn, &mc); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + cleaned_gc_id = head_gc_id = *(txnid_t *)key.iov_base; + mdbx_tassert(txn, cleaned_gc_id <= env->me_last_reclaimed); + mdbx_tassert(txn, cleaned_gc_id < *env->me_oldest); + mdbx_trace("%s.cleanup-reclaimed-id %" PRIaTXN, dbg_prefix_mode, + cleaned_gc_id); + rc = mdbx_cursor_del(&mc, 0); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + settled = 0; + } + } + + // handle loose pages - put ones into the reclaimed- or befree-list + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, befree_stored); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + if (txn->mt_loose_pages) { + /* Return loose page numbers to me_reclaimed_pglist, + * though usually none are left at this point. + * The pages themselves remain in dirtylist. */ + if (unlikely(!env->me_reclaimed_pglist) && !txn->mt_lifo_reclaimed && + env->me_last_reclaimed < 1) { + /* Put loose page numbers in mt_befree_pages, + * since unable to return them to me_reclaimed_pglist. */ + if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages, + txn->mt_loose_count)) != 0)) + goto bailout; + for (MDBX_page *mp = txn->mt_loose_pages; mp; mp = NEXT_LOOSE_PAGE(mp)) + mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno); + mdbx_trace("%s: append %u loose-pages to befree-pages", dbg_prefix_mode, + txn->mt_loose_count); + } else { + /* Room for loose pages + temp PNL with same */ + if (likely(env->me_reclaimed_pglist != NULL)) { + rc = mdbx_pnl_need(&env->me_reclaimed_pglist, + 2 * txn->mt_loose_count + 2); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + MDBX_PNL loose = env->me_reclaimed_pglist + + MDBX_PNL_ALLOCLEN(env->me_reclaimed_pglist) - + txn->mt_loose_count - 1; + unsigned count = 0; + for (MDBX_page *mp = txn->mt_loose_pages; mp; + mp = NEXT_LOOSE_PAGE(mp)) + loose[++count] = mp->mp_pgno; + MDBX_PNL_SIZE(loose) = count; + mdbx_pnl_sort(loose); + mdbx_pnl_xmerge(env->me_reclaimed_pglist, loose); + } else { + env->me_reclaimed_pglist = mdbx_pnl_alloc(txn->mt_loose_count); + if (unlikely(env->me_reclaimed_pglist == NULL)) { + rc = MDBX_ENOMEM; + goto bailout; + } + for (MDBX_page *mp = txn->mt_loose_pages; mp; + mp = NEXT_LOOSE_PAGE(mp)) + mdbx_pnl_xappend(env->me_reclaimed_pglist, mp->mp_pgno); + mdbx_pnl_sort(env->me_reclaimed_pglist); + } + mdbx_trace("%s: append %u loose-pages to reclaimed-pages", + dbg_prefix_mode, txn->mt_loose_count); + } + + // filter-out list of dirty-pages from loose-pages + MDBX_DPL dl = txn->mt_rw_dirtylist; + mdbx_dpl_sort(dl); + unsigned left = dl->length; + for (MDBX_page *mp = txn->mt_loose_pages; mp;) { + mdbx_tassert(txn, mp->mp_pgno < txn->mt_next_pgno); + mdbx_ensure(env, mp->mp_pgno >= NUM_METAS); + + if (left > 0) { + const unsigned i = mdbx_dpl_search(dl, mp->mp_pgno); + if (i <= dl->length && dl[i].pgno == mp->mp_pgno) { + mdbx_tassert(txn, i > 0 && dl[i].ptr != dl); + dl[i].ptr = dl /* mark for deletion */; + } + left -= 1; + } + + MDBX_page *dp = mp; + mp = NEXT_LOOSE_PAGE(mp); + if ((env->me_flags & MDBX_WRITEMAP) == 0) + mdbx_dpage_free(env, dp, 1); + } + + if (left > 0) { + MDBX_DPL r, w, end = dl + dl->length; + for (r = w = dl + 1; r <= end; r++) { + if (r->ptr != dl) { + if (r != w) + *w = *r; + ++w; + } + } + mdbx_tassert(txn, w - dl == (int)left + 1); + } + + if (left != dl->length) + mdbx_trace("%s: filtered-out loose-pages from %u -> %u dirty-pages", + dbg_prefix_mode, dl->length, left); + dl->length = left; + + txn->mt_loose_pages = NULL; + txn->mt_loose_count = 0; + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, befree_stored); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + } + + // handle reclaimed pages - return suitable into unallocated space + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (env->me_reclaimed_pglist) { + pgno_t tail = txn->mt_next_pgno; + pgno_t *const begin = MDBX_PNL_BEGIN(env->me_reclaimed_pglist); + pgno_t *const end = MDBX_PNL_END(env->me_reclaimed_pglist); + pgno_t *higest; +#if MDBX_PNL_ASCENDING + for (higest = end; --higest >= begin;) { +#else + for (higest = begin; higest < end; ++higest) { +#endif /* MDBX_PNL sort-order */ + mdbx_tassert(txn, *higest >= NUM_METAS && *higest < tail); + if (*higest != tail - 1) + break; + tail -= 1; + } + if (tail != txn->mt_next_pgno) { +#if MDBX_PNL_ASCENDING + MDBX_PNL_SIZE(env->me_reclaimed_pglist) = + (unsigned)(higest + 1 - begin); +#else + MDBX_PNL_SIZE(env->me_reclaimed_pglist) -= (unsigned)(higest - begin); + for (pgno_t *move = begin; higest < end; ++move, ++higest) + *move = *higest; +#endif /* MDBX_PNL sort-order */ + mdbx_info( + "%s.refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO, + dbg_prefix_mode, txn->mt_next_pgno - tail, tail, txn->mt_next_pgno); + txn->mt_next_pgno = tail; + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, befree_stored); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + } + } + + // handle befree-list - store ones into singe gc-record + if (befree_stored < MDBX_PNL_SIZE(txn->mt_befree_pages)) { + if (unlikely(!befree_stored)) { + /* Make sure last page of freeDB is touched and on befree-list */ + mc.mc_flags &= ~C_RECLAIMING; + rc = mdbx_page_search(&mc, NULL, MDBX_PS_LAST | MDBX_PS_MODIFY); + mc.mc_flags |= C_RECLAIMING; + if (unlikely(rc != MDBX_SUCCESS) && rc != MDBX_NOTFOUND) + goto bailout; + } + /* Write to last page of freeDB */ + key.iov_len = sizeof(txn->mt_txnid); + key.iov_base = &txn->mt_txnid; + do { + data.iov_len = MDBX_PNL_SIZEOF(txn->mt_befree_pages); + mdbx_prep_backlog_data(txn, &mc, data.iov_len); + rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + /* Retry if mt_befree_pages[] grew during the Put() */ + } while (data.iov_len < MDBX_PNL_SIZEOF(txn->mt_befree_pages)); + + befree_stored = (unsigned)MDBX_PNL_SIZE(txn->mt_befree_pages); + mdbx_pnl_sort(txn->mt_befree_pages); + memcpy(data.iov_base, txn->mt_befree_pages, data.iov_len); + + mdbx_trace("%s.put-befree #%u @ %" PRIaTXN, dbg_prefix_mode, + befree_stored, txn->mt_txnid); + + if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) { + unsigned i = befree_stored; + mdbx_debug_extra("PNL write txn %" PRIaTXN " root %" PRIaPGNO + " num %u, PNL", + txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i); + for (; i; i--) + mdbx_debug_extra_print(" %" PRIaPGNO, txn->mt_befree_pages[i]); + mdbx_debug_extra_print("\n"); + } + continue; + } + + // handle reclaimed and loost pages - merge and store both into gc + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + mdbx_tassert(txn, txn->mt_loose_count == 0); + + mdbx_trace(" >> reserving"); + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, befree_stored); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + const unsigned amount = + env->me_reclaimed_pglist ? MDBX_PNL_SIZE(env->me_reclaimed_pglist) : 0; + const unsigned left = amount - settled; + mdbx_trace("%s: amount %u, settled %d, left %d, lifo-reclaimed-slots %u, " + "reused-gc-slots %u", + dbg_prefix_mode, amount, settled, (int)left, + txn->mt_lifo_reclaimed + ? (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) + : 0, + reused_gc_slot); + if (0 >= (int)left) + break; + + if (unlikely(head_gc_id == 0)) { + head_gc_id = mdbx_find_oldest(txn) - 1; + if (txn->mt_lifo_reclaimed == NULL) { + rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_FIRST); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_NOTFOUND) + goto bailout; + } else if (unlikely(key.iov_len != sizeof(txnid_t))) { + rc = MDBX_CORRUPTED; + goto bailout; + } else { + txnid_t first_txn; + memcpy(&first_txn, key.iov_base, sizeof(txnid_t)); + if (head_gc_id >= first_txn) + head_gc_id = first_txn - 1; + } + } + } + + const unsigned prefer_max_scatter = 257; + txnid_t reservation_gc_id; + if (lifo) { + mdbx_tassert(txn, txn->mt_lifo_reclaimed != NULL); + if (unlikely(!txn->mt_lifo_reclaimed)) { + txn->mt_lifo_reclaimed = mdbx_txl_alloc(); + if (unlikely(!txn->mt_lifo_reclaimed)) { + rc = MDBX_ENOMEM; + goto bailout; + } + } + + if (head_gc_id > 1 && + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) < prefer_max_scatter && + left > ((unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - + reused_gc_slot) * + env->me_maxgc_ov1page) { + /* LY: need just a txn-id for save page list. */ + mc.mc_flags &= ~C_RECLAIMING; + rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK); + mc.mc_flags |= C_RECLAIMING; + if (likely(rc == MDBX_SUCCESS)) { + /* LY: ok, reclaimed from freedb. */ + mdbx_trace("%s: took @%" PRIaTXN " from GC, continue", + dbg_prefix_mode, MDBX_PNL_LAST(txn->mt_lifo_reclaimed)); + continue; + } + if (unlikely(rc != MDBX_NOTFOUND)) + /* LY: other troubles... */ + goto bailout; + + /* LY: freedb is empty, will look any free txn-id in high2low order. */ + do { + --head_gc_id; + mdbx_assert(env, + MDBX_PNL_IS_EMPTY(txn->mt_lifo_reclaimed) || + MDBX_PNL_LAST(txn->mt_lifo_reclaimed) > head_gc_id); + rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, head_gc_id); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + cleaned_gc_slot += 1 /* mark GC cleanup is not needed. */; + + mdbx_trace("%s: append @%" PRIaTXN + " to lifo-reclaimed, cleaned-gc-slot = %u", + dbg_prefix_mode, head_gc_id, cleaned_gc_slot); + } while (head_gc_id > 1 && + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) < prefer_max_scatter && + left > ((unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - + reused_gc_slot) * + env->me_maxgc_ov1page); + } + + if ((unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) <= reused_gc_slot) { + mdbx_notice("** restart: reserve depleted (reused_gc_slot %u >= " + "lifo_reclaimed %u" PRIaTXN, + reused_gc_slot, + (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + goto retry; + } + const unsigned i = + (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - reused_gc_slot; + mdbx_tassert(txn, i > 0 && i <= MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + reservation_gc_id = txn->mt_lifo_reclaimed[i]; + mdbx_trace("%s: take @%" PRIaTXN " from lifo-reclaimed[%u]", + dbg_prefix_mode, reservation_gc_id, i); + } else { + mdbx_tassert(txn, txn->mt_lifo_reclaimed == NULL); + reservation_gc_id = head_gc_id--; + mdbx_trace("%s: take @%" PRIaTXN " from head-gc-id", dbg_prefix_mode, + reservation_gc_id); + } + ++reused_gc_slot; + + unsigned chunk = left; + if (unlikely(chunk > env->me_maxgc_ov1page)) { + const unsigned avail_gs_slots = + txn->mt_lifo_reclaimed + ? (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - + reused_gc_slot + 1 + : (head_gc_id < INT16_MAX) ? (unsigned)head_gc_id : INT16_MAX; + if (avail_gs_slots > 1) { + if (chunk < env->me_maxgc_ov1page * 2) + chunk /= 2; + else { + const unsigned threshold = + env->me_maxgc_ov1page * ((avail_gs_slots < prefer_max_scatter) + ? avail_gs_slots + : prefer_max_scatter); + if (left < threshold) + chunk = env->me_maxgc_ov1page; + else { + const unsigned tail = left - threshold + env->me_maxgc_ov1page + 1; + unsigned span = 1; + unsigned avail = (unsigned)((pgno2bytes(env, span) - PAGEHDRSZ) / + sizeof(pgno_t)) /*- 1 + span */; + if (tail > avail) { + for (unsigned i = amount - span; i > 0; --i) { + if (MDBX_PNL_ASCENDING + ? (env->me_reclaimed_pglist[i] + span) + : (env->me_reclaimed_pglist[i] - span) == + env->me_reclaimed_pglist[i + span]) { + span += 1; + avail = (unsigned)((pgno2bytes(env, span) - PAGEHDRSZ) / + sizeof(pgno_t)) - + 1 + span; + if (avail >= tail) + break; + } + } + } + + chunk = (avail >= tail) ? tail - span + : (avail_gs_slots > 3 && + reused_gc_slot < prefer_max_scatter - 3) + ? avail - span + : tail; + } + } + } + } + mdbx_tassert(txn, chunk > 0); + + mdbx_trace("%s: head_gc_id %" PRIaTXN ", reused_gc_slot %u, reservation-id " + "%" PRIaTXN, + dbg_prefix_mode, head_gc_id, reused_gc_slot, reservation_gc_id); + + mdbx_trace("%s: chunk %u, gc-per-ovpage %u", dbg_prefix_mode, chunk, + env->me_maxgc_ov1page); + + mdbx_tassert(txn, reservation_gc_id < *env->me_oldest); + if (unlikely(reservation_gc_id < 1 || + reservation_gc_id >= *env->me_oldest)) { + /* LY: not any txn in the past of freedb. */ + rc = MDBX_PROBLEM; + goto bailout; + } + + key.iov_len = sizeof(reservation_gc_id); + key.iov_base = &reservation_gc_id; + data.iov_len = (chunk + 1) * sizeof(pgno_t); + mdbx_trace("%s.reserve: %u [%u...%u] @%" PRIaTXN, dbg_prefix_mode, chunk, + settled + 1, settled + chunk + 1, reservation_gc_id); + mdbx_prep_backlog_data(txn, &mc, data.iov_len); + rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE | MDBX_NOOVERWRITE); + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + /* PNL is initially empty, zero out at least the length */ + memset(data.iov_base, 0, sizeof(pgno_t)); + settled += chunk; + mdbx_trace("%s.settled %u (+%u), continue", dbg_prefix_mode, settled, + chunk); + + if (txn->mt_lifo_reclaimed && + unlikely(amount < MDBX_PNL_SIZE(env->me_reclaimed_pglist))) { + mdbx_notice("** restart: reclaimed-list growth %u -> %u", amount, + (unsigned)MDBX_PNL_SIZE(env->me_reclaimed_pglist)); + goto retry; + } + + continue; + } + + mdbx_tassert( + txn, + cleaned_gc_slot == + (txn->mt_lifo_reclaimed ? MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) : 0)); + + mdbx_trace(" >> filling"); + /* Fill in the reserved records */ + filled_gc_slot = + txn->mt_lifo_reclaimed + ? (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) - reused_gc_slot + : reused_gc_slot; + rc = MDBX_SUCCESS; + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + if (env->me_reclaimed_pglist && MDBX_PNL_SIZE(env->me_reclaimed_pglist)) { + MDBX_val key, data; + key.iov_len = data.iov_len = 0; /* avoid MSVC warning */ + key.iov_base = data.iov_base = NULL; + + const unsigned amount = MDBX_PNL_SIZE(env->me_reclaimed_pglist); + unsigned left = amount; + if (txn->mt_lifo_reclaimed == nullptr) { + mdbx_tassert(txn, lifo == 0); + rc = mdbx_cursor_first(&mc, &key, &data); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } else { + mdbx_tassert(txn, lifo != 0); + } + + while (1) { + txnid_t fill_gc_id; + mdbx_trace("%s: left %u of %u", dbg_prefix_mode, left, + (unsigned)MDBX_PNL_SIZE(env->me_reclaimed_pglist)); + if (txn->mt_lifo_reclaimed == nullptr) { + mdbx_tassert(txn, lifo == 0); + fill_gc_id = *(txnid_t *)key.iov_base; + if (filled_gc_slot-- == 0 || fill_gc_id > env->me_last_reclaimed) { + mdbx_notice( + "** restart: reserve depleted (filled_slot %u, fill_id %" PRIaTXN + " > last_reclaimed %" PRIaTXN, + filled_gc_slot, fill_gc_id, env->me_last_reclaimed); + goto retry; + } + } else { + mdbx_tassert(txn, lifo != 0); + if (++filled_gc_slot > + (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)) { + mdbx_notice("** restart: reserve depleted (filled_gc_slot %u > " + "lifo_reclaimed %u" PRIaTXN, + filled_gc_slot, + (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + goto retry; + } + fill_gc_id = txn->mt_lifo_reclaimed[filled_gc_slot]; + mdbx_trace("%s.seek-reservation @%" PRIaTXN " at lifo_reclaimed[%u]", + dbg_prefix_mode, fill_gc_id, filled_gc_slot); + key.iov_base = &fill_gc_id; + key.iov_len = sizeof(fill_gc_id); + rc = mdbx_cursor_get(&mc, &key, &data, MDBX_SET_KEY); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + mdbx_tassert(txn, cleaned_gc_slot == + (txn->mt_lifo_reclaimed + ? MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) + : 0)); + mdbx_tassert(txn, fill_gc_id > 0 && fill_gc_id < *env->me_oldest); + key.iov_base = &fill_gc_id; + key.iov_len = sizeof(fill_gc_id); + + mdbx_tassert(txn, data.iov_len >= sizeof(pgno_t) * 2); + mc.mc_flags |= C_GCFREEZE; + unsigned chunk = (unsigned)(data.iov_len / sizeof(pgno_t)) - 1; + if (unlikely(chunk > left)) { + mdbx_trace("%s: chunk %u > left %u, @%" PRIaTXN, dbg_prefix_mode, chunk, + left, fill_gc_id); + if ((loop < 5 && chunk - left > loop / 2) || + chunk - left > env->me_maxgc_ov1page) { + data.iov_len = (left + 1) * sizeof(pgno_t); + if (loop < 7) + mc.mc_flags &= ~C_GCFREEZE; + } + chunk = left; + } + rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT | MDBX_RESERVE); + mc.mc_flags &= ~C_GCFREEZE; + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + if (unlikely(txn->mt_loose_count || + amount != MDBX_PNL_SIZE(env->me_reclaimed_pglist))) { + memset(data.iov_base, 0, sizeof(pgno_t)); + mdbx_notice("** restart: reclaimed-list changed (%u -> %u, %u)", amount, + MDBX_PNL_SIZE(env->me_reclaimed_pglist), + txn->mt_loose_count); + goto retry; + } + if (unlikely(txn->mt_lifo_reclaimed + ? cleaned_gc_slot < MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) + : cleaned_gc_id < env->me_last_reclaimed)) { + memset(data.iov_base, 0, sizeof(pgno_t)); + mdbx_notice("** restart: reclaimed-slots changed"); + goto retry; + } + + pgno_t *dst = data.iov_base; + *dst++ = chunk; + pgno_t *src = MDBX_PNL_BEGIN(env->me_reclaimed_pglist) + left - chunk; + memcpy(dst, src, chunk * sizeof(pgno_t)); + pgno_t *from = src, *to = src + chunk; + mdbx_trace("%s.fill: %u [ %u:%" PRIaPGNO "...%u:%" PRIaPGNO + "] @%" PRIaTXN, + dbg_prefix_mode, chunk, + (unsigned)(from - env->me_reclaimed_pglist), from[0], + (unsigned)(to - env->me_reclaimed_pglist), to[-1], fill_gc_id); + + left -= chunk; + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, befree_stored + amount - left); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } + if (left == 0) { + rc = MDBX_SUCCESS; + break; + } + + if (txn->mt_lifo_reclaimed == nullptr) { + mdbx_tassert(txn, lifo == 0); + rc = mdbx_cursor_next(&mc, &key, &data, MDBX_NEXT); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } else { + mdbx_tassert(txn, lifo != 0); + } + } + } + + mdbx_tassert(txn, rc == MDBX_SUCCESS); + if (unlikely(txn->mt_loose_count != 0 || + filled_gc_slot != + (txn->mt_lifo_reclaimed + ? (unsigned)MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) + : 0))) { + mdbx_notice("** restart: reserve excess (filled-slot %u, loose-count %u)", + filled_gc_slot, txn->mt_loose_count); + goto retry; + } + + mdbx_tassert(txn, + txn->mt_lifo_reclaimed == NULL || + cleaned_gc_slot == MDBX_PNL_SIZE(txn->mt_lifo_reclaimed)); + +bailout: + txn->mt_cursors[FREE_DBI] = mc.mc_next; + +bailout_notracking: + if (txn->mt_lifo_reclaimed) { + MDBX_PNL_SIZE(txn->mt_lifo_reclaimed) = 0; + if (txn != env->me_txn0) { + mdbx_txl_free(txn->mt_lifo_reclaimed); + txn->mt_lifo_reclaimed = NULL; + } + } + + mdbx_trace("<<< %u loops, rc = %d", loop, rc); + return rc; +} + +/* Flush (some) dirty pages to the map, after clearing their dirty flag. + * [in] txn the transaction that's being committed + * [in] keep number of initial pages in dirtylist to keep dirty. + * Returns 0 on success, non-zero on failure. */ +static int mdbx_page_flush(MDBX_txn *txn, pgno_t keep) { + MDBX_env *env = txn->mt_env; + MDBX_DPL dl = txn->mt_rw_dirtylist; + unsigned i, j, pagecount = dl->length; + int rc; + size_t size = 0, pos = 0; + pgno_t pgno = 0; + MDBX_page *dp = NULL; + struct iovec iov[MDBX_COMMIT_PAGES]; + intptr_t wpos = 0, wsize = 0; + size_t next_pos = 1; /* impossible pos, so pos != next_pos */ + int n = 0; + + j = i = keep; + + if (env->me_flags & MDBX_WRITEMAP) { + /* Clear dirty flags */ + while (++i <= pagecount) { + dp = dl[i].ptr; + /* Don't flush this page yet */ + if (dp->mp_flags & (P_LOOSE | P_KEEP)) { + dp->mp_flags &= ~P_KEEP; + dl[++j] = dl[i]; + continue; + } + dp->mp_flags &= ~P_DIRTY; + dp->mp_validator = 0 /* TODO */; + *env->me_unsynced_pages += IS_OVERFLOW(dp) ? dp->mp_pages : 1; + } + goto done; + } + + /* Write the pages */ + for (;;) { + if (++i <= pagecount) { + dp = dl[i].ptr; + /* Don't flush this page yet */ + if (dp->mp_flags & (P_LOOSE | P_KEEP)) { + dp->mp_flags &= ~P_KEEP; + dl[i].pgno = 0; + continue; + } + pgno = dl[i].pgno; + mdbx_tassert(txn, pgno >= MIN_PAGENO); + /* clear dirty flag */ + dp->mp_flags &= ~P_DIRTY; + dp->mp_validator = 0 /* TODO */; + pos = pgno2bytes(env, pgno); + const unsigned npages = IS_OVERFLOW(dp) ? dp->mp_pages : 1; + *env->me_unsynced_pages += npages; + size = pgno2bytes(env, npages); + } + /* Write up to MDBX_COMMIT_PAGES dirty pages at a time. */ + if (pos != next_pos || n == MDBX_COMMIT_PAGES || wsize + size > MAX_WRITE) { + if (n) { + /* Write previous page(s) */ + rc = mdbx_pwritev(env->me_fd, iov, n, wpos, wsize); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_debug("Write error: %s", mdbx_strerror(rc)); + return rc; + } + +#if MDBX_CPU_CACHE_MMAP_NONCOHERENT +#if defined(__linux__) || defined(__gnu_linux__) + if (linux_kernel_version >= 0x02060b00) + /* Linux kernels older than version 2.6.11 ignore the addr and nbytes + * arguments, making this function fairly expensive. Therefore, the + * whole cache is always flushed. */ +#endif /* Linux */ + mdbx_invalidate_mmap_noncoherent_cache(env->me_map + wpos, wsize); +#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ + + n = 0; + } + if (i > pagecount) + break; + wpos = pos; + wsize = 0; + } + mdbx_debug("committing page %" PRIaPGNO, pgno); + next_pos = pos + size; + iov[n].iov_len = size; + iov[n].iov_base = (char *)dp; + wsize += size; + n++; + } + +#if MDBX_CPU_CACHE_MMAP_NONCOHERENT && \ + (defined(__linux__) || defined(__gnu_linux__)) + if (linux_kernel_version < 0x02060b00) { + /* Linux kernels older than version 2.6.11 ignore the addr and nbytes + * arguments, making this function fairly expensive. Therefore, the whole + * cache is always flushed. */ + mdbx_invalidate_mmap_noncoherent_cache(env->me_map, + pgno2bytes(env, txn->mt_next_pgno)); + } +#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT && Linux */ + + for (i = keep; ++i <= pagecount;) { + dp = dl[i].ptr; + /* This is a page we skipped above */ + if (!dl[i].pgno) { + dl[++j] = dl[i]; + dl[j].pgno = dp->mp_pgno; + continue; + } + mdbx_dpage_free(env, dp, IS_OVERFLOW(dp) ? dp->mp_pages : 1); + } + +done: + i--; + txn->mt_dirtyroom += i - j; + dl->length = j; + return MDBX_SUCCESS; +} + +/* Check for misused dbi handles */ +#define TXN_DBI_CHANGED(txn, dbi) \ + ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi]) + +/* Import DBI which opened after txn started into context */ +static __cold bool mdbx_txn_import_dbi(MDBX_txn *txn, MDBX_dbi dbi) { + MDBX_env *env = txn->mt_env; + if (dbi < CORE_DBS || dbi >= env->me_numdbs) + return false; + + mdbx_ensure(env, mdbx_fastmutex_acquire(&env->me_dbi_lock) == MDBX_SUCCESS); + const unsigned snap_numdbs = env->me_numdbs; + mdbx_compiler_barrier(); + for (unsigned i = CORE_DBS; i < snap_numdbs; ++i) { + if (i >= txn->mt_numdbs) + txn->mt_dbflags[i] = 0; + if (!(txn->mt_dbflags[i] & DB_USRVALID) && + (env->me_dbflags[i] & MDBX_VALID)) { + txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS; + txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE; + mdbx_tassert(txn, txn->mt_dbxs[i].md_cmp != NULL); + } + } + txn->mt_numdbs = snap_numdbs; + + mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); + return txn->mt_dbflags[dbi] & DB_USRVALID; +} + +/* Check txn and dbi arguments to a function */ +static __inline bool TXN_DBI_EXIST(MDBX_txn *txn, MDBX_dbi dbi, + unsigned validity) { + if (likely(dbi < txn->mt_numdbs && (txn->mt_dbflags[dbi] & validity))) + return true; + + return mdbx_txn_import_dbi(txn, dbi); +} + +int mdbx_txn_commit(MDBX_txn *txn) { + int rc; + + if (unlikely(txn == NULL)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + MDBX_env *env = txn->mt_env; +#if MDBX_TXN_CHECKPID + if (unlikely(env->me_pid != mdbx_getpid())) { + env->me_flags |= MDBX_FATAL_ERROR; + return MDBX_PANIC; + } +#endif /* MDBX_TXN_CHECKPID */ + + if (txn->mt_child) { + rc = mdbx_txn_commit(txn->mt_child); + txn->mt_child = NULL; + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } + + /* mdbx_txn_end() mode for a commit which writes nothing */ + unsigned end_mode = + MDBX_END_EMPTY_COMMIT | MDBX_END_UPDATE | MDBX_END_SLOT | MDBX_END_FREE; + if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))) + goto done; + + if (unlikely(txn->mt_flags & (MDBX_TXN_FINISHED | MDBX_TXN_ERROR))) { + mdbx_debug("error flag is set, can't commit"); + if (txn->mt_parent) + txn->mt_parent->mt_flags |= MDBX_TXN_ERROR; + rc = MDBX_BAD_TXN; + goto fail; + } + + if (txn->mt_parent) { + MDBX_txn *parent = txn->mt_parent; + MDBX_page **lp; + MDBX_DPL dst, src; + MDBX_PNL pspill; + unsigned i, x, y, len, ps_len; + + /* Append our reclaim list to parent's */ + if (txn->mt_lifo_reclaimed) { + if (parent->mt_lifo_reclaimed) { + rc = mdbx_txl_append_list(&parent->mt_lifo_reclaimed, + txn->mt_lifo_reclaimed); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + mdbx_txl_free(txn->mt_lifo_reclaimed); + } else + parent->mt_lifo_reclaimed = txn->mt_lifo_reclaimed; + txn->mt_lifo_reclaimed = NULL; + } + + /* Append our free list to parent's */ + rc = mdbx_pnl_append_list(&parent->mt_befree_pages, txn->mt_befree_pages); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + mdbx_pnl_free(txn->mt_befree_pages); + /* Failures after this must either undo the changes + * to the parent or set MDBX_TXN_ERROR in the parent. */ + + parent->mt_next_pgno = txn->mt_next_pgno; + parent->mt_end_pgno = txn->mt_end_pgno; + parent->mt_flags = txn->mt_flags; + + /* Merge our cursors into parent's and close them */ + mdbx_cursors_eot(txn, 1); + + /* Update parent's DB table. */ + memcpy(parent->mt_dbs, txn->mt_dbs, txn->mt_numdbs * sizeof(MDBX_db)); + parent->mt_numdbs = txn->mt_numdbs; + parent->mt_dbflags[FREE_DBI] = txn->mt_dbflags[FREE_DBI]; + parent->mt_dbflags[MAIN_DBI] = txn->mt_dbflags[MAIN_DBI]; + for (i = CORE_DBS; i < txn->mt_numdbs; i++) { + /* preserve parent's DB_NEW status */ + parent->mt_dbflags[i] = + txn->mt_dbflags[i] | (parent->mt_dbflags[i] & (DB_CREAT | DB_FRESH)); + } + + dst = parent->mt_rw_dirtylist; + src = txn->mt_rw_dirtylist; + /* Remove anything in our dirty list from parent's spill list */ + if ((pspill = parent->mt_spill_pages) && (ps_len = MDBX_PNL_SIZE(pspill))) { + x = y = ps_len; + MDBX_PNL_SIZE(pspill) = ~(pgno_t)0; + /* Mark our dirty pages as deleted in parent spill list */ + for (i = 0, len = src->length; ++i <= len;) { + pgno_t pn = src[i].pgno << 1; + while (pn > pspill[x]) + x--; + if (pn == pspill[x]) { + pspill[x] = 1; + y = --x; + } + } + /* Squash deleted pagenums if we deleted any */ + for (x = y; ++x <= ps_len;) + if ((pspill[x] & 1) == 0) + pspill[++y] = pspill[x]; + MDBX_PNL_SIZE(pspill) = y; + } + + /* Remove anything in our spill list from parent's dirty list */ + if (txn->mt_spill_pages && MDBX_PNL_SIZE(txn->mt_spill_pages)) { + for (i = 1; i <= MDBX_PNL_SIZE(txn->mt_spill_pages); i++) { + pgno_t pn = txn->mt_spill_pages[i]; + if (pn & 1) + continue; /* deleted spillpg */ + pn >>= 1; + y = mdbx_dpl_search(dst, pn); + if (y <= dst->length && dst[y].pgno == pn) { + mdbx_free(dst[y].ptr); + while (y < dst->length) { + dst[y] = dst[y + 1]; + y++; + } + dst->length--; + } + } + } + + /* Find len = length of merging our dirty list with parent's */ + x = dst->length; + dst->length = 0; /* simplify loops */ + if (parent->mt_parent) { + len = x + src->length; + y = mdbx_dpl_search(src, dst[x].pgno + 1) - 1; + for (i = x; y && i; y--) { + pgno_t yp = src[y].pgno; + while (yp < dst[i].pgno) + i--; + if (yp == dst[i].pgno) { + i--; + len--; + } + } + } else { /* Simplify the above for single-ancestor case */ + len = MDBX_DPL_TXNFULL - txn->mt_dirtyroom; + } + /* Merge our dirty list with parent's */ + y = src->length; + for (i = len; y; dst[i--] = src[y--]) { + pgno_t yp = src[y].pgno; + while (yp < dst[x].pgno) + dst[i--] = dst[x--]; + if (yp == dst[x].pgno) + mdbx_free(dst[x--].ptr); + } + mdbx_tassert(txn, i == x); + dst->length = len; + mdbx_free(txn->mt_rw_dirtylist); + parent->mt_dirtyroom = txn->mt_dirtyroom; + if (txn->mt_spill_pages) { + if (parent->mt_spill_pages) { + /* TODO: Prevent failure here, so parent does not fail */ + rc = mdbx_pnl_append_list(&parent->mt_spill_pages, txn->mt_spill_pages); + if (unlikely(rc != MDBX_SUCCESS)) + parent->mt_flags |= MDBX_TXN_ERROR; + mdbx_pnl_free(txn->mt_spill_pages); + mdbx_pnl_sort(parent->mt_spill_pages); + } else { + parent->mt_spill_pages = txn->mt_spill_pages; + } + } + + /* Append our loose page list to parent's */ + for (lp = &parent->mt_loose_pages; *lp; lp = &NEXT_LOOSE_PAGE(*lp)) + ; + *lp = txn->mt_loose_pages; + parent->mt_loose_count += txn->mt_loose_count; + + parent->mt_child = NULL; + mdbx_pnl_free(((MDBX_ntxn *)txn)->mnt_pgstate.mf_reclaimed_pglist); + txn->mt_signature = 0; + mdbx_free(txn); + return rc; + } + + if (unlikely(txn != env->me_txn)) { + mdbx_debug("attempt to commit unknown transaction"); + rc = MDBX_EINVAL; + goto fail; + } + + mdbx_cursors_eot(txn, 0); + end_mode |= MDBX_END_EOTDONE; + + if (txn->mt_rw_dirtylist->length == 0 && + !(txn->mt_flags & (MDBX_TXN_DIRTY | MDBX_TXN_SPILLS))) + goto done; + + mdbx_debug("committing txn %" PRIaTXN " %p on mdbenv %p, root page %" PRIaPGNO + "/%" PRIaPGNO, + txn->mt_txnid, (void *)txn, (void *)env, + txn->mt_dbs[MAIN_DBI].md_root, txn->mt_dbs[FREE_DBI].md_root); + + /* Update DB root pointers */ + if (txn->mt_numdbs > CORE_DBS) { + MDBX_cursor mc; + MDBX_dbi i; + MDBX_val data; + data.iov_len = sizeof(MDBX_db); + + rc = mdbx_cursor_init(&mc, txn, MAIN_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + for (i = CORE_DBS; i < txn->mt_numdbs; i++) { + if (txn->mt_dbflags[i] & DB_DIRTY) { + if (unlikely(TXN_DBI_CHANGED(txn, i))) { + rc = MDBX_BAD_DBI; + goto fail; + } + data.iov_base = &txn->mt_dbs[i]; + WITH_CURSOR_TRACKING(mc, + rc = mdbx_cursor_put(&mc, &txn->mt_dbxs[i].md_name, + &data, F_SUBDATA)); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } + } + } + + rc = mdbx_update_gc(txn); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + + mdbx_pnl_free(env->me_reclaimed_pglist); + env->me_reclaimed_pglist = NULL; + mdbx_pnl_shrink(&txn->mt_befree_pages); + + if (mdbx_audit_enabled()) { + rc = mdbx_audit(txn, 0); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } + + rc = mdbx_page_flush(txn, 0); + if (likely(rc == MDBX_SUCCESS)) { + MDBX_meta meta, *head = mdbx_meta_head(env); + + meta.mm_magic_and_version = head->mm_magic_and_version; + meta.mm_extra_flags = head->mm_extra_flags; + meta.mm_validator_id = head->mm_validator_id; + meta.mm_extra_pagehdr = head->mm_extra_pagehdr; + + meta.mm_geo = head->mm_geo; + meta.mm_geo.next = txn->mt_next_pgno; + meta.mm_geo.now = txn->mt_end_pgno; + meta.mm_dbs[FREE_DBI] = txn->mt_dbs[FREE_DBI]; + meta.mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI]; + meta.mm_canary = txn->mt_canary; + mdbx_meta_set_txnid(env, &meta, txn->mt_txnid); + + rc = mdbx_sync_locked( + env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED, &meta); + } + if (unlikely(rc != MDBX_SUCCESS)) { + env->me_flags |= MDBX_FATAL_ERROR; + goto fail; + } + + if (likely(env->me_lck)) + env->me_lck->mti_readers_refresh_flag = false; + end_mode = MDBX_END_COMMITTED | MDBX_END_UPDATE | MDBX_END_EOTDONE; + +done: + return mdbx_txn_end(txn, end_mode); + +fail: + mdbx_txn_abort(txn); + return rc; +} + +/* Read the environment parameters of a DB environment + * before mapping it into memory. */ +static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta, + uint64_t *filesize) { + STATIC_ASSERT(offsetof(MDBX_page, mp_meta) == PAGEHDRSZ); + + int rc = mdbx_filesize(env->me_fd, filesize); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + memset(meta, 0, sizeof(MDBX_meta)); + meta->mm_datasync_sign = MDBX_DATASIGN_WEAK; + rc = MDBX_CORRUPTED; + + /* Read twice all meta pages so we can find the latest one. */ + unsigned loop_limit = NUM_METAS * 2; + for (unsigned loop_count = 0; loop_count < loop_limit; ++loop_count) { + MDBX_page page; + + /* We don't know the page size on first time. + * So, just guess it. */ + unsigned guess_pagesize = meta->mm_psize; + if (guess_pagesize == 0) + guess_pagesize = + (loop_count > NUM_METAS) ? env->me_psize : env->me_os_psize; + + const unsigned meta_number = loop_count % NUM_METAS; + const unsigned offset = guess_pagesize * meta_number; + + unsigned retryleft = 42; + while (1) { + mdbx_trace("reading meta[%d]: offset %u, bytes %u, retry-left %u", + meta_number, offset, (unsigned)sizeof(page), retryleft); + int err = mdbx_pread(env->me_fd, &page, sizeof(page), offset); + if (err != MDBX_SUCCESS) { + mdbx_error("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(page), + err, mdbx_strerror(err)); + return err; + } + + MDBX_page again; + err = mdbx_pread(env->me_fd, &again, sizeof(again), offset); + if (err != MDBX_SUCCESS) { + mdbx_error("read meta[%u,%u]: %i, %s", offset, (unsigned)sizeof(again), + err, mdbx_strerror(err)); + return err; + } + + if (memcmp(&page, &again, sizeof(page)) == 0 || --retryleft == 0) + break; + + mdbx_info("meta[%u] was updated, re-read it", meta_number); + } + + if (page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC && + page.mp_meta.mm_magic_and_version != MDBX_DATA_MAGIC_DEVEL) { + mdbx_error("meta[%u] has invalid magic/version %" PRIx64, meta_number, + page.mp_meta.mm_magic_and_version); + return ((page.mp_meta.mm_magic_and_version >> 8) != MDBX_MAGIC) + ? MDBX_INVALID + : MDBX_VERSION_MISMATCH; + } + + if (page.mp_pgno != meta_number) { + mdbx_error("meta[%u] has invalid pageno %" PRIaPGNO, meta_number, + page.mp_pgno); + return MDBX_INVALID; + } + + if (page.mp_flags != P_META) { + mdbx_error("page #%u not a meta-page", meta_number); + return MDBX_INVALID; + } + + if (!retryleft) { + mdbx_error("meta[%u] is too volatile, skip it", meta_number); + continue; + } + + /* LY: check pagesize */ + if (!mdbx_is_power2(page.mp_meta.mm_psize) || + page.mp_meta.mm_psize < MIN_PAGESIZE || + page.mp_meta.mm_psize > MAX_PAGESIZE) { + mdbx_notice("meta[%u] has invalid pagesize (%u), skip it", meta_number, + page.mp_meta.mm_psize); + rc = mdbx_is_power2(page.mp_meta.mm_psize) ? MDBX_VERSION_MISMATCH + : MDBX_INVALID; + continue; + } + + if (meta_number == 0 && guess_pagesize != page.mp_meta.mm_psize) { + meta->mm_psize = page.mp_meta.mm_psize; + mdbx_info("meta[%u] took pagesize %u", meta_number, + page.mp_meta.mm_psize); + } + + if (page.mp_meta.mm_txnid_a != page.mp_meta.mm_txnid_b) { + mdbx_warning("meta[%u] not completely updated, skip it", meta_number); + continue; + } + + /* LY: check signature as a checksum */ + if (META_IS_STEADY(&page.mp_meta) && + page.mp_meta.mm_datasync_sign != mdbx_meta_sign(&page.mp_meta)) { + mdbx_notice("meta[%u] has invalid steady-checksum (0x%" PRIx64 + " != 0x%" PRIx64 "), skip it", + meta_number, page.mp_meta.mm_datasync_sign, + mdbx_meta_sign(&page.mp_meta)); + continue; + } + + mdbx_debug("read meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO + ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO + " +%u -%u, txn_id %" PRIaTXN ", %s", + page.mp_pgno, page.mp_meta.mm_dbs[MAIN_DBI].md_root, + page.mp_meta.mm_dbs[FREE_DBI].md_root, page.mp_meta.mm_geo.lower, + page.mp_meta.mm_geo.next, page.mp_meta.mm_geo.now, + page.mp_meta.mm_geo.upper, page.mp_meta.mm_geo.grow, + page.mp_meta.mm_geo.shrink, page.mp_meta.mm_txnid_a, + mdbx_durable_str(&page.mp_meta)); + + /* LY: check min-pages value */ + if (page.mp_meta.mm_geo.lower < MIN_PAGENO || + page.mp_meta.mm_geo.lower > MAX_PAGENO) { + mdbx_notice("meta[%u] has invalid min-pages (%" PRIaPGNO "), skip it", + meta_number, page.mp_meta.mm_geo.lower); + rc = MDBX_INVALID; + continue; + } + + /* LY: check max-pages value */ + if (page.mp_meta.mm_geo.upper < MIN_PAGENO || + page.mp_meta.mm_geo.upper > MAX_PAGENO || + page.mp_meta.mm_geo.upper < page.mp_meta.mm_geo.lower) { + mdbx_notice("meta[%u] has invalid max-pages (%" PRIaPGNO "), skip it", + meta_number, page.mp_meta.mm_geo.upper); + rc = MDBX_INVALID; + continue; + } + + /* LY: check last_pgno */ + if (page.mp_meta.mm_geo.next < MIN_PAGENO || + page.mp_meta.mm_geo.next - 1 > MAX_PAGENO) { + mdbx_notice("meta[%u] has invalid next-pageno (%" PRIaPGNO "), skip it", + meta_number, page.mp_meta.mm_geo.next); + rc = MDBX_CORRUPTED; + continue; + } + + /* LY: check filesize & used_bytes */ + const uint64_t used_bytes = + page.mp_meta.mm_geo.next * (uint64_t)page.mp_meta.mm_psize; + if (used_bytes > *filesize) { + /* Here could be a race with DB-shrinking performed by other process */ + rc = mdbx_filesize(env->me_fd, filesize); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (used_bytes > *filesize) { + mdbx_notice("meta[%u] used-bytes (%" PRIu64 + ") beyond filesize (%" PRIu64 "), skip it", + meta_number, used_bytes, *filesize); + rc = MDBX_CORRUPTED; + continue; + } + } + + /* LY: check mapsize limits */ + const uint64_t mapsize_min = + page.mp_meta.mm_geo.lower * (uint64_t)page.mp_meta.mm_psize; + STATIC_ASSERT(MAX_MAPSIZE < PTRDIFF_MAX - MAX_PAGESIZE); + STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE); + if (mapsize_min < MIN_MAPSIZE || mapsize_min > MAX_MAPSIZE) { + mdbx_notice("meta[%u] has invalid min-mapsize (%" PRIu64 "), skip it", + meta_number, mapsize_min); + rc = MDBX_VERSION_MISMATCH; + continue; + } + + const uint64_t mapsize_max = + page.mp_meta.mm_geo.upper * (uint64_t)page.mp_meta.mm_psize; + STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE); + if (mapsize_max > MAX_MAPSIZE || + MAX_PAGENO < mdbx_roundup2((size_t)mapsize_max, env->me_os_psize) / + (size_t)page.mp_meta.mm_psize) { + if (page.mp_meta.mm_geo.next - 1 > MAX_PAGENO || + used_bytes > MAX_MAPSIZE) { + mdbx_notice("meta[%u] has too large max-mapsize (%" PRIu64 "), skip it", + meta_number, mapsize_max); + rc = MDBX_TOO_LARGE; + continue; + } + + /* allow to open large DB from a 32-bit environment */ + mdbx_notice("meta[%u] has too large max-mapsize (%" PRIu64 "), " + "but size of used space still acceptable (%" PRIu64 ")", + meta_number, mapsize_max, used_bytes); + page.mp_meta.mm_geo.upper = (pgno_t)(MAX_MAPSIZE / page.mp_meta.mm_psize); + } + + /* LY: check and silently put mm_geo.now into [geo.lower...geo.upper]. + * + * Copy-with-compaction by previous version of libmdbx could produce DB-file + * less than meta.geo.lower bound, in case actual filling is low or no data + * at all. This is not a problem as there is no damage or loss of data. + * Therefore it is better not to consider such situation as an error, but + * silently correct it. */ + if (page.mp_meta.mm_geo.now < page.mp_meta.mm_geo.lower) + page.mp_meta.mm_geo.now = page.mp_meta.mm_geo.lower; + if (page.mp_meta.mm_geo.now > page.mp_meta.mm_geo.upper) + page.mp_meta.mm_geo.now = page.mp_meta.mm_geo.upper; + + if (page.mp_meta.mm_geo.next > page.mp_meta.mm_geo.now) { + mdbx_notice("meta[%u] next-pageno (%" PRIaPGNO + ") is beyond end-pgno (%" PRIaPGNO "), skip it", + meta_number, page.mp_meta.mm_geo.next, + page.mp_meta.mm_geo.now); + rc = MDBX_CORRUPTED; + continue; + } + + /* LY: FreeDB root */ + if (page.mp_meta.mm_dbs[FREE_DBI].md_root == P_INVALID) { + if (page.mp_meta.mm_dbs[FREE_DBI].md_branch_pages || + page.mp_meta.mm_dbs[FREE_DBI].md_depth || + page.mp_meta.mm_dbs[FREE_DBI].md_entries || + page.mp_meta.mm_dbs[FREE_DBI].md_leaf_pages || + page.mp_meta.mm_dbs[FREE_DBI].md_overflow_pages) { + mdbx_notice("meta[%u] has false-empty freedb, skip it", meta_number); + rc = MDBX_CORRUPTED; + continue; + } + } else if (page.mp_meta.mm_dbs[FREE_DBI].md_root >= + page.mp_meta.mm_geo.next) { + mdbx_notice("meta[%u] has invalid freedb-root %" PRIaPGNO ", skip it", + meta_number, page.mp_meta.mm_dbs[FREE_DBI].md_root); + rc = MDBX_CORRUPTED; + continue; + } + + /* LY: MainDB root */ + if (page.mp_meta.mm_dbs[MAIN_DBI].md_root == P_INVALID) { + if (page.mp_meta.mm_dbs[MAIN_DBI].md_branch_pages || + page.mp_meta.mm_dbs[MAIN_DBI].md_depth || + page.mp_meta.mm_dbs[MAIN_DBI].md_entries || + page.mp_meta.mm_dbs[MAIN_DBI].md_leaf_pages || + page.mp_meta.mm_dbs[MAIN_DBI].md_overflow_pages) { + mdbx_notice("meta[%u] has false-empty maindb", meta_number); + rc = MDBX_CORRUPTED; + continue; + } + } else if (page.mp_meta.mm_dbs[MAIN_DBI].md_root >= + page.mp_meta.mm_geo.next) { + mdbx_notice("meta[%u] has invalid maindb-root %" PRIaPGNO ", skip it", + meta_number, page.mp_meta.mm_dbs[MAIN_DBI].md_root); + rc = MDBX_CORRUPTED; + continue; + } + + if (page.mp_meta.mm_txnid_a == 0) { + mdbx_warning("meta[%u] has zero txnid, skip it", meta_number); + continue; + } + + if (mdbx_meta_ot(prefer_noweak, env, meta, &page.mp_meta)) { + *meta = page.mp_meta; + if (META_IS_WEAK(meta)) + loop_limit += 1; /* LY: should re-read to hush race with update */ + mdbx_info("latch meta[%u]", meta_number); + } + } + + if (META_IS_WEAK(meta)) { + mdbx_error("no usable meta-pages, database is corrupted"); + return rc; + } + + return MDBX_SUCCESS; +} + +static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model, + unsigned num) { + + mdbx_ensure(env, mdbx_is_power2(env->me_psize)); + mdbx_ensure(env, env->me_psize >= MIN_PAGESIZE); + mdbx_ensure(env, env->me_psize <= MAX_PAGESIZE); + mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE); + mdbx_ensure(env, env->me_dbgeo.upper <= MAX_MAPSIZE); + mdbx_ensure(env, env->me_dbgeo.now >= env->me_dbgeo.lower); + mdbx_ensure(env, env->me_dbgeo.now <= env->me_dbgeo.upper); + + memset(model, 0, sizeof(*model)); + model->mp_pgno = num; + model->mp_flags = P_META; + model->mp_meta.mm_magic_and_version = MDBX_DATA_MAGIC; + + model->mp_meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); + model->mp_meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); + model->mp_meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); + model->mp_meta.mm_geo.shrink = + (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); + model->mp_meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); + model->mp_meta.mm_geo.next = NUM_METAS; + + mdbx_ensure(env, model->mp_meta.mm_geo.lower >= MIN_PAGENO); + mdbx_ensure(env, model->mp_meta.mm_geo.upper <= MAX_PAGENO); + mdbx_ensure(env, model->mp_meta.mm_geo.now >= model->mp_meta.mm_geo.lower); + mdbx_ensure(env, model->mp_meta.mm_geo.now <= model->mp_meta.mm_geo.upper); + mdbx_ensure(env, model->mp_meta.mm_geo.next >= MIN_PAGENO); + mdbx_ensure(env, model->mp_meta.mm_geo.next <= model->mp_meta.mm_geo.now); + mdbx_ensure(env, model->mp_meta.mm_geo.grow == + bytes2pgno(env, env->me_dbgeo.grow)); + mdbx_ensure(env, model->mp_meta.mm_geo.shrink == + bytes2pgno(env, env->me_dbgeo.shrink)); + + model->mp_meta.mm_psize = env->me_psize; + model->mp_meta.mm_flags = (uint16_t)env->me_flags; + model->mp_meta.mm_flags |= + MDBX_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */ + model->mp_meta.mm_dbs[FREE_DBI].md_root = P_INVALID; + model->mp_meta.mm_dbs[MAIN_DBI].md_root = P_INVALID; + mdbx_meta_set_txnid(env, &model->mp_meta, MIN_TXNID + num); + model->mp_meta.mm_datasync_sign = mdbx_meta_sign(&model->mp_meta); + return (MDBX_page *)((uint8_t *)model + env->me_psize); +} + +/* Fill in most of the zeroed meta-pages for an empty database environment. + * Return pointer to recenly (head) meta-page. */ +static MDBX_page *__cold mdbx_init_metas(const MDBX_env *env, void *buffer) { + MDBX_page *page0 = (MDBX_page *)buffer; + MDBX_page *page1 = mdbx_meta_model(env, page0, 0); + MDBX_page *page2 = mdbx_meta_model(env, page1, 1); + mdbx_meta_model(env, page2, 2); + mdbx_assert(env, !mdbx_meta_eq(env, &page0->mp_meta, &page1->mp_meta)); + mdbx_assert(env, !mdbx_meta_eq(env, &page1->mp_meta, &page2->mp_meta)); + mdbx_assert(env, !mdbx_meta_eq(env, &page2->mp_meta, &page0->mp_meta)); + return page2; +} + +static int mdbx_sync_locked(MDBX_env *env, unsigned flags, + MDBX_meta *const pending) { + mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); + MDBX_meta *const meta0 = METAPAGE(env, 0); + MDBX_meta *const meta1 = METAPAGE(env, 1); + MDBX_meta *const meta2 = METAPAGE(env, 2); + MDBX_meta *const head = mdbx_meta_head(env); + + mdbx_assert(env, mdbx_meta_eq_mask(env) == 0); + mdbx_assert(env, + pending < METAPAGE(env, 0) || pending > METAPAGE(env, NUM_METAS)); + mdbx_assert(env, (env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)) == 0); + mdbx_assert(env, !META_IS_STEADY(head) || *env->me_unsynced_pages != 0); + mdbx_assert(env, pending->mm_geo.next <= pending->mm_geo.now); + + if (flags & (MDBX_NOSYNC | MDBX_MAPASYNC)) { + /* Check auto-sync conditions */ + const pgno_t autosync_threshold = *env->me_autosync_threshold; + const uint64_t unsynced_timeout = *env->me_unsynced_timeout; + if ((autosync_threshold && *env->me_unsynced_pages >= autosync_threshold) || + (unsynced_timeout && mdbx_osal_monotime() >= unsynced_timeout)) + flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED; /* force steady */ + } + + /* LY: check conditions to shrink datafile */ + const pgno_t backlog_gap = + pending->mm_dbs[FREE_DBI].md_depth + mdbx_backlog_extragap(env); + pgno_t shrink = 0; + if ((flags & MDBX_SHRINK_ALLOWED) && pending->mm_geo.shrink && + pending->mm_geo.now - pending->mm_geo.next > + pending->mm_geo.shrink + backlog_gap) { + const pgno_t largest = mdbx_find_largest( + env, (head->mm_geo.next > pending->mm_geo.next) ? head->mm_geo.next + : pending->mm_geo.next); + if (pending->mm_geo.now > largest && + pending->mm_geo.now - largest > pending->mm_geo.shrink + backlog_gap) { + const pgno_t aligner = + pending->mm_geo.grow ? pending->mm_geo.grow : pending->mm_geo.shrink; + const pgno_t with_backlog_gap = largest + backlog_gap; + const pgno_t aligned = pgno_align2os_pgno( + env, with_backlog_gap + aligner - with_backlog_gap % aligner); + const pgno_t bottom = + (aligned > pending->mm_geo.lower) ? aligned : pending->mm_geo.lower; + if (pending->mm_geo.now > bottom) { + flags &= MDBX_WRITEMAP | MDBX_SHRINK_ALLOWED; /* force steady */ + shrink = pending->mm_geo.now - bottom; + pending->mm_geo.now = bottom; + if (mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a) + mdbx_meta_set_txnid(env, pending, pending->mm_txnid_a + 1); + } + } + } + + /* LY: step#1 - sync previously written/updated data-pages */ + int rc = *env->me_unsynced_pages ? MDBX_RESULT_TRUE /* carry non-steady */ + : MDBX_RESULT_FALSE /* carry steady */; + if (rc != MDBX_RESULT_FALSE && (flags & MDBX_NOSYNC) == 0) { + mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); + MDBX_meta *const recent_steady_meta = mdbx_meta_steady(env); + if (flags & MDBX_WRITEMAP) { + const size_t usedbytes = pgno_align2os_bytes(env, pending->mm_geo.next); + rc = mdbx_msync(&env->me_dxb_mmap, 0, usedbytes, flags & MDBX_MAPASYNC); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + rc = MDBX_RESULT_TRUE /* carry non-steady */; + if ((flags & MDBX_MAPASYNC) == 0) { + if (unlikely(pending->mm_geo.next > recent_steady_meta->mm_geo.now)) { + rc = mdbx_filesync(env->me_fd, MDBX_SYNC_SIZE); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } + rc = MDBX_RESULT_FALSE /* carry steady */; + } + } else { + rc = mdbx_filesync(env->me_fd, + (pending->mm_geo.next > recent_steady_meta->mm_geo.now) + ? MDBX_SYNC_DATA | MDBX_SYNC_SIZE + : MDBX_SYNC_DATA); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } + } + + /* Steady or Weak */ + if (rc == MDBX_RESULT_FALSE /* carry steady */) { + pending->mm_datasync_sign = mdbx_meta_sign(pending); + *env->me_unsynced_pages = 0; + *env->me_unsynced_timeout = 0; + } else { + assert(rc == MDBX_RESULT_TRUE /* carry non-steady */); + const uint64_t autosync_period = *env->me_autosync_period; + if (autosync_period && *env->me_unsynced_timeout == 0) + *env->me_unsynced_timeout = mdbx_osal_monotime() + autosync_period; + pending->mm_datasync_sign = + (flags & MDBX_UTTERLY_NOSYNC) == MDBX_UTTERLY_NOSYNC + ? MDBX_DATASIGN_NONE + : MDBX_DATASIGN_WEAK; + } + + MDBX_meta *target = nullptr; + if (mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a) { + mdbx_assert(env, memcmp(&head->mm_dbs, &pending->mm_dbs, + sizeof(head->mm_dbs)) == 0); + mdbx_assert(env, memcmp(&head->mm_canary, &pending->mm_canary, + sizeof(head->mm_canary)) == 0); + mdbx_assert(env, memcmp(&head->mm_geo, &pending->mm_geo, + sizeof(pending->mm_geo)) == 0); + if (!META_IS_STEADY(head) && META_IS_STEADY(pending)) + target = head; + else { + mdbx_ensure(env, mdbx_meta_eq(env, head, pending)); + mdbx_debug("skip update meta"); + return MDBX_SUCCESS; + } + } else if (head == meta0) + target = mdbx_meta_ancient(prefer_steady, env, meta1, meta2); + else if (head == meta1) + target = mdbx_meta_ancient(prefer_steady, env, meta0, meta2); + else { + mdbx_assert(env, head == meta2); + target = mdbx_meta_ancient(prefer_steady, env, meta0, meta1); + } + + /* LY: step#2 - update meta-page. */ + mdbx_debug("writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO + ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO + " +%u -%u, txn_id %" PRIaTXN ", %s", + container_of(target, MDBX_page, mp_data)->mp_pgno, + pending->mm_dbs[MAIN_DBI].md_root, + pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower, + pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper, + pending->mm_geo.grow, pending->mm_geo.shrink, pending->mm_txnid_a, + mdbx_durable_str(pending)); + + mdbx_debug("meta0: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO + "/%" PRIaPGNO, + (meta0 == head) ? "head" : (meta0 == target) ? "tail" : "stay", + mdbx_durable_str(meta0), mdbx_meta_txnid_fluid(env, meta0), + meta0->mm_dbs[MAIN_DBI].md_root, meta0->mm_dbs[FREE_DBI].md_root); + mdbx_debug("meta1: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO + "/%" PRIaPGNO, + (meta1 == head) ? "head" : (meta1 == target) ? "tail" : "stay", + mdbx_durable_str(meta1), mdbx_meta_txnid_fluid(env, meta1), + meta1->mm_dbs[MAIN_DBI].md_root, meta1->mm_dbs[FREE_DBI].md_root); + mdbx_debug("meta2: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO + "/%" PRIaPGNO, + (meta2 == head) ? "head" : (meta2 == target) ? "tail" : "stay", + mdbx_durable_str(meta2), mdbx_meta_txnid_fluid(env, meta2), + meta2->mm_dbs[MAIN_DBI].md_root, meta2->mm_dbs[FREE_DBI].md_root); + + mdbx_assert(env, !mdbx_meta_eq(env, pending, meta0)); + mdbx_assert(env, !mdbx_meta_eq(env, pending, meta1)); + mdbx_assert(env, !mdbx_meta_eq(env, pending, meta2)); + + mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); + mdbx_ensure(env, target == head || mdbx_meta_txnid_stable(env, target) < + pending->mm_txnid_a); + if (env->me_flags & MDBX_WRITEMAP) { + mdbx_jitter4testing(true); + if (likely(target != head)) { + /* LY: 'invalidate' the meta. */ + target->mm_datasync_sign = MDBX_DATASIGN_WEAK; + mdbx_meta_update_begin(env, target, pending->mm_txnid_a); +#ifndef NDEBUG + /* debug: provoke failure to catch a violators, but don't touch mm_psize + * and mm_flags to allow readers catch actual pagesize. */ + uint8_t *provoke_begin = (uint8_t *)&target->mm_dbs[FREE_DBI].md_root; + uint8_t *provoke_end = (uint8_t *)&target->mm_datasync_sign; + memset(provoke_begin, 0xCC, provoke_end - provoke_begin); + mdbx_jitter4testing(false); +#endif + + /* LY: update info */ + target->mm_geo = pending->mm_geo; + target->mm_dbs[FREE_DBI] = pending->mm_dbs[FREE_DBI]; + target->mm_dbs[MAIN_DBI] = pending->mm_dbs[MAIN_DBI]; + target->mm_canary = pending->mm_canary; + mdbx_jitter4testing(true); + mdbx_flush_noncoherent_cpu_writeback(); + + /* LY: 'commit' the meta */ + mdbx_meta_update_end(env, target, pending->mm_txnid_b); + mdbx_jitter4testing(true); + } else { + /* dangerous case (target == head), only mm_datasync_sign could + * me updated, check assertions once again */ + mdbx_ensure(env, + mdbx_meta_txnid_stable(env, head) == pending->mm_txnid_a && + !META_IS_STEADY(head) && META_IS_STEADY(pending)); + mdbx_ensure(env, memcmp(&head->mm_geo, &pending->mm_geo, + sizeof(head->mm_geo)) == 0); + mdbx_ensure(env, memcmp(&head->mm_dbs, &pending->mm_dbs, + sizeof(head->mm_dbs)) == 0); + mdbx_ensure(env, memcmp(&head->mm_canary, &pending->mm_canary, + sizeof(head->mm_canary)) == 0); + } + target->mm_datasync_sign = pending->mm_datasync_sign; + mdbx_flush_noncoherent_cpu_writeback(); + mdbx_jitter4testing(true); + } else { + rc = mdbx_pwrite(env->me_fd, pending, sizeof(MDBX_meta), + (uint8_t *)target - env->me_map); + if (unlikely(rc != MDBX_SUCCESS)) { + undo: + mdbx_debug("write failed, disk error?"); + /* On a failure, the pagecache still contains the new data. + * Try write some old data back, to prevent it from being used. */ + mdbx_pwrite(env->me_fd, (void *)target, sizeof(MDBX_meta), + (uint8_t *)target - env->me_map); + goto fail; + } + mdbx_invalidate_mmap_noncoherent_cache(target, sizeof(MDBX_meta)); + } + + /* LY: step#3 - sync meta-pages. */ + mdbx_assert(env, ((env->me_flags ^ flags) & MDBX_WRITEMAP) == 0); + if ((flags & (MDBX_NOSYNC | MDBX_NOMETASYNC)) == 0) { + mdbx_assert(env, ((flags ^ env->me_flags) & MDBX_WRITEMAP) == 0); + if (flags & MDBX_WRITEMAP) { + const size_t offset = + ((uint8_t *)container_of(head, MDBX_page, mp_meta)) - + env->me_dxb_mmap.dxb; + const size_t paged_offset = offset & ~(env->me_os_psize - 1); + const size_t paged_length = mdbx_roundup2( + env->me_psize + offset - paged_offset, env->me_os_psize); + rc = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, + flags & MDBX_MAPASYNC); + if (unlikely(rc != MDBX_SUCCESS)) + goto fail; + } else { + rc = mdbx_filesync(env->me_fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ); + if (rc != MDBX_SUCCESS) + goto undo; + } + } + + /* LY: shrink datafile if needed */ + if (unlikely(shrink)) { + mdbx_info("shrink to %" PRIaPGNO " pages (-%" PRIaPGNO ")", + pending->mm_geo.now, shrink); + rc = mdbx_mapresize(env, pending->mm_geo.now, pending->mm_geo.upper); + if (MDBX_IS_ERROR(rc)) + goto fail; + } + + return MDBX_SUCCESS; + +fail: + env->me_flags |= MDBX_FATAL_ERROR; + return rc; +} + +int __cold mdbx_env_get_maxkeysize(MDBX_env *env) { + if (!env || env->me_signature != MDBX_ME_SIGNATURE || !env->me_maxkey_limit) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + return env->me_maxkey_limit; +} + +#define mdbx_nodemax(pagesize) \ + (((((pagesize)-PAGEHDRSZ) / MDBX_MINKEYS) & ~(uintptr_t)1) - sizeof(indx_t)) + +#define mdbx_maxkey(nodemax) (((nodemax)-NODESIZE - sizeof(MDBX_db)) / 2) + +#define mdbx_maxgc_ov1page(pagesize) \ + (((pagesize)-PAGEHDRSZ) / sizeof(pgno_t) - 1) + +static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) { + STATIC_ASSERT(PTRDIFF_MAX > MAX_MAPSIZE); + STATIC_ASSERT(MIN_PAGESIZE > sizeof(MDBX_page)); + mdbx_ensure(env, mdbx_is_power2(pagesize)); + mdbx_ensure(env, pagesize >= MIN_PAGESIZE); + mdbx_ensure(env, pagesize <= MAX_PAGESIZE); + env->me_psize = (unsigned)pagesize; + + STATIC_ASSERT(mdbx_maxgc_ov1page(MIN_PAGESIZE) > 42); + STATIC_ASSERT(mdbx_maxgc_ov1page(MAX_PAGESIZE) < MDBX_DPL_TXNFULL); + const intptr_t maxgc_ov1page = (pagesize - PAGEHDRSZ) / sizeof(pgno_t) - 1; + mdbx_ensure(env, + maxgc_ov1page > 42 && maxgc_ov1page < (intptr_t)MDBX_DPL_TXNFULL); + env->me_maxgc_ov1page = (unsigned)maxgc_ov1page; + + STATIC_ASSERT(mdbx_nodemax(MIN_PAGESIZE) > 42); + STATIC_ASSERT(mdbx_nodemax(MAX_PAGESIZE) < UINT16_MAX); + const intptr_t nodemax = mdbx_nodemax(pagesize); + mdbx_ensure(env, nodemax > 42 && nodemax < UINT16_MAX && nodemax % 2 == 0); + env->me_nodemax = (unsigned)nodemax; + + STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) > 42); + STATIC_ASSERT(mdbx_maxkey(MIN_PAGESIZE) < MIN_PAGESIZE); + STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) > 42); + STATIC_ASSERT(mdbx_maxkey(MAX_PAGESIZE) < MAX_PAGESIZE); + const intptr_t maxkey_limit = mdbx_maxkey(env->me_nodemax); + mdbx_ensure(env, maxkey_limit > 42 && (size_t)maxkey_limit < pagesize && + maxkey_limit % 2 == 0); + env->me_maxkey_limit = (unsigned)maxkey_limit; + + env->me_psize2log = mdbx_log2(pagesize); + mdbx_assert(env, pgno2bytes(env, 1) == pagesize); + mdbx_assert(env, bytes2pgno(env, pagesize + pagesize) == 2); +} + +int __cold mdbx_env_create(MDBX_env **penv) { + MDBX_env *env = mdbx_calloc(1, sizeof(MDBX_env)); + if (!env) + return MDBX_ENOMEM; + + env->me_maxreaders = DEFAULT_READERS; + env->me_maxdbs = env->me_numdbs = CORE_DBS; + env->me_fd = INVALID_HANDLE_VALUE; + env->me_lfd = INVALID_HANDLE_VALUE; + env->me_pid = mdbx_getpid(); + + int rc; + const size_t os_psize = mdbx_syspagesize(); + if (!mdbx_is_power2(os_psize) || os_psize < MIN_PAGESIZE) { + mdbx_error("unsuitable system pagesize %" PRIuPTR, os_psize); + rc = MDBX_INCOMPATIBLE; + goto bailout; + } + env->me_os_psize = (unsigned)os_psize; + mdbx_setup_pagesize(env, env->me_os_psize); + + rc = mdbx_fastmutex_init(&env->me_dbi_lock); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + +#if defined(_WIN32) || defined(_WIN64) + mdbx_srwlock_Init(&env->me_remap_guard); + InitializeCriticalSection(&env->me_windowsbug_lock); +#else + rc = mdbx_fastmutex_init(&env->me_remap_guard); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_fastmutex_destroy(&env->me_dbi_lock); + goto bailout; + } + rc = mdbx_fastmutex_init(&env->me_lckless_stub.wmutex); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_fastmutex_destroy(&env->me_remap_guard); + mdbx_fastmutex_destroy(&env->me_dbi_lock); + goto bailout; + } +#endif /* Windows */ + + VALGRIND_CREATE_MEMPOOL(env, 0, 0); + env->me_signature = MDBX_ME_SIGNATURE; + *penv = env; + return MDBX_SUCCESS; + +bailout: + mdbx_free(env); + *penv = nullptr; + return rc; +} + +static int __cold mdbx_env_map(MDBX_env *env, const int is_exclusive, + const size_t usedsize) { + int rc = mdbx_mmap(env->me_flags, &env->me_dxb_mmap, env->me_dbgeo.now, + env->me_dbgeo.upper); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + +#ifdef MADV_DONTFORK + if (unlikely(madvise(env->me_map, env->me_mapsize, MADV_DONTFORK) != 0)) + return errno; +#endif + +#ifdef MADV_NOHUGEPAGE + (void)madvise(env->me_map, env->me_mapsize, MADV_NOHUGEPAGE); +#endif + +#if defined(MADV_DODUMP) && defined(MADV_DONTDUMP) + const size_t meta_length = pgno2bytes(env, NUM_METAS); + (void)madvise(env->me_map, meta_length, MADV_DODUMP); + if (!(env->me_flags & MDBX_PAGEPERTURB)) + (void)madvise(env->me_map + meta_length, env->me_mapsize - meta_length, + MADV_DONTDUMP); +#endif + + if (is_exclusive && (env->me_flags & MDBX_WRITEMAP) != 0) { +#ifdef MADV_REMOVE_OR_FREE + const size_t used_alined2os = mdbx_roundup2(usedsize, env->me_os_psize); + if (used_alined2os < env->me_mapsize) + (void)madvise(env->me_map + used_alined2os, + env->me_mapsize - used_alined2os, MADV_REMOVE_OR_FREE); +#else + (void)usedsize; +#endif + } + +#ifdef POSIX_FADV_RANDOM + /* this also checks that the file size is valid for a particular FS */ + rc = posix_fadvise(env->me_fd, 0, env->me_dbgeo.upper, POSIX_FADV_RANDOM); + if (unlikely(rc != 0)) + return rc; +#elif defined(F_RDAHEAD) + if (unlikely(fcntl(env->me_fd, F_RDAHEAD, 0) == -1)) + return errno; +#endif + +#if defined(MADV_RANDOM) + if (unlikely(madvise(env->me_map, env->me_mapsize, MADV_RANDOM) != 0)) + return errno; +#elif defined(POSIX_MADV_RANDOM) + rc = posix_madvise(env->me_map, env->me_mapsize, POSIX_MADV_RANDOM); + if (unlikely(rc != 0)) + return errno; +#endif + + /* Turn on/off readahead. It's harmful when the DB is larger than RAM. */ + if (env->me_flags & MDBX_NORDAHEAD) { +#ifdef POSIX_FADV_DONTNEED + rc = posix_fadvise(env->me_fd, 0, env->me_mapsize, POSIX_FADV_DONTNEED); + if (unlikely(rc != 0)) + return rc; +#endif +#if defined(MADV_DONTNEED) + if (unlikely(madvise(env->me_map, env->me_mapsize, MADV_DONTNEED) != 0)) + return errno; +#elif defined(POSIX_MADV_DONTNEED) + rc = posix_madvise(env->me_map, env->me_mapsize, POSIX_MADV_DONTNEED); + if (unlikely(rc != 0)) + return errno; +#endif + } else { +#ifdef POSIX_FADV_WILLNEED + rc = posix_fadvise(env->me_fd, 0, usedsize, POSIX_FADV_WILLNEED); + if (unlikely(rc != 0)) + return rc; +#elif defined(F_RDADVISE) + struct radvisory hint; + hint.ra_offset = 0; + hint.ra_count = usedsize; + if (unlikely(fcntl(env->me_fd, F_RDADVISE, &hint) == -1)) + return errno; +#endif +#if defined(MADV_WILLNEED) + if (unlikely(madvise(env->me_map, usedsize, MADV_WILLNEED) != 0)) + return errno; +#elif defined(POSIX_MADV_WILLNEED) + rc = posix_madvise(env->me_map, usedsize, POSIX_MADV_WILLNEED); + if (unlikely(rc != 0)) + return errno; +#endif +#if defined(_WIN32) || defined(_WIN64) + if (mdbx_PrefetchVirtualMemory) { + WIN32_MEMORY_RANGE_ENTRY hint; + hint.VirtualAddress = env->me_map; + hint.NumberOfBytes = usedsize; + (void)mdbx_PrefetchVirtualMemory(GetCurrentProcess(), 1, &hint, 0); + } +#endif /* Windows */ + } + +#ifdef USE_VALGRIND + env->me_valgrind_handle = + VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx"); +#endif + + return MDBX_SUCCESS; +} + +__cold LIBMDBX_API int +mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, + intptr_t size_upper, intptr_t growth_step, + intptr_t shrink_threshold, intptr_t pagesize) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + +#if MDBX_TXN_CHECKPID + if (unlikely(env->me_pid != mdbx_getpid())) + env->me_flags |= MDBX_FATAL_ERROR; +#endif /* MDBX_TXN_CHECKPID */ + + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) + return MDBX_PANIC; + + const bool inside_txn = + (env->me_txn0 && env->me_txn0->mt_owner == mdbx_thread_self()); + +#if MDBX_DEBUG + if (growth_step < 0) + growth_step = 1; + if (shrink_threshold < 0) + shrink_threshold = 1; +#endif + + bool need_unlock = false; + int rc = MDBX_PROBLEM; + if (env->me_map) { + /* env already mapped */ + if (!env->me_lck || (env->me_flags & MDBX_RDONLY)) + return MDBX_EACCESS; + + if (!inside_txn) { + int err = mdbx_txn_lock(env, false); + if (unlikely(err != MDBX_SUCCESS)) + return err; + need_unlock = true; + } + MDBX_meta *head = mdbx_meta_head(env); + if (!inside_txn) { + env->me_txn0->mt_txnid = meta_txnid(env, head, false); + mdbx_find_oldest(env->me_txn0); + } + + if (pagesize < 0) + pagesize = env->me_psize; + if (pagesize != (intptr_t)env->me_psize) { + rc = MDBX_EINVAL; + goto bailout; + } + + if (size_lower < 0) + size_lower = pgno2bytes(env, head->mm_geo.lower); + if (size_now < 0) + size_now = pgno2bytes(env, head->mm_geo.now); + if (size_upper < 0) + size_upper = pgno2bytes(env, head->mm_geo.upper); + if (growth_step < 0) + growth_step = pgno2bytes(env, head->mm_geo.grow); + if (shrink_threshold < 0) + shrink_threshold = pgno2bytes(env, head->mm_geo.shrink); + + const size_t usedbytes = + pgno2bytes(env, mdbx_find_largest(env, head->mm_geo.next)); + if ((size_t)size_upper < usedbytes) { + rc = MDBX_MAP_FULL; + goto bailout; + } + if ((size_t)size_now < usedbytes) + size_now = usedbytes; + } else { + /* env NOT yet mapped */ + if (unlikely(inside_txn)) + return MDBX_PANIC; + + if (pagesize < 0) { + pagesize = env->me_os_psize; + if ((uintptr_t)pagesize > MAX_PAGESIZE) + pagesize = MAX_PAGESIZE; + mdbx_assert(env, (uintptr_t)pagesize >= MIN_PAGESIZE); + } + } + + if (pagesize == 0) + pagesize = MIN_PAGESIZE; + else if (pagesize == INTPTR_MAX) + pagesize = MAX_PAGESIZE; + + if (pagesize < (intptr_t)MIN_PAGESIZE || pagesize > (intptr_t)MAX_PAGESIZE || + !mdbx_is_power2(pagesize)) { + rc = MDBX_EINVAL; + goto bailout; + } + + if (size_lower <= 0) { + size_lower = MIN_MAPSIZE; + if (MIN_MAPSIZE / pagesize < MIN_PAGENO) + size_lower = MIN_PAGENO * pagesize; + } + + if (size_now <= 0) { + size_now = DEFAULT_MAPSIZE; + if (size_now < size_lower) + size_now = size_lower; + if (size_upper >= size_lower && size_now > size_upper) + size_now = size_upper; + } + + if (size_upper <= 0) { + if ((size_t)size_now >= MAX_MAPSIZE / 2) + size_upper = MAX_MAPSIZE; + else if (MAX_MAPSIZE != MAX_MAPSIZE32 && + (size_t)size_now >= MAX_MAPSIZE32 / 2 && + (size_t)size_now <= MAX_MAPSIZE32 / 4 * 3) + size_upper = MAX_MAPSIZE32; + else { + size_upper = size_now + size_now; + if ((size_t)size_upper < DEFAULT_MAPSIZE * 2) + size_upper = DEFAULT_MAPSIZE * 2; + } + if ((size_t)size_upper / pagesize > MAX_PAGENO) + size_upper = pagesize * MAX_PAGENO; + } + + if (unlikely(size_lower < (intptr_t)MIN_MAPSIZE || size_lower > size_upper)) { + rc = MDBX_EINVAL; + goto bailout; + } + + if ((uint64_t)size_lower / pagesize < MIN_PAGENO) { + rc = MDBX_EINVAL; + goto bailout; + } + + if (unlikely((size_t)size_upper > MAX_MAPSIZE || + (uint64_t)size_upper / pagesize > MAX_PAGENO)) { + rc = MDBX_TOO_LARGE; + goto bailout; + } + + size_lower = mdbx_roundup2(size_lower, env->me_os_psize); + size_upper = mdbx_roundup2(size_upper, env->me_os_psize); + size_now = mdbx_roundup2(size_now, env->me_os_psize); + + /* LY: подбираем значение size_upper: + * - кратное размеру системной страницы + * - без нарушения MAX_MAPSIZE или MAX_PAGENO */ + while (unlikely((size_t)size_upper > MAX_MAPSIZE || + (uint64_t)size_upper / pagesize > MAX_PAGENO)) { + if ((size_t)size_upper < env->me_os_psize + MIN_MAPSIZE || + (size_t)size_upper < env->me_os_psize * (MIN_PAGENO + 1)) { + /* паранойа на случай переполнения при невероятных значениях */ + rc = MDBX_EINVAL; + goto bailout; + } + size_upper -= env->me_os_psize; + if ((size_t)size_upper < (size_t)size_lower) + size_lower = size_upper; + } + mdbx_assert(env, (size_upper - size_lower) % env->me_os_psize == 0); + + if (size_now < size_lower) + size_now = size_lower; + if (size_now > size_upper) + size_now = size_upper; + + if (growth_step < 0) { + growth_step = ((size_t)(size_upper - size_lower)) / 42; + if (growth_step > size_lower) + growth_step = size_lower; + if (growth_step < 65536) + growth_step = 65536; + if ((size_t)growth_step > MEGABYTE * 16) + growth_step = MEGABYTE * 16; + } + growth_step = mdbx_roundup2(growth_step, env->me_os_psize); + if (bytes2pgno(env, growth_step) > UINT16_MAX) + growth_step = pgno2bytes(env, UINT16_MAX); + + if (shrink_threshold < 0) { + shrink_threshold = growth_step + growth_step; + if (shrink_threshold < growth_step) + shrink_threshold = growth_step; + } + shrink_threshold = mdbx_roundup2(shrink_threshold, env->me_os_psize); + if (bytes2pgno(env, shrink_threshold) > UINT16_MAX) + shrink_threshold = pgno2bytes(env, UINT16_MAX); + +#ifdef POSIX_FADV_RANDOM + if (env->me_fd != INVALID_HANDLE_VALUE) { + /* this also checks that the file size is valid for a particular FS */ + rc = posix_fadvise(env->me_fd, 0, env->me_dbgeo.upper, POSIX_FADV_RANDOM); + if (unlikely(rc != 0)) + goto bailout; + } +#endif + + /* save user's geo-params for future open/create */ + env->me_dbgeo.lower = size_lower; + env->me_dbgeo.now = size_now; + env->me_dbgeo.upper = size_upper; + env->me_dbgeo.grow = growth_step; + env->me_dbgeo.shrink = shrink_threshold; + rc = MDBX_SUCCESS; + + if (env->me_map) { + /* apply new params */ + mdbx_assert(env, pagesize == (intptr_t)env->me_psize); + + MDBX_meta *head = mdbx_meta_head(env); + MDBX_meta meta = *head; + meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); + meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); + meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); + meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); + meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); + + mdbx_assert(env, env->me_dbgeo.lower >= MIN_MAPSIZE); + mdbx_assert(env, meta.mm_geo.lower >= MIN_PAGENO); + mdbx_assert(env, env->me_dbgeo.upper <= MAX_MAPSIZE); + mdbx_assert(env, meta.mm_geo.upper <= MAX_PAGENO); + mdbx_assert(env, meta.mm_geo.now >= meta.mm_geo.next); + mdbx_assert(env, env->me_dbgeo.upper >= env->me_dbgeo.lower); + mdbx_assert(env, meta.mm_geo.upper >= meta.mm_geo.now); + mdbx_assert(env, meta.mm_geo.now >= meta.mm_geo.lower); + mdbx_assert(env, meta.mm_geo.grow == bytes2pgno(env, env->me_dbgeo.grow)); + mdbx_assert(env, + meta.mm_geo.shrink == bytes2pgno(env, env->me_dbgeo.shrink)); + + if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) { + +#if defined(_WIN32) || defined(_WIN64) + /* Was DB shrinking disabled before and now it will be enabled? */ + if (meta.mm_geo.lower < meta.mm_geo.upper && meta.mm_geo.shrink && + !(head->mm_geo.lower < head->mm_geo.upper && head->mm_geo.shrink)) { + rc = mdbx_rdt_lock(env); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + /* Check if there are any reading threads that do not use the SRWL */ + const mdbx_pid_t CurrentTid = GetCurrentThreadId(); + const MDBX_reader *const begin = env->me_lck->mti_readers; + const MDBX_reader *const end = begin + env->me_lck->mti_numreaders; + for (const MDBX_reader *reader = begin; reader < end; ++reader) { + if (reader->mr_pid == env->me_pid && reader->mr_tid && + reader->mr_tid != CurrentTid) { + /* At least one thread may don't use SRWL */ + rc = MDBX_EPERM; + break; + } + } + + mdbx_rdt_unlock(env); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + } +#endif + + if (meta.mm_geo.now != head->mm_geo.now || + meta.mm_geo.upper != head->mm_geo.upper) { + rc = mdbx_mapresize(env, meta.mm_geo.now, meta.mm_geo.upper); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + head = /* base address could be changed */ mdbx_meta_head(env); + } + *env->me_unsynced_pages += 1; + mdbx_meta_set_txnid(env, &meta, mdbx_meta_txnid_stable(env, head) + 1); + rc = mdbx_sync_locked(env, env->me_flags, &meta); + } + } else if (pagesize != (intptr_t)env->me_psize) { + mdbx_setup_pagesize(env, pagesize); + } + +bailout: + if (need_unlock) + mdbx_txn_unlock(env); + return rc; +} + +int __cold mdbx_env_set_mapsize(MDBX_env *env, size_t size) { + return mdbx_env_set_geometry(env, -1, size, -1, -1, -1, -1); +} + +int __cold mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { + if (unlikely(dbs > MAX_DBI)) + return MDBX_EINVAL; + + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(env->me_map)) + return MDBX_EPERM; + + env->me_maxdbs = dbs + CORE_DBS; + return MDBX_SUCCESS; +} + +int __cold mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) { + if (unlikely(readers < 1 || readers > INT16_MAX)) + return MDBX_EINVAL; + + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(env->me_map)) + return MDBX_EPERM; + + env->me_maxreaders = readers; + return MDBX_SUCCESS; +} + +int __cold mdbx_env_get_maxreaders(MDBX_env *env, unsigned *readers) { + if (!env || !readers) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + *readers = env->me_maxreaders; + return MDBX_SUCCESS; +} + +/* Further setup required for opening an MDBX environment */ +static int __cold mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { + uint64_t filesize_before_mmap; + MDBX_meta meta; + int rc = MDBX_RESULT_FALSE; + int err = mdbx_read_header(env, &meta, &filesize_before_mmap); + if (unlikely(err != MDBX_SUCCESS)) { + if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE || err != MDBX_ENODATA || + (env->me_flags & MDBX_RDONLY) != 0) + return err; + + mdbx_debug("create new database"); + rc = /* new database */ MDBX_RESULT_TRUE; + + if (!env->me_dbgeo.now) { + /* set defaults if not configured */ + err = mdbx_env_set_mapsize(env, DEFAULT_MAPSIZE); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + + void *buffer = mdbx_calloc(NUM_METAS, env->me_psize); + if (!buffer) + return MDBX_ENOMEM; + + meta = mdbx_init_metas(env, buffer)->mp_meta; + err = mdbx_pwrite(env->me_fd, buffer, env->me_psize * NUM_METAS, 0); + mdbx_free(buffer); + if (unlikely(err != MDBX_SUCCESS)) + return err; + + err = mdbx_ftruncate(env->me_fd, filesize_before_mmap = env->me_dbgeo.now); + if (unlikely(err != MDBX_SUCCESS)) + return err; + +#ifndef NDEBUG /* just for checking */ + err = mdbx_read_header(env, &meta, &filesize_before_mmap); + if (unlikely(err != MDBX_SUCCESS)) + return err; +#endif + } + + mdbx_info("header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO + "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO + " +%u -%u, txn_id %" PRIaTXN ", %s", + meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, + meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, + meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, + meta.mm_txnid_a, mdbx_durable_str(&meta)); + + mdbx_setup_pagesize(env, meta.mm_psize); + const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next); + if ((env->me_flags & MDBX_RDONLY) /* readonly */ + || lck_rc != MDBX_RESULT_TRUE /* not exclusive */) { + /* use present params from db */ + err = mdbx_env_set_geometry( + env, meta.mm_geo.lower * (uint64_t)meta.mm_psize, + meta.mm_geo.now * (uint64_t)meta.mm_psize, + meta.mm_geo.upper * (uint64_t)meta.mm_psize, + meta.mm_geo.grow * (uint64_t)meta.mm_psize, + meta.mm_geo.shrink * (uint64_t)meta.mm_psize, meta.mm_psize); + if (unlikely(err != MDBX_SUCCESS)) { + mdbx_error("could not use present dbsize-params from db"); + return MDBX_INCOMPATIBLE; + } + } else if (env->me_dbgeo.now) { + /* silently growth to last used page */ + if (env->me_dbgeo.now < used_bytes) + env->me_dbgeo.now = used_bytes; + if (env->me_dbgeo.upper < used_bytes) + env->me_dbgeo.upper = used_bytes; + + /* apply preconfigured params, but only if substantial changes: + * - upper or lower limit changes + * - shrink threshold or growth step + * But ignore just chagne just a 'now/current' size. */ + if (bytes_align2os_bytes(env, env->me_dbgeo.upper) != + pgno_align2os_bytes(env, meta.mm_geo.upper) || + bytes_align2os_bytes(env, env->me_dbgeo.lower) != + pgno_align2os_bytes(env, meta.mm_geo.lower) || + bytes_align2os_bytes(env, env->me_dbgeo.shrink) != + pgno_align2os_bytes(env, meta.mm_geo.shrink) || + bytes_align2os_bytes(env, env->me_dbgeo.grow) != + pgno_align2os_bytes(env, meta.mm_geo.grow)) { + + if (env->me_dbgeo.shrink && env->me_dbgeo.now > used_bytes) + /* pre-shrink if enabled */ + env->me_dbgeo.now = used_bytes + env->me_dbgeo.shrink - + used_bytes % env->me_dbgeo.shrink; + + err = mdbx_env_set_geometry(env, env->me_dbgeo.lower, env->me_dbgeo.now, + env->me_dbgeo.upper, env->me_dbgeo.grow, + env->me_dbgeo.shrink, meta.mm_psize); + if (unlikely(err != MDBX_SUCCESS)) { + mdbx_error("could not apply preconfigured dbsize-params to db"); + return MDBX_INCOMPATIBLE; + } + + /* update meta fields */ + meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); + meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); + meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); + meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); + meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); + + mdbx_info("amended: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO + "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO + " +%u -%u, txn_id %" PRIaTXN ", %s", + meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, + meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, + meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, + meta.mm_txnid_a, mdbx_durable_str(&meta)); + } + mdbx_ensure(env, meta.mm_geo.now >= meta.mm_geo.next); + } else { + /* geo-params not pre-configured by user, + * get current values from a meta. */ + env->me_dbgeo.now = pgno2bytes(env, meta.mm_geo.now); + env->me_dbgeo.lower = pgno2bytes(env, meta.mm_geo.lower); + env->me_dbgeo.upper = pgno2bytes(env, meta.mm_geo.upper); + env->me_dbgeo.grow = pgno2bytes(env, meta.mm_geo.grow); + env->me_dbgeo.shrink = pgno2bytes(env, meta.mm_geo.shrink); + } + + const size_t expected_bytes = + mdbx_roundup2(pgno2bytes(env, meta.mm_geo.now), env->me_os_psize); + mdbx_ensure(env, expected_bytes >= used_bytes); + if (filesize_before_mmap != expected_bytes) { + if (lck_rc != /* lck exclusive */ MDBX_RESULT_TRUE) { + mdbx_info("filesize mismatch (expect %" PRIuPTR "/%" PRIaPGNO + ", have %" PRIu64 "/%" PRIaPGNO "), " + "assume collision in non-exclusive mode", + expected_bytes, bytes2pgno(env, expected_bytes), + filesize_before_mmap, + bytes2pgno(env, (size_t)filesize_before_mmap)); + } else { + mdbx_notice("filesize mismatch (expect %" PRIuSIZE "/%" PRIaPGNO + ", have %" PRIu64 "/%" PRIaPGNO ")", + expected_bytes, bytes2pgno(env, expected_bytes), + filesize_before_mmap, + bytes2pgno(env, (size_t)filesize_before_mmap)); + if (filesize_before_mmap < used_bytes) { + mdbx_error("last-page beyond end-of-file (last %" PRIaPGNO + ", have %" PRIaPGNO ")", + meta.mm_geo.next, + bytes2pgno(env, (size_t)filesize_before_mmap)); + return MDBX_CORRUPTED; + } + + if (env->me_flags & MDBX_RDONLY) { + if (filesize_before_mmap % env->me_os_psize) { + mdbx_error("filesize should be rounded-up to system page"); + return MDBX_WANNA_RECOVERY; + } + mdbx_notice("ignore filesize mismatch in readonly-mode"); + } else { + mdbx_info("resize datafile to %" PRIuSIZE " bytes, %" PRIaPGNO " pages", + expected_bytes, bytes2pgno(env, expected_bytes)); + err = mdbx_ftruncate(env->me_fd, expected_bytes); + if (unlikely(err != MDBX_SUCCESS)) { + mdbx_error("error %d, while resize datafile to %" PRIuSIZE + " bytes, %" PRIaPGNO " pages", + rc, expected_bytes, bytes2pgno(env, expected_bytes)); + return err; + } + filesize_before_mmap = expected_bytes; + } + } + } + + err = mdbx_env_map(env, lck_rc /* exclusive status */, expected_bytes); + if (err != MDBX_SUCCESS) + return err; + + const unsigned meta_clash_mask = mdbx_meta_eq_mask(env); + if (meta_clash_mask) { + mdbx_error("meta-pages are clashed: mask 0x%d", meta_clash_mask); + return MDBX_WANNA_RECOVERY; + } + + while (1) { + MDBX_meta *head = mdbx_meta_head(env); + const txnid_t head_txnid = mdbx_meta_txnid_fluid(env, head); + if (head_txnid == meta.mm_txnid_a) + break; + + if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) { + mdbx_assert(env, META_IS_STEADY(&meta) && !META_IS_STEADY(head)); + if (env->me_flags & MDBX_RDONLY) { + mdbx_error("rollback needed: (from head %" PRIaTXN + " to steady %" PRIaTXN "), but unable in read-only mode", + head_txnid, meta.mm_txnid_a); + return MDBX_WANNA_RECOVERY /* LY: could not recovery/rollback */; + } + + const MDBX_meta *const meta0 = METAPAGE(env, 0); + const MDBX_meta *const meta1 = METAPAGE(env, 1); + const MDBX_meta *const meta2 = METAPAGE(env, 2); + txnid_t undo_txnid = 0; + while ( + (head != meta0 && mdbx_meta_txnid_fluid(env, meta0) == undo_txnid) || + (head != meta1 && mdbx_meta_txnid_fluid(env, meta1) == undo_txnid) || + (head != meta2 && mdbx_meta_txnid_fluid(env, meta2) == undo_txnid)) + undo_txnid += 1; + if (unlikely(undo_txnid >= meta.mm_txnid_a)) { + mdbx_fatal("rollback failed: no suitable txnid (0,1,2) < %" PRIaTXN, + meta.mm_txnid_a); + return MDBX_PANIC /* LY: could not recovery/rollback */; + } + + /* LY: rollback weak checkpoint */ + mdbx_trace("rollback: from %" PRIaTXN ", to %" PRIaTXN " as %" PRIaTXN, + head_txnid, meta.mm_txnid_a, undo_txnid); + mdbx_ensure(env, head_txnid == mdbx_meta_txnid_stable(env, head)); + + if (env->me_flags & MDBX_WRITEMAP) { + head->mm_txnid_a = undo_txnid; + head->mm_datasync_sign = MDBX_DATASIGN_WEAK; + head->mm_txnid_b = undo_txnid; + const size_t offset = + ((uint8_t *)container_of(head, MDBX_page, mp_meta)) - + env->me_dxb_mmap.dxb; + const size_t paged_offset = offset & ~(env->me_os_psize - 1); + const size_t paged_length = mdbx_roundup2( + env->me_psize + offset - paged_offset, env->me_os_psize); + err = mdbx_msync(&env->me_dxb_mmap, paged_offset, paged_length, false); + } else { + MDBX_meta rollback = *head; + mdbx_meta_set_txnid(env, &rollback, undo_txnid); + rollback.mm_datasync_sign = MDBX_DATASIGN_WEAK; + err = mdbx_pwrite(env->me_fd, &rollback, sizeof(MDBX_meta), + (uint8_t *)head - (uint8_t *)env->me_map); + } + if (err) + return err; + + mdbx_invalidate_mmap_noncoherent_cache(env->me_map, + pgno2bytes(env, NUM_METAS)); + mdbx_ensure(env, undo_txnid == mdbx_meta_txnid_fluid(env, head)); + mdbx_ensure(env, 0 == mdbx_meta_eq_mask(env)); + continue; + } + + if (!env->me_lck) { + /* LY: without-lck (read-only) mode, so it is imposible that other + * process made weak checkpoint. */ + mdbx_error("without-lck, unable recovery/rollback"); + return MDBX_WANNA_RECOVERY; + } + + /* LY: assume just have a collision with other running process, + * or someone make a weak checkpoint */ + mdbx_info("assume collision or online weak checkpoint"); + break; + } + + const MDBX_meta *head = mdbx_meta_head(env); + if (lck_rc == /* lck exclusive */ MDBX_RESULT_TRUE) { + /* re-check file size after mmap */ + uint64_t filesize_after_mmap; + err = mdbx_filesize(env->me_fd, &filesize_after_mmap); + if (unlikely(err != MDBX_SUCCESS)) + return err; + if (filesize_after_mmap != expected_bytes) { + if (filesize_after_mmap != filesize_before_mmap) + mdbx_info("datafile resized by system to %" PRIu64 " bytes", + filesize_after_mmap); + if (filesize_after_mmap % env->me_os_psize || + filesize_after_mmap > env->me_dbgeo.upper || + filesize_after_mmap < used_bytes) { + mdbx_info("unacceptable/unexpected datafile size %" PRIu64, + filesize_after_mmap); + return MDBX_PROBLEM; + } + if ((env->me_flags & MDBX_RDONLY) == 0) { + meta.mm_geo.now = + bytes2pgno(env, env->me_dbgeo.now = (size_t)filesize_after_mmap); + mdbx_info("update meta-geo to filesize %" PRIuPTR " bytes, %" PRIaPGNO + " pages", + env->me_dbgeo.now, meta.mm_geo.now); + } + } + + if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) { + const txnid_t txnid = mdbx_meta_txnid_stable(env, head); + mdbx_info("updating meta.geo: " + "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO + "/s%u-g%u (txn#%" PRIaTXN "), " + "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO + "/s%u-g%u (txn#%" PRIaTXN ")", + head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, + head->mm_geo.shrink, head->mm_geo.grow, txnid, + meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, + meta.mm_geo.shrink, meta.mm_geo.grow, txnid + 1); + + mdbx_ensure(env, mdbx_meta_eq(env, &meta, head)); + mdbx_meta_set_txnid(env, &meta, txnid + 1); + *env->me_unsynced_pages += 1; + err = mdbx_sync_locked(env, env->me_flags | MDBX_SHRINK_ALLOWED, &meta); + if (err) { + mdbx_info("error %d, while updating meta.geo: " + "from l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO + "/s%u-g%u (txn#%" PRIaTXN "), " + "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO + "/s%u-g%u (txn#%" PRIaTXN ")", + err, head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, + head->mm_geo.shrink, head->mm_geo.grow, txnid, + meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, + meta.mm_geo.shrink, meta.mm_geo.grow, txnid + 1); + return err; + } + } + } + + return rc; +} + +/****************************************************************************/ + +/* Open and/or initialize the lock region for the environment. */ +static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname, + mode_t mode) { + mdbx_assert(env, env->me_fd != INVALID_HANDLE_VALUE); + mdbx_assert(env, env->me_lfd == INVALID_HANDLE_VALUE); + + int err = mdbx_openfile(lck_pathname, O_RDWR | O_CREAT, mode, &env->me_lfd, + (env->me_flags & MDBX_EXCLUSIVE) ? true : false); + if (err != MDBX_SUCCESS) { + if (!(err == MDBX_ENOFILE && (env->me_flags & MDBX_EXCLUSIVE)) && + !(err == MDBX_EROFS && (env->me_flags & MDBX_RDONLY))) + return err; + + /* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */ + env->me_lfd = INVALID_HANDLE_VALUE; + const int rc = mdbx_lck_seize(env); + if (MDBX_IS_ERROR(rc)) + return rc; + + env->me_oldest = &env->me_lckless_stub.oldest; + env->me_unsynced_timeout = &env->me_lckless_stub.unsynced_timeout; + env->me_autosync_period = &env->me_lckless_stub.autosync_period; + env->me_unsynced_pages = &env->me_lckless_stub.autosync_pending; + env->me_autosync_threshold = &env->me_lckless_stub.autosync_threshold; + env->me_maxreaders = UINT_MAX; +#ifdef MDBX_OSAL_LOCK + env->me_wmutex = &env->me_lckless_stub.wmutex; +#endif + mdbx_debug("lck-setup:%s%s%s", " lck-less", + (env->me_flags & MDBX_RDONLY) ? " readonly" : "", + (rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative"); + return rc; + } + + /* Try to get exclusive lock. If we succeed, then + * nobody is using the lock region and we should initialize it. */ + const int rc = mdbx_lck_seize(env); + if (MDBX_IS_ERROR(rc)) + return rc; + + mdbx_debug("lck-setup:%s%s%s", " with-lck", + (env->me_flags & MDBX_RDONLY) ? " readonly" : "", + (rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative"); + + uint64_t size; + err = mdbx_filesize(env->me_lfd, &size); + if (unlikely(err != MDBX_SUCCESS)) + return err; + + if (rc == MDBX_RESULT_TRUE) { + uint64_t wanna = mdbx_roundup2( + (env->me_maxreaders - 1) * sizeof(MDBX_reader) + sizeof(MDBX_lockinfo), + env->me_os_psize); +#ifndef NDEBUG + err = mdbx_ftruncate(env->me_lfd, size = 0); + if (unlikely(err != MDBX_SUCCESS)) + return err; +#endif + mdbx_jitter4testing(false); + + if (size != wanna) { + err = mdbx_ftruncate(env->me_lfd, wanna); + if (unlikely(err != MDBX_SUCCESS)) + return err; + size = wanna; + } + } else { + if (env->me_flags & MDBX_EXCLUSIVE) + return MDBX_BUSY; + if (size > PTRDIFF_MAX || (size & (env->me_os_psize - 1)) || + size < env->me_os_psize) { + mdbx_notice("lck-file has invalid size %" PRIu64 " bytes", size); + return MDBX_PROBLEM; + } + } + + const size_t maxreaders = + ((size_t)size - sizeof(MDBX_lockinfo)) / sizeof(MDBX_reader) + 1; + if (maxreaders > UINT16_MAX) { + mdbx_error("lck-size too big (up to %" PRIuPTR " readers)", maxreaders); + return MDBX_PROBLEM; + } + env->me_maxreaders = (unsigned)maxreaders; + + err = mdbx_mmap(MDBX_WRITEMAP, &env->me_lck_mmap, (size_t)size, (size_t)size); + if (unlikely(err != MDBX_SUCCESS)) + return err; + +#ifdef MADV_DODUMP + (void)madvise(env->me_lck, size, MADV_DODUMP); +#endif + +#ifdef MADV_DONTFORK + if (madvise(env->me_lck, size, MADV_DONTFORK) < 0) + return errno; +#endif + +#ifdef MADV_WILLNEED + if (madvise(env->me_lck, size, MADV_WILLNEED) < 0) + return errno; +#endif + +#ifdef MADV_RANDOM + if (madvise(env->me_lck, size, MADV_RANDOM) < 0) + return errno; +#endif + + if (rc == MDBX_RESULT_TRUE) { + /* LY: exlcusive mode, init lck */ + memset(env->me_lck, 0, (size_t)size); + err = mdbx_lck_init(env); + if (err) + return err; + + env->me_lck->mti_magic_and_version = MDBX_LOCK_MAGIC; + env->me_lck->mti_os_and_format = MDBX_LOCK_FORMAT; + } else { + if (env->me_lck->mti_magic_and_version != MDBX_LOCK_MAGIC) { + mdbx_error("lock region has invalid magic/version"); + return ((env->me_lck->mti_magic_and_version >> 8) != MDBX_MAGIC) + ? MDBX_INVALID + : MDBX_VERSION_MISMATCH; + } + if (env->me_lck->mti_os_and_format != MDBX_LOCK_FORMAT) { + mdbx_error("lock region has os/format 0x%" PRIx32 ", expected 0x%" PRIx32, + env->me_lck->mti_os_and_format, MDBX_LOCK_FORMAT); + return MDBX_VERSION_MISMATCH; + } + } + + mdbx_assert(env, !MDBX_IS_ERROR(rc)); + env->me_oldest = &env->me_lck->mti_oldest_reader; + env->me_unsynced_timeout = &env->me_lck->mti_unsynced_timeout; + env->me_autosync_period = &env->me_lck->mti_autosync_period; + env->me_unsynced_pages = &env->me_lck->mti_unsynced_pages; + env->me_autosync_threshold = &env->me_lck->mti_autosync_threshold; +#ifdef MDBX_OSAL_LOCK + env->me_wmutex = &env->me_lck->mti_wmutex; +#endif + return rc; +} + +/* Only a subset of the mdbx_env flags can be changed + * at runtime. Changing other flags requires closing the + * environment and re-opening it with the new flags. */ +#define CHANGEABLE \ + (MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC | MDBX_NOMEMINIT | \ + MDBX_COALESCE | MDBX_PAGEPERTURB) +#define CHANGELESS \ + (MDBX_NOSUBDIR | MDBX_RDONLY | MDBX_WRITEMAP | MDBX_NOTLS | MDBX_NORDAHEAD | \ + MDBX_LIFORECLAIM | MDBX_EXCLUSIVE) + +#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE | CHANGELESS) +#error "Persistent DB flags & env flags overlap, but both go in mm_flags" +#endif + +int __cold mdbx_env_open(MDBX_env *env, const char *path, unsigned flags, + mode_t mode) { + if (unlikely(!env || !path)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (flags & ~(CHANGEABLE | CHANGELESS)) + return MDBX_EINVAL; + + if (env->me_fd != INVALID_HANDLE_VALUE || + (env->me_flags & MDBX_ENV_ACTIVE) != 0) + return MDBX_EPERM; + + size_t len_full, len = strlen(path); + if (flags & MDBX_NOSUBDIR) { + len_full = len + sizeof(MDBX_LOCK_SUFFIX) + len + 1; + } else { + len_full = len + sizeof(MDBX_LOCKNAME) + len + sizeof(MDBX_DATANAME); + } + char *lck_pathname = mdbx_malloc(len_full); + if (!lck_pathname) + return MDBX_ENOMEM; + + char *dxb_pathname; + if (flags & MDBX_NOSUBDIR) { + dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCK_SUFFIX); + sprintf(lck_pathname, "%s" MDBX_LOCK_SUFFIX, path); + strcpy(dxb_pathname, path); + } else { + dxb_pathname = lck_pathname + len + sizeof(MDBX_LOCKNAME); + sprintf(lck_pathname, "%s" MDBX_LOCKNAME, path); + sprintf(dxb_pathname, "%s" MDBX_DATANAME, path); + } + + int rc = MDBX_SUCCESS; + flags |= env->me_flags; + if (flags & MDBX_RDONLY) { + /* LY: silently ignore irrelevant flags when + * we're only getting read access */ + flags &= ~(MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NOSYNC | MDBX_NOMETASYNC | + MDBX_COALESCE | MDBX_LIFORECLAIM | MDBX_NOMEMINIT); + } else { + if (!((env->me_free_pgs = mdbx_pnl_alloc(MDBX_PNL_INITIAL)) && + (env->me_dirtylist = + mdbx_calloc(MDBX_DPL_TXNFULL + 1, sizeof(MDBX_DP))))) + rc = MDBX_ENOMEM; + } + + const uint32_t saved_me_flags = env->me_flags; + env->me_flags = (flags & ~MDBX_FATAL_ERROR) | MDBX_ENV_ACTIVE; + if (rc) + goto bailout; + + env->me_path = mdbx_strdup(path); + env->me_dbxs = mdbx_calloc(env->me_maxdbs, sizeof(MDBX_dbx)); + env->me_dbflags = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbflags[0])); + env->me_dbiseqs = mdbx_calloc(env->me_maxdbs, sizeof(env->me_dbiseqs[0])); + if (!(env->me_dbxs && env->me_path && env->me_dbflags && env->me_dbiseqs)) { + rc = MDBX_ENOMEM; + goto bailout; + } + env->me_dbxs[FREE_DBI].md_cmp = mdbx_cmp_int_ai; /* aligned MDBX_INTEGERKEY */ + + int oflags; + if (F_ISSET(flags, MDBX_RDONLY)) + oflags = O_RDONLY; + else if (mode != 0) + oflags = O_RDWR | O_CREAT; + else + oflags = O_RDWR; + + rc = mdbx_openfile(dxb_pathname, oflags, mode, &env->me_fd, + (env->me_flags & MDBX_EXCLUSIVE) ? true : false); + if (rc != MDBX_SUCCESS) + goto bailout; + + const int lck_rc = mdbx_setup_lck(env, lck_pathname, mode); + if (MDBX_IS_ERROR(lck_rc)) { + rc = lck_rc; + goto bailout; + } + + const int dxb_rc = mdbx_setup_dxb(env, lck_rc); + if (MDBX_IS_ERROR(dxb_rc)) { + rc = dxb_rc; + goto bailout; + } + + mdbx_debug("opened dbenv %p", (void *)env); + if (env->me_lck) { + const unsigned mode_flags = + MDBX_WRITEMAP | MDBX_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC; + if (lck_rc == MDBX_RESULT_TRUE) { + env->me_lck->mti_envmode = env->me_flags & (mode_flags | MDBX_RDONLY); + if ((env->me_flags & MDBX_EXCLUSIVE) == 0) { + /* LY: downgrade lock only if exclusive access not requested. + * in case exclusive==1, just leave value as is. */ + rc = mdbx_lck_downgrade(env, true); + mdbx_debug("lck-downgrade-full: rc %i ", rc); + } else { + rc = mdbx_lck_downgrade(env, false); + mdbx_debug("lck-downgrade-partial: rc %i ", rc); + } + if (rc != MDBX_SUCCESS) + goto bailout; + } else { + if ((env->me_flags & MDBX_RDONLY) == 0) { + while (env->me_lck->mti_envmode == MDBX_RDONLY) { + if (mdbx_atomic_compare_and_swap32(&env->me_lck->mti_envmode, + MDBX_RDONLY, + env->me_flags & mode_flags)) + break; + /* TODO: yield/relax cpu */ + } + if ((env->me_lck->mti_envmode ^ env->me_flags) & mode_flags) { + mdbx_error("current mode/flags incompatible with requested"); + rc = MDBX_INCOMPATIBLE; + goto bailout; + } + } + } + + if ((env->me_flags & MDBX_NOTLS) == 0) { + rc = mdbx_rthc_alloc(&env->me_txkey, &env->me_lck->mti_readers[0], + &env->me_lck->mti_readers[env->me_maxreaders]); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + env->me_flags |= MDBX_ENV_TXKEY; + } + } + + if ((flags & MDBX_RDONLY) == 0) { + MDBX_txn *txn; + int tsize = sizeof(MDBX_txn), + size = + tsize + env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + + sizeof(unsigned) + 1); + if ((env->me_pbuf = mdbx_calloc(2, env->me_psize)) && + (txn = mdbx_calloc(1, size))) { + txn->mt_dbs = (MDBX_db *)((char *)txn + tsize); + txn->mt_cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs); + txn->mt_dbiseqs = (unsigned *)(txn->mt_cursors + env->me_maxdbs); + txn->mt_dbflags = (uint8_t *)(txn->mt_dbiseqs + env->me_maxdbs); + txn->mt_env = env; + txn->mt_dbxs = env->me_dbxs; + txn->mt_flags = MDBX_TXN_FINISHED; + env->me_txn0 = txn; + } else { + rc = MDBX_ENOMEM; + } + } + +#if MDBX_DEBUG + if (rc == MDBX_SUCCESS) { + MDBX_meta *meta = mdbx_meta_head(env); + MDBX_db *db = &meta->mm_dbs[MAIN_DBI]; + + mdbx_debug("opened database version %u, pagesize %u", + (uint8_t)meta->mm_magic_and_version, env->me_psize); + mdbx_debug("using meta page %" PRIaPGNO ", txn %" PRIaTXN, + container_of(meta, MDBX_page, mp_data)->mp_pgno, + mdbx_meta_txnid_fluid(env, meta)); + mdbx_debug("depth: %u", db->md_depth); + mdbx_debug("entries: %" PRIu64, db->md_entries); + mdbx_debug("branch pages: %" PRIaPGNO, db->md_branch_pages); + mdbx_debug("leaf pages: %" PRIaPGNO, db->md_leaf_pages); + mdbx_debug("overflow pages: %" PRIaPGNO, db->md_overflow_pages); + mdbx_debug("root: %" PRIaPGNO, db->md_root); + } +#endif + +bailout: + if (rc) { + mdbx_env_close0(env); + env->me_flags = saved_me_flags | MDBX_FATAL_ERROR; + } + mdbx_free(lck_pathname); + return rc; +} + +/* Destroy resources from mdbx_env_open(), clear our readers & DBIs */ +static void __cold mdbx_env_close0(MDBX_env *env) { + if (!(env->me_flags & MDBX_ENV_ACTIVE)) + return; + env->me_flags &= ~MDBX_ENV_ACTIVE; + + /* Doing this here since me_dbxs may not exist during mdbx_env_close */ + if (env->me_dbxs) { + for (unsigned i = env->me_maxdbs; --i >= CORE_DBS;) + mdbx_free(env->me_dbxs[i].md_name.iov_base); + mdbx_free(env->me_dbxs); + } + + mdbx_free(env->me_pbuf); + mdbx_free(env->me_dbiseqs); + mdbx_free(env->me_dbflags); + mdbx_free(env->me_path); + mdbx_free(env->me_dirtylist); + if (env->me_txn0) { + mdbx_txl_free(env->me_txn0->mt_lifo_reclaimed); + mdbx_free(env->me_txn0); + } + mdbx_pnl_free(env->me_free_pgs); + + if (env->me_flags & MDBX_ENV_TXKEY) + mdbx_rthc_remove(env->me_txkey); + if (env->me_live_reader) + (void)mdbx_rpid_clear(env); + + if (env->me_map) { + mdbx_munmap(&env->me_dxb_mmap); +#ifdef USE_VALGRIND + VALGRIND_DISCARD(env->me_valgrind_handle); + env->me_valgrind_handle = -1; +#endif + } + if (env->me_fd != INVALID_HANDLE_VALUE) { + (void)mdbx_closefile(env->me_fd); + env->me_fd = INVALID_HANDLE_VALUE; + } + + if (env->me_lck) + mdbx_munmap(&env->me_lck_mmap); + env->me_oldest = nullptr; + env->me_unsynced_timeout = nullptr; + env->me_autosync_period = nullptr; + env->me_unsynced_pages = nullptr; + env->me_autosync_threshold = nullptr; + + mdbx_lck_destroy(env); + if (env->me_lfd != INVALID_HANDLE_VALUE) { + (void)mdbx_closefile(env->me_lfd); + env->me_lfd = INVALID_HANDLE_VALUE; + } + env->me_flags = 0; +} + +int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) { + MDBX_page *dp; + int rc = MDBX_SUCCESS; + + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if ((env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR)) == 0) { + if (env->me_txn0 && env->me_txn0->mt_owner && + env->me_txn0->mt_owner != mdbx_thread_self()) + return MDBX_BUSY; + if (!dont_sync) { +#if defined(_WIN32) || defined(_WIN64) + /* On windows, without blocking is impossible to determine whether another + * process is running a writing transaction or not. + * Because in the "owner died" condition kernel don't release + * file lock immediately. */ + rc = mdbx_env_sync_ex(env, true, false); +#else + rc = mdbx_env_sync_ex(env, true, true); + rc = (rc == MDBX_BUSY || rc == EAGAIN || rc == EACCES || rc == EBUSY || + rc == EWOULDBLOCK) + ? MDBX_SUCCESS + : rc; +#endif + } + } + + VALGRIND_DESTROY_MEMPOOL(env); + while ((dp = env->me_dpages) != NULL) { + ASAN_UNPOISON_MEMORY_REGION(&dp->mp_next, sizeof(dp->mp_next)); + VALGRIND_MAKE_MEM_DEFINED(&dp->mp_next, sizeof(dp->mp_next)); + env->me_dpages = dp->mp_next; + mdbx_free(dp); + } + + mdbx_env_close0(env); + mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS); +#if defined(_WIN32) || defined(_WIN64) + /* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */ + DeleteCriticalSection(&env->me_windowsbug_lock); +#else + mdbx_ensure(env, + mdbx_fastmutex_destroy(&env->me_remap_guard) == MDBX_SUCCESS); +#endif /* Windows */ + +#ifdef MDBX_OSAL_LOCK + mdbx_ensure(env, mdbx_fastmutex_destroy(&env->me_lckless_stub.wmutex) == + MDBX_SUCCESS); +#endif + + env->me_pid = 0; + env->me_signature = 0; + mdbx_free(env); + + return rc; +} + +__cold int mdbx_env_close(MDBX_env *env) { + return mdbx_env_close_ex(env, false); +} + +/* Compare two items pointing at aligned unsigned int's. */ +static int __hot mdbx_cmp_int_ai(const MDBX_val *a, const MDBX_val *b) { + mdbx_assert(NULL, a->iov_len == b->iov_len); + mdbx_assert(NULL, 0 == (uintptr_t)a->iov_base % sizeof(int) && + 0 == (uintptr_t)b->iov_base % sizeof(int)); + switch (a->iov_len) { + case 4: + return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base); + case 8: + return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base); + default: + mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_, + __LINE__); + return 0; + } +} + +/* Compare two items pointing at 2-byte aligned unsigned int's. */ +static int __hot mdbx_cmp_int_a2(const MDBX_val *a, const MDBX_val *b) { + mdbx_assert(NULL, a->iov_len == b->iov_len); + mdbx_assert(NULL, 0 == (uintptr_t)a->iov_base % sizeof(uint16_t) && + 0 == (uintptr_t)b->iov_base % sizeof(uint16_t)); +#if UNALIGNED_OK + switch (a->iov_len) { + case 4: + return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base); + case 8: + return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base); + default: + mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_, + __LINE__); + return 0; + } +#else + mdbx_assert(NULL, 0 == a->iov_len % sizeof(uint16_t)); + { + int diff; + const uint16_t *pa, *pb, *end; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + end = (const uint16_t *)a->iov_base; + pa = (const uint16_t *)((char *)a->iov_base + a->iov_len); + pb = (const uint16_t *)((char *)b->iov_base + a->iov_len); + do { + diff = *--pa - *--pb; +#else /* __BYTE_ORDER__ */ + end = (const uint16_t *)((char *)a->iov_base + a->iov_len); + pa = (const uint16_t *)a->iov_base; + pb = (const uint16_t *)b->iov_base; + do { + diff = *pa++ - *pb++; +#endif /* __BYTE_ORDER__ */ + if (likely(diff != 0)) + break; + } while (pa != end); + return diff; + } +#endif /* UNALIGNED_OK */ +} + +/* Compare two items pointing at unsigneds of unknown alignment. + * + * This is also set as MDBX_INTEGERDUP|MDBX_DUPFIXED's MDBX_dbx.md_dcmp. */ +static int __hot mdbx_cmp_int_ua(const MDBX_val *a, const MDBX_val *b) { + mdbx_assert(NULL, a->iov_len == b->iov_len); +#if UNALIGNED_OK + switch (a->iov_len) { + case 4: + return mdbx_cmp2int(*(uint32_t *)a->iov_base, *(uint32_t *)b->iov_base); + case 8: + return mdbx_cmp2int(*(uint64_t *)a->iov_base, *(uint64_t *)b->iov_base); + default: + mdbx_assert_fail(NULL, "invalid size for INTEGERKEY/INTEGERDUP", mdbx_func_, + __LINE__); + return 0; + } +#else + mdbx_assert(NULL, a->iov_len == sizeof(int) || a->iov_len == sizeof(size_t)); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + { + int diff; + const uint8_t *pa, *pb; + + pa = (const uint8_t *)a->iov_base + a->iov_len; + pb = (const uint8_t *)b->iov_base + a->iov_len; + + do { + diff = *--pa - *--pb; + if (likely(diff != 0)) + break; + } while (pa != a->iov_base); + return diff; + } +#else /* __BYTE_ORDER__ */ + return memcmp(a->iov_base, b->iov_base, a->iov_len); +#endif /* __BYTE_ORDER__ */ +#endif /* UNALIGNED_OK */ +} + +/* Compare two items lexically */ +static int __hot mdbx_cmp_memn(const MDBX_val *a, const MDBX_val *b) { +/* LY: assumes that length of keys are NOT equal for most cases, + * if no then branch-prediction should mitigate the problem */ +#if 0 + /* LY: without branch instructions on x86, + * but isn't best for equal length of keys */ + int diff_len = mdbx_cmp2int(a->iov_len, b->iov_len); +#else + /* LY: best when length of keys are equal, + * but got a branch-penalty otherwise */ + if (likely(a->iov_len == b->iov_len)) + return memcmp(a->iov_base, b->iov_base, a->iov_len); + int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; +#endif + size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; + int diff_data = memcmp(a->iov_base, b->iov_base, shortest); + return likely(diff_data) ? diff_data : diff_len; +} + +/* Compare two items in reverse byte order */ +static int __hot mdbx_cmp_memnr(const MDBX_val *a, const MDBX_val *b) { + const uint8_t *pa, *pb, *end; + + pa = (const uint8_t *)a->iov_base + a->iov_len; + pb = (const uint8_t *)b->iov_base + b->iov_len; + size_t minlen = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; + end = pa - minlen; + + while (pa != end) { + int diff = *--pa - *--pb; + if (likely(diff)) + return diff; + } + return mdbx_cmp2int(a->iov_len, b->iov_len); +} + +/* Search for key within a page, using binary search. + * Returns the smallest entry larger or equal to the key. + * If exactp is non-null, stores whether the found entry was an exact match + * in *exactp (1 or 0). + * Updates the cursor index with the index of the found entry. + * If no entry larger or equal to the key is found, returns NULL. */ +static MDBX_node *__hot mdbx_node_search(MDBX_cursor *mc, MDBX_val *key, + int *exactp) { + int low, high; + int rc = 0; + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + MDBX_node *node = NULL; + MDBX_val nodekey; + MDBX_cmp_func *cmp; + DKBUF; + + const unsigned nkeys = NUMKEYS(mp); + + mdbx_debug("searching %u keys in %s %spage %" PRIaPGNO, nkeys, + IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "", + mp->mp_pgno); + + low = IS_LEAF(mp) ? 0 : 1; + high = nkeys - 1; + cmp = mc->mc_dbx->md_cmp; + + /* Branch pages have no data, so if using integer keys, + * alignment is guaranteed. Use faster mdbx_cmp_int_ai. + */ + if (cmp == mdbx_cmp_int_a2 && IS_BRANCH(mp)) + cmp = mdbx_cmp_int_ai; + + unsigned i = 0; + if (IS_LEAF2(mp)) { + nodekey.iov_len = mc->mc_db->md_xsize; + node = NODEPTR(mp, 0); /* fake */ + while (low <= high) { + i = (low + high) >> 1; + nodekey.iov_base = LEAF2KEY(mp, i, nodekey.iov_len); + rc = cmp(key, &nodekey); + mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); + if (rc == 0) + break; + if (rc > 0) + low = i + 1; + else + high = i - 1; + } + } else { + while (low <= high) { + i = (low + high) >> 1; + + node = NODEPTR(mp, i); + nodekey.iov_len = NODEKSZ(node); + nodekey.iov_base = NODEKEY(node); + + rc = cmp(key, &nodekey); + if (IS_LEAF(mp)) + mdbx_debug("found leaf index %u [%s], rc = %i", i, DKEY(&nodekey), rc); + else + mdbx_debug("found branch index %u [%s -> %" PRIaPGNO "], rc = %i", i, + DKEY(&nodekey), NODEPGNO(node), rc); + if (rc == 0) + break; + if (rc > 0) + low = i + 1; + else + high = i - 1; + } + } + + if (rc > 0) /* Found entry is less than the key. */ + i++; /* Skip to get the smallest entry larger than key. */ + + if (exactp) + *exactp = (rc == 0 && nkeys > 0); + /* store the key index */ + mdbx_cassert(mc, i <= UINT16_MAX); + mc->mc_ki[mc->mc_top] = (indx_t)i; + if (i >= nkeys) + /* There is no entry larger or equal to the key. */ + return NULL; + + /* nodeptr is fake for LEAF2 */ + return IS_LEAF2(mp) ? node : NODEPTR(mp, i); +} + +#if 0 /* unused for now */ +static void mdbx_cursor_adjust(MDBX_cursor *mc, func) { + MDBX_cursor *m2; + + for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { + if (m2->mc_pg[m2->mc_top] == mc->mc_pg[mc->mc_top]) { + func(mc, m2); + } + } +} +#endif + +/* Pop a page off the top of the cursor's stack. */ +static void mdbx_cursor_pop(MDBX_cursor *mc) { + if (mc->mc_snum) { + mdbx_debug("popped page %" PRIaPGNO " off db %d cursor %p", + mc->mc_pg[mc->mc_top]->mp_pgno, DDBI(mc), (void *)mc); + + mc->mc_snum--; + if (mc->mc_snum) { + mc->mc_top--; + } else { + mc->mc_flags &= ~C_INITIALIZED; + } + } +} + +/* Push a page onto the top of the cursor's stack. + * Set MDBX_TXN_ERROR on failure. */ +static int mdbx_cursor_push(MDBX_cursor *mc, MDBX_page *mp) { + mdbx_debug("pushing page %" PRIaPGNO " on db %d cursor %p", mp->mp_pgno, + DDBI(mc), (void *)mc); + + if (unlikely(mc->mc_snum >= CURSOR_STACK)) { + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_CURSOR_FULL; + } + + mdbx_cassert(mc, mc->mc_snum < UINT16_MAX); + mc->mc_top = mc->mc_snum++; + mc->mc_pg[mc->mc_top] = mp; + mc->mc_ki[mc->mc_top] = 0; + + return MDBX_SUCCESS; +} + +/* Find the address of the page corresponding to a given page number. + * Set MDBX_TXN_ERROR on failure. + * + * [in] mc the cursor accessing the page. + * [in] pgno the page number for the page to retrieve. + * [out] ret address of a pointer where the page's address will be + * stored. + * [out] lvl dirtylist inheritance level of found page. 1=current txn, + * 0=mapped page. + * + * Returns 0 on success, non-zero on failure. */ +__hot static int mdbx_page_get(MDBX_cursor *mc, pgno_t pgno, MDBX_page **ret, + int *lvl) { + MDBX_txn *txn = mc->mc_txn; + MDBX_env *env = txn->mt_env; + MDBX_page *p = NULL; + int level; + + if (!(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_WRITEMAP))) { + MDBX_txn *tx2 = txn; + level = 1; + do { + MDBX_DPL dl = tx2->mt_rw_dirtylist; + /* Spilled pages were dirtied in this txn and flushed + * because the dirty list got full. Bring this page + * back in from the map (but don't unspill it here, + * leave that unless page_touch happens again). */ + if (tx2->mt_spill_pages) { + pgno_t pn = pgno << 1; + unsigned x = mdbx_pnl_search(tx2->mt_spill_pages, pn); + if (x <= MDBX_PNL_SIZE(tx2->mt_spill_pages) && + tx2->mt_spill_pages[x] == pn) + goto mapped; + } + if (dl->length) { + unsigned y = mdbx_dpl_search(dl, pgno); + if (y <= dl->length && dl[y].pgno == pgno) { + p = dl[y].ptr; + goto done; + } + } + level++; + } while ((tx2 = tx2->mt_parent) != NULL); + } + + if (unlikely(pgno >= txn->mt_next_pgno)) { + mdbx_debug("page %" PRIaPGNO " not found", pgno); + txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PAGE_NOTFOUND; + } + level = 0; + +mapped: + p = pgno2page(env, pgno); + +done: + if (unlikely(p->mp_pgno != pgno)) { + mdbx_error("mismatch pgno %" PRIaPGNO " (actual) != %" PRIaPGNO + " (expected)", + p->mp_pgno, pgno); + return MDBX_CORRUPTED; + } + + if (unlikely(p->mp_upper < p->mp_lower || + PAGEHDRSZ + p->mp_upper > env->me_psize) && + !IS_OVERFLOW(p)) { + mdbx_error("invalid page lower(%u)/upper(%u), pg-limit %u", p->mp_lower, + p->mp_upper, env->me_psize - PAGEHDRSZ); + return MDBX_CORRUPTED; + } + /* TODO: more checks here, including p->mp_validator */ + + *ret = p; + if (lvl) + *lvl = level; + return MDBX_SUCCESS; +} + +/* Finish mdbx_page_search() / mdbx_page_search_lowest(). + * The cursor is at the root page, set up the rest of it. */ +__hot static int mdbx_page_search_root(MDBX_cursor *mc, MDBX_val *key, + int flags) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + int rc; + DKBUF; + + while (IS_BRANCH(mp)) { + MDBX_node *node; + indx_t i; + + mdbx_debug("branch page %" PRIaPGNO " has %u keys", mp->mp_pgno, + NUMKEYS(mp)); + /* Don't assert on branch pages in the FreeDB. We can get here + * while in the process of rebalancing a FreeDB branch page; we must + * let that proceed. ITS#8336 */ + mdbx_cassert(mc, !mc->mc_dbi || NUMKEYS(mp) > 1); + mdbx_debug("found index 0 to page %" PRIaPGNO, NODEPGNO(NODEPTR(mp, 0))); + + if (flags & (MDBX_PS_FIRST | MDBX_PS_LAST)) { + i = 0; + if (flags & MDBX_PS_LAST) { + i = NUMKEYS(mp) - 1; + /* if already init'd, see if we're already in right place */ + if (mc->mc_flags & C_INITIALIZED) { + if (mc->mc_ki[mc->mc_top] == i) { + mc->mc_top = mc->mc_snum++; + mp = mc->mc_pg[mc->mc_top]; + goto ready; + } + } + } + } else { + int exact; + node = mdbx_node_search(mc, key, &exact); + if (node == NULL) + i = NUMKEYS(mp) - 1; + else { + i = mc->mc_ki[mc->mc_top]; + if (!exact) { + mdbx_cassert(mc, i > 0); + i--; + } + } + mdbx_debug("following index %u for key [%s]", i, DKEY(key)); + } + + mdbx_cassert(mc, i < NUMKEYS(mp)); + node = NODEPTR(mp, i); + + if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0)) + return rc; + + mc->mc_ki[mc->mc_top] = i; + if (unlikely(rc = mdbx_cursor_push(mc, mp))) + return rc; + + ready: + if (flags & MDBX_PS_MODIFY) { + if (unlikely((rc = mdbx_page_touch(mc)) != 0)) + return rc; + mp = mc->mc_pg[mc->mc_top]; + } + } + + if (unlikely(!IS_LEAF(mp))) { + mdbx_debug("internal error, index points to a page with 0x%02x flags!?", + mp->mp_flags); + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_CORRUPTED; + } + + mdbx_debug("found leaf page %" PRIaPGNO " for key [%s]", mp->mp_pgno, + DKEY(key)); + mc->mc_flags |= C_INITIALIZED; + mc->mc_flags &= ~C_EOF; + + return MDBX_SUCCESS; +} + +/* Search for the lowest key under the current branch page. + * This just bypasses a NUMKEYS check in the current page + * before calling mdbx_page_search_root(), because the callers + * are all in situations where the current page is known to + * be underfilled. */ +__hot static int mdbx_page_search_lowest(MDBX_cursor *mc) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + mdbx_cassert(mc, IS_BRANCH(mp)); + MDBX_node *node = NODEPTR(mp, 0); + int rc; + + if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(node), &mp, NULL)) != 0)) + return rc; + + mc->mc_ki[mc->mc_top] = 0; + if (unlikely(rc = mdbx_cursor_push(mc, mp))) + return rc; + return mdbx_page_search_root(mc, NULL, MDBX_PS_FIRST); +} + +/* Search for the page a given key should be in. + * Push it and its parent pages on the cursor stack. + * + * [in,out] mc the cursor for this operation. + * [in] key the key to search for, or NULL for first/last page. + * [in] flags If MDBX_PS_MODIFY is set, visited pages in the DB + * are touched (updated with new page numbers). + * If MDBX_PS_FIRST or MDBX_PS_LAST is set, find first or last + * leaf. + * This is used by mdbx_cursor_first() and mdbx_cursor_last(). + * If MDBX_PS_ROOTONLY set, just fetch root node, no further + * lookups. + * + * Returns 0 on success, non-zero on failure. */ +__hot static int mdbx_page_search(MDBX_cursor *mc, MDBX_val *key, int flags) { + int rc; + pgno_t root; + + /* Make sure the txn is still viable, then find the root from + * the txn's db table and set it as the root of the cursor's stack. */ + if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) { + mdbx_debug("transaction has failed, must abort"); + return MDBX_BAD_TXN; + } + + /* Make sure we're using an up-to-date root */ + if (unlikely(*mc->mc_dbflag & DB_STALE)) { + MDBX_cursor mc2; + if (unlikely(TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))) + return MDBX_BAD_DBI; + rc = mdbx_cursor_init(&mc2, mc->mc_txn, MAIN_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_page_search(&mc2, &mc->mc_dbx->md_name, 0); + if (unlikely(rc != MDBX_SUCCESS)) + return (rc == MDBX_NOTFOUND) ? MDBX_BAD_DBI : rc; + { + MDBX_val data; + int exact = 0; + MDBX_node *leaf = mdbx_node_search(&mc2, &mc->mc_dbx->md_name, &exact); + if (!exact) + return MDBX_BAD_DBI; + if (unlikely((leaf->mn_flags & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA)) + return MDBX_INCOMPATIBLE; /* not a named DB */ + rc = mdbx_node_read(&mc2, leaf, &data); + if (rc) + return rc; + + uint16_t md_flags; + memcpy(&md_flags, ((char *)data.iov_base + offsetof(MDBX_db, md_flags)), + sizeof(uint16_t)); + /* The txn may not know this DBI, or another process may + * have dropped and recreated the DB with other flags. */ + if (unlikely((mc->mc_db->md_flags & PERSISTENT_FLAGS) != md_flags)) + return MDBX_INCOMPATIBLE; + memcpy(mc->mc_db, data.iov_base, sizeof(MDBX_db)); + } + *mc->mc_dbflag &= ~DB_STALE; + } + root = mc->mc_db->md_root; + + if (unlikely(root == P_INVALID)) { /* Tree is empty. */ + mdbx_debug("tree is empty"); + return MDBX_NOTFOUND; + } + + mdbx_cassert(mc, root >= NUM_METAS); + if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root) + if (unlikely((rc = mdbx_page_get(mc, root, &mc->mc_pg[0], NULL)) != 0)) + return rc; + + mc->mc_snum = 1; + mc->mc_top = 0; + + mdbx_debug("db %d root page %" PRIaPGNO " has flags 0x%X", DDBI(mc), root, + mc->mc_pg[0]->mp_flags); + + if (flags & MDBX_PS_MODIFY) { + if (unlikely(rc = mdbx_page_touch(mc))) + return rc; + } + + if (flags & MDBX_PS_ROOTONLY) + return MDBX_SUCCESS; + + return mdbx_page_search_root(mc, key, flags); +} + +static int mdbx_ovpage_free(MDBX_cursor *mc, MDBX_page *mp) { + MDBX_txn *txn = mc->mc_txn; + pgno_t pg = mp->mp_pgno; + unsigned x = 0, ovpages = mp->mp_pages; + MDBX_env *env = txn->mt_env; + MDBX_PNL sl = txn->mt_spill_pages; + pgno_t pn = pg << 1; + int rc; + + mdbx_cassert(mc, (mc->mc_flags & C_GCFREEZE) == 0); + mdbx_cassert(mc, IS_OVERFLOW(mp)); + mdbx_debug("free ov page %" PRIaPGNO " (%u)", pg, ovpages); + + if (mdbx_audit_enabled() && env->me_reclaimed_pglist) { + mdbx_cassert(mc, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + const unsigned a = mdbx_pnl_search(env->me_reclaimed_pglist, pg); + mdbx_cassert(mc, a > MDBX_PNL_SIZE(env->me_reclaimed_pglist) || + env->me_reclaimed_pglist[a] != pg); + if (a <= MDBX_PNL_SIZE(env->me_reclaimed_pglist) && + unlikely(env->me_reclaimed_pglist[a] == pg)) + return MDBX_PROBLEM; + + if (ovpages > 1) { + const unsigned b = + mdbx_pnl_search(env->me_reclaimed_pglist, pg + ovpages - 1); + mdbx_cassert(mc, a == b); + if (unlikely(a != b)) + return MDBX_PROBLEM; + } + } + + /* If the page is dirty or on the spill list we just acquired it, + * so we should give it back to our current free list, if any. + * Otherwise put it onto the list of pages we freed in this txn. + * + * Won't create me_reclaimed_pglist: me_last_reclaimed must be inited along + * with it. + * Unsupported in nested txns: They would need to hide the page + * range in ancestor txns' dirty and spilled lists. */ + if (env->me_reclaimed_pglist && !txn->mt_parent && + (IS_DIRTY(mp) || + (sl && (x = mdbx_pnl_search(sl, pn)) <= MDBX_PNL_SIZE(sl) && + sl[x] == pn))) { + unsigned i, j; + pgno_t *mop; + MDBX_DP *dl, ix, iy; + rc = mdbx_pnl_need(&env->me_reclaimed_pglist, ovpages); + if (unlikely(rc)) + return rc; + + if (!IS_DIRTY(mp)) { + /* This page is no longer spilled */ + if (x == MDBX_PNL_SIZE(sl)) + MDBX_PNL_SIZE(sl)--; + else + sl[x] |= 1; + goto release; + } + /* Remove from dirty list */ + dl = txn->mt_rw_dirtylist; + x = dl->length--; + for (ix = dl[x]; ix.ptr != mp; ix = iy) { + if (likely(x > 1)) { + x--; + iy = dl[x]; + dl[x] = ix; + } else { + mdbx_cassert(mc, x > 1); + mdbx_error("not found page 0x%p #%" PRIaPGNO " in the dirtylist", mp, + mp->mp_pgno); + j = dl->length += 1; + dl[j] = ix; /* Unsorted. OK when MDBX_TXN_ERROR. */ + txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PROBLEM; + } + } + txn->mt_dirtyroom++; + if (!(env->me_flags & MDBX_WRITEMAP)) + mdbx_dpage_free(env, mp, IS_OVERFLOW(mp) ? mp->mp_pages : 1); + release: + /* Insert in me_reclaimed_pglist */ + mop = env->me_reclaimed_pglist; + j = MDBX_PNL_SIZE(mop) + ovpages; + for (i = MDBX_PNL_SIZE(mop); i && MDBX_PNL_DISORDERED(mop[i], pg);) + mop[j--] = mop[i--]; + MDBX_PNL_SIZE(mop) += ovpages; + + pgno_t n = MDBX_PNL_ASCENDING ? pg + ovpages : pg; + while (j > i) + mop[j--] = MDBX_PNL_ASCENDING ? --n : n++; + mdbx_tassert(txn, mdbx_pnl_check(env->me_reclaimed_pglist, true)); + } else { + rc = mdbx_pnl_append_range(&txn->mt_befree_pages, pg, ovpages); + if (unlikely(rc)) + return rc; + } + + mc->mc_db->md_overflow_pages -= ovpages; + if (unlikely(mc->mc_flags & C_SUB)) { + MDBX_db *outer = mdbx_outer_db(mc); + outer->md_overflow_pages -= ovpages; + } + return 0; +} + +/* Return the data associated with a given node. + * + * [in] mc The cursor for this operation. + * [in] leaf The node being read. + * [out] data Updated to point to the node's data. + * + * Returns 0 on success, non-zero on failure. */ +static __inline int mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf, + MDBX_val *data) { + MDBX_page *omp; /* overflow page */ + pgno_t pgno; + int rc; + + if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) { + data->iov_len = NODEDSZ(leaf); + data->iov_base = NODEDATA(leaf); + return MDBX_SUCCESS; + } + + /* Read overflow data. */ + data->iov_len = NODEDSZ(leaf); + memcpy(&pgno, NODEDATA(leaf), sizeof(pgno)); + if (unlikely((rc = mdbx_page_get(mc, pgno, &omp, NULL)) != 0)) { + mdbx_debug("read overflow page %" PRIaPGNO " failed", pgno); + return rc; + } + data->iov_base = PAGEDATA(omp); + + return MDBX_SUCCESS; +} + +int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) { + int exact = 0; + DKBUF; + + mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); + + if (unlikely(!key || !data || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + return mdbx_cursor_set(&cx.outer, key, data, MDBX_SET, &exact); +} + +int mdbx_get2(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) { + int exact = 0; + DKBUF; + + mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); + + if (unlikely(!key || !data || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + const int op = + (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) ? MDBX_GET_BOTH : MDBX_SET_KEY; + rc = mdbx_cursor_set(&cx.outer, key, data, op, &exact); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + return exact ? MDBX_SUCCESS : MDBX_RESULT_TRUE; +} + +/* Find a sibling for a page. + * Replaces the page at the top of the cursor's stack with the specified + * sibling, if one exists. + * + * [in] mc The cursor for this operation. + * [in] move_right Non-zero if the right sibling is requested, + * otherwise the left sibling. + * + * Returns 0 on success, non-zero on failure. */ +static int mdbx_cursor_sibling(MDBX_cursor *mc, int move_right) { + int rc; + MDBX_node *indx; + MDBX_page *mp; + + if (unlikely(mc->mc_snum < 2)) { + return MDBX_NOTFOUND; /* root has no siblings */ + } + + mdbx_cursor_pop(mc); + mdbx_debug("parent page is page %" PRIaPGNO ", index %u", + mc->mc_pg[mc->mc_top]->mp_pgno, mc->mc_ki[mc->mc_top]); + + if (move_right + ? (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mc->mc_pg[mc->mc_top])) + : (mc->mc_ki[mc->mc_top] == 0)) { + mdbx_debug("no more keys left, moving to %s sibling", + move_right ? "right" : "left"); + if (unlikely((rc = mdbx_cursor_sibling(mc, move_right)) != MDBX_SUCCESS)) { + /* undo cursor_pop before returning */ + mc->mc_top++; + mc->mc_snum++; + return rc; + } + } else { + if (move_right) + mc->mc_ki[mc->mc_top]++; + else + mc->mc_ki[mc->mc_top]--; + mdbx_debug("just moving to %s index key %u", move_right ? "right" : "left", + mc->mc_ki[mc->mc_top]); + } + mdbx_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top])); + + indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (unlikely((rc = mdbx_page_get(mc, NODEPGNO(indx), &mp, NULL)) != 0)) { + /* mc will be inconsistent if caller does mc_snum++ as above */ + mc->mc_flags &= ~(C_INITIALIZED | C_EOF); + return rc; + } + + rc = mdbx_cursor_push(mc, mp); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (!move_right) + mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1; + + return MDBX_SUCCESS; +} + +/* Move the cursor to the next data item. */ +static int mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + MDBX_cursor_op op) { + MDBX_page *mp; + MDBX_node *leaf; + int rc; + + if ((mc->mc_flags & C_DEL) && op == MDBX_NEXT_DUP) + return MDBX_NOTFOUND; + + if (!(mc->mc_flags & C_INITIALIZED)) + return mdbx_cursor_first(mc, key, data); + + mp = mc->mc_pg[mc->mc_top]; + if (mc->mc_flags & C_EOF) { + if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) + return MDBX_NOTFOUND; + mc->mc_flags ^= C_EOF; + } + + if (mc->mc_db->md_flags & MDBX_DUPSORT) { + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (op == MDBX_NEXT || op == MDBX_NEXT_DUP) { + rc = + mdbx_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT); + if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) { + if (likely(rc == MDBX_SUCCESS)) + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + return rc; + } + } + } else { + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + if (op == MDBX_NEXT_DUP) + return MDBX_NOTFOUND; + } + } + + mdbx_debug("cursor_next: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno, + (void *)mc); + if (mc->mc_flags & C_DEL) { + mc->mc_flags ^= C_DEL; + goto skip; + } + + if (mc->mc_ki[mc->mc_top] + 1u >= NUMKEYS(mp)) { + mdbx_debug("=====> move to next sibling page"); + if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) { + mc->mc_flags |= C_EOF; + return rc; + } + mp = mc->mc_pg[mc->mc_top]; + mdbx_debug("next page is %" PRIaPGNO ", key index %u", mp->mp_pgno, + mc->mc_ki[mc->mc_top]); + } else + mc->mc_ki[mc->mc_top]++; + +skip: + mdbx_debug("==> cursor points to page %" PRIaPGNO + " with %u keys, key index %u", + mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]); + + if (IS_LEAF2(mp)) { + if (likely(key)) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len); + } + return MDBX_SUCCESS; + } + + mdbx_cassert(mc, IS_LEAF(mp)); + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + if (data) { + if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS)) + return rc; + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + } + + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + return MDBX_SUCCESS; +} + +/* Move the cursor to the previous data item. */ +static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + MDBX_cursor_op op) { + MDBX_page *mp; + MDBX_node *leaf; + int rc; + + if ((mc->mc_flags & C_DEL) && op == MDBX_PREV_DUP) + return MDBX_NOTFOUND; + + if (!(mc->mc_flags & C_INITIALIZED)) { + rc = mdbx_cursor_last(mc, key, data); + if (unlikely(rc)) + return rc; + mc->mc_ki[mc->mc_top]++; + } + + mp = mc->mc_pg[mc->mc_top]; + if ((mc->mc_db->md_flags & MDBX_DUPSORT) && + mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (op == MDBX_PREV || op == MDBX_PREV_DUP) { + rc = + mdbx_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV); + if (op != MDBX_PREV || rc != MDBX_NOTFOUND) { + if (likely(rc == MDBX_SUCCESS)) { + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + mc->mc_flags &= ~C_EOF; + } + return rc; + } + } + } else { + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + if (op == MDBX_PREV_DUP) + return MDBX_NOTFOUND; + } + } + + mdbx_debug("cursor_prev: top page is %" PRIaPGNO " in cursor %p", mp->mp_pgno, + (void *)mc); + + mc->mc_flags &= ~(C_EOF | C_DEL); + + if (mc->mc_ki[mc->mc_top] == 0) { + mdbx_debug("=====> move to prev sibling page"); + if ((rc = mdbx_cursor_sibling(mc, 0)) != MDBX_SUCCESS) { + return rc; + } + mp = mc->mc_pg[mc->mc_top]; + mc->mc_ki[mc->mc_top] = NUMKEYS(mp) - 1; + mdbx_debug("prev page is %" PRIaPGNO ", key index %u", mp->mp_pgno, + mc->mc_ki[mc->mc_top]); + } else + mc->mc_ki[mc->mc_top]--; + + mdbx_debug("==> cursor points to page %" PRIaPGNO + " with %u keys, key index %u", + mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]); + + if (IS_LEAF2(mp)) { + if (likely(key)) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len); + } + return MDBX_SUCCESS; + } + + mdbx_cassert(mc, IS_LEAF(mp)); + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + if (data) { + if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS)) + return rc; + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + } + + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + return MDBX_SUCCESS; +} + +/* Set the cursor on a specific data item. */ +__hot static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + MDBX_cursor_op op, int *exactp) { + int rc; + MDBX_page *mp; + MDBX_node *leaf = NULL; + DKBUF; + + if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) && + unlikely(key->iov_len != sizeof(uint32_t) && + key->iov_len != sizeof(uint64_t))) { + mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY"); + return MDBX_BAD_VALSIZE; + } + + if (mc->mc_xcursor) + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + + /* See if we're already on the right page */ + if (mc->mc_flags & C_INITIALIZED) { + MDBX_val nodekey; + + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); + mp = mc->mc_pg[mc->mc_top]; + if (!NUMKEYS(mp)) { + mc->mc_ki[mc->mc_top] = 0; + return MDBX_NOTFOUND; + } + if (IS_LEAF2(mp)) { + nodekey.iov_len = mc->mc_db->md_xsize; + nodekey.iov_base = LEAF2KEY(mp, 0, nodekey.iov_len); + } else { + leaf = NODEPTR(mp, 0); + MDBX_GET_KEYVALUE(leaf, nodekey); + } + rc = mc->mc_dbx->md_cmp(key, &nodekey); + if (unlikely(rc == 0)) { + /* Probably happens rarely, but first node on the page + * was the one we wanted. */ + mc->mc_ki[mc->mc_top] = 0; + if (exactp) + *exactp = 1; + goto set1; + } + if (rc > 0) { + const unsigned nkeys = NUMKEYS(mp); + unsigned i; + if (nkeys > 1) { + if (IS_LEAF2(mp)) { + nodekey.iov_base = LEAF2KEY(mp, nkeys - 1, nodekey.iov_len); + } else { + leaf = NODEPTR(mp, nkeys - 1); + MDBX_GET_KEYVALUE(leaf, nodekey); + } + rc = mc->mc_dbx->md_cmp(key, &nodekey); + if (rc == 0) { + /* last node was the one we wanted */ + mdbx_cassert(mc, nkeys >= 1 && nkeys <= UINT16_MAX + 1); + mc->mc_ki[mc->mc_top] = (indx_t)(nkeys - 1); + if (exactp) + *exactp = 1; + goto set1; + } + if (rc < 0) { + if (mc->mc_ki[mc->mc_top] < NUMKEYS(mp)) { + /* This is definitely the right page, skip search_page */ + if (IS_LEAF2(mp)) { + nodekey.iov_base = + LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.iov_len); + } else { + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + MDBX_GET_KEYVALUE(leaf, nodekey); + } + rc = mc->mc_dbx->md_cmp(key, &nodekey); + if (rc == 0) { + /* current node was the one we wanted */ + if (exactp) + *exactp = 1; + goto set1; + } + } + rc = 0; + mc->mc_flags &= ~C_EOF; + goto set2; + } + } + /* If any parents have right-sibs, search. + * Otherwise, there's nothing further. */ + for (i = 0; i < mc->mc_top; i++) + if (mc->mc_ki[i] < NUMKEYS(mc->mc_pg[i]) - 1) + break; + if (i == mc->mc_top) { + /* There are no other pages */ + mdbx_cassert(mc, nkeys <= UINT16_MAX); + mc->mc_ki[mc->mc_top] = (uint16_t)nkeys; + return MDBX_NOTFOUND; + } + } + if (!mc->mc_top) { + /* There are no other pages */ + mc->mc_ki[mc->mc_top] = 0; + if (op == MDBX_SET_RANGE && !exactp) { + rc = 0; + goto set1; + } else + return MDBX_NOTFOUND; + } + } else { + mc->mc_pg[0] = 0; + } + + rc = mdbx_page_search(mc, key, 0); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + mp = mc->mc_pg[mc->mc_top]; + mdbx_cassert(mc, IS_LEAF(mp)); + +set2: + leaf = mdbx_node_search(mc, key, exactp); + if (exactp != NULL && !*exactp) { + /* MDBX_SET specified and not an exact match. */ + return MDBX_NOTFOUND; + } + + if (leaf == NULL) { + mdbx_debug("===> inexact leaf not found, goto sibling"); + if (unlikely((rc = mdbx_cursor_sibling(mc, 1)) != MDBX_SUCCESS)) { + mc->mc_flags |= C_EOF; + return rc; /* no entries matched */ + } + mp = mc->mc_pg[mc->mc_top]; + mdbx_cassert(mc, IS_LEAF(mp)); + leaf = NODEPTR(mp, 0); + } + +set1: + mc->mc_flags |= C_INITIALIZED; + mc->mc_flags &= ~C_EOF; + + if (IS_LEAF2(mp)) { + if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len); + } + return MDBX_SUCCESS; + } + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + if (likely(data)) { + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (op == MDBX_SET || op == MDBX_SET_KEY || op == MDBX_SET_RANGE) { + rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + } else { + int ex2, *ex2p; + if (op == MDBX_GET_BOTH) { + ex2p = &ex2; + ex2 = 0; + } else { + ex2p = NULL; + } + rc = mdbx_cursor_set(&mc->mc_xcursor->mx_cursor, data, NULL, + MDBX_SET_RANGE, ex2p); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + } else if (op == MDBX_GET_BOTH || op == MDBX_GET_BOTH_RANGE) { + MDBX_val olddata; + if (unlikely((rc = mdbx_node_read(mc, leaf, &olddata)) != MDBX_SUCCESS)) + return rc; + if (unlikely(mc->mc_dbx->md_dcmp == NULL)) + return MDBX_EINVAL; + rc = mc->mc_dbx->md_dcmp(data, &olddata); + if (rc) { + if (op != MDBX_GET_BOTH_RANGE || rc > 0) + return MDBX_NOTFOUND; + rc = 0; + } + *data = olddata; + } else { + if (mc->mc_xcursor) + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS)) + return rc; + } + } + + /* The key already matches in all other cases */ + if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY) + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + + mdbx_debug("==> cursor placed on key [%s], data [%s]", DKEY(key), DVAL(data)); + return rc; +} + +/* Move the cursor to the first item in the database. */ +static int mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) { + int rc; + MDBX_node *leaf; + + if (mc->mc_xcursor) + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + + if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { + rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); + + leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0); + mc->mc_flags |= C_INITIALIZED; + mc->mc_flags &= ~C_EOF; + + mc->mc_ki[mc->mc_top] = 0; + + if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = LEAF2KEY(mc->mc_pg[mc->mc_top], 0, key->iov_len); + return MDBX_SUCCESS; + } + + if (likely(data)) { + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (unlikely(rc)) + return rc; + } else { + if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS)) + return rc; + } + } + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + return MDBX_SUCCESS; +} + +/* Move the cursor to the last item in the database. */ +static int mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) { + int rc; + MDBX_node *leaf; + + if (mc->mc_xcursor) + mc->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + + if (likely((mc->mc_flags & (C_EOF | C_DEL)) != C_EOF)) { + if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) { + rc = mdbx_page_search(mc, NULL, MDBX_PS_LAST); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); + } + + mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1; + mc->mc_flags |= C_INITIALIZED | C_EOF; + leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + + if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = + LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], key->iov_len); + return MDBX_SUCCESS; + } + + if (likely(data)) { + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_cursor_last(&mc->mc_xcursor->mx_cursor, data, NULL); + if (unlikely(rc)) + return rc; + } else { + if (unlikely((rc = mdbx_node_read(mc, leaf, data)) != MDBX_SUCCESS)) + return rc; + } + } + + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + return MDBX_SUCCESS; +} + +int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + MDBX_cursor_op op) { + int rc; + int exact = 0; + int (*mfunc)(MDBX_cursor * mc, MDBX_val * key, MDBX_val * data); + + if (unlikely(mc == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + switch (op) { + case MDBX_GET_CURRENT: { + if (unlikely(!(mc->mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + const unsigned nkeys = NUMKEYS(mp); + if (mc->mc_ki[mc->mc_top] >= nkeys) { + mdbx_cassert(mc, nkeys <= UINT16_MAX); + mc->mc_ki[mc->mc_top] = (uint16_t)nkeys; + return MDBX_NOTFOUND; + } + mdbx_cassert(mc, nkeys > 0); + + rc = MDBX_SUCCESS; + if (IS_LEAF2(mp)) { + key->iov_len = mc->mc_db->md_xsize; + key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len); + } else { + MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + if (data) { + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) { + rc = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL); + if (unlikely(rc)) + return rc; + } + rc = mdbx_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, + MDBX_GET_CURRENT); + } else { + rc = mdbx_node_read(mc, leaf, data); + } + if (unlikely(rc)) + return rc; + } + } + break; + } + case MDBX_GET_BOTH: + case MDBX_GET_BOTH_RANGE: + if (unlikely(data == NULL)) + return MDBX_EINVAL; + if (unlikely(mc->mc_xcursor == NULL)) + return MDBX_INCOMPATIBLE; + /* FALLTHRU */ + case MDBX_SET: + case MDBX_SET_KEY: + case MDBX_SET_RANGE: + if (unlikely(key == NULL)) + return MDBX_EINVAL; + rc = mdbx_cursor_set(mc, key, data, op, + op == MDBX_SET_RANGE ? NULL : &exact); + break; + case MDBX_GET_MULTIPLE: + if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED))) + return MDBX_INCOMPATIBLE; + rc = MDBX_SUCCESS; + if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) || + (mc->mc_xcursor->mx_cursor.mc_flags & C_EOF)) + break; + goto fetchm; + case MDBX_NEXT_MULTIPLE: + if (unlikely(data == NULL)) + return MDBX_EINVAL; + if (unlikely(!(mc->mc_db->md_flags & MDBX_DUPFIXED))) + return MDBX_INCOMPATIBLE; + rc = mdbx_cursor_next(mc, key, data, MDBX_NEXT_DUP); + if (rc == MDBX_SUCCESS) { + if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { + MDBX_cursor *mx; + fetchm: + mx = &mc->mc_xcursor->mx_cursor; + data->iov_len = NUMKEYS(mx->mc_pg[mx->mc_top]) * mx->mc_db->md_xsize; + data->iov_base = PAGEDATA(mx->mc_pg[mx->mc_top]); + mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top]) - 1; + } else { + rc = MDBX_NOTFOUND; + } + } + break; + case MDBX_PREV_MULTIPLE: + if (data == NULL) + return MDBX_EINVAL; + if (!(mc->mc_db->md_flags & MDBX_DUPFIXED)) + return MDBX_INCOMPATIBLE; + rc = MDBX_SUCCESS; + if (!(mc->mc_flags & C_INITIALIZED)) + rc = mdbx_cursor_last(mc, key, data); + if (rc == MDBX_SUCCESS) { + MDBX_cursor *mx = &mc->mc_xcursor->mx_cursor; + if (mx->mc_flags & C_INITIALIZED) { + rc = mdbx_cursor_sibling(mx, 0); + if (rc == MDBX_SUCCESS) + goto fetchm; + } else { + rc = MDBX_NOTFOUND; + } + } + break; + case MDBX_NEXT: + case MDBX_NEXT_DUP: + case MDBX_NEXT_NODUP: + rc = mdbx_cursor_next(mc, key, data, op); + break; + case MDBX_PREV: + case MDBX_PREV_DUP: + case MDBX_PREV_NODUP: + rc = mdbx_cursor_prev(mc, key, data, op); + break; + case MDBX_FIRST: + rc = mdbx_cursor_first(mc, key, data); + break; + case MDBX_FIRST_DUP: + mfunc = mdbx_cursor_first; + mmove: + if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + if (unlikely(mc->mc_xcursor == NULL)) + return MDBX_INCOMPATIBLE; + if (mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) { + mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]); + return MDBX_NOTFOUND; + } + { + MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { + MDBX_GET_MAYNULL_KEYPTR(leaf, key); + rc = mdbx_node_read(mc, leaf, data); + break; + } + } + if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL); + break; + case MDBX_LAST: + rc = mdbx_cursor_last(mc, key, data); + break; + case MDBX_LAST_DUP: + mfunc = mdbx_cursor_last; + goto mmove; + default: + mdbx_debug("unhandled/unimplemented cursor operation %u", op); + return MDBX_EINVAL; + } + + mc->mc_flags &= ~C_DEL; + return rc; +} + +/* Touch all the pages in the cursor stack. Set mc_top. + * Makes sure all the pages are writable, before attempting a write operation. + * [in] mc The cursor to operate on. */ +static int mdbx_cursor_touch(MDBX_cursor *mc) { + int rc = MDBX_SUCCESS; + + if (mc->mc_dbi >= CORE_DBS && + (*mc->mc_dbflag & (DB_DIRTY | DB_DUPDATA)) == 0) { + mdbx_cassert(mc, (mc->mc_flags & C_RECLAIMING) == 0); + /* Touch DB record of named DB */ + MDBX_cursor_couple cx; + if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)) + return MDBX_BAD_DBI; + rc = mdbx_cursor_init(&cx.outer, mc->mc_txn, MAIN_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_page_search(&cx.outer, &mc->mc_dbx->md_name, MDBX_PS_MODIFY); + if (unlikely(rc)) + return rc; + *mc->mc_dbflag |= DB_DIRTY; + } + mc->mc_top = 0; + if (mc->mc_snum) { + do { + rc = mdbx_page_touch(mc); + } while (!rc && ++(mc->mc_top) < mc->mc_snum); + mc->mc_top = mc->mc_snum - 1; + } + return rc; +} + +int mdbx_cursor_put(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + unsigned flags) { + MDBX_env *env; + MDBX_page *fp, *sub_root = NULL; + uint16_t fp_flags; + MDBX_val xdata, *rdata, dkey, olddata; + MDBX_db dummy; + unsigned mcount = 0, dcount = 0, nospill; + size_t nsize; + int rc = MDBX_SUCCESS, rc2; + unsigned nflags; + DKBUF; + + if (unlikely(mc == NULL || key == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + env = mc->mc_txn->mt_env; + + /* Check this first so counter will always be zero on any early failures. */ + if (flags & MDBX_MULTIPLE) { + if (unlikely(!F_ISSET(mc->mc_db->md_flags, MDBX_DUPFIXED))) + return MDBX_INCOMPATIBLE; + if (unlikely(data[1].iov_len >= INT_MAX)) + return MDBX_EINVAL; + dcount = (unsigned)data[1].iov_len; + data[1].iov_len = 0; + } + + if (flags & MDBX_RESERVE) { + if (unlikely(mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_REVERSEDUP))) + return MDBX_INCOMPATIBLE; + data->iov_base = nullptr; + } + + nospill = flags & MDBX_NOSPILL; + flags &= ~MDBX_NOSPILL; + + if (unlikely(mc->mc_txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (mc->mc_txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS + : MDBX_BAD_TXN; + + if (unlikely(key->iov_len > env->me_maxkey_limit)) + return MDBX_BAD_VALSIZE; + + if (unlikely(data->iov_len > ((mc->mc_db->md_flags & MDBX_DUPSORT) + ? env->me_maxkey_limit + : MDBX_MAXDATASIZE))) + return MDBX_BAD_VALSIZE; + + if ((mc->mc_db->md_flags & MDBX_INTEGERKEY) && + unlikely(key->iov_len != sizeof(uint32_t) && + key->iov_len != sizeof(uint64_t))) { + mdbx_cassert(mc, !"key-size is invalid for MDBX_INTEGERKEY"); + return MDBX_BAD_VALSIZE; + } + + if ((mc->mc_db->md_flags & MDBX_INTEGERDUP) && + unlikely(data->iov_len != sizeof(uint32_t) && + data->iov_len != sizeof(uint64_t))) { + mdbx_cassert(mc, !"data-size is invalid MDBX_INTEGERDUP"); + return MDBX_BAD_VALSIZE; + } + + mdbx_debug("==> put db %d key [%s], size %" PRIuPTR + ", data [%s] size %" PRIuPTR, + DDBI(mc), DKEY(key), key ? key->iov_len : 0, + DVAL((flags & MDBX_RESERVE) ? nullptr : data), data->iov_len); + + int dupdata_flag = 0; + if ((flags & MDBX_CURRENT) != 0 && (mc->mc_flags & C_SUB) == 0) { + /* Опция MDBX_CURRENT означает, что запрошено обновление текущей записи, + * на которой сейчас стоит курсор. Проверяем что переданный ключ совпадает + * со значением в текущей позиции курсора. + * Здесь проще вызвать mdbx_cursor_get(), так как для обслуживания таблиц + * с MDBX_DUPSORT также требуется текущий размер данных. */ + MDBX_val current_key, current_data; + rc = mdbx_cursor_get(mc, ¤t_key, ¤t_data, MDBX_GET_CURRENT); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (mc->mc_dbx->md_cmp(key, ¤t_key) != 0) + return MDBX_EKEYMISMATCH; + + if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) { + MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdbx_cassert(mc, + mc->mc_xcursor != NULL && + (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)); + /* Если за ключом более одного значения, либо если размер данных + * отличается, то вместо inplace обновления требуется удаление и + * последующая вставка. */ + if (mc->mc_xcursor->mx_db.md_entries > 1 || + current_data.iov_len != data->iov_len) { + rc = mdbx_cursor_del(mc, 0); + if (rc != MDBX_SUCCESS) + return rc; + flags -= MDBX_CURRENT; + } + } + } + } + + if (mc->mc_db->md_root == P_INVALID) { + /* new database, cursor has nothing to point to */ + mc->mc_snum = 0; + mc->mc_top = 0; + mc->mc_flags &= ~C_INITIALIZED; + rc = MDBX_NO_ROOT; + } else if ((flags & MDBX_CURRENT) == 0) { + int exact = 0; + MDBX_val d2; + if (flags & MDBX_APPEND) { + MDBX_val k2; + rc = mdbx_cursor_last(mc, &k2, &d2); + if (rc == 0) { + rc = mc->mc_dbx->md_cmp(key, &k2); + if (rc > 0) { + rc = MDBX_NOTFOUND; + mc->mc_ki[mc->mc_top]++; + } else if (unlikely(rc < 0 || (flags & MDBX_APPENDDUP) == 0)) { + /* new key is <= last key */ + rc = MDBX_EKEYMISMATCH; + } + } + } else { + rc = mdbx_cursor_set(mc, key, &d2, MDBX_SET, &exact); + } + if ((flags & MDBX_NOOVERWRITE) && + (rc == MDBX_SUCCESS || rc == MDBX_EKEYMISMATCH)) { + mdbx_debug("duplicate key [%s]", DKEY(key)); + *data = d2; + return MDBX_KEYEXIST; + } + if (rc && unlikely(rc != MDBX_NOTFOUND)) + return rc; + } + + mc->mc_flags &= ~C_DEL; + + /* Cursor is positioned, check for room in the dirty list */ + if (!nospill) { + if (flags & MDBX_MULTIPLE) { + rdata = &xdata; + xdata.iov_len = data->iov_len * dcount; + } else { + rdata = data; + } + if (unlikely(rc2 = mdbx_page_spill(mc, key, rdata))) + return rc2; + } + + if (rc == MDBX_NO_ROOT) { + MDBX_page *np; + /* new database, write a root leaf page */ + mdbx_debug("allocating new root leaf page"); + if (unlikely(rc2 = mdbx_page_new(mc, P_LEAF, 1, &np))) { + return rc2; + } + rc2 = mdbx_cursor_push(mc, np); + if (unlikely(rc2 != MDBX_SUCCESS)) + return rc2; + mc->mc_db->md_root = np->mp_pgno; + mc->mc_db->md_depth++; + *mc->mc_dbflag |= DB_DIRTY; + if ((mc->mc_db->md_flags & (MDBX_DUPSORT | MDBX_DUPFIXED)) == MDBX_DUPFIXED) + np->mp_flags |= P_LEAF2; + mc->mc_flags |= C_INITIALIZED; + } else { + /* make sure all cursor pages are writable */ + rc2 = mdbx_cursor_touch(mc); + if (unlikely(rc2)) + return rc2; + } + + bool insert_key, insert_data, do_sub = false; + insert_key = insert_data = (rc != MDBX_SUCCESS); + if (insert_key) { + /* The key does not exist */ + mdbx_debug("inserting key at index %i", mc->mc_ki[mc->mc_top]); + if ((mc->mc_db->md_flags & MDBX_DUPSORT) && + LEAFSIZE(key, data) > env->me_nodemax) { + /* Too big for a node, insert in sub-DB. Set up an empty + * "old sub-page" for prep_subDB to expand to a full page. */ + fp_flags = P_LEAF | P_DIRTY; + fp = env->me_pbuf; + fp->mp_leaf2_ksize = (uint16_t)data->iov_len; /* used if MDBX_DUPFIXED */ + fp->mp_lower = fp->mp_upper = 0; + olddata.iov_len = PAGEHDRSZ; + goto prep_subDB; + } + } else { + /* there's only a key anyway, so this is a no-op */ + if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { + char *ptr; + unsigned ksize = mc->mc_db->md_xsize; + if (key->iov_len != ksize) + return MDBX_BAD_VALSIZE; + ptr = LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], ksize); + memcpy(ptr, key->iov_base, ksize); + fix_parent: + /* if overwriting slot 0 of leaf, need to + * update branch key if there is a parent page */ + if (mc->mc_top && !mc->mc_ki[mc->mc_top]) { + unsigned dtop = 1; + mc->mc_top--; + /* slot 0 is always an empty key, find real slot */ + while (mc->mc_top && !mc->mc_ki[mc->mc_top]) { + mc->mc_top--; + dtop++; + } + if (mc->mc_ki[mc->mc_top]) + rc2 = mdbx_update_key(mc, key); + else + rc2 = MDBX_SUCCESS; + mdbx_cassert(mc, mc->mc_top + dtop < UINT16_MAX); + mc->mc_top += (uint16_t)dtop; + if (rc2) + return rc2; + } + + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, false); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + return MDBX_SUCCESS; + } + + more:; + MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + olddata.iov_len = NODEDSZ(leaf); + olddata.iov_base = NODEDATA(leaf); + + /* DB has dups? */ + if (F_ISSET(mc->mc_db->md_flags, MDBX_DUPSORT)) { + /* Prepare (sub-)page/sub-DB to accept the new item, if needed. + * fp: old sub-page or a header faking it. + * mp: new (sub-)page. offset: growth in page size. + * xdata: node data with new page or DB. */ + unsigned i, offset = 0; + MDBX_page *mp = fp = xdata.iov_base = env->me_pbuf; + mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno; + + /* Was a single item before, must convert now */ + if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { + + /* does data match? */ + if (!mc->mc_dbx->md_dcmp(data, &olddata)) { + if (unlikely(flags & (MDBX_NODUPDATA | MDBX_APPENDDUP))) + return MDBX_KEYEXIST; + /* overwrite it */ + goto current; + } + + /* Just overwrite the current item */ + if (flags & MDBX_CURRENT) + goto current; + + /* Back up original data item */ + dupdata_flag = 1; + dkey.iov_len = olddata.iov_len; + dkey.iov_base = memcpy(fp + 1, olddata.iov_base, olddata.iov_len); + + /* Make sub-page header for the dup items, with dummy body */ + fp->mp_flags = P_LEAF | P_DIRTY | P_SUBP; + fp->mp_lower = 0; + xdata.iov_len = PAGEHDRSZ + dkey.iov_len + data->iov_len; + if (mc->mc_db->md_flags & MDBX_DUPFIXED) { + fp->mp_flags |= P_LEAF2; + fp->mp_leaf2_ksize = (uint16_t)data->iov_len; + xdata.iov_len += 2 * data->iov_len; /* leave space for 2 more */ + } else { + xdata.iov_len += 2 * (sizeof(indx_t) + NODESIZE) + + (dkey.iov_len & 1) + (data->iov_len & 1); + } + fp->mp_upper = (uint16_t)(xdata.iov_len - PAGEHDRSZ); + olddata.iov_len = xdata.iov_len; /* pretend olddata is fp */ + } else if (leaf->mn_flags & F_SUBDATA) { + /* Data is on sub-DB, just store it */ + flags |= F_DUPDATA | F_SUBDATA; + goto put_sub; + } else { + /* Data is on sub-page */ + fp = olddata.iov_base; + switch (flags) { + default: + if (!(mc->mc_db->md_flags & MDBX_DUPFIXED)) { + offset = EVEN(NODESIZE + sizeof(indx_t) + data->iov_len); + break; + } + offset = fp->mp_leaf2_ksize; + if (SIZELEFT(fp) < offset) { + offset *= 4; /* space for 4 more */ + break; + } + /* FALLTHRU: Big enough MDBX_DUPFIXED sub-page */ + __fallthrough; + case MDBX_CURRENT | MDBX_NODUPDATA: + case MDBX_CURRENT: + fp->mp_flags |= P_DIRTY; + fp->mp_pgno = mp->mp_pgno; + mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; + flags |= F_DUPDATA; + goto put_sub; + } + xdata.iov_len = olddata.iov_len + offset; + } + + fp_flags = fp->mp_flags; + if (NODESIZE + NODEKSZ(leaf) + xdata.iov_len > env->me_nodemax) { + /* Too big for a sub-page, convert to sub-DB */ + fp_flags &= ~P_SUBP; + prep_subDB: + dummy.md_xsize = 0; + dummy.md_flags = 0; + if (mc->mc_db->md_flags & MDBX_DUPFIXED) { + fp_flags |= P_LEAF2; + dummy.md_xsize = fp->mp_leaf2_ksize; + dummy.md_flags = MDBX_DUPFIXED; + if (mc->mc_db->md_flags & MDBX_INTEGERDUP) + dummy.md_flags |= MDBX_INTEGERKEY; + } + dummy.md_depth = 1; + dummy.md_branch_pages = 0; + dummy.md_leaf_pages = 1; + dummy.md_overflow_pages = 0; + dummy.md_entries = NUMKEYS(fp); + xdata.iov_len = sizeof(MDBX_db); + xdata.iov_base = &dummy; + if ((rc = mdbx_page_alloc(mc, 1, &mp, MDBX_ALLOC_ALL))) + return rc; + mc->mc_db->md_leaf_pages += 1; + mdbx_cassert(mc, env->me_psize > olddata.iov_len); + offset = env->me_psize - (unsigned)olddata.iov_len; + flags |= F_DUPDATA | F_SUBDATA; + dummy.md_root = mp->mp_pgno; + dummy.md_seq = dummy.md_merkle = 0; + sub_root = mp; + } + if (mp != fp) { + mp->mp_flags = fp_flags | P_DIRTY; + mp->mp_leaf2_ksize = fp->mp_leaf2_ksize; + mp->mp_lower = fp->mp_lower; + mdbx_cassert(mc, fp->mp_upper + offset <= UINT16_MAX); + mp->mp_upper = (indx_t)(fp->mp_upper + offset); + if (unlikely(fp_flags & P_LEAF2)) { + memcpy(PAGEDATA(mp), PAGEDATA(fp), NUMKEYS(fp) * fp->mp_leaf2_ksize); + } else { + memcpy((char *)mp + mp->mp_upper + PAGEHDRSZ, + (char *)fp + fp->mp_upper + PAGEHDRSZ, + olddata.iov_len - fp->mp_upper - PAGEHDRSZ); + memcpy((char *)(&mp->mp_ptrs), (char *)(&fp->mp_ptrs), + NUMKEYS(fp) * sizeof(mp->mp_ptrs[0])); + for (i = 0; i < NUMKEYS(fp); i++) { + mdbx_cassert(mc, mp->mp_ptrs[i] + offset <= UINT16_MAX); + mp->mp_ptrs[i] += (indx_t)offset; + } + } + } + + rdata = &xdata; + flags |= F_DUPDATA; + do_sub = true; + if (!insert_key) + mdbx_node_del(mc, 0); + goto new_sub; + } + current: + /* MDBX passes F_SUBDATA in 'flags' to write a DB record */ + if (unlikely((leaf->mn_flags ^ flags) & F_SUBDATA)) + return MDBX_INCOMPATIBLE; + /* overflow page overwrites need special handling */ + if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { + MDBX_page *omp; + pgno_t pg; + int level, ovpages, + dpages = (LEAFSIZE(key, data) > env->me_nodemax) + ? OVPAGES(env, data->iov_len) + : 0; + + memcpy(&pg, olddata.iov_base, sizeof(pg)); + if (unlikely((rc2 = mdbx_page_get(mc, pg, &omp, &level)) != 0)) + return rc2; + ovpages = omp->mp_pages; + + /* Is the ov page large enough? */ + if (unlikely(mc->mc_flags & C_GCFREEZE) + ? ovpages >= dpages + : ovpages == + /* LY: add configurable threshold to keep reserve space */ + dpages) { + if (!IS_DIRTY(omp) && (level || (env->me_flags & MDBX_WRITEMAP))) { + rc = mdbx_page_unspill(mc->mc_txn, omp, &omp); + if (unlikely(rc)) + return rc; + level = 0; /* dirty in this txn or clean */ + } + /* Is it dirty? */ + if (IS_DIRTY(omp)) { + /* yes, overwrite it. Note in this case we don't + * bother to try shrinking the page if the new data + * is smaller than the overflow threshold. */ + if (unlikely(level > 1)) { + /* It is writable only in a parent txn */ + MDBX_page *np = mdbx_page_malloc(mc->mc_txn, ovpages); + if (unlikely(!np)) + return MDBX_ENOMEM; + /* Note - this page is already counted in parent's dirtyroom */ + rc2 = mdbx_dpl_insert(mc->mc_txn->mt_rw_dirtylist, pg, np); + if (unlikely(rc2 != MDBX_SUCCESS)) { + rc = rc2; + mdbx_dpage_free(env, np, ovpages); + goto fail; + } + + /* Currently we make the page look as with put() in the + * parent txn, in case the user peeks at MDBX_RESERVEd + * or unused parts. Some users treat ovpages specially. */ + const size_t whole = pgno2bytes(env, ovpages); + /* Skip the part where MDBX will put *data. + * Copy end of page, adjusting alignment so + * compiler may copy words instead of bytes. */ + const size_t off = + (PAGEHDRSZ + data->iov_len) & -(intptr_t)sizeof(size_t); + memcpy((size_t *)((char *)np + off), (size_t *)((char *)omp + off), + whole - off); + memcpy(np, omp, PAGEHDRSZ); /* Copy header of page */ + omp = np; + } + SETDSZ(leaf, data->iov_len); + if (F_ISSET(flags, MDBX_RESERVE)) + data->iov_base = PAGEDATA(omp); + else + memcpy(PAGEDATA(omp), data->iov_base, data->iov_len); + + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, false); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + return MDBX_SUCCESS; + } + } + if ((rc2 = mdbx_ovpage_free(mc, omp)) != MDBX_SUCCESS) + return rc2; + } else if (data->iov_len == olddata.iov_len) { + mdbx_cassert(mc, EVEN(key->iov_len) == EVEN(leaf->mn_ksize)); + /* same size, just replace it. Note that we could + * also reuse this node if the new data is smaller, + * but instead we opt to shrink the node in that case. */ + if (F_ISSET(flags, MDBX_RESERVE)) + data->iov_base = olddata.iov_base; + else if (!(mc->mc_flags & C_SUB)) + memcpy(olddata.iov_base, data->iov_base, data->iov_len); + else { + mdbx_cassert(mc, NUMKEYS(mc->mc_pg[mc->mc_top]) == 1); + mdbx_cassert(mc, PAGETYPE(mc->mc_pg[mc->mc_top]) == P_LEAF); + mdbx_cassert(mc, NODEDSZ(leaf) == 0); + mdbx_cassert(mc, leaf->mn_flags == 0); + mdbx_cassert(mc, key->iov_len < UINT16_MAX); + leaf->mn_ksize = (uint16_t)key->iov_len; + memcpy(NODEKEY(leaf), key->iov_base, key->iov_len); + mdbx_cassert(mc, (char *)NODEKEY(leaf) + NODEDSZ(leaf) < + (char *)(mc->mc_pg[mc->mc_top]) + env->me_psize); + goto fix_parent; + } + + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, false); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + return MDBX_SUCCESS; + } + mdbx_node_del(mc, 0); + } + + rdata = data; + +new_sub: + nflags = flags & NODE_ADD_FLAGS; + nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->iov_len + : mdbx_leaf_size(env, key, rdata); + if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) { + if ((flags & (F_DUPDATA | F_SUBDATA)) == F_DUPDATA) + nflags &= ~MDBX_APPEND; /* sub-page may need room to grow */ + if (!insert_key) + nflags |= MDBX_SPLIT_REPLACE; + rc = mdbx_page_split(mc, key, rdata, P_INVALID, nflags); + if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) + rc = mdbx_cursor_check(mc, false); + } else { + /* There is room already in this leaf page. */ + if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { + mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0 && + rdata->iov_len == 0); + rc = mdbx_node_add_leaf2(mc, mc->mc_ki[mc->mc_top], key); + } else + rc = mdbx_node_add_leaf(mc, mc->mc_ki[mc->mc_top], key, rdata, nflags); + if (likely(rc == 0)) { + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2, *m3; + MDBX_dbi dbi = mc->mc_dbi; + unsigned i = mc->mc_top; + MDBX_page *mp = mc->mc_pg[i]; + + for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc || m3->mc_snum < mc->mc_snum || m3->mc_pg[i] != mp) + continue; + if (m3->mc_ki[i] >= mc->mc_ki[i] && insert_key) { + m3->mc_ki[i]++; + } + if (XCURSOR_INITED(m3)) + XCURSOR_REFRESH(m3, mp, m3->mc_ki[i]); + } + } + } + + if (likely(rc == MDBX_SUCCESS)) { + /* Now store the actual data in the child DB. Note that we're + * storing the user data in the keys field, so there are strict + * size limits on dupdata. The actual data fields of the child + * DB are all zero size. */ + if (do_sub) { + int xflags; + size_t ecount; + put_sub: + xdata.iov_len = 0; + xdata.iov_base = ""; + MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (flags & MDBX_CURRENT) { + xflags = (flags & MDBX_NODUPDATA) + ? MDBX_CURRENT | MDBX_NOOVERWRITE | MDBX_NOSPILL + : MDBX_CURRENT | MDBX_NOSPILL; + } else { + rc2 = mdbx_xcursor_init1(mc, leaf); + if (unlikely(rc2 != MDBX_SUCCESS)) + return rc2; + xflags = (flags & MDBX_NODUPDATA) ? MDBX_NOOVERWRITE | MDBX_NOSPILL + : MDBX_NOSPILL; + } + if (sub_root) + mc->mc_xcursor->mx_cursor.mc_pg[0] = sub_root; + /* converted, write the original data first */ + if (dupdata_flag) { + rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags); + if (unlikely(rc)) + goto bad_sub; + /* we've done our job */ + dkey.iov_len = 0; + } + if (!(leaf->mn_flags & F_SUBDATA) || sub_root) { + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2; + MDBX_xcursor *mx = mc->mc_xcursor; + unsigned i = mc->mc_top; + MDBX_page *mp = mc->mc_pg[i]; + const int nkeys = NUMKEYS(mp); + + for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { + if (m2 == mc || m2->mc_snum < mc->mc_snum) + continue; + if (!(m2->mc_flags & C_INITIALIZED)) + continue; + if (m2->mc_pg[i] == mp) { + if (m2->mc_ki[i] == mc->mc_ki[i]) { + rc2 = mdbx_xcursor_init2(m2, mx, dupdata_flag); + if (unlikely(rc2 != MDBX_SUCCESS)) + return rc2; + } else if (!insert_key && m2->mc_ki[i] < nkeys) { + XCURSOR_REFRESH(m2, mp, m2->mc_ki[i]); + } + } + } + } + mdbx_cassert(mc, mc->mc_xcursor->mx_db.md_entries < PTRDIFF_MAX); + ecount = (size_t)mc->mc_xcursor->mx_db.md_entries; + if (flags & MDBX_APPENDDUP) + xflags |= MDBX_APPEND; + rc = mdbx_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags); + if (flags & F_SUBDATA) { + void *db = NODEDATA(leaf); + memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db)); + } + insert_data = (ecount != (size_t)mc->mc_xcursor->mx_db.md_entries); + } + /* Increment count unless we just replaced an existing item. */ + if (insert_data) + mc->mc_db->md_entries++; + if (insert_key) { + /* Invalidate txn if we created an empty sub-DB */ + if (unlikely(rc)) + goto bad_sub; + /* If we succeeded and the key didn't exist before, + * make sure the cursor is marked valid. */ + mc->mc_flags |= C_INITIALIZED; + } + if (flags & MDBX_MULTIPLE) { + if (!rc) { + mcount++; + /* let caller know how many succeeded, if any */ + data[1].iov_len = mcount; + if (mcount < dcount) { + data[0].iov_base = (char *)data[0].iov_base + data[0].iov_len; + insert_key = insert_data = false; + goto more; + } + } + } + if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) + rc = mdbx_cursor_check(mc, false); + return rc; + bad_sub: + if (unlikely(rc == MDBX_KEYEXIST)) + mdbx_error("unexpected %s", "MDBX_KEYEXIST"); + /* should not happen, we deleted that item */ + rc = MDBX_PROBLEM; + } +fail: + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return rc; +} + +int mdbx_cursor_del(MDBX_cursor *mc, unsigned flags) { + MDBX_node *leaf; + MDBX_page *mp; + int rc; + + if (unlikely(!mc)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(mc->mc_txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (mc->mc_txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS + : MDBX_BAD_TXN; + + if (unlikely(!(mc->mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + + if (unlikely(mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top]))) + return MDBX_NOTFOUND; + + if (unlikely(!(flags & MDBX_NOSPILL) && + (rc = mdbx_page_spill(mc, NULL, NULL)))) + return rc; + + rc = mdbx_cursor_touch(mc); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + mp = mc->mc_pg[mc->mc_top]; + if (IS_LEAF2(mp)) + goto del_key; + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + if (flags & MDBX_NODUPDATA) { + /* mdbx_cursor_del0() will subtract the final entry */ + mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1; + mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; + } else { + if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { + mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); + } + rc = mdbx_cursor_del(&mc->mc_xcursor->mx_cursor, MDBX_NOSPILL); + if (unlikely(rc)) + return rc; + /* If sub-DB still has entries, we're done */ + if (mc->mc_xcursor->mx_db.md_entries) { + if (leaf->mn_flags & F_SUBDATA) { + /* update subDB info */ + void *db = NODEDATA(leaf); + memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDBX_db)); + } else { + MDBX_cursor *m2; + /* shrink fake page */ + mdbx_node_shrink(mp, mc->mc_ki[mc->mc_top]); + leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf); + /* fix other sub-DB cursors pointed at fake pages on this page */ + for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2 = m2->mc_next) { + if (m2 == mc || m2->mc_snum < mc->mc_snum) + continue; + if (!(m2->mc_flags & C_INITIALIZED)) + continue; + if (m2->mc_pg[mc->mc_top] == mp) { + MDBX_node *n2 = leaf; + if (m2->mc_ki[mc->mc_top] >= NUMKEYS(mp)) + continue; + if (m2->mc_ki[mc->mc_top] != mc->mc_ki[mc->mc_top]) { + n2 = NODEPTR(mp, m2->mc_ki[mc->mc_top]); + if (n2->mn_flags & F_SUBDATA) + continue; + } + m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2); + } + } + } + mc->mc_db->md_entries--; + mdbx_cassert(mc, mc->mc_db->md_entries > 0 && mc->mc_db->md_depth > 0 && + mc->mc_db->md_root != P_INVALID); + return rc; + } else { + mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED; + } + /* otherwise fall thru and delete the sub-DB */ + } + + if (leaf->mn_flags & F_SUBDATA) { + /* add all the child DB's pages to the free list */ + mc->mc_db->md_branch_pages -= mc->mc_xcursor->mx_db.md_branch_pages; + mc->mc_db->md_leaf_pages -= mc->mc_xcursor->mx_db.md_leaf_pages; + mc->mc_db->md_overflow_pages -= mc->mc_xcursor->mx_db.md_overflow_pages; + rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0); + if (unlikely(rc)) + goto fail; + } + } + /* MDBX passes F_SUBDATA in 'flags' to delete a DB record */ + else if (unlikely((leaf->mn_flags ^ flags) & F_SUBDATA)) { + rc = MDBX_INCOMPATIBLE; + goto fail; + } + + /* add overflow pages to free list */ + if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { + MDBX_page *omp; + pgno_t pg; + + memcpy(&pg, NODEDATA(leaf), sizeof(pg)); + if (unlikely((rc = mdbx_page_get(mc, pg, &omp, NULL)) || + (rc = mdbx_ovpage_free(mc, omp)))) + goto fail; + } + +del_key: + return mdbx_cursor_del0(mc); + +fail: + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return rc; +} + +/* Allocate and initialize new pages for a database. + * Set MDBX_TXN_ERROR on failure. + * + * [in] mc a cursor on the database being added to. + * [in] flags flags defining what type of page is being allocated. + * [in] num the number of pages to allocate. This is usually 1, + * unless allocating overflow pages for a large record. + * [out] mp Address of a page, or NULL on failure. + * + * Returns 0 on success, non-zero on failure. */ +static int mdbx_page_new(MDBX_cursor *mc, unsigned flags, unsigned num, + MDBX_page **mp) { + MDBX_page *np; + int rc; + + if (unlikely((rc = mdbx_page_alloc(mc, num, &np, MDBX_ALLOC_ALL)))) + return rc; + mdbx_debug("allocated new page #%" PRIaPGNO ", size %u", np->mp_pgno, + mc->mc_txn->mt_env->me_psize); + np->mp_flags = (uint16_t)(flags | P_DIRTY); + np->mp_lower = 0; + np->mp_upper = (indx_t)(mc->mc_txn->mt_env->me_psize - PAGEHDRSZ); + + if (IS_BRANCH(np)) + mc->mc_db->md_branch_pages++; + else if (IS_LEAF(np)) + mc->mc_db->md_leaf_pages++; + else { + mdbx_cassert(mc, IS_OVERFLOW(np)); + mc->mc_db->md_overflow_pages += num; + np->mp_pages = num; + } + + if (unlikely(mc->mc_flags & C_SUB)) { + MDBX_db *outer = mdbx_outer_db(mc); + if (IS_BRANCH(np)) + outer->md_branch_pages++; + else if (IS_LEAF(np)) + outer->md_leaf_pages++; + else { + mdbx_cassert(mc, IS_OVERFLOW(np)); + outer->md_overflow_pages += num; + } + } + + *mp = np; + return MDBX_SUCCESS; +} + +/* Calculate the size of a leaf node. + * + * The size depends on the environment's page size; if a data item + * is too large it will be put onto an overflow page and the node + * size will only include the key and not the data. Sizes are always + * rounded up to an even number of bytes, to guarantee 2-byte alignment + * of the MDBX_node headers. + * + * [in] env The environment handle. + * [in] key The key for the node. + * [in] data The data for the node. + * + * Returns The number of bytes needed to store the node. */ +static __inline size_t mdbx_leaf_size(MDBX_env *env, const MDBX_val *key, + const MDBX_val *data) { + size_t sz = LEAFSIZE(key, data); + if (sz > env->me_nodemax) { + /* put on overflow page */ + sz = sz - data->iov_len + sizeof(pgno_t); + } + + return EVEN(sz) + sizeof(indx_t); +} + +/* Calculate the size of a branch node. + * + * The size should depend on the environment's page size but since + * we currently don't support spilling large keys onto overflow + * pages, it's simply the size of the MDBX_node header plus the + * size of the key. Sizes are always rounded up to an even number + * of bytes, to guarantee 2-byte alignment of the MDBX_node headers. + * + * [in] env The environment handle. + * [in] key The key for the node. + * + * Returns The number of bytes needed to store the node. */ +static __inline size_t mdbx_branch_size(MDBX_env *env, const MDBX_val *key) { + size_t sz = INDXSIZE(key); + if (unlikely(sz > env->me_nodemax)) { + /* put on overflow page */ + /* not implemented */ + mdbx_assert_fail(env, "INDXSIZE(key) <= env->me_nodemax", __FUNCTION__, + __LINE__); + sz = sz - key->iov_len + sizeof(pgno_t); + } + + return EVEN(sz) + sizeof(indx_t); +} + +static int __must_check_result mdbx_node_add_leaf2(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + DKBUF; + mdbx_debug("add to leaf2-%spage %" PRIaPGNO " index %i, " + " key size %" PRIuPTR " [%s]", + IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, + key ? key->iov_len : 0, DKEY(key)); + + mdbx_cassert(mc, key); + mdbx_cassert(mc, PAGETYPE(mp) == (P_LEAF | P_LEAF2)); + const unsigned ksize = mc->mc_db->md_xsize; + mdbx_cassert(mc, ksize == key->iov_len); + + const int room = SIZELEFT(mp); + mdbx_cassert(mc, room >= (int)ksize); + if (unlikely(room < (int)ksize)) { + bailout: + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PAGE_FULL; + } + + char *const ptr = LEAF2KEY(mp, indx, ksize); + mdbx_cassert(mc, NUMKEYS(mp) >= indx); + if (unlikely(NUMKEYS(mp) < indx)) + goto bailout; + + const unsigned diff = NUMKEYS(mp) - indx; + if (likely(diff > 0)) + /* Move higher keys up one slot. */ + memmove(ptr + ksize, ptr, diff * ksize); + /* insert new key */ + memcpy(ptr, key->iov_base, ksize); + + /* Just using these for counting */ + mdbx_cassert(mc, UINT16_MAX - mp->mp_lower >= (int)sizeof(indx_t)); + mp->mp_lower += sizeof(indx_t); + mdbx_cassert(mc, mp->mp_upper >= ksize - sizeof(indx_t)); + mp->mp_upper -= (indx_t)(ksize - sizeof(indx_t)); + + mdbx_cassert(mc, + mp->mp_upper >= mp->mp_lower && + PAGEHDRSZ + mp->mp_upper <= mc->mc_txn->mt_env->me_psize); + return MDBX_SUCCESS; +} + +static int __must_check_result mdbx_node_add_branch(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key, + pgno_t pgno) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + DKBUF; + mdbx_debug("add to branch-%spage %" PRIaPGNO " index %i, node-pgno %" PRIaPGNO + " key size %" PRIuPTR " [%s]", + IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, pgno, + key ? key->iov_len : 0, DKEY(key)); + + mdbx_cassert(mc, PAGETYPE(mp) == P_BRANCH); + STATIC_ASSERT(NODESIZE % 2 == 0); + + const size_t room = SIZELEFT(mp); + const size_t node_size = + likely(key != NULL) ? NODESIZE + EVEN(key->iov_len) : NODESIZE; + mdbx_cassert(mc, mdbx_branch_size(mc->mc_txn->mt_env, key) == + node_size + sizeof(indx_t)); + mdbx_cassert(mc, room >= node_size + sizeof(indx_t)); + if (unlikely(room < node_size + sizeof(indx_t))) { + bailout: + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PAGE_FULL; + } + + const unsigned numkeys = NUMKEYS(mp); + mdbx_cassert(mc, numkeys >= indx); + if (unlikely(numkeys < indx)) + goto bailout; + + /* Move higher pointers up one slot. */ + for (unsigned i = numkeys; i > indx; --i) + mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; + + /* Adjust free space offsets. */ + const size_t ofs = mp->mp_upper - node_size; + mdbx_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t)); + mdbx_cassert(mc, ofs <= UINT16_MAX); + mp->mp_ptrs[indx] = (uint16_t)ofs; + mp->mp_upper = (uint16_t)ofs; + mp->mp_lower += sizeof(indx_t); + + /* Write the node data. */ + MDBX_node *node = NODEPTR(mp, indx); + SETPGNO(node, pgno); + node->mn_ksize = 0; + node->mn_flags = 0; + if (likely(key != NULL)) { + node->mn_ksize = (uint16_t)key->iov_len; + memcpy(NODEKEY(node), key->iov_base, key->iov_len); + } + + mdbx_cassert(mc, + mp->mp_upper >= mp->mp_lower && + PAGEHDRSZ + mp->mp_upper <= mc->mc_txn->mt_env->me_psize); + return MDBX_SUCCESS; +} + +static int __must_check_result mdbx_node_add_leaf(MDBX_cursor *mc, + unsigned indx, + const MDBX_val *key, + MDBX_val *data, + unsigned flags) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + DKBUF; + mdbx_debug("add to leaf-%spage %" PRIaPGNO " index %i, data size %" PRIuPTR + " key size %" PRIuPTR " [%s]", + IS_SUBP(mp) ? "sub-" : "", mp->mp_pgno, indx, + data ? data->iov_len : 0, key ? key->iov_len : 0, DKEY(key)); + mdbx_cassert(mc, key != NULL && data != NULL); + mdbx_cassert(mc, PAGETYPE(mp) == P_LEAF); + MDBX_page *largepage = NULL; + + const size_t room = SIZELEFT(mp); + size_t node_size = NODESIZE + key->iov_len; + if (unlikely(flags & F_BIGDATA)) { + /* Data already on overflow page. */ + STATIC_ASSERT(sizeof(pgno_t) % 2 == 0); + node_size += sizeof(pgno_t); + } else if (unlikely(node_size + data->iov_len > + mc->mc_txn->mt_env->me_nodemax)) { + const pgno_t ovpages = OVPAGES(mc->mc_txn->mt_env, data->iov_len); + /* Put data on overflow page. */ + mdbx_debug("data size is %" PRIuPTR ", node would be %" PRIuPTR + ", put data on %u-overflow page(s)", + data->iov_len, node_size + data->iov_len, ovpages); + int rc = mdbx_page_new(mc, P_OVERFLOW, ovpages, &largepage); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mdbx_debug("allocated overflow page %" PRIaPGNO, largepage->mp_pgno); + flags |= F_BIGDATA; + node_size += sizeof(pgno_t); + mdbx_cassert(mc, mdbx_leaf_size(mc->mc_txn->mt_env, key, data) == + EVEN(node_size) + sizeof(indx_t)); + } else { + node_size += data->iov_len; + mdbx_cassert(mc, mdbx_leaf_size(mc->mc_txn->mt_env, key, data) == + EVEN(node_size) + sizeof(indx_t)); + } + + node_size = EVEN(node_size); + mdbx_cassert(mc, room >= node_size + sizeof(indx_t)); + if (unlikely(room < node_size + sizeof(indx_t))) { + bailout: + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PAGE_FULL; + } + + const unsigned numkeys = NUMKEYS(mp); + mdbx_cassert(mc, numkeys >= indx); + if (unlikely(numkeys < indx)) + goto bailout; + + /* Move higher pointers up one slot. */ + for (unsigned i = numkeys; i > indx; --i) + mp->mp_ptrs[i] = mp->mp_ptrs[i - 1]; + + /* Adjust free space offsets. */ + const size_t ofs = mp->mp_upper - node_size; + mdbx_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t)); + mdbx_cassert(mc, ofs <= UINT16_MAX); + mp->mp_ptrs[indx] = (uint16_t)ofs; + mp->mp_upper = (uint16_t)ofs; + mp->mp_lower += sizeof(indx_t); + + /* Write the node data. */ + MDBX_node *node = NODEPTR(mp, indx); + node->mn_ksize = (uint16_t)key->iov_len; + node->mn_flags = (uint16_t)flags; + SETDSZ(node, data->iov_len); + memcpy(NODEKEY(node), key->iov_base, key->iov_len); + + void *nodedata = NODEDATA(node); + if (likely(largepage == NULL)) { + if (unlikely(flags & F_BIGDATA)) + memcpy(nodedata, data->iov_base, sizeof(pgno_t)); + else if (unlikely(flags & MDBX_RESERVE)) + data->iov_base = nodedata; + else if (likely(nodedata != data->iov_base)) + memcpy(nodedata, data->iov_base, data->iov_len); + } else { + memcpy(nodedata, &largepage->mp_pgno, sizeof(pgno_t)); + nodedata = PAGEDATA(largepage); + if (unlikely(flags & MDBX_RESERVE)) + data->iov_base = nodedata; + else if (likely(nodedata != data->iov_base)) + memcpy(nodedata, data->iov_base, data->iov_len); + } + + mdbx_cassert(mc, + mp->mp_upper >= mp->mp_lower && + PAGEHDRSZ + mp->mp_upper <= mc->mc_txn->mt_env->me_psize); + return MDBX_SUCCESS; +} + +/* Delete the specified node from a page. + * [in] mc Cursor pointing to the node to delete. + * [in] ksize The size of a node. Only used if the page is + * part of a MDBX_DUPFIXED database. */ +static void mdbx_node_del(MDBX_cursor *mc, size_t ksize) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + indx_t indx = mc->mc_ki[mc->mc_top]; + indx_t i, j, numkeys, ptr; + MDBX_node *node; + char *base; + + mdbx_debug("delete node %u on %s page %" PRIaPGNO, indx, + IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno); + numkeys = NUMKEYS(mp); + mdbx_cassert(mc, indx < numkeys); + + if (IS_LEAF2(mp)) { + mdbx_cassert(mc, ksize >= sizeof(indx_t)); + unsigned diff = numkeys - 1 - indx; + base = LEAF2KEY(mp, indx, ksize); + if (diff) + memmove(base, base + ksize, diff * ksize); + mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t)); + mp->mp_lower -= sizeof(indx_t); + mdbx_cassert(mc, + (size_t)UINT16_MAX - mp->mp_upper >= ksize - sizeof(indx_t)); + mp->mp_upper += (indx_t)(ksize - sizeof(indx_t)); + return; + } + + node = NODEPTR(mp, indx); + size_t sz = NODESIZE + node->mn_ksize; + if (IS_LEAF(mp)) { + if (F_ISSET(node->mn_flags, F_BIGDATA)) + sz += sizeof(pgno_t); + else + sz += NODEDSZ(node); + } + sz = EVEN(sz); + + ptr = mp->mp_ptrs[indx]; + for (i = j = 0; i < numkeys; i++) { + if (i != indx) { + mp->mp_ptrs[j] = mp->mp_ptrs[i]; + if (mp->mp_ptrs[i] < ptr) { + mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_ptrs[j] >= sz); + mp->mp_ptrs[j] += (indx_t)sz; + } + j++; + } + } + + base = (char *)mp + mp->mp_upper + PAGEHDRSZ; + memmove(base + sz, base, ptr - mp->mp_upper); + + mdbx_cassert(mc, mp->mp_lower >= sizeof(indx_t)); + mp->mp_lower -= sizeof(indx_t); + mdbx_cassert(mc, (size_t)UINT16_MAX - mp->mp_upper >= sz); + mp->mp_upper += (indx_t)sz; +} + +/* Compact the main page after deleting a node on a subpage. + * [in] mp The main page to operate on. + * [in] indx The index of the subpage on the main page. */ +static void mdbx_node_shrink(MDBX_page *mp, unsigned indx) { + MDBX_node *node; + MDBX_page *sp, *xp; + char *base; + size_t nsize, delta, len, ptr; + int i; + + node = NODEPTR(mp, indx); + sp = (MDBX_page *)NODEDATA(node); + delta = SIZELEFT(sp); + assert(delta > 0); + + /* Prepare to shift upward, set len = length(subpage part to shift) */ + if (IS_LEAF2(sp)) { + delta &= /* do not make the node uneven-sized */ ~1u; + if (unlikely(delta) == 0) + return; + nsize = NODEDSZ(node) - delta; + assert(nsize % 1 == 0); + len = nsize; + } else { + xp = (MDBX_page *)((char *)sp + delta); /* destination subpage */ + for (i = NUMKEYS(sp); --i >= 0;) { + assert(sp->mp_ptrs[i] >= delta); + xp->mp_ptrs[i] = (indx_t)(sp->mp_ptrs[i] - delta); + } + nsize = NODEDSZ(node) - delta; + len = PAGEHDRSZ; + } + sp->mp_upper = sp->mp_lower; + sp->mp_pgno = mp->mp_pgno; + SETDSZ(node, nsize); + + /* Shift upward */ + base = (char *)mp + mp->mp_upper + PAGEHDRSZ; + memmove(base + delta, base, (char *)sp + len - base); + + ptr = mp->mp_ptrs[indx]; + for (i = NUMKEYS(mp); --i >= 0;) { + if (mp->mp_ptrs[i] <= ptr) { + assert((size_t)UINT16_MAX - mp->mp_ptrs[i] >= delta); + mp->mp_ptrs[i] += (indx_t)delta; + } + } + assert((size_t)UINT16_MAX - mp->mp_upper >= delta); + mp->mp_upper += (indx_t)delta; +} + +/* Initial setup of a sorted-dups cursor. + * + * Sorted duplicates are implemented as a sub-database for the given key. + * The duplicate data items are actually keys of the sub-database. + * Operations on the duplicate data items are performed using a sub-cursor + * initialized when the sub-database is first accessed. This function does + * the preliminary setup of the sub-cursor, filling in the fields that + * depend only on the parent DB. + * + * [in] mc The main cursor whose sorted-dups cursor is to be initialized. */ +static int mdbx_xcursor_init0(MDBX_cursor *mc) { + MDBX_xcursor *mx = mc->mc_xcursor; + if (unlikely(mx == nullptr)) + return MDBX_CORRUPTED; + + mx->mx_cursor.mc_xcursor = NULL; + mx->mx_cursor.mc_txn = mc->mc_txn; + mx->mx_cursor.mc_db = &mx->mx_db; + mx->mx_cursor.mc_dbx = &mx->mx_dbx; + mx->mx_cursor.mc_dbi = mc->mc_dbi; + mx->mx_cursor.mc_dbflag = &mx->mx_dbflag; + mx->mx_cursor.mc_snum = 0; + mx->mx_cursor.mc_top = 0; + mx->mx_cursor.mc_flags = C_SUB; + mx->mx_dbx.md_name.iov_len = 0; + mx->mx_dbx.md_name.iov_base = NULL; + mx->mx_dbx.md_cmp = mc->mc_dbx->md_dcmp; + mx->mx_dbx.md_dcmp = NULL; + return MDBX_SUCCESS; +} + +/* Final setup of a sorted-dups cursor. + * Sets up the fields that depend on the data from the main cursor. + * [in] mc The main cursor whose sorted-dups cursor is to be initialized. + * [in] node The data containing the MDBX_db record for the sorted-dup database. + */ +static int mdbx_xcursor_init1(MDBX_cursor *mc, MDBX_node *node) { + MDBX_xcursor *mx = mc->mc_xcursor; + if (unlikely(mx == nullptr)) + return MDBX_CORRUPTED; + + if (node->mn_flags & F_SUBDATA) { + memcpy(&mx->mx_db, NODEDATA(node), sizeof(MDBX_db)); + mx->mx_cursor.mc_pg[0] = 0; + mx->mx_cursor.mc_snum = 0; + mx->mx_cursor.mc_top = 0; + mx->mx_cursor.mc_flags = C_SUB; + } else { + MDBX_page *fp = NODEDATA(node); + mx->mx_db.md_xsize = 0; + mx->mx_db.md_flags = 0; + mx->mx_db.md_depth = 1; + mx->mx_db.md_branch_pages = 0; + mx->mx_db.md_leaf_pages = 1; + mx->mx_db.md_overflow_pages = 0; + mx->mx_db.md_entries = NUMKEYS(fp); + mx->mx_db.md_root = fp->mp_pgno; + mx->mx_cursor.mc_snum = 1; + mx->mx_cursor.mc_top = 0; + mx->mx_cursor.mc_flags = C_INITIALIZED | C_SUB; + mx->mx_cursor.mc_pg[0] = fp; + mx->mx_cursor.mc_ki[0] = 0; + if (mc->mc_db->md_flags & MDBX_DUPFIXED) { + mx->mx_db.md_flags = MDBX_DUPFIXED; + mx->mx_db.md_xsize = fp->mp_leaf2_ksize; + if (mc->mc_db->md_flags & MDBX_INTEGERDUP) + mx->mx_db.md_flags |= MDBX_INTEGERKEY; + } + } + mdbx_debug("Sub-db -%u root page %" PRIaPGNO, mx->mx_cursor.mc_dbi, + mx->mx_db.md_root); + mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA; + /* FIXME: #if UINT_MAX < SIZE_MAX + if (mx->mx_dbx.md_cmp == mdbx_cmp_int && mx->mx_db.md_pad == + sizeof(size_t)) + mx->mx_dbx.md_cmp = mdbx_cmp_clong; + #endif */ + + return MDBX_SUCCESS; +} + +/* Fixup a sorted-dups cursor due to underlying update. + * Sets up some fields that depend on the data from the main cursor. + * Almost the same as init1, but skips initialization steps if the + * xcursor had already been used. + * [in] mc The main cursor whose sorted-dups cursor is to be fixed up. + * [in] src_mx The xcursor of an up-to-date cursor. + * [in] new_dupdata True if converting from a non-F_DUPDATA item. */ +static int mdbx_xcursor_init2(MDBX_cursor *mc, MDBX_xcursor *src_mx, + int new_dupdata) { + MDBX_xcursor *mx = mc->mc_xcursor; + if (unlikely(mx == nullptr)) + return MDBX_CORRUPTED; + + if (new_dupdata) { + mx->mx_cursor.mc_snum = 1; + mx->mx_cursor.mc_top = 0; + mx->mx_cursor.mc_flags |= C_INITIALIZED; + mx->mx_cursor.mc_ki[0] = 0; + mx->mx_dbflag = DB_VALID | DB_USRVALID | DB_DUPDATA; + mx->mx_dbx.md_cmp = src_mx->mx_dbx.md_cmp; + } else if (!(mx->mx_cursor.mc_flags & C_INITIALIZED)) { + return MDBX_SUCCESS; + } + mx->mx_db = src_mx->mx_db; + mx->mx_cursor.mc_pg[0] = src_mx->mx_cursor.mc_pg[0]; + mdbx_debug("Sub-db -%u root page %" PRIaPGNO, mx->mx_cursor.mc_dbi, + mx->mx_db.md_root); + return MDBX_SUCCESS; +} + +/* Initialize a cursor for a given transaction and database. */ +static int mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, MDBX_dbi dbi) { + mc->mc_signature = MDBX_MC_SIGNATURE; + mc->mc_next = NULL; + mc->mc_backup = NULL; + mc->mc_dbi = dbi; + mc->mc_txn = txn; + mc->mc_db = &txn->mt_dbs[dbi]; + mc->mc_dbx = &txn->mt_dbxs[dbi]; + mc->mc_dbflag = &txn->mt_dbflags[dbi]; + mc->mc_snum = 0; + mc->mc_top = 0; + mc->mc_pg[0] = 0; + mc->mc_flags = 0; + mc->mc_ki[0] = 0; + mc->mc_xcursor = NULL; + + if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) { + STATIC_ASSERT(offsetof(MDBX_cursor_couple, outer) == 0); + MDBX_xcursor *mx = &container_of(mc, MDBX_cursor_couple, outer)->inner; + mdbx_tassert(txn, mx != NULL); + mx->mx_cursor.mc_signature = MDBX_MC_SIGNATURE; + mc->mc_xcursor = mx; + int rc = mdbx_xcursor_init0(mc); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + int rc = MDBX_SUCCESS; + if (unlikely(*mc->mc_dbflag & DB_STALE)) { + rc = mdbx_page_search(mc, NULL, MDBX_PS_ROOTONLY); + rc = (rc != MDBX_NOTFOUND) ? rc : MDBX_SUCCESS; + } + return rc; +} + +int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) { + if (unlikely(!ret || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + if (unlikely(dbi == FREE_DBI && !F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))) + return MDBX_EINVAL; + + const size_t size = (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) + ? sizeof(MDBX_cursor_couple) + : sizeof(MDBX_cursor); + + MDBX_cursor *mc; + if (likely((mc = mdbx_malloc(size)) != NULL)) { + int rc = mdbx_cursor_init(mc, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_free(mc); + return rc; + } + if (txn->mt_cursors) { + mc->mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = mc; + mc->mc_flags |= C_UNTRACK; + } + } else { + return MDBX_ENOMEM; + } + + *ret = mc; + return MDBX_SUCCESS; +} + +int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) { + if (unlikely(!mc || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return txn->mt_owner ? MDBX_THREAD_MISMATCH : MDBX_BAD_TXN; + + if (unlikely(txn->mt_flags & (MDBX_TXN_FINISHED | MDBX_TXN_ERROR))) + return MDBX_BAD_TXN; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE && + mc->mc_signature != MDBX_MC_READY4CLOSE)) + return MDBX_EINVAL; + + if (unlikely(!TXN_DBI_EXIST(txn, mc->mc_dbi, DB_VALID))) + return MDBX_EINVAL; + + if (unlikely(mc->mc_backup)) + return MDBX_EINVAL; + + if (unlikely((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)) { + MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; + while (*prev && *prev != mc) + prev = &(*prev)->mc_next; + if (*prev == mc) + *prev = mc->mc_next; + mc->mc_signature = MDBX_MC_READY4CLOSE; + } + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + return mdbx_cursor_init(mc, txn, mc->mc_dbi); +} + +/* Return the count of duplicate data items for the current key */ +int mdbx_cursor_count(MDBX_cursor *mc, size_t *countp) { + if (unlikely(mc == NULL || countp == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(mc->mc_txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + if (unlikely(!(mc->mc_flags & C_INITIALIZED))) + return MDBX_EINVAL; + + if (!mc->mc_snum) { + *countp = 0; + return MDBX_NOTFOUND; + } + + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + if ((mc->mc_flags & C_EOF) && mc->mc_ki[mc->mc_top] >= NUMKEYS(mp)) { + *countp = 0; + return MDBX_NOTFOUND; + } + + *countp = 1; + if (mc->mc_xcursor != NULL) { + MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdbx_cassert(mc, mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags & + C_INITIALIZED)); + *countp = unlikely(mc->mc_xcursor->mx_db.md_entries > PTRDIFF_MAX) + ? PTRDIFF_MAX + : (size_t)mc->mc_xcursor->mx_db.md_entries; + } + } + return MDBX_SUCCESS; +} + +void mdbx_cursor_close(MDBX_cursor *mc) { + if (mc) { + mdbx_ensure(NULL, mc->mc_signature == MDBX_MC_SIGNATURE || + mc->mc_signature == MDBX_MC_READY4CLOSE); + if (!mc->mc_backup) { + /* Remove from txn, if tracked. + * A read-only txn (!C_UNTRACK) may have been freed already, + * so do not peek inside it. Only write txns track cursors. */ + if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { + MDBX_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; + while (*prev && *prev != mc) + prev = &(*prev)->mc_next; + if (*prev == mc) + *prev = mc->mc_next; + } + mc->mc_signature = 0; + mdbx_free(mc); + } else { + /* cursor closed before nested txn ends */ + mdbx_cassert(mc, mc->mc_signature == MDBX_MC_SIGNATURE); + mc->mc_signature = MDBX_MC_WAIT4EOT; + } + } +} + +MDBX_txn *mdbx_cursor_txn(MDBX_cursor *mc) { + if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE)) + return NULL; + MDBX_txn *txn = mc->mc_txn; + if (unlikely(!txn || txn->mt_signature != MDBX_MT_SIGNATURE)) + return NULL; + if (unlikely(txn->mt_flags & MDBX_TXN_FINISHED)) + return NULL; + return txn; +} + +MDBX_dbi mdbx_cursor_dbi(MDBX_cursor *mc) { + if (unlikely(!mc || mc->mc_signature != MDBX_MC_SIGNATURE)) + return UINT_MAX; + return mc->mc_dbi; +} + +/* Replace the key for a branch node with a new key. + * Set MDBX_TXN_ERROR on failure. + * [in] mc Cursor pointing to the node to operate on. + * [in] key The new key to use. + * Returns 0 on success, non-zero on failure. */ +static int mdbx_update_key(MDBX_cursor *mc, const MDBX_val *key) { + MDBX_page *mp; + MDBX_node *node; + char *base; + size_t len; + int delta, ksize, oksize; + indx_t ptr, i, numkeys, indx; + DKBUF; + + indx = mc->mc_ki[mc->mc_top]; + mp = mc->mc_pg[mc->mc_top]; + node = NODEPTR(mp, indx); + ptr = mp->mp_ptrs[indx]; + if (MDBX_DEBUG) { + MDBX_val k2; + char kbuf2[DKBUF_MAXKEYSIZE * 2 + 1]; + k2.iov_base = NODEKEY(node); + k2.iov_len = node->mn_ksize; + mdbx_debug("update key %u (ofs %u) [%s] to [%s] on page %" PRIaPGNO, indx, + ptr, mdbx_dkey(&k2, kbuf2, sizeof(kbuf2)), DKEY(key), + mp->mp_pgno); + } + + /* Sizes must be 2-byte aligned. */ + ksize = EVEN(key->iov_len); + oksize = EVEN(node->mn_ksize); + delta = ksize - oksize; + + /* Shift node contents if EVEN(key length) changed. */ + if (delta) { + if (SIZELEFT(mp) < delta) { + /* not enough space left, do a delete and split */ + mdbx_debug("Not enough room, delta = %d, splitting...", delta); + pgno_t pgno = NODEPGNO(node); + mdbx_node_del(mc, 0); + int rc = mdbx_page_split(mc, key, NULL, pgno, MDBX_SPLIT_REPLACE); + if (rc == MDBX_SUCCESS && mdbx_audit_enabled()) + rc = mdbx_cursor_check(mc, true); + return rc; + } + + numkeys = NUMKEYS(mp); + for (i = 0; i < numkeys; i++) { + if (mp->mp_ptrs[i] <= ptr) { + mdbx_cassert(mc, mp->mp_ptrs[i] >= delta); + mp->mp_ptrs[i] -= (indx_t)delta; + } + } + + base = (char *)mp + mp->mp_upper + PAGEHDRSZ; + len = ptr - mp->mp_upper + NODESIZE; + memmove(base - delta, base, len); + mdbx_cassert(mc, mp->mp_upper >= delta); + mp->mp_upper -= (indx_t)delta; + + node = NODEPTR(mp, indx); + } + + /* But even if no shift was needed, update ksize */ + if (node->mn_ksize != key->iov_len) + node->mn_ksize = (uint16_t)key->iov_len; + + memcpy(NODEKEY(node), key->iov_base, key->iov_len); + return MDBX_SUCCESS; +} + +static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst); + +/* Move a node from csrc to cdst. */ +static int mdbx_node_move(MDBX_cursor *csrc, MDBX_cursor *cdst, int fromleft) { + int rc; + DKBUF; + + /* Mark src and dst as dirty. */ + if (unlikely((rc = mdbx_page_touch(csrc)) || (rc = mdbx_page_touch(cdst)))) + return rc; + + MDBX_page *const psrc = csrc->mc_pg[csrc->mc_top]; + MDBX_page *const pdst = cdst->mc_pg[cdst->mc_top]; + mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); + mdbx_cassert(csrc, csrc->mc_dbi == cdst->mc_dbi); + mdbx_cassert(csrc, csrc->mc_top == cdst->mc_top); + if (unlikely(PAGETYPE(psrc) != PAGETYPE(pdst))) { + bailout: + csrc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return MDBX_PROBLEM; + } + + MDBX_val key4move; + switch (PAGETYPE(psrc)) { + case P_BRANCH: { + const MDBX_node *srcnode = NODEPTR(psrc, csrc->mc_ki[csrc->mc_top]); + mdbx_cassert(csrc, srcnode->mn_flags == 0); + const pgno_t srcpg = NODEPGNO(srcnode); + key4move.iov_len = NODEKSZ(srcnode); + key4move.iov_base = NODEKEY(srcnode); + if (csrc->mc_ki[csrc->mc_top] == 0) { + const uint16_t snum = csrc->mc_snum; + mdbx_cassert(csrc, snum > 0); + /* must find the lowest key below src */ + rc = mdbx_page_search_lowest(csrc); + MDBX_page *psrc2 = csrc->mc_pg[csrc->mc_top]; + if (unlikely(rc)) + return rc; + mdbx_cassert(csrc, IS_LEAF(psrc2)); + if (unlikely(!IS_LEAF(psrc2))) + goto bailout; + if (IS_LEAF2(psrc2)) { + key4move.iov_len = csrc->mc_db->md_xsize; + key4move.iov_base = LEAF2KEY(psrc2, 0, key4move.iov_len); + } else { + const MDBX_node *s2 = NODEPTR(psrc2, 0); + key4move.iov_len = NODEKSZ(s2); + key4move.iov_base = NODEKEY(s2); + } + csrc->mc_snum = snum; + csrc->mc_top = snum - 1; + csrc->mc_ki[csrc->mc_top] = 0; + /* paranoia */ + mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); + mdbx_cassert(csrc, IS_BRANCH(psrc)); + if (unlikely(!IS_BRANCH(psrc))) + goto bailout; + } + + if (cdst->mc_ki[cdst->mc_top] == 0) { + const uint16_t snum = cdst->mc_snum; + mdbx_cassert(csrc, snum > 0); + MDBX_cursor mn; + mdbx_cursor_copy(cdst, &mn); + mn.mc_xcursor = NULL; + /* must find the lowest key below dst */ + rc = mdbx_page_search_lowest(&mn); + if (unlikely(rc)) + return rc; + MDBX_page *const pdst2 = mn.mc_pg[mn.mc_top]; + mdbx_cassert(cdst, IS_LEAF(pdst2)); + if (unlikely(!IS_LEAF(pdst2))) + goto bailout; + MDBX_val key; + if (IS_LEAF2(pdst2)) { + key.iov_len = mn.mc_db->md_xsize; + key.iov_base = LEAF2KEY(pdst2, 0, key.iov_len); + } else { + MDBX_node *s2 = NODEPTR(pdst2, 0); + key.iov_len = NODEKSZ(s2); + key.iov_base = NODEKEY(s2); + } + mn.mc_snum = snum; + mn.mc_top = snum - 1; + mn.mc_ki[mn.mc_top] = 0; + rc = mdbx_update_key(&mn, &key); + if (unlikely(rc)) + return rc; + } + + mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO + " to node %u on page %" PRIaPGNO, + "branch", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), + psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); + /* Add the node to the destination page. */ + rc = + mdbx_node_add_branch(cdst, cdst->mc_ki[cdst->mc_top], &key4move, srcpg); + } break; + + case P_LEAF: { + const MDBX_node *srcnode = NODEPTR(psrc, csrc->mc_ki[csrc->mc_top]); + MDBX_val data; + data.iov_len = NODEDSZ(srcnode); + data.iov_base = NODEDATA(srcnode); + key4move.iov_len = NODEKSZ(srcnode); + key4move.iov_base = NODEKEY(srcnode); + mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO + " to node %u on page %" PRIaPGNO, + "leaf", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), + psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); + /* Add the node to the destination page. */ + rc = mdbx_node_add_leaf(cdst, cdst->mc_ki[cdst->mc_top], &key4move, &data, + srcnode->mn_flags); + } break; + + case P_LEAF | P_LEAF2: { + key4move.iov_len = csrc->mc_db->md_xsize; + key4move.iov_base = + LEAF2KEY(psrc, csrc->mc_ki[csrc->mc_top], key4move.iov_len); + mdbx_debug("moving %s-node %u [%s] on page %" PRIaPGNO + " to node %u on page %" PRIaPGNO, + "leaf2", csrc->mc_ki[csrc->mc_top], DKEY(&key4move), + psrc->mp_pgno, cdst->mc_ki[cdst->mc_top], pdst->mp_pgno); + /* Add the node to the destination page. */ + rc = mdbx_node_add_leaf2(cdst, cdst->mc_ki[cdst->mc_top], &key4move); + } break; + + default: + goto bailout; + } + + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + /* Delete the node from the source page. */ + mdbx_node_del(csrc, key4move.iov_len); + + mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); + mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); + mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); + + { + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2, *m3; + const MDBX_dbi dbi = csrc->mc_dbi; + mdbx_cassert(csrc, csrc->mc_top == cdst->mc_top); + if (fromleft) { + /* If we're adding on the left, bump others up */ + for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) + continue; + if (m3 != cdst && m3->mc_pg[csrc->mc_top] == pdst && + m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) { + m3->mc_ki[csrc->mc_top]++; + } + if (m3 != csrc && m3->mc_pg[csrc->mc_top] == psrc && + m3->mc_ki[csrc->mc_top] == csrc->mc_ki[csrc->mc_top]) { + m3->mc_pg[csrc->mc_top] = pdst; + m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; + mdbx_cassert(csrc, csrc->mc_top > 0); + m3->mc_ki[csrc->mc_top - 1]++; + } + if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) + XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], m3->mc_ki[csrc->mc_top]); + } + } else { + /* Adding on the right, bump others down */ + for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == csrc) + continue; + if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top) + continue; + if (m3->mc_pg[csrc->mc_top] == psrc) { + if (!m3->mc_ki[csrc->mc_top]) { + m3->mc_pg[csrc->mc_top] = pdst; + m3->mc_ki[csrc->mc_top] = cdst->mc_ki[cdst->mc_top]; + mdbx_cassert(csrc, csrc->mc_top > 0); + m3->mc_ki[csrc->mc_top - 1]--; + } else { + m3->mc_ki[csrc->mc_top]--; + } + if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) + XCURSOR_REFRESH(m3, m3->mc_pg[csrc->mc_top], + m3->mc_ki[csrc->mc_top]); + } + } + } + } + + /* Update the parent separators. */ + if (csrc->mc_ki[csrc->mc_top] == 0) { + mdbx_cassert(csrc, csrc->mc_top > 0); + if (csrc->mc_ki[csrc->mc_top - 1] != 0) { + MDBX_val key; + if (IS_LEAF2(psrc)) { + key.iov_len = psrc->mp_leaf2_ksize; + key.iov_base = LEAF2KEY(psrc, 0, key.iov_len); + } else { + MDBX_node *srcnode = NODEPTR(psrc, 0); + key.iov_len = NODEKSZ(srcnode); + key.iov_base = NODEKEY(srcnode); + } + mdbx_debug("update separator for source page %" PRIaPGNO " to [%s]", + psrc->mp_pgno, DKEY(&key)); + MDBX_cursor mn; + mdbx_cursor_copy(csrc, &mn); + mn.mc_xcursor = NULL; + mdbx_cassert(csrc, mn.mc_snum > 0); + mn.mc_snum--; + mn.mc_top--; + /* We want mdbx_rebalance to find mn when doing fixups */ + WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + if (IS_BRANCH(psrc)) { + const MDBX_val nullkey = {0, 0}; + const indx_t ix = csrc->mc_ki[csrc->mc_top]; + csrc->mc_ki[csrc->mc_top] = 0; + rc = mdbx_update_key(csrc, &nullkey); + csrc->mc_ki[csrc->mc_top] = ix; + mdbx_cassert(csrc, rc == MDBX_SUCCESS); + } + } + + if (cdst->mc_ki[cdst->mc_top] == 0) { + mdbx_cassert(cdst, cdst->mc_top > 0); + if (cdst->mc_ki[cdst->mc_top - 1] != 0) { + MDBX_val key; + if (IS_LEAF2(pdst)) { + key.iov_len = pdst->mp_leaf2_ksize; + key.iov_base = LEAF2KEY(pdst, 0, key.iov_len); + } else { + MDBX_node *srcnode = NODEPTR(pdst, 0); + key.iov_len = NODEKSZ(srcnode); + key.iov_base = NODEKEY(srcnode); + } + mdbx_debug("update separator for destination page %" PRIaPGNO " to [%s]", + pdst->mp_pgno, DKEY(&key)); + MDBX_cursor mn; + mdbx_cursor_copy(cdst, &mn); + mn.mc_xcursor = NULL; + mdbx_cassert(cdst, mn.mc_snum > 0); + mn.mc_snum--; + mn.mc_top--; + /* We want mdbx_rebalance to find mn when doing fixups */ + WITH_CURSOR_TRACKING(mn, rc = mdbx_update_key(&mn, &key)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + if (IS_BRANCH(pdst)) { + const MDBX_val nullkey = {0, 0}; + const indx_t ix = cdst->mc_ki[cdst->mc_top]; + cdst->mc_ki[cdst->mc_top] = 0; + rc = mdbx_update_key(cdst, &nullkey); + cdst->mc_ki[cdst->mc_top] = ix; + mdbx_cassert(cdst, rc == MDBX_SUCCESS); + } + } + + return MDBX_SUCCESS; +} + +/* Merge one page into another. + * + * The nodes from the page pointed to by csrc will be copied to the page + * pointed to by cdst and then the csrc page will be freed. + * + * [in] csrc Cursor pointing to the source page. + * [in] cdst Cursor pointing to the destination page. + * + * Returns 0 on success, non-zero on failure. */ +static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) { + MDBX_node *srcnode; + MDBX_val key; + int rc; + + mdbx_cassert(csrc, csrc != cdst); + + /* Mark dst as dirty. */ + if (unlikely(rc = mdbx_page_touch(cdst))) + return rc; + + MDBX_page *const psrc = csrc->mc_pg[csrc->mc_top]; + MDBX_page *const pdst = cdst->mc_pg[cdst->mc_top]; + + mdbx_debug("merging page %" PRIaPGNO " into %" PRIaPGNO, psrc->mp_pgno, + pdst->mp_pgno); + + mdbx_cassert(csrc, PAGETYPE(psrc) == PAGETYPE(pdst)); + mdbx_cassert(csrc, + csrc->mc_dbi == cdst->mc_dbi && csrc->mc_db == cdst->mc_db); + mdbx_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */ + mdbx_cassert(cdst, cdst->mc_snum > 1); + mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || + IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); + mdbx_cassert(csrc, csrc->mc_snum < csrc->mc_db->md_depth || + IS_LEAF(csrc->mc_pg[csrc->mc_db->md_depth - 1])); + const int pagetype = PAGETYPE(psrc); + + /* Move all nodes from src to dst */ + const unsigned nkeys = NUMKEYS(pdst); + unsigned j = nkeys; + if (unlikely(pagetype & P_LEAF2)) { + key.iov_len = csrc->mc_db->md_xsize; + key.iov_base = PAGEDATA(psrc); + for (unsigned i = 0; i < NUMKEYS(psrc); i++, j++) { + rc = mdbx_node_add_leaf2(cdst, j, &key); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + key.iov_base = (char *)key.iov_base + key.iov_len; + } + } else { + for (unsigned i = 0; i < NUMKEYS(psrc); i++, j++) { + srcnode = NODEPTR(psrc, i); + if (i == 0 && (pagetype & P_BRANCH)) { + MDBX_cursor mn; + mdbx_cursor_copy(csrc, &mn); + mn.mc_xcursor = NULL; + /* must find the lowest key below src */ + rc = mdbx_page_search_lowest(&mn); + if (unlikely(rc)) + return rc; + if (IS_LEAF2(mn.mc_pg[mn.mc_top])) { + key.iov_len = mn.mc_db->md_xsize; + key.iov_base = LEAF2KEY(mn.mc_pg[mn.mc_top], 0, key.iov_len); + } else { + MDBX_node *s2 = NODEPTR(mn.mc_pg[mn.mc_top], 0); + key.iov_len = NODEKSZ(s2); + key.iov_base = NODEKEY(s2); + } + } else { + key.iov_len = srcnode->mn_ksize; + key.iov_base = NODEKEY(srcnode); + } + + if (pagetype & P_LEAF) { + MDBX_val data; + data.iov_len = NODEDSZ(srcnode); + data.iov_base = NODEDATA(srcnode); + rc = mdbx_node_add_leaf(cdst, j, &key, &data, srcnode->mn_flags); + } else { + mdbx_cassert(csrc, srcnode->mn_flags == 0); + rc = mdbx_node_add_branch(cdst, j, &key, NODEPGNO(srcnode)); + } + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + } + + mdbx_debug("dst page %" PRIaPGNO " now has %u keys (%.1f%% filled)", + pdst->mp_pgno, NUMKEYS(pdst), + PAGEFILL(cdst->mc_txn->mt_env, pdst) / 10.24); + + mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); + mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); + + /* Unlink the src page from parent and add to free list. */ + csrc->mc_top--; + mdbx_node_del(csrc, 0); + if (csrc->mc_ki[csrc->mc_top] == 0) { + const MDBX_val nullkey = {0, 0}; + rc = mdbx_update_key(csrc, &nullkey); + if (unlikely(rc)) { + csrc->mc_top++; + return rc; + } + } + csrc->mc_top++; + + mdbx_cassert(csrc, psrc == csrc->mc_pg[csrc->mc_top]); + mdbx_cassert(cdst, pdst == cdst->mc_pg[cdst->mc_top]); + + { + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2, *m3; + const MDBX_dbi dbi = csrc->mc_dbi; + const unsigned top = csrc->mc_top; + + for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (csrc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == csrc || top >= m3->mc_snum) + continue; + if (m3->mc_pg[top] == psrc) { + m3->mc_pg[top] = pdst; + mdbx_cassert(m3, nkeys + m3->mc_ki[top] <= UINT16_MAX); + m3->mc_ki[top] += (indx_t)nkeys; + m3->mc_ki[top - 1] = cdst->mc_ki[top - 1]; + } else if (m3->mc_pg[top - 1] == csrc->mc_pg[top - 1] && + m3->mc_ki[top - 1] > csrc->mc_ki[top - 1]) { + m3->mc_ki[top - 1]--; + } + if (XCURSOR_INITED(m3) && IS_LEAF(psrc)) + XCURSOR_REFRESH(m3, m3->mc_pg[top], m3->mc_ki[top]); + } + } + + /* If not operating on FreeDB, allow this page to be reused + * in this txn. Otherwise just add to free list. */ + rc = mdbx_page_loose(csrc, psrc); + if (unlikely(rc)) + return rc; + + mdbx_cassert(cdst, cdst->mc_db->md_entries > 0); + mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth); + mdbx_cassert(cdst, cdst->mc_top > 0); + mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1); + MDBX_page *const top_page = cdst->mc_pg[cdst->mc_top]; + const indx_t top_indx = cdst->mc_ki[cdst->mc_top]; + const uint16_t save_snum = cdst->mc_snum; + const uint16_t save_depth = cdst->mc_db->md_depth; + mdbx_cursor_pop(cdst); + rc = mdbx_rebalance(cdst); + if (unlikely(rc)) + return rc; + + mdbx_cassert(cdst, cdst->mc_db->md_entries > 0); + mdbx_cassert(cdst, cdst->mc_snum <= cdst->mc_db->md_depth); + mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1); + + if (IS_LEAF(cdst->mc_pg[cdst->mc_top])) { + /* LY: don't touch cursor if top-page is a LEAF */ + mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || + PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); + return MDBX_SUCCESS; + } + + if (pagetype != PAGETYPE(top_page)) { + /* LY: LEAF-page becomes BRANCH, unable restore cursor's stack */ + goto bailout; + } + + if (top_page == cdst->mc_pg[cdst->mc_top]) { + /* LY: don't touch cursor if prev top-page already on the top */ + mdbx_cassert(cdst, cdst->mc_ki[cdst->mc_top] == top_indx); + mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || + PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); + return MDBX_SUCCESS; + } + + const int new_snum = save_snum - save_depth + cdst->mc_db->md_depth; + if (unlikely(new_snum < 1 || new_snum > cdst->mc_db->md_depth)) { + /* LY: out of range, unable restore cursor's stack */ + goto bailout; + } + + if (top_page == cdst->mc_pg[new_snum - 1]) { + mdbx_cassert(cdst, cdst->mc_ki[new_snum - 1] == top_indx); + /* LY: restore cursor stack */ + cdst->mc_snum = (uint16_t)new_snum; + cdst->mc_top = (uint16_t)new_snum - 1; + mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || + IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); + mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || + PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); + return MDBX_SUCCESS; + } + + MDBX_page *const stub_page = (MDBX_page *)(~(uintptr_t)top_page); + const indx_t stub_indx = top_indx; + if (save_depth > cdst->mc_db->md_depth && + ((cdst->mc_pg[save_snum - 1] == top_page && + cdst->mc_ki[save_snum - 1] == top_indx) || + (cdst->mc_pg[save_snum - 1] == stub_page && + cdst->mc_ki[save_snum - 1] == stub_indx))) { + /* LY: restore cursor stack */ + cdst->mc_pg[new_snum - 1] = top_page; + cdst->mc_ki[new_snum - 1] = top_indx; + cdst->mc_pg[new_snum] = (MDBX_page *)(~(uintptr_t)cdst->mc_pg[new_snum]); + cdst->mc_ki[new_snum] = ~cdst->mc_ki[new_snum]; + cdst->mc_snum = (uint16_t)new_snum; + cdst->mc_top = (uint16_t)new_snum - 1; + mdbx_cassert(cdst, cdst->mc_snum < cdst->mc_db->md_depth || + IS_LEAF(cdst->mc_pg[cdst->mc_db->md_depth - 1])); + mdbx_cassert(cdst, IS_LEAF(cdst->mc_pg[cdst->mc_top]) || + PAGETYPE(cdst->mc_pg[cdst->mc_top]) == pagetype); + return MDBX_SUCCESS; + } + +bailout: + /* LY: unable restore cursor's stack */ + cdst->mc_flags &= ~C_INITIALIZED; + return MDBX_CURSOR_FULL; +} + +/* Copy the contents of a cursor. + * [in] csrc The cursor to copy from. + * [out] cdst The cursor to copy to. */ +static void mdbx_cursor_copy(const MDBX_cursor *csrc, MDBX_cursor *cdst) { + unsigned i; + + mdbx_cassert(csrc, + csrc->mc_txn->mt_txnid >= *csrc->mc_txn->mt_env->me_oldest); + cdst->mc_txn = csrc->mc_txn; + cdst->mc_dbi = csrc->mc_dbi; + cdst->mc_db = csrc->mc_db; + cdst->mc_dbx = csrc->mc_dbx; + cdst->mc_snum = csrc->mc_snum; + cdst->mc_top = csrc->mc_top; + cdst->mc_flags = csrc->mc_flags; + + for (i = 0; i < csrc->mc_snum; i++) { + cdst->mc_pg[i] = csrc->mc_pg[i]; + cdst->mc_ki[i] = csrc->mc_ki[i]; + } +} + +/* Rebalance the tree after a delete operation. + * [in] mc Cursor pointing to the page where rebalancing should begin. + * Returns 0 on success, non-zero on failure. */ +static int mdbx_rebalance(MDBX_cursor *mc) { + MDBX_node *node; + int rc; + unsigned minkeys, thresh; + + mdbx_cassert(mc, mc->mc_snum > 0); + mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || + IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); + const int pagetype = PAGETYPE(mc->mc_pg[mc->mc_top]); + if (pagetype == P_BRANCH) { + minkeys = 2; + thresh = 1; + } else { + minkeys = 1; + thresh = FILL_THRESHOLD; + } + mdbx_debug("rebalancing %s page %" PRIaPGNO " (has %u keys, %.1f%% full)", + (pagetype & P_LEAF) ? "leaf" : "branch", + mc->mc_pg[mc->mc_top]->mp_pgno, NUMKEYS(mc->mc_pg[mc->mc_top]), + PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10.24); + + if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= thresh && + NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) { + mdbx_debug("no need to rebalance page %" PRIaPGNO ", above fill threshold", + mc->mc_pg[mc->mc_top]->mp_pgno); + mdbx_cassert(mc, mc->mc_db->md_entries > 0); + return MDBX_SUCCESS; + } + + if (mc->mc_snum < 2) { + MDBX_page *const mp = mc->mc_pg[0]; + const unsigned nkeys = NUMKEYS(mp); + mdbx_cassert(mc, (mc->mc_db->md_entries == 0) == (nkeys == 0)); + if (IS_SUBP(mp)) { + mdbx_debug("Can't rebalance a subpage, ignoring"); + mdbx_cassert(mc, pagetype & P_LEAF); + return MDBX_SUCCESS; + } + if (nkeys == 0) { + mdbx_cassert(mc, IS_LEAF(mp)); + mdbx_debug("tree is completely empty"); + mc->mc_db->md_root = P_INVALID; + mc->mc_db->md_depth = 0; + mdbx_cassert(mc, mc->mc_db->md_branch_pages == 0 && + mc->mc_db->md_overflow_pages == 0 && + mc->mc_db->md_leaf_pages == 1); + mc->mc_db->md_leaf_pages = 0; + if (mc->mc_flags & C_SUB) + mdbx_outer_db(mc)->md_leaf_pages -= 1; + rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + /* Adjust cursors pointing to mp */ + const MDBX_dbi dbi = mc->mc_dbi; + for (MDBX_cursor *m2 = mc->mc_txn->mt_cursors[dbi]; m2; + m2 = m2->mc_next) { + MDBX_cursor *m3 = + (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc || !(m3->mc_flags & C_INITIALIZED)) + continue; + if (m3->mc_pg[0] == mp) { + m3->mc_snum = 0; + m3->mc_top = 0; + m3->mc_flags &= ~C_INITIALIZED; + } + } + mc->mc_snum = 0; + mc->mc_top = 0; + mc->mc_flags &= ~C_INITIALIZED; + } else if (IS_BRANCH(mp) && nkeys == 1) { + mdbx_debug("collapsing root page!"); + rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno); + if (unlikely(rc)) + return rc; + mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0)); + rc = mdbx_page_get(mc, mc->mc_db->md_root, &mc->mc_pg[0], NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mc->mc_db->md_depth--; + mc->mc_db->md_branch_pages--; + if (mc->mc_flags & C_SUB) + mdbx_outer_db(mc)->md_branch_pages -= 1; + mc->mc_ki[0] = mc->mc_ki[1]; + for (int i = 1; i < mc->mc_db->md_depth; i++) { + mc->mc_pg[i] = mc->mc_pg[i + 1]; + mc->mc_ki[i] = mc->mc_ki[i + 1]; + } + + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2, *m3; + MDBX_dbi dbi = mc->mc_dbi; + + for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc || !(m3->mc_flags & C_INITIALIZED)) + continue; + if (m3->mc_pg[0] == mp) { + for (int i = 0; i < mc->mc_db->md_depth; i++) { + m3->mc_pg[i] = m3->mc_pg[i + 1]; + m3->mc_ki[i] = m3->mc_ki[i + 1]; + } + m3->mc_snum--; + m3->mc_top--; + } + } + + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || + PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); + mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || + IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); + } else { + mdbx_debug("root page %" PRIaPGNO + " doesn't need rebalancing (flags 0x%x)", + mp->mp_pgno, mp->mp_flags); + } + return MDBX_SUCCESS; + } + + /* The parent (branch page) must have at least 2 pointers, + * otherwise the tree is invalid. */ + const unsigned pre_top = mc->mc_top - 1; + mdbx_cassert(mc, IS_BRANCH(mc->mc_pg[pre_top])); + mdbx_cassert(mc, !IS_SUBP(mc->mc_pg[0])); + mdbx_cassert(mc, NUMKEYS(mc->mc_pg[pre_top]) > 1); + + /* Leaf page fill factor is below the threshold. + * Try to move keys from left or right neighbor, or + * merge with a neighbor page. */ + + /* Find neighbors. */ + MDBX_cursor mn; + mdbx_cursor_copy(mc, &mn); + mn.mc_xcursor = NULL; + + indx_t oldki = mc->mc_ki[mc->mc_top]; + bool fromleft; + if (mc->mc_ki[pre_top] == 0) { + /* We're the leftmost leaf in our parent. */ + mdbx_debug("reading right neighbor"); + mn.mc_ki[pre_top]++; + node = NODEPTR(mc->mc_pg[pre_top], mn.mc_ki[pre_top]); + rc = mdbx_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mdbx_cassert(mc, PAGETYPE(mn.mc_pg[mn.mc_top]) == + PAGETYPE(mc->mc_pg[mc->mc_top])); + mn.mc_ki[mn.mc_top] = 0; + mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]); + fromleft = false; + } else { + /* There is at least one neighbor to the left. */ + mdbx_debug("reading left neighbor"); + mn.mc_ki[pre_top]--; + node = NODEPTR(mc->mc_pg[pre_top], mn.mc_ki[pre_top]); + rc = mdbx_page_get(mc, NODEPGNO(node), &mn.mc_pg[mn.mc_top], NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mdbx_cassert(mc, PAGETYPE(mn.mc_pg[mn.mc_top]) == + PAGETYPE(mc->mc_pg[mc->mc_top])); + mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1; + mc->mc_ki[mc->mc_top] = 0; + fromleft = true; + } + + mdbx_debug("found neighbor page %" PRIaPGNO " (%u keys, %.1f%% full)", + mn.mc_pg[mn.mc_top]->mp_pgno, NUMKEYS(mn.mc_pg[mn.mc_top]), + PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) / 10.24); + + /* If the neighbor page is above threshold and has enough keys, + * move one key from it. Otherwise we should try to merge them. + * (A branch page must never have less than 2 keys.) */ + if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= thresh && + NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) { + rc = mdbx_node_move(&mn, mc, fromleft); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + oldki += fromleft /* if we inserted on left, bump position up */; + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || + PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); + mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || + IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); + } else { + if (!fromleft) { + rc = mdbx_page_merge(&mn, mc); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || + PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); + mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || + IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); + } else { + oldki += NUMKEYS(mn.mc_pg[mn.mc_top]); + mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1; + /* We want mdbx_rebalance to find mn when doing fixups */ + WITH_CURSOR_TRACKING(mn, rc = mdbx_page_merge(mc, &mn)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + mdbx_cursor_copy(&mn, mc); + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]) || + PAGETYPE(mc->mc_pg[mc->mc_top]) == pagetype); + mdbx_cassert(mc, mc->mc_snum < mc->mc_db->md_depth || + IS_LEAF(mc->mc_pg[mc->mc_db->md_depth - 1])); + } + mc->mc_flags &= ~C_EOF; + } + mc->mc_ki[mc->mc_top] = oldki; + return MDBX_SUCCESS; +} + +static __cold int mdbx_cursor_check(MDBX_cursor *mc, bool pending) { + mdbx_cassert(mc, mc->mc_top == mc->mc_snum - 1); + if (unlikely(mc->mc_top != mc->mc_snum - 1)) + return MDBX_CURSOR_FULL; + mdbx_cassert(mc, pending ? mc->mc_snum <= mc->mc_db->md_depth + : mc->mc_snum == mc->mc_db->md_depth); + if (unlikely(pending ? mc->mc_snum > mc->mc_db->md_depth + : mc->mc_snum != mc->mc_db->md_depth)) + return MDBX_CURSOR_FULL; + + for (int n = 0; n < mc->mc_snum; ++n) { + MDBX_page *mp = mc->mc_pg[n]; + const unsigned numkeys = NUMKEYS(mp); + const bool expect_branch = (n < mc->mc_db->md_depth - 1) ? true : false; + const bool expect_nested_leaf = + (n + 1 == mc->mc_db->md_depth - 1) ? true : false; + const bool branch = IS_BRANCH(mp) ? true : false; + mdbx_cassert(mc, branch == expect_branch); + if (unlikely(branch != expect_branch)) + return MDBX_CURSOR_FULL; + if (!pending) { + mdbx_cassert(mc, numkeys > mc->mc_ki[n] || + (!branch && numkeys == mc->mc_ki[n] && + (mc->mc_flags & C_EOF) != 0)); + if (unlikely(numkeys <= mc->mc_ki[n] && + !(!branch && numkeys == mc->mc_ki[n] && + (mc->mc_flags & C_EOF) != 0))) + return MDBX_CURSOR_FULL; + } else { + mdbx_cassert(mc, numkeys + 1 >= mc->mc_ki[n]); + if (unlikely(numkeys + 1 < mc->mc_ki[n])) + return MDBX_CURSOR_FULL; + } + + for (unsigned i = 0; i < numkeys; ++i) { + MDBX_node *node = NODEPTR(mp, i); + if (branch) { + mdbx_cassert(mc, node->mn_flags == 0); + if (unlikely(node->mn_flags != 0)) + return MDBX_CURSOR_FULL; + pgno_t pgno = NODEPGNO(node); + MDBX_page *np; + int rc = mdbx_page_get(mc, pgno, &np, NULL); + mdbx_cassert(mc, rc == MDBX_SUCCESS); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + const bool nested_leaf = IS_LEAF(np) ? true : false; + mdbx_cassert(mc, nested_leaf == expect_nested_leaf); + if (unlikely(nested_leaf != expect_nested_leaf)) + return MDBX_CURSOR_FULL; + } + } + } + return MDBX_SUCCESS; +} + +/* Complete a delete operation started by mdbx_cursor_del(). */ +static int mdbx_cursor_del0(MDBX_cursor *mc) { + int rc; + MDBX_page *mp; + indx_t ki; + unsigned nkeys; + MDBX_cursor *m2, *m3; + MDBX_dbi dbi = mc->mc_dbi; + + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); + ki = mc->mc_ki[mc->mc_top]; + mp = mc->mc_pg[mc->mc_top]; + mdbx_node_del(mc, mc->mc_db->md_xsize); + mc->mc_db->md_entries--; + { + /* Adjust other cursors pointing to mp */ + for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc || !(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) + continue; + if (m3->mc_snum < mc->mc_snum) + continue; + if (m3->mc_pg[mc->mc_top] == mp) { + if (m3->mc_ki[mc->mc_top] == ki) { + m3->mc_flags |= C_DEL; + if (mc->mc_db->md_flags & MDBX_DUPSORT) { + /* Sub-cursor referred into dataset which is gone */ + m3->mc_xcursor->mx_cursor.mc_flags &= ~(C_INITIALIZED | C_EOF); + } + continue; + } else if (m3->mc_ki[mc->mc_top] > ki) { + m3->mc_ki[mc->mc_top]--; + } + if (XCURSOR_INITED(m3)) + XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); + } + } + } + rc = mdbx_rebalance(mc); + + if (likely(rc == MDBX_SUCCESS)) { + /* DB is totally empty now, just bail out. + * Other cursors adjustments were already done + * by mdbx_rebalance and aren't needed here. */ + if (!mc->mc_snum) { + mdbx_cassert(mc, mc->mc_db->md_entries == 0 && mc->mc_db->md_depth == 0 && + mc->mc_db->md_root == P_INVALID); + mc->mc_flags |= C_DEL | C_EOF; + return rc; + } + + ki = mc->mc_ki[mc->mc_top]; + mp = mc->mc_pg[mc->mc_top]; + mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top])); + nkeys = NUMKEYS(mp); + mdbx_cassert(mc, (mc->mc_db->md_entries > 0 && nkeys > 0) || + ((mc->mc_flags & C_SUB) && + mc->mc_db->md_entries == 0 && nkeys == 0)); + + /* Adjust THIS and other cursors pointing to mp */ + for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc || !(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) + continue; + if (m3->mc_snum < mc->mc_snum) + continue; + if (m3->mc_pg[mc->mc_top] == mp) { + /* if m3 points past last node in page, find next sibling */ + if (m3->mc_ki[mc->mc_top] >= nkeys) { + rc = mdbx_cursor_sibling(m3, true); + if (rc == MDBX_NOTFOUND) { + m3->mc_flags |= C_EOF; + rc = MDBX_SUCCESS; + continue; + } else if (unlikely(rc != MDBX_SUCCESS)) + break; + } + if (m3->mc_ki[mc->mc_top] >= ki || m3->mc_pg[mc->mc_top] != mp) { + if ((mc->mc_db->md_flags & MDBX_DUPSORT) != 0 && + (m3->mc_flags & C_EOF) == 0) { + MDBX_node *node = + NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]); + /* If this node has dupdata, it may need to be reinited + * because its data has moved. + * If the xcursor was not initd it must be reinited. + * Else if node points to a subDB, nothing is needed. */ + if (node->mn_flags & F_DUPDATA) { + if (m3->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { + if (!(node->mn_flags & F_SUBDATA)) + m3->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); + } else { + rc = mdbx_xcursor_init1(m3, node); + if (unlikely(rc != MDBX_SUCCESS)) + break; + m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL; + } + } + } + } + } + } + + if (mc->mc_ki[mc->mc_top] >= nkeys) { + rc = mdbx_cursor_sibling(mc, true); + if (rc == MDBX_NOTFOUND) { + mc->mc_flags |= C_EOF; + rc = MDBX_SUCCESS; + } + } + if ((mc->mc_db->md_flags & MDBX_DUPSORT) != 0 && + (mc->mc_flags & C_EOF) == 0) { + MDBX_node *node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + /* If this node has dupdata, it may need to be reinited + * because its data has moved. + * If the xcursor was not initd it must be reinited. + * Else if node points to a subDB, nothing is needed. */ + if (node->mn_flags & F_DUPDATA) { + if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) { + if (!(node->mn_flags & F_SUBDATA)) + mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(node); + } else { + rc = mdbx_xcursor_init1(mc, node); + if (likely(rc != MDBX_SUCCESS)) + mc->mc_xcursor->mx_cursor.mc_flags |= C_DEL; + } + } + } + mc->mc_flags |= C_DEL; + } + + if (unlikely(rc)) + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + else if (mdbx_audit_enabled()) + rc = mdbx_cursor_check(mc, false); + + return rc; +} + +int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) { + if (unlikely(!key || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; + + return mdbx_del0(txn, dbi, key, data, 0); +} + +static int mdbx_del0(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + unsigned flags) { + MDBX_cursor_couple cx; + MDBX_cursor_op op; + MDBX_val rdata; + int rc, exact = 0; + DKBUF; + + mdbx_debug("====> delete db %u key [%s], data [%s]", dbi, DKEY(key), + DVAL(data)); + + rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + if (data) { + op = MDBX_GET_BOTH; + rdata = *data; + data = &rdata; + } else { + op = MDBX_SET; + flags |= MDBX_NODUPDATA; + } + rc = mdbx_cursor_set(&cx.outer, key, data, op, &exact); + if (likely(rc == MDBX_SUCCESS)) { + /* let mdbx_page_split know about this cursor if needed: + * delete will trigger a rebalance; if it needs to move + * a node from one page to another, it will have to + * update the parent's separator key(s). If the new sepkey + * is larger than the current one, the parent page may + * run out of space, triggering a split. We need this + * cursor to be consistent until the end of the rebalance. */ + cx.outer.mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = &cx.outer; + rc = mdbx_cursor_del(&cx.outer, flags); + txn->mt_cursors[dbi] = cx.outer.mc_next; + } + return rc; +} + +/* Split a page and insert a new node. + * Set MDBX_TXN_ERROR on failure. + * [in,out] mc Cursor pointing to the page and desired insertion index. + * The cursor will be updated to point to the actual page and index where + * the node got inserted after the split. + * [in] newkey The key for the newly inserted node. + * [in] newdata The data for the newly inserted node. + * [in] newpgno The page number, if the new node is a branch node. + * [in] nflags The NODE_ADD_FLAGS for the new node. + * Returns 0 on success, non-zero on failure. */ +static int mdbx_page_split(MDBX_cursor *mc, const MDBX_val *newkey, + MDBX_val *newdata, pgno_t newpgno, unsigned nflags) { + unsigned flags; + int rc = MDBX_SUCCESS, foliage = 0, did_split = 0; + pgno_t pgno = 0; + unsigned i, ptop; + MDBX_env *env = mc->mc_txn->mt_env; + MDBX_node *node; + MDBX_val sepkey, rkey, xdata; + MDBX_page *copy = NULL; + MDBX_page *rp, *pp; + MDBX_cursor mn; + DKBUF; + + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + unsigned newindx = mc->mc_ki[mc->mc_top]; + unsigned nkeys = NUMKEYS(mp); + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, true); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + + mdbx_debug("-----> splitting %s page %" PRIaPGNO + " and adding [%s] at index %i/%i", + IS_LEAF(mp) ? "leaf" : "branch", mp->mp_pgno, DKEY(newkey), + mc->mc_ki[mc->mc_top], nkeys); + + /* Create a right sibling. */ + if ((rc = mdbx_page_new(mc, mp->mp_flags, 1, &rp))) + return rc; + rp->mp_leaf2_ksize = mp->mp_leaf2_ksize; + mdbx_debug("new right sibling: page %" PRIaPGNO, rp->mp_pgno); + + /* Usually when splitting the root page, the cursor + * height is 1. But when called from mdbx_update_key, + * the cursor height may be greater because it walks + * up the stack while finding the branch slot to update. */ + if (mc->mc_top < 1) { + if ((rc = mdbx_page_new(mc, P_BRANCH, 1, &pp))) + goto done; + /* shift current top to make room for new parent */ + mdbx_cassert(mc, mc->mc_snum < 2 && mc->mc_db->md_depth > 0); + mc->mc_pg[2] = mc->mc_pg[1]; + mc->mc_ki[2] = mc->mc_ki[1]; + mc->mc_pg[1] = mc->mc_pg[0]; + mc->mc_ki[1] = mc->mc_ki[0]; + mc->mc_pg[0] = pp; + mc->mc_ki[0] = 0; + mc->mc_db->md_root = pp->mp_pgno; + mdbx_debug("root split! new root = %" PRIaPGNO, pp->mp_pgno); + foliage = mc->mc_db->md_depth++; + + /* Add left (implicit) pointer. */ + if (unlikely((rc = mdbx_node_add_branch(mc, 0, NULL, mp->mp_pgno)) != + MDBX_SUCCESS)) { + /* undo the pre-push */ + mc->mc_pg[0] = mc->mc_pg[1]; + mc->mc_ki[0] = mc->mc_ki[1]; + mc->mc_db->md_root = mp->mp_pgno; + mc->mc_db->md_depth--; + goto done; + } + mc->mc_snum++; + mc->mc_top++; + ptop = 0; + } else { + ptop = mc->mc_top - 1; + mdbx_debug("parent branch page is %" PRIaPGNO, mc->mc_pg[ptop]->mp_pgno); + } + + mdbx_cursor_copy(mc, &mn); + mn.mc_xcursor = NULL; + mn.mc_pg[mn.mc_top] = rp; + mn.mc_ki[mn.mc_top] = 0; + mn.mc_ki[ptop] = mc->mc_ki[ptop] + 1; + + unsigned split_indx; + if (nflags & MDBX_APPEND) { + mn.mc_ki[mn.mc_top] = 0; + sepkey = *newkey; + split_indx = newindx; + nkeys = 0; + } else { + split_indx = (nkeys + 1) / 2; + if (IS_LEAF2(rp)) { + char *split, *ins; + int x; + unsigned lsize, rsize, ksize; + /* Move half of the keys to the right sibling */ + x = mc->mc_ki[mc->mc_top] - split_indx; + ksize = mc->mc_db->md_xsize; + split = LEAF2KEY(mp, split_indx, ksize); + rsize = (nkeys - split_indx) * ksize; + lsize = (nkeys - split_indx) * sizeof(indx_t); + mdbx_cassert(mc, mp->mp_lower >= lsize); + mp->mp_lower -= (indx_t)lsize; + mdbx_cassert(mc, rp->mp_lower + lsize <= UINT16_MAX); + rp->mp_lower += (indx_t)lsize; + mdbx_cassert(mc, mp->mp_upper + rsize - lsize <= UINT16_MAX); + mp->mp_upper += (indx_t)(rsize - lsize); + mdbx_cassert(mc, rp->mp_upper >= rsize - lsize); + rp->mp_upper -= (indx_t)(rsize - lsize); + sepkey.iov_len = ksize; + if (newindx == split_indx) { + sepkey.iov_base = newkey->iov_base; + } else { + sepkey.iov_base = split; + } + if (x < 0) { + mdbx_cassert(mc, ksize >= sizeof(indx_t)); + ins = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], ksize); + memcpy(rp->mp_ptrs, split, rsize); + sepkey.iov_base = rp->mp_ptrs; + memmove(ins + ksize, ins, (split_indx - mc->mc_ki[mc->mc_top]) * ksize); + memcpy(ins, newkey->iov_base, ksize); + mdbx_cassert(mc, UINT16_MAX - mp->mp_lower >= (int)sizeof(indx_t)); + mp->mp_lower += sizeof(indx_t); + mdbx_cassert(mc, mp->mp_upper >= ksize - sizeof(indx_t)); + mp->mp_upper -= (indx_t)(ksize - sizeof(indx_t)); + } else { + if (x) + memcpy(rp->mp_ptrs, split, x * ksize); + ins = LEAF2KEY(rp, x, ksize); + memcpy(ins, newkey->iov_base, ksize); + memcpy(ins + ksize, split + x * ksize, rsize - x * ksize); + mdbx_cassert(mc, UINT16_MAX - rp->mp_lower >= (int)sizeof(indx_t)); + rp->mp_lower += sizeof(indx_t); + mdbx_cassert(mc, rp->mp_upper >= ksize - sizeof(indx_t)); + rp->mp_upper -= (indx_t)(ksize - sizeof(indx_t)); + mdbx_cassert(mc, x <= UINT16_MAX); + mc->mc_ki[mc->mc_top] = (indx_t)x; + } + } else { + size_t psize, nsize, k; + /* Maximum free space in an empty page */ + const unsigned pmax = env->me_psize - PAGEHDRSZ; + nsize = IS_LEAF(mp) ? mdbx_leaf_size(env, newkey, newdata) + : mdbx_branch_size(env, newkey); + + /* grab a page to hold a temporary copy */ + copy = mdbx_page_malloc(mc->mc_txn, 1); + if (unlikely(copy == NULL)) { + rc = MDBX_ENOMEM; + goto done; + } + copy->mp_pgno = mp->mp_pgno; + copy->mp_flags = mp->mp_flags; + copy->mp_lower = 0; + mdbx_cassert(mc, env->me_psize - PAGEHDRSZ <= UINT16_MAX); + copy->mp_upper = (indx_t)(env->me_psize - PAGEHDRSZ); + + /* prepare to insert */ + for (unsigned j = i = 0; i < nkeys; i++) { + if (i == newindx) + copy->mp_ptrs[j++] = 0; + copy->mp_ptrs[j++] = mp->mp_ptrs[i]; + } + + /* When items are relatively large the split point needs + * to be checked, because being off-by-one will make the + * difference between success or failure in mdbx_node_add. + * + * It's also relevant if a page happens to be laid out + * such that one half of its nodes are all "small" and + * the other half of its nodes are "large." If the new + * item is also "large" and falls on the half with + * "large" nodes, it also may not fit. + * + * As a final tweak, if the new item goes on the last + * spot on the page (and thus, onto the new page), bias + * the split so the new page is emptier than the old page. + * This yields better packing during sequential inserts. + */ + int dir; + if (nkeys < 32 || nsize > pmax / 16 || newindx >= nkeys) { + /* Find split point */ + psize = 0; + if (newindx <= split_indx || newindx >= nkeys) { + i = 0; + dir = 1; + k = (newindx >= nkeys) ? nkeys : split_indx + 1 + IS_LEAF(mp); + } else { + i = nkeys; + dir = -1; + k = split_indx - 1; + } + for (; i != k; i += dir) { + if (i == newindx) { + psize += nsize; + node = NULL; + } else { + node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ); + psize += NODESIZE + NODEKSZ(node) + sizeof(indx_t); + if (IS_LEAF(mp)) { + if (F_ISSET(node->mn_flags, F_BIGDATA)) + psize += sizeof(pgno_t); + else + psize += NODEDSZ(node); + } + psize = EVEN(psize); + } + if (psize > pmax || i == k - dir) { + split_indx = i + (dir < 0); + break; + } + } + } + if (split_indx == newindx) { + sepkey.iov_len = newkey->iov_len; + sepkey.iov_base = newkey->iov_base; + } else { + node = + (MDBX_node *)((char *)mp + copy->mp_ptrs[split_indx] + PAGEHDRSZ); + sepkey.iov_len = node->mn_ksize; + sepkey.iov_base = NODEKEY(node); + } + } + } + + mdbx_debug("separator is %d [%s]", split_indx, DKEY(&sepkey)); + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, true); + if (unlikely(err != MDBX_SUCCESS)) + return err; + err = mdbx_cursor_check(&mn, true); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + + /* Copy separator key to the parent. */ + if (SIZELEFT(mn.mc_pg[ptop]) < mdbx_branch_size(env, &sepkey)) { + const int snum = mc->mc_snum; + const int depth = mc->mc_db->md_depth; + mn.mc_snum--; + mn.mc_top--; + did_split = 1; + /* We want other splits to find mn when doing fixups */ + WITH_CURSOR_TRACKING( + mn, rc = mdbx_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0)); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + mdbx_cassert(mc, mc->mc_snum - snum == mc->mc_db->md_depth - depth); + if (mdbx_audit_enabled()) { + int err = mdbx_cursor_check(mc, true); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + + /* root split? */ + ptop += mc->mc_snum - snum; + + /* Right page might now have changed parent. + * Check if left page also changed parent. */ + if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && + mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { + for (i = 0; i < ptop; i++) { + mc->mc_pg[i] = mn.mc_pg[i]; + mc->mc_ki[i] = mn.mc_ki[i]; + } + mc->mc_pg[ptop] = mn.mc_pg[ptop]; + if (mn.mc_ki[ptop]) { + mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1; + } else { + /* find right page's left sibling */ + mc->mc_ki[ptop] = mn.mc_ki[ptop]; + rc = mdbx_cursor_sibling(mc, false); + } + } + } else { + mn.mc_top--; + rc = mdbx_node_add_branch(&mn, mn.mc_ki[ptop], &sepkey, rp->mp_pgno); + mn.mc_top++; + } + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc == MDBX_NOTFOUND) /* improper mdbx_cursor_sibling() result */ { + mdbx_error("unexpected %s", "MDBX_NOTFOUND"); + rc = MDBX_PROBLEM; + } + goto done; + } + + if (nflags & MDBX_APPEND) { + mc->mc_pg[mc->mc_top] = rp; + mc->mc_ki[mc->mc_top] = 0; + switch (PAGETYPE(rp)) { + case P_BRANCH: { + mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); + mdbx_cassert(mc, newpgno != 0 && newpgno != P_INVALID); + rc = mdbx_node_add_branch(mc, 0, newkey, newpgno); + } break; + case P_LEAF: { + mdbx_cassert(mc, newpgno == 0 || newpgno == P_INVALID); + rc = mdbx_node_add_leaf(mc, 0, newkey, newdata, nflags); + } break; + case P_LEAF | P_LEAF2: { + mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); + mdbx_cassert(mc, newpgno == 0 || newpgno == P_INVALID); + rc = mdbx_node_add_leaf2(mc, 0, newkey); + } break; + default: + rc = MDBX_CORRUPTED; + } + if (rc) + goto done; + for (i = 0; i < mc->mc_top; i++) + mc->mc_ki[i] = mn.mc_ki[i]; + } else if (!IS_LEAF2(mp)) { + /* Move nodes */ + mc->mc_pg[mc->mc_top] = rp; + i = split_indx; + indx_t n = 0; + do { + MDBX_val *rdata = NULL; + if (i == newindx) { + rkey.iov_base = newkey->iov_base; + rkey.iov_len = newkey->iov_len; + if (IS_LEAF(mp)) { + rdata = newdata; + } else + pgno = newpgno; + flags = nflags; + /* Update index for the new key. */ + mc->mc_ki[mc->mc_top] = n; + } else { + node = (MDBX_node *)((char *)mp + copy->mp_ptrs[i] + PAGEHDRSZ); + rkey.iov_base = NODEKEY(node); + rkey.iov_len = node->mn_ksize; + if (IS_LEAF(mp)) { + xdata.iov_base = NODEDATA(node); + xdata.iov_len = NODEDSZ(node); + rdata = &xdata; + } else + pgno = NODEPGNO(node); + flags = node->mn_flags; + } + + switch (PAGETYPE(rp)) { + case P_BRANCH: { + mdbx_cassert(mc, 0 == (uint16_t)flags); + if (n == 0) { + /* First branch index doesn't need key data. */ + rkey.iov_len = 0; + } + rc = mdbx_node_add_branch(mc, n, &rkey, pgno); + } break; + case P_LEAF: { + mdbx_cassert(mc, pgno == 0); + mdbx_cassert(mc, rdata != NULL); + rc = mdbx_node_add_leaf(mc, n, &rkey, rdata, flags); + } break; + /* case P_LEAF | P_LEAF2: { + mdbx_cassert(mc, (nflags & (F_BIGDATA | F_SUBDATA | F_DUPDATA)) == 0); + mdbx_cassert(mc, gno == 0); + rc = mdbx_node_add_leaf2(mc, n, &rkey); + } break; */ + default: + rc = MDBX_CORRUPTED; + } + if (rc) + goto done; + + if (i == nkeys) { + i = 0; + n = 0; + mc->mc_pg[mc->mc_top] = copy; + } else { + i++; + n++; + } + } while (i != split_indx); + + nkeys = NUMKEYS(copy); + for (i = 0; i < nkeys; i++) + mp->mp_ptrs[i] = copy->mp_ptrs[i]; + mp->mp_lower = copy->mp_lower; + mp->mp_upper = copy->mp_upper; + memcpy(NODEPTR(mp, nkeys - 1), NODEPTR(copy, nkeys - 1), + env->me_psize - copy->mp_upper - PAGEHDRSZ); + + /* reset back to original page */ + if (newindx < split_indx) { + mc->mc_pg[mc->mc_top] = mp; + } else { + mc->mc_pg[mc->mc_top] = rp; + mc->mc_ki[ptop]++; + /* Make sure mc_ki is still valid. */ + if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && + mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { + for (i = 0; i <= ptop; i++) { + mc->mc_pg[i] = mn.mc_pg[i]; + mc->mc_ki[i] = mn.mc_ki[i]; + } + } + } + if (nflags & MDBX_RESERVE) { + node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); + if (!(node->mn_flags & F_BIGDATA)) + newdata->iov_base = NODEDATA(node); + } + } else { + if (newindx >= split_indx) { + mc->mc_pg[mc->mc_top] = rp; + mc->mc_ki[ptop]++; + /* Make sure mc_ki is still valid. */ + if (mn.mc_pg[ptop] != mc->mc_pg[ptop] && + mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) { + for (i = 0; i <= ptop; i++) { + mc->mc_pg[i] = mn.mc_pg[i]; + mc->mc_ki[i] = mn.mc_ki[i]; + } + } + } + } + + { + /* Adjust other cursors pointing to mp */ + MDBX_cursor *m2, *m3; + MDBX_dbi dbi = mc->mc_dbi; + nkeys = NUMKEYS(mp); + + for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) { + m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2; + if (m3 == mc) + continue; + if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED)) + continue; + if (foliage) { + int k; + /* sub cursors may be on different DB */ + if (m3->mc_pg[0] != mp) + continue; + /* root split */ + for (k = foliage; k >= 0; k--) { + m3->mc_ki[k + 1] = m3->mc_ki[k]; + m3->mc_pg[k + 1] = m3->mc_pg[k]; + } + m3->mc_ki[0] = (m3->mc_ki[0] >= nkeys) ? 1 : 0; + m3->mc_pg[0] = mc->mc_pg[0]; + m3->mc_snum++; + m3->mc_top++; + } + if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) { + if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDBX_SPLIT_REPLACE)) + m3->mc_ki[mc->mc_top]++; + if (m3->mc_ki[mc->mc_top] >= nkeys) { + m3->mc_pg[mc->mc_top] = rp; + mdbx_cassert(mc, m3->mc_ki[mc->mc_top] >= nkeys); + m3->mc_ki[mc->mc_top] -= (indx_t)nkeys; + for (i = 0; i < mc->mc_top; i++) { + m3->mc_ki[i] = mn.mc_ki[i]; + m3->mc_pg[i] = mn.mc_pg[i]; + } + } + } else if (!did_split && m3->mc_top >= ptop && + m3->mc_pg[ptop] == mc->mc_pg[ptop] && + m3->mc_ki[ptop] >= mc->mc_ki[ptop]) { + m3->mc_ki[ptop]++; + } + if (XCURSOR_INITED(m3) && IS_LEAF(mp)) + XCURSOR_REFRESH(m3, m3->mc_pg[mc->mc_top], m3->mc_ki[mc->mc_top]); + } + } + mdbx_debug("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp)); + +done: + if (copy) /* tmp page */ + mdbx_dpage_free(env, copy, 1); + if (unlikely(rc)) + mc->mc_txn->mt_flags |= MDBX_TXN_ERROR; + return rc; +} + +int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + unsigned flags) { + + if (unlikely(!key || !data || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE | + MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + cx.outer.mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = &cx.outer; + + /* LY: support for update (explicit overwrite) */ + if (flags & MDBX_CURRENT) { + rc = mdbx_cursor_get(&cx.outer, key, NULL, MDBX_SET); + if (likely(rc == MDBX_SUCCESS) && + (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT)) { + /* LY: allows update (explicit overwrite) only for unique keys */ + MDBX_node *leaf = NODEPTR(cx.outer.mc_pg[cx.outer.mc_top], + cx.outer.mc_ki[cx.outer.mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdbx_tassert(txn, XCURSOR_INITED(&cx.outer) && + cx.outer.mc_xcursor->mx_db.md_entries > 1); + rc = MDBX_EMULTIVAL; + } + } + } + + if (likely(rc == MDBX_SUCCESS)) + rc = mdbx_cursor_put(&cx.outer, key, data, flags); + txn->mt_cursors[dbi] = cx.outer.mc_next; + + return rc; +} + +#ifndef MDBX_WBUF +#define MDBX_WBUF ((size_t)1024 * 1024) +#endif +#define MDBX_EOF 0x10 /* mdbx_env_copyfd1() is done reading */ + +/* State needed for a double-buffering compacting copy. */ +typedef struct mdbx_copy { + MDBX_env *mc_env; + MDBX_txn *mc_txn; + mdbx_condmutex_t mc_condmutex; + uint8_t *mc_wbuf[2]; + uint8_t *mc_over[2]; + size_t mc_wlen[2]; + size_t mc_olen[2]; + mdbx_filehandle_t mc_fd; + volatile int mc_error; + pgno_t mc_next_pgno; + short mc_toggle; /* Buffer number in provider */ + short mc_new; /* (0-2 buffers to write) | (MDBX_EOF at end) */ + /* Error code. Never cleared if set. Both threads can set nonzero + * to fail the copy. Not mutex-protected, MDBX expects atomic int. */ +} mdbx_copy; + +/* Dedicated writer thread for compacting copy. */ +static THREAD_RESULT __cold THREAD_CALL mdbx_env_copythr(void *arg) { + mdbx_copy *my = arg; + uint8_t *ptr; + int toggle = 0; + int rc; + size_t offset = pgno2bytes(my->mc_env, NUM_METAS); + + mdbx_condmutex_lock(&my->mc_condmutex); + while (!my->mc_error) { + while (!my->mc_new) + mdbx_condmutex_wait(&my->mc_condmutex); + if (my->mc_new == 0 + MDBX_EOF) /* 0 buffers, just EOF */ + break; + size_t wsize = my->mc_wlen[toggle]; + ptr = my->mc_wbuf[toggle]; + again: + if (wsize > 0 && !my->mc_error) { + rc = mdbx_pwrite(my->mc_fd, ptr, wsize, offset); + if (rc != MDBX_SUCCESS) { + my->mc_error = rc; + break; + } + offset += wsize; + } + + /* If there's an overflow page tail, write it too */ + if (my->mc_olen[toggle]) { + wsize = my->mc_olen[toggle]; + ptr = my->mc_over[toggle]; + my->mc_olen[toggle] = 0; + goto again; + } + my->mc_wlen[toggle] = 0; + toggle ^= 1; + /* Return the empty buffer to provider */ + my->mc_new--; + mdbx_condmutex_signal(&my->mc_condmutex); + } + mdbx_condmutex_unlock(&my->mc_condmutex); + return (THREAD_RESULT)0; +} + +/* Give buffer and/or MDBX_EOF to writer thread, await unused buffer. + * + * [in] my control structure. + * [in] adjust (1 to hand off 1 buffer) | (MDBX_EOF when ending). */ +static int __cold mdbx_env_cthr_toggle(mdbx_copy *my, int adjust) { + mdbx_condmutex_lock(&my->mc_condmutex); + my->mc_new += (short)adjust; + mdbx_condmutex_signal(&my->mc_condmutex); + while (my->mc_new & 2) /* both buffers in use */ + mdbx_condmutex_wait(&my->mc_condmutex); + mdbx_condmutex_unlock(&my->mc_condmutex); + + my->mc_toggle ^= (adjust & 1); + /* Both threads reset mc_wlen, to be safe from threading errors */ + my->mc_wlen[my->mc_toggle] = 0; + return my->mc_error; +} + +/* Depth-first tree traversal for compacting copy. + * [in] my control structure. + * [in,out] pg database root. + * [in] flags includes F_DUPDATA if it is a sorted-duplicate sub-DB. */ +static int __cold mdbx_env_cwalk(mdbx_copy *my, pgno_t *pg, int flags) { + MDBX_cursor mc; + MDBX_node *ni; + MDBX_page *mo, *mp, *leaf; + char *buf, *ptr; + int rc, toggle; + unsigned i; + + /* Empty DB, nothing to do */ + if (*pg == P_INVALID) + return MDBX_SUCCESS; + + memset(&mc, 0, sizeof(mc)); + mc.mc_snum = 1; + mc.mc_txn = my->mc_txn; + + rc = mdbx_page_get(&mc, *pg, &mc.mc_pg[0], NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_page_search_root(&mc, NULL, MDBX_PS_FIRST); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + /* Make cursor pages writable */ + buf = ptr = mdbx_malloc(pgno2bytes(my->mc_env, mc.mc_snum)); + if (buf == NULL) + return MDBX_ENOMEM; + + for (i = 0; i < mc.mc_top; i++) { + mdbx_page_copy((MDBX_page *)ptr, mc.mc_pg[i], my->mc_env->me_psize); + mc.mc_pg[i] = (MDBX_page *)ptr; + ptr += my->mc_env->me_psize; + } + + /* This is writable space for a leaf page. Usually not needed. */ + leaf = (MDBX_page *)ptr; + + toggle = my->mc_toggle; + while (mc.mc_snum > 0) { + unsigned n; + mp = mc.mc_pg[mc.mc_top]; + n = NUMKEYS(mp); + + if (IS_LEAF(mp)) { + if (!IS_LEAF2(mp) && !(flags & F_DUPDATA)) { + for (i = 0; i < n; i++) { + ni = NODEPTR(mp, i); + if (ni->mn_flags & F_BIGDATA) { + MDBX_page *omp; + + /* Need writable leaf */ + if (mp != leaf) { + mc.mc_pg[mc.mc_top] = leaf; + mdbx_page_copy(leaf, mp, my->mc_env->me_psize); + mp = leaf; + ni = NODEPTR(mp, i); + } + + pgno_t pgno; + memcpy(&pgno, NODEDATA(ni), sizeof(pgno)); + memcpy(NODEDATA(ni), &my->mc_next_pgno, sizeof(pgno_t)); + rc = mdbx_page_get(&mc, pgno, &omp, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + if (my->mc_wlen[toggle] >= MDBX_WBUF) { + rc = mdbx_env_cthr_toggle(my, 1); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + toggle = my->mc_toggle; + } + mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); + memcpy(mo, omp, my->mc_env->me_psize); + mo->mp_pgno = my->mc_next_pgno; + my->mc_next_pgno += omp->mp_pages; + my->mc_wlen[toggle] += my->mc_env->me_psize; + if (omp->mp_pages > 1) { + my->mc_olen[toggle] = pgno2bytes(my->mc_env, omp->mp_pages - 1); + my->mc_over[toggle] = (uint8_t *)omp + my->mc_env->me_psize; + rc = mdbx_env_cthr_toggle(my, 1); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + toggle = my->mc_toggle; + } + } else if (ni->mn_flags & F_SUBDATA) { + MDBX_db db; + + /* Need writable leaf */ + if (mp != leaf) { + mc.mc_pg[mc.mc_top] = leaf; + mdbx_page_copy(leaf, mp, my->mc_env->me_psize); + mp = leaf; + ni = NODEPTR(mp, i); + } + + memcpy(&db, NODEDATA(ni), sizeof(db)); + my->mc_toggle = (short)toggle; + rc = mdbx_env_cwalk(my, &db.md_root, ni->mn_flags & F_DUPDATA); + if (rc) + goto done; + toggle = my->mc_toggle; + memcpy(NODEDATA(ni), &db, sizeof(db)); + } + } + } + } else { + mc.mc_ki[mc.mc_top]++; + if (mc.mc_ki[mc.mc_top] < n) { + pgno_t pgno; + again: + ni = NODEPTR(mp, mc.mc_ki[mc.mc_top]); + pgno = NODEPGNO(ni); + rc = mdbx_page_get(&mc, pgno, &mp, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + mc.mc_top++; + mc.mc_snum++; + mc.mc_ki[mc.mc_top] = 0; + if (IS_BRANCH(mp)) { + /* Whenever we advance to a sibling branch page, + * we must proceed all the way down to its first leaf. */ + mdbx_page_copy(mc.mc_pg[mc.mc_top], mp, my->mc_env->me_psize); + goto again; + } else + mc.mc_pg[mc.mc_top] = mp; + continue; + } + } + if (my->mc_wlen[toggle] >= MDBX_WBUF) { + rc = mdbx_env_cthr_toggle(my, 1); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + toggle = my->mc_toggle; + } + mo = (MDBX_page *)(my->mc_wbuf[toggle] + my->mc_wlen[toggle]); + mdbx_page_copy(mo, mp, my->mc_env->me_psize); + mo->mp_pgno = my->mc_next_pgno++; + my->mc_wlen[toggle] += my->mc_env->me_psize; + if (mc.mc_top) { + /* Update parent if there is one */ + ni = NODEPTR(mc.mc_pg[mc.mc_top - 1], mc.mc_ki[mc.mc_top - 1]); + SETPGNO(ni, mo->mp_pgno); + mdbx_cursor_pop(&mc); + } else { + /* Otherwise we're done */ + *pg = mo->mp_pgno; + break; + } + } +done: + mdbx_free(buf); + return rc; +} + +/* Copy environment with compaction. */ +static int __cold mdbx_env_compact(MDBX_env *env, MDBX_txn *read_txn, + mdbx_filehandle_t fd, uint8_t *buffer) { + MDBX_page *const meta = mdbx_init_metas(env, buffer); + /* copy canary sequenses if present */ + if (read_txn->mt_canary.v) { + meta->mp_meta.mm_canary = read_txn->mt_canary; + meta->mp_meta.mm_canary.v = mdbx_meta_txnid_stable(env, &meta->mp_meta); + } + + /* Set metapage 1 with current main DB */ + pgno_t new_root, root = read_txn->mt_dbs[MAIN_DBI].md_root; + if ((new_root = root) == P_INVALID) { + /* When the DB is empty, handle it specially to + * fix any breakage like page leaks from ITS#8174. */ + meta->mp_meta.mm_dbs[MAIN_DBI].md_flags = + read_txn->mt_dbs[MAIN_DBI].md_flags; + } else { + /* Count free pages + freeDB pages. Subtract from last_pg + * to find the new last_pg, which also becomes the new root. */ + pgno_t freecount = 0; + MDBX_cursor mc; + MDBX_val key, data; + + int rc = mdbx_cursor_init(&mc, read_txn, FREE_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + while ((rc = mdbx_cursor_get(&mc, &key, &data, MDBX_NEXT)) == 0) + freecount += *(pgno_t *)data.iov_base; + if (unlikely(rc != MDBX_NOTFOUND)) + return rc; + + freecount += read_txn->mt_dbs[FREE_DBI].md_branch_pages + + read_txn->mt_dbs[FREE_DBI].md_leaf_pages + + read_txn->mt_dbs[FREE_DBI].md_overflow_pages; + + new_root = read_txn->mt_next_pgno - 1 - freecount; + meta->mp_meta.mm_geo.next = new_root + 1; + meta->mp_meta.mm_dbs[MAIN_DBI] = read_txn->mt_dbs[MAIN_DBI]; + meta->mp_meta.mm_dbs[MAIN_DBI].md_root = new_root; + + mdbx_copy ctx; + memset(&ctx, 0, sizeof(ctx)); + rc = mdbx_condmutex_init(&ctx.mc_condmutex); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + ctx.mc_wbuf[0] = buffer + pgno2bytes(env, NUM_METAS); + memset(ctx.mc_wbuf[0], 0, MDBX_WBUF * 2); + ctx.mc_wbuf[1] = ctx.mc_wbuf[0] + MDBX_WBUF; + ctx.mc_next_pgno = NUM_METAS; + ctx.mc_env = env; + ctx.mc_fd = fd; + ctx.mc_txn = read_txn; + + mdbx_thread_t thread; + int thread_err = mdbx_thread_create(&thread, mdbx_env_copythr, &ctx); + if (likely(thread_err == MDBX_SUCCESS)) { + rc = mdbx_env_cwalk(&ctx, &root, 0); + mdbx_env_cthr_toggle(&ctx, 1 | MDBX_EOF); + thread_err = mdbx_thread_join(thread); + mdbx_condmutex_destroy(&ctx.mc_condmutex); + } + if (unlikely(thread_err != MDBX_SUCCESS)) + return thread_err; + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (unlikely(ctx.mc_error != MDBX_SUCCESS)) + return ctx.mc_error; + + if (root > new_root) { + mdbx_error("post-compactification root %" PRIaPGNO + " GT expected %" PRIaPGNO " (source DB corrupted)", + root, new_root); + return MDBX_CORRUPTED; /* page leak or corrupt DB */ + } + if (root < new_root) { + mdbx_notice("post-compactification root %" PRIaPGNO + " LT expected %" PRIaPGNO " (page leak(s) in source DB)", + root, new_root); + /* fixup meta */ + meta->mp_meta.mm_dbs[MAIN_DBI].md_root = root; + meta->mp_meta.mm_geo.next = root + 1; + } + } + + /* Calculate filesize taking in account shrink/growing thresholds */ + if (meta->mp_meta.mm_geo.next > meta->mp_meta.mm_geo.now) { + const pgno_t aligned = + pgno_align2os_pgno(env, pgno_add(meta->mp_meta.mm_geo.next, + meta->mp_meta.mm_geo.grow - + meta->mp_meta.mm_geo.next % + meta->mp_meta.mm_geo.grow)); + meta->mp_meta.mm_geo.now = aligned; + } else if (meta->mp_meta.mm_geo.next < meta->mp_meta.mm_geo.now) { + meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.next; + const pgno_t aligner = meta->mp_meta.mm_geo.grow + ? meta->mp_meta.mm_geo.grow + : meta->mp_meta.mm_geo.shrink; + const pgno_t aligned = + pgno_align2os_pgno(env, meta->mp_meta.mm_geo.next + aligner - + meta->mp_meta.mm_geo.next % aligner); + meta->mp_meta.mm_geo.now = aligned; + } + + if (meta->mp_meta.mm_geo.now < meta->mp_meta.mm_geo.lower) + meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.lower; + if (meta->mp_meta.mm_geo.now > meta->mp_meta.mm_geo.upper) + meta->mp_meta.mm_geo.now = meta->mp_meta.mm_geo.upper; + + /* Update signature */ + assert(meta->mp_meta.mm_geo.now >= meta->mp_meta.mm_geo.next); + meta->mp_meta.mm_datasync_sign = mdbx_meta_sign(&meta->mp_meta); + + /* Extend file if required */ + return (meta->mp_meta.mm_geo.now != meta->mp_meta.mm_geo.next) + ? mdbx_ftruncate(fd, pgno2bytes(env, meta->mp_meta.mm_geo.now)) + : MDBX_SUCCESS; +} + +/* Copy environment as-is. */ +static int __cold mdbx_env_copy_asis(MDBX_env *env, MDBX_txn *read_txn, + mdbx_filehandle_t fd, uint8_t *buffer) { + /* We must start the actual read txn after blocking writers */ + int rc = mdbx_txn_end(read_txn, MDBX_END_RESET_TMP); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + /* Temporarily block writers until we snapshot the meta pages */ + rc = mdbx_txn_lock(env, false); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + rc = mdbx_txn_renew0(read_txn, MDBX_RDONLY); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_txn_unlock(env); + return rc; + } + + mdbx_jitter4testing(false); + const size_t meta_bytes = pgno2bytes(env, NUM_METAS); + /* Make a snapshot of meta-pages, + * but writing ones after the data was flushed */ + memcpy(buffer, env->me_map, meta_bytes); + MDBX_meta *const headcopy = /* LY: get pointer to the spanshot copy */ + (MDBX_meta *)(buffer + ((uint8_t *)mdbx_meta_head(env) - env->me_map)); + /* Update signature to steady */ + headcopy->mm_datasync_sign = mdbx_meta_sign(headcopy); + mdbx_txn_unlock(env); + + /* Copy the data */ + const uint64_t whole_size = + mdbx_roundup2(pgno2bytes(env, read_txn->mt_end_pgno), env->me_os_psize); + const size_t used_size = pgno2bytes(env, read_txn->mt_next_pgno); + mdbx_jitter4testing(false); +#if __GLIBC_PREREQ(2, 27) && defined(_GNU_SOURCE) + for (off_t in_offset = meta_bytes; in_offset < (off_t)used_size;) { + off_t out_offset = in_offset; + ssize_t bytes_copied = copy_file_range( + env->me_fd, &in_offset, fd, &out_offset, used_size - in_offset, 0); + if (unlikely(bytes_copied <= 0)) { + rc = bytes_copied ? errno : MDBX_ENODATA; + break; + } + } +#else + uint8_t *data_buffer = buffer + meta_bytes; + for (size_t offset = meta_bytes; offset < used_size;) { + const size_t chunk = + (MDBX_WBUF < used_size - offset) ? MDBX_WBUF : used_size - offset; + memcpy(data_buffer, env->me_map + offset, chunk); + rc = mdbx_pwrite(fd, data_buffer, chunk, offset); + if (unlikely(rc != MDBX_SUCCESS)) + break; + offset += chunk; + } +#endif + + if (likely(rc == MDBX_SUCCESS) && whole_size != used_size) + rc = mdbx_ftruncate(fd, whole_size); + + return rc; +} + +int __cold mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd, + unsigned flags) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + int rc = mdbx_fseek(fd, 0); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + const size_t buffer_size = + pgno2bytes(env, NUM_METAS) + + ((flags & MDBX_CP_COMPACT) ? MDBX_WBUF * 2 : MDBX_WBUF); + + uint8_t *buffer = NULL; + rc = mdbx_memalign_alloc(env->me_os_psize, buffer_size, (void **)&buffer); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + MDBX_txn *read_txn = NULL; + /* Do the lock/unlock of the reader mutex before starting the + * write txn. Otherwise other read txns could block writers. */ + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &read_txn); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_memalign_free(buffer); + return rc; + } + + /* Firstly write a stub to meta-pages. + * Now we sure to incomplete copy will not be used. */ + memset(buffer, -1, pgno2bytes(env, NUM_METAS)); + rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0); + if (likely(rc == MDBX_SUCCESS)) { + memset(buffer, 0, pgno2bytes(env, NUM_METAS)); + rc = (flags & MDBX_CP_COMPACT) + ? mdbx_env_compact(env, read_txn, fd, buffer) + : mdbx_env_copy_asis(env, read_txn, fd, buffer); + } + mdbx_txn_abort(read_txn); + + if (likely(rc == MDBX_SUCCESS)) + rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_SIZE); + + /* Write actual meta */ + if (likely(rc == MDBX_SUCCESS)) + rc = mdbx_pwrite(fd, buffer, pgno2bytes(env, NUM_METAS), 0); + + if (likely(rc == MDBX_SUCCESS)) + rc = mdbx_filesync(fd, MDBX_SYNC_DATA | MDBX_SYNC_IODQ); + + mdbx_memalign_free(buffer); + return rc; +} + +int __cold mdbx_env_copy(MDBX_env *env, const char *dest_path, unsigned flags) { + if (unlikely(!env || !dest_path)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + char *dxb_pathname; + mdbx_filehandle_t newfd = INVALID_HANDLE_VALUE; + + if (env->me_flags & MDBX_NOSUBDIR) { + dxb_pathname = (char *)dest_path; + } else { + size_t len = strlen(dest_path); + len += sizeof(MDBX_DATANAME); + dxb_pathname = mdbx_malloc(len); + if (!dxb_pathname) + return MDBX_ENOMEM; + sprintf(dxb_pathname, "%s" MDBX_DATANAME, dest_path); + } + + /* The destination path must exist, but the destination file must not. + * We don't want the OS to cache the writes, since the source data is + * already in the OS cache. */ + int rc = mdbx_openfile(dxb_pathname, O_WRONLY | O_CREAT | O_EXCL, 0640, + &newfd, true); + if (rc == MDBX_SUCCESS) { + if (env->me_psize >= env->me_os_psize) { +#ifdef F_NOCACHE /* __APPLE__ */ + (void)fcntl(newfd, F_NOCACHE, 1); +#elif defined(O_DIRECT) && defined(F_GETFL) + /* Set O_DIRECT if the file system supports it */ + if ((rc = fcntl(newfd, F_GETFL)) != -1) + (void)fcntl(newfd, F_SETFL, rc | O_DIRECT); +#endif + } + rc = mdbx_env_copy2fd(env, newfd, flags); + } + + if (newfd != INVALID_HANDLE_VALUE) { + int err = mdbx_closefile(newfd); + if (rc == MDBX_SUCCESS && err != rc) + rc = err; + if (rc != MDBX_SUCCESS) + (void)mdbx_removefile(dxb_pathname); + } + + if (dxb_pathname != dest_path) + mdbx_free(dxb_pathname); + + return rc; +} + +int __cold mdbx_env_set_flags(MDBX_env *env, unsigned flags, int onoff) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(flags & ~CHANGEABLE)) + return MDBX_EINVAL; + + int rc = mdbx_txn_lock(env, false); + if (unlikely(rc)) + return rc; + + if (onoff) + env->me_flags |= flags; + else + env->me_flags &= ~flags; + + mdbx_txn_unlock(env); + return MDBX_SUCCESS; +} + +int __cold mdbx_env_get_flags(MDBX_env *env, unsigned *arg) { + if (unlikely(!env || !arg)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + *arg = env->me_flags & (CHANGEABLE | CHANGELESS); + return MDBX_SUCCESS; +} + +int __cold mdbx_env_set_userctx(MDBX_env *env, void *ctx) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + env->me_userctx = ctx; + return MDBX_SUCCESS; +} + +void *__cold mdbx_env_get_userctx(MDBX_env *env) { + return env ? env->me_userctx : NULL; +} + +int __cold mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + +#if MDBX_DEBUG + env->me_assert_func = func; + return MDBX_SUCCESS; +#else + (void)func; + return MDBX_ENOSYS; +#endif +} + +int __cold mdbx_env_get_path(MDBX_env *env, const char **arg) { + if (unlikely(!env || !arg)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + *arg = env->me_path; + return MDBX_SUCCESS; +} + +int __cold mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *arg) { + if (unlikely(!env || !arg)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + *arg = env->me_fd; + return MDBX_SUCCESS; +} + +/* Common code for mdbx_dbi_stat() and mdbx_env_stat(). + * [in] env the environment to operate in. + * [in] db the MDBX_db record containing the stats to return. + * [out] arg the address of an MDBX_stat structure to receive the stats. + * Returns 0, this function always succeeds. */ +static int __cold mdbx_stat0(const MDBX_env *env, const MDBX_db *db, + MDBX_stat *arg) { + arg->ms_psize = env->me_psize; + arg->ms_depth = db->md_depth; + arg->ms_branch_pages = db->md_branch_pages; + arg->ms_leaf_pages = db->md_leaf_pages; + arg->ms_overflow_pages = db->md_overflow_pages; + arg->ms_entries = db->md_entries; + return MDBX_SUCCESS; +} + +int __cold mdbx_env_stat(MDBX_env *env, MDBX_stat *arg, size_t bytes) { + return mdbx_env_stat2(env, NULL, arg, bytes); +} + +int __cold mdbx_env_stat2(const MDBX_env *env, const MDBX_txn *txn, + MDBX_stat *arg, size_t bytes) { + if (unlikely((env == NULL && txn == NULL) || arg == NULL)) + return MDBX_EINVAL; + + if (txn) { + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + } + if (env) { + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + if (txn && unlikely(txn->mt_env != env)) + return MDBX_EINVAL; + } + + if (unlikely(bytes != sizeof(MDBX_stat))) + return MDBX_EINVAL; + + const MDBX_db *db = + txn ? &txn->mt_dbs[MAIN_DBI] : &mdbx_meta_head(env)->mm_dbs[MAIN_DBI]; + return mdbx_stat0(txn ? txn->mt_env : env, db, arg); +} + +int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) { + return mdbx_env_info2(env, NULL, arg, bytes); +} + +int __cold mdbx_env_info2(const MDBX_env *env, const MDBX_txn *txn, + MDBX_envinfo *arg, size_t bytes) { + if (unlikely((env == NULL && txn == NULL) || arg == NULL)) + return MDBX_EINVAL; + + if (txn) { + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + } + if (env) { + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + if (txn && unlikely(txn->mt_env != env)) + return MDBX_EINVAL; + } else { + env = txn->mt_env; + } + + if (unlikely(bytes != sizeof(MDBX_envinfo))) + return MDBX_EINVAL; + + const MDBX_meta *const meta0 = METAPAGE(env, 0); + const MDBX_meta *const meta1 = METAPAGE(env, 1); + const MDBX_meta *const meta2 = METAPAGE(env, 2); + while (1) { + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) + return MDBX_PANIC; + + const MDBX_meta *const recent_meta = mdbx_meta_head(env); + arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, recent_meta); + arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0); + arg->mi_meta0_sign = meta0->mm_datasync_sign; + arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1); + arg->mi_meta1_sign = meta1->mm_datasync_sign; + arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); + arg->mi_meta2_sign = meta2->mm_datasync_sign; + + const MDBX_meta *txn_meta = recent_meta; + arg->mi_last_pgno = txn_meta->mm_geo.next - 1; + arg->mi_geo.current = pgno2bytes(env, txn_meta->mm_geo.now); + if (txn) { + arg->mi_last_pgno = txn->mt_next_pgno - 1; + arg->mi_geo.current = pgno2bytes(env, txn->mt_end_pgno); + + const txnid_t wanna_meta_txnid = + (txn->mt_flags & MDBX_RDONLY) ? txn->mt_txnid : txn->mt_txnid - 1; + txn_meta = (arg->mi_meta0_txnid == wanna_meta_txnid) ? meta0 : txn_meta; + txn_meta = (arg->mi_meta1_txnid == wanna_meta_txnid) ? meta1 : txn_meta; + txn_meta = (arg->mi_meta2_txnid == wanna_meta_txnid) ? meta2 : txn_meta; + } + arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower); + arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper); + arg->mi_geo.shrink = pgno2bytes(env, txn_meta->mm_geo.shrink); + arg->mi_geo.grow = pgno2bytes(env, txn_meta->mm_geo.grow); + + arg->mi_mapsize = env->me_mapsize; + mdbx_compiler_barrier(); + if (likely(arg->mi_meta0_txnid == mdbx_meta_txnid_fluid(env, meta0) && + arg->mi_meta0_sign == meta0->mm_datasync_sign && + arg->mi_meta1_txnid == mdbx_meta_txnid_fluid(env, meta1) && + arg->mi_meta1_sign == meta1->mm_datasync_sign && + arg->mi_meta2_txnid == mdbx_meta_txnid_fluid(env, meta2) && + arg->mi_meta2_sign == meta2->mm_datasync_sign && + recent_meta == mdbx_meta_head(env) && + arg->mi_recent_txnid == mdbx_meta_txnid_fluid(env, recent_meta))) + break; + } + + arg->mi_maxreaders = env->me_maxreaders; + arg->mi_numreaders = env->me_lck ? env->me_lck->mti_numreaders : INT32_MAX; + arg->mi_dxb_pagesize = env->me_psize; + arg->mi_sys_pagesize = env->me_os_psize; + + arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = 0; + if (env->me_lck) { + MDBX_reader *r = env->me_lck->mti_readers; + arg->mi_self_latter_reader_txnid = arg->mi_latter_reader_txnid = + arg->mi_recent_txnid; + for (unsigned i = 0; i < arg->mi_numreaders; ++i) { + const mdbx_pid_t pid = r[i].mr_pid; + if (pid) { + const txnid_t txnid = r[i].mr_txnid; + if (arg->mi_latter_reader_txnid > txnid) + arg->mi_latter_reader_txnid = txnid; + if (pid == env->me_pid && arg->mi_self_latter_reader_txnid > txnid) + arg->mi_self_latter_reader_txnid = txnid; + } + } + } + + return MDBX_SUCCESS; +} + +static MDBX_cmp_func *mdbx_default_keycmp(unsigned flags) { + return (flags & MDBX_REVERSEKEY) + ? mdbx_cmp_memnr + : (flags & MDBX_INTEGERKEY) ? mdbx_cmp_int_a2 : mdbx_cmp_memn; +} + +static MDBX_cmp_func *mdbx_default_datacmp(unsigned flags) { + return !(flags & MDBX_DUPSORT) + ? mdbx_cmp_memn + : ((flags & MDBX_INTEGERDUP) + ? mdbx_cmp_int_ua + : ((flags & MDBX_REVERSEDUP) ? mdbx_cmp_memnr + : mdbx_cmp_memn)); +} + +static int mdbx_dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, + MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp) { + /* LY: so, accepting only three cases for the table's flags: + * 1) user_flags and both comparators are zero + * = assume that a by-default mode/flags is requested for reading; + * 2) user_flags exactly the same + * = assume that the target mode/flags are requested properly; + * 3) user_flags differs, but table is empty and MDBX_CREATE is provided + * = assume that a properly create request with custom flags; + */ + if ((user_flags ^ txn->mt_dbs[dbi].md_flags) & PERSISTENT_FLAGS) { + /* flags ara differs, check other conditions */ + if (!user_flags && (!keycmp || keycmp == txn->mt_dbxs[dbi].md_cmp) && + (!datacmp || datacmp == txn->mt_dbxs[dbi].md_dcmp)) { + /* no comparators were provided and flags are zero, + * seems that is case #1 above */ + user_flags = txn->mt_dbs[dbi].md_flags; + } else if ((user_flags & MDBX_CREATE) && txn->mt_dbs[dbi].md_entries == 0) { + if (txn->mt_flags & MDBX_TXN_RDONLY) + return /* FIXME: return extended info */ MDBX_EACCESS; + /* make sure flags changes get committed */ + txn->mt_dbs[dbi].md_flags = user_flags & PERSISTENT_FLAGS; + txn->mt_flags |= MDBX_TXN_DIRTY; + } else { + return /* FIXME: return extended info */ MDBX_INCOMPATIBLE; + } + } + + if (!txn->mt_dbxs[dbi].md_cmp || MDBX_DEBUG) { + if (!keycmp) + keycmp = mdbx_default_keycmp(user_flags); + mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_cmp || + txn->mt_dbxs[dbi].md_cmp == keycmp); + txn->mt_dbxs[dbi].md_cmp = keycmp; + } + + if (!txn->mt_dbxs[dbi].md_dcmp || MDBX_DEBUG) { + if (!datacmp) + datacmp = mdbx_default_datacmp(user_flags); + mdbx_tassert(txn, !txn->mt_dbxs[dbi].md_dcmp || + txn->mt_dbxs[dbi].md_dcmp == datacmp); + txn->mt_dbxs[dbi].md_dcmp = datacmp; + } + + return MDBX_SUCCESS; +} + +int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags, + MDBX_dbi *dbi, MDBX_cmp_func *keycmp, + MDBX_cmp_func *datacmp) { + if (unlikely(!txn || !dbi || (user_flags & ~VALID_FLAGS) != 0)) + return MDBX_EINVAL; + + switch (user_flags & + (MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT | MDBX_REVERSEDUP)) { + default: + return MDBX_EINVAL; + case MDBX_DUPSORT: + case MDBX_DUPSORT | MDBX_REVERSEDUP: + case MDBX_DUPSORT | MDBX_DUPFIXED: + case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_REVERSEDUP: + case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP: + case MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP: + case 0: + break; + } + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + /* main table? */ + if (!table_name) { + *dbi = MAIN_DBI; + return mdbx_dbi_bind(txn, MAIN_DBI, user_flags, keycmp, datacmp); + } + + if (txn->mt_dbxs[MAIN_DBI].md_cmp == NULL) { + txn->mt_dbxs[MAIN_DBI].md_cmp = + mdbx_default_keycmp(txn->mt_dbs[MAIN_DBI].md_flags); + txn->mt_dbxs[MAIN_DBI].md_dcmp = + mdbx_default_datacmp(txn->mt_dbs[MAIN_DBI].md_flags); + } + + /* Is the DB already open? */ + size_t len = strlen(table_name); + MDBX_dbi scan, slot; + for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) { + if (!txn->mt_dbxs[scan].md_name.iov_len) { + /* Remember this free slot */ + slot = scan; + continue; + } + if (len == txn->mt_dbxs[scan].md_name.iov_len && + !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) { + *dbi = scan; + return mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp); + } + } + + /* Fail, if no free slot and max hit */ + MDBX_env *env = txn->mt_env; + if (unlikely(slot >= env->me_maxdbs)) + return MDBX_DBS_FULL; + + /* Cannot mix named table with some main-table flags */ + if (unlikely(txn->mt_dbs[MAIN_DBI].md_flags & + (MDBX_DUPSORT | MDBX_INTEGERKEY))) + return (user_flags & MDBX_CREATE) ? MDBX_INCOMPATIBLE : MDBX_NOTFOUND; + + /* Find the DB info */ + int exact = 0; + MDBX_val key, data; + key.iov_len = len; + key.iov_base = (void *)table_name; + MDBX_cursor mc; + int rc = mdbx_cursor_init(&mc, txn, MAIN_DBI); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_cursor_set(&mc, &key, &data, MDBX_SET, &exact); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_NOTFOUND || !(user_flags & MDBX_CREATE)) + return rc; + } else { + /* make sure this is actually a table */ + MDBX_node *node = NODEPTR(mc.mc_pg[mc.mc_top], mc.mc_ki[mc.mc_top]); + if (unlikely((node->mn_flags & (F_DUPDATA | F_SUBDATA)) != F_SUBDATA)) + return MDBX_INCOMPATIBLE; + } + + if (rc != MDBX_SUCCESS && unlikely(txn->mt_flags & MDBX_TXN_RDONLY)) + return MDBX_EACCESS; + + /* Done here so we cannot fail after creating a new DB */ + char *namedup = mdbx_strdup(table_name); + if (unlikely(!namedup)) + return MDBX_ENOMEM; + + int err = mdbx_fastmutex_acquire(&env->me_dbi_lock); + if (unlikely(err != MDBX_SUCCESS)) { + mdbx_free(namedup); + return err; + } + + if (txn->mt_numdbs < env->me_numdbs) { + for (unsigned i = txn->mt_numdbs; i < env->me_numdbs; ++i) { + txn->mt_dbflags[i] = 0; + if (env->me_dbflags[i] & MDBX_VALID) { + txn->mt_dbs[i].md_flags = env->me_dbflags[i] & PERSISTENT_FLAGS; + txn->mt_dbflags[i] = DB_VALID | DB_USRVALID | DB_STALE; + mdbx_tassert(txn, txn->mt_dbxs[i].md_cmp != NULL); + } + } + txn->mt_numdbs = env->me_numdbs; + } + + for (slot = scan = txn->mt_numdbs; --scan >= CORE_DBS;) { + if (!txn->mt_dbxs[scan].md_name.iov_len) { + /* Remember this free slot */ + slot = scan; + continue; + } + if (len == txn->mt_dbxs[scan].md_name.iov_len && + !strncmp(table_name, txn->mt_dbxs[scan].md_name.iov_base, len)) { + *dbi = scan; + rc = mdbx_dbi_bind(txn, scan, user_flags, keycmp, datacmp); + goto bailout; + } + } + + if (unlikely(slot >= env->me_maxdbs)) { + rc = MDBX_DBS_FULL; + goto bailout; + } + + unsigned dbflag = DB_FRESH | DB_VALID | DB_USRVALID; + MDBX_db db_dummy; + if (unlikely(rc)) { + /* MDBX_NOTFOUND and MDBX_CREATE: Create new DB */ + mdbx_tassert(txn, rc == MDBX_NOTFOUND); + memset(&db_dummy, 0, sizeof(db_dummy)); + db_dummy.md_root = P_INVALID; + db_dummy.md_flags = user_flags & PERSISTENT_FLAGS; + data.iov_len = sizeof(db_dummy); + data.iov_base = &db_dummy; + WITH_CURSOR_TRACKING( + mc, + rc = mdbx_cursor_put(&mc, &key, &data, F_SUBDATA | MDBX_NOOVERWRITE)); + + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + + dbflag |= DB_DIRTY | DB_CREAT; + } + + /* Got info, register DBI in this txn */ + txn->mt_dbxs[slot].md_cmp = nullptr; + txn->mt_dbxs[slot].md_dcmp = nullptr; + txn->mt_dbs[slot] = *(MDBX_db *)data.iov_base; + env->me_dbflags[slot] = 0; + rc = mdbx_dbi_bind(txn, slot, user_flags, keycmp, datacmp); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_tassert(txn, (dbflag & DB_CREAT) == 0); + bailout: + mdbx_free(namedup); + } else { + txn->mt_dbflags[slot] = (uint8_t)dbflag; + txn->mt_dbxs[slot].md_name.iov_base = namedup; + txn->mt_dbxs[slot].md_name.iov_len = len; + txn->mt_numdbs += (slot == txn->mt_numdbs); + if ((dbflag & DB_CREAT) == 0) { + env->me_dbflags[slot] = txn->mt_dbs[slot].md_flags | MDBX_VALID; + mdbx_compiler_barrier(); + if (env->me_numdbs <= slot) + env->me_numdbs = slot + 1; + } else { + env->me_dbiseqs[slot] += 1; + } + txn->mt_dbiseqs[slot] = env->me_dbiseqs[slot]; + *dbi = slot; + } + + mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); + return rc; +} + +int mdbx_dbi_open(MDBX_txn *txn, const char *table_name, unsigned table_flags, + MDBX_dbi *dbi) { + return mdbx_dbi_open_ex(txn, table_name, table_flags, dbi, nullptr, nullptr); +} + +int __cold mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *arg, + size_t bytes) { + if (unlikely(!arg || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) + return MDBX_EINVAL; + + if (unlikely(bytes != sizeof(MDBX_stat))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) { + MDBX_cursor_couple cx; + /* Stale, must read the DB's root. cursor_init does it for us. */ + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + return mdbx_stat0(txn->mt_env, &txn->mt_dbs[dbi], arg); +} + +static int mdbx_dbi_close_locked(MDBX_env *env, MDBX_dbi dbi) { + if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs)) + return MDBX_EINVAL; + + char *ptr = env->me_dbxs[dbi].md_name.iov_base; + /* If there was no name, this was already closed */ + if (unlikely(!ptr)) + return MDBX_BAD_DBI; + + env->me_dbflags[dbi] = 0; + env->me_dbxs[dbi].md_name.iov_len = 0; + mdbx_compiler_barrier(); + env->me_dbiseqs[dbi]++; + env->me_dbxs[dbi].md_name.iov_base = NULL; + mdbx_free(ptr); + return MDBX_SUCCESS; +} + +int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(dbi < CORE_DBS || dbi >= env->me_maxdbs)) + return MDBX_EINVAL; + + int rc = mdbx_fastmutex_acquire(&env->me_dbi_lock); + if (likely(rc == MDBX_SUCCESS)) { + rc = mdbx_dbi_close_locked(env, dbi); + mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); + } + return rc; +} + +int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, + unsigned *state) { + if (unlikely(!txn || !flags || !state)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) + return MDBX_EINVAL; + + *flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS; + *state = txn->mt_dbflags[dbi] & (DB_FRESH | DB_CREAT | DB_DIRTY | DB_STALE); + + return MDBX_SUCCESS; +} + +int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { + unsigned state; + return mdbx_dbi_flags_ex(txn, dbi, flags, &state); +} + +/* Add all the DB's pages to the free list. + * [in] mc Cursor on the DB to free. + * [in] subs non-Zero to check for sub-DBs in this DB. + * Returns 0 on success, non-zero on failure. */ +static int mdbx_drop0(MDBX_cursor *mc, int subs) { + int rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST); + if (likely(rc == MDBX_SUCCESS)) { + MDBX_txn *txn = mc->mc_txn; + MDBX_node *ni; + MDBX_cursor mx; + unsigned i; + + /* DUPSORT sub-DBs have no ovpages/DBs. Omit scanning leaves. + * This also avoids any P_LEAF2 pages, which have no nodes. + * Also if the DB doesn't have sub-DBs and has no overflow + * pages, omit scanning leaves. */ + + if (mc->mc_flags & C_SUB) { + MDBX_db *outer = mdbx_outer_db(mc); + outer->md_branch_pages -= mc->mc_db->md_branch_pages; + outer->md_leaf_pages -= mc->mc_db->md_leaf_pages; + outer->md_overflow_pages -= mc->mc_db->md_overflow_pages; + mdbx_cursor_pop(mc); + } else if (!subs && !mc->mc_db->md_overflow_pages) + mdbx_cursor_pop(mc); + + mdbx_cursor_copy(mc, &mx); + while (mc->mc_snum > 0) { + MDBX_page *mp = mc->mc_pg[mc->mc_top]; + unsigned n = NUMKEYS(mp); + if (IS_LEAF(mp)) { + for (i = 0; i < n; i++) { + ni = NODEPTR(mp, i); + if (ni->mn_flags & F_BIGDATA) { + MDBX_page *omp; + pgno_t pg; + memcpy(&pg, NODEDATA(ni), sizeof(pg)); + rc = mdbx_page_get(mc, pg, &omp, NULL); + if (unlikely(rc)) + goto done; + mdbx_cassert(mc, IS_OVERFLOW(omp)); + rc = mdbx_page_befree(mc, omp); + if (unlikely(rc)) + goto done; + if (!mc->mc_db->md_overflow_pages && !subs) + break; + } else if (subs && (ni->mn_flags & F_SUBDATA)) { + rc = mdbx_xcursor_init1(mc, ni); + if (unlikely(rc != MDBX_SUCCESS)) + goto done; + rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, 0); + if (unlikely(rc)) + goto done; + } + } + if (!subs && !mc->mc_db->md_overflow_pages) + goto pop; + } else { + if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages, n)) != 0)) + goto done; + for (i = 0; i < n; i++) { + pgno_t pg; + ni = NODEPTR(mp, i); + pg = NODEPGNO(ni); + /* free it */ + mdbx_pnl_xappend(txn->mt_befree_pages, pg); + } + } + if (!mc->mc_top) + break; + mdbx_cassert(mc, i <= UINT16_MAX); + mc->mc_ki[mc->mc_top] = (indx_t)i; + rc = mdbx_cursor_sibling(mc, 1); + if (rc) { + if (unlikely(rc != MDBX_NOTFOUND)) + goto done; + /* no more siblings, go back to beginning + * of previous level. */ + pop: + mdbx_cursor_pop(mc); + mc->mc_ki[0] = 0; + for (i = 1; i < mc->mc_snum; i++) { + mc->mc_ki[i] = 0; + mc->mc_pg[i] = mx.mc_pg[i]; + } + } + } + /* free it */ + rc = mdbx_pnl_append(&txn->mt_befree_pages, mc->mc_db->md_root); + done: + if (unlikely(rc)) + txn->mt_flags |= MDBX_TXN_ERROR; + } else if (rc == MDBX_NOTFOUND) { + rc = MDBX_SUCCESS; + } + mc->mc_flags &= ~C_INITIALIZED; + return rc; +} + +int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del) { + if (unlikely(1 < (unsigned)del || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(TXN_DBI_CHANGED(txn, dbi))) + return MDBX_BAD_DBI; + + if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))) + return MDBX_EACCESS; + + MDBX_cursor *mc; + int rc = mdbx_cursor_open(txn, dbi, &mc); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + MDBX_env *env = txn->mt_env; + rc = mdbx_fastmutex_acquire(&env->me_dbi_lock); + if (unlikely(rc != MDBX_SUCCESS)) { + mdbx_cursor_close(mc); + return rc; + } + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) { + rc = MDBX_EINVAL; + goto bailout; + } + + if (unlikely(TXN_DBI_CHANGED(txn, dbi))) { + rc = MDBX_BAD_DBI; + goto bailout; + } + + rc = mdbx_drop0(mc, mc->mc_db->md_flags & MDBX_DUPSORT); + /* Invalidate the dropped DB's cursors */ + for (MDBX_cursor *m2 = txn->mt_cursors[dbi]; m2; m2 = m2->mc_next) + m2->mc_flags &= ~(C_INITIALIZED | C_EOF); + if (unlikely(rc)) + goto bailout; + + /* Can't delete the main DB */ + if (del && dbi >= CORE_DBS) { + rc = mdbx_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, F_SUBDATA); + if (likely(!rc)) { + txn->mt_dbflags[dbi] = DB_STALE; + mdbx_dbi_close_locked(env, dbi); + } else { + txn->mt_flags |= MDBX_TXN_ERROR; + } + } else { + /* reset the DB record, mark it dirty */ + txn->mt_dbflags[dbi] |= DB_DIRTY; + txn->mt_dbs[dbi].md_depth = 0; + txn->mt_dbs[dbi].md_branch_pages = 0; + txn->mt_dbs[dbi].md_leaf_pages = 0; + txn->mt_dbs[dbi].md_overflow_pages = 0; + txn->mt_dbs[dbi].md_entries = 0; + txn->mt_dbs[dbi].md_root = P_INVALID; + txn->mt_dbs[dbi].md_seq = 0; + txn->mt_flags |= MDBX_TXN_DIRTY; + } + +bailout: + mdbx_cursor_close(mc); + mdbx_ensure(env, mdbx_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); + return rc; +} + +int mdbx_set_compare(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + txn->mt_dbxs[dbi].md_cmp = cmp; + return MDBX_SUCCESS; +} + +int mdbx_set_dupsort(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + txn->mt_dbxs[dbi].md_dcmp = cmp; + return MDBX_SUCCESS; +} + +int __cold mdbx_reader_list(MDBX_env *env, MDBX_msg_func *func, void *ctx) { + char buf[64]; + int rc = 0, first = 1; + + if (unlikely(!env || !func)) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + const MDBX_lockinfo *const lck = env->me_lck; + if (likely(lck)) { + const unsigned snap_nreaders = lck->mti_numreaders; + for (unsigned i = 0; i < snap_nreaders; i++) { + if (lck->mti_readers[i].mr_pid) { + const txnid_t txnid = lck->mti_readers[i].mr_txnid; + if (txnid == ~(txnid_t)0) + snprintf(buf, sizeof(buf), "%10" PRIuPTR " %" PRIxPTR " -\n", + (uintptr_t)lck->mti_readers[i].mr_pid, + (uintptr_t)lck->mti_readers[i].mr_tid); + else + snprintf(buf, sizeof(buf), + "%10" PRIuPTR " %" PRIxPTR " %" PRIaTXN "\n", + (uintptr_t)lck->mti_readers[i].mr_pid, + (uintptr_t)lck->mti_readers[i].mr_tid, txnid); + + if (first) { + first = 0; + rc = func(" pid thread txnid\n", ctx); + if (rc < 0) + break; + } + rc = func(buf, ctx); + if (rc < 0) + break; + } + } + } + if (first) + rc = func("(no active readers)\n", ctx); + + return rc; +} + +/* Insert pid into list if not already present. + * return -1 if already present. */ +static int __cold mdbx_pid_insert(mdbx_pid_t *ids, mdbx_pid_t pid) { + /* binary search of pid in list */ + unsigned base = 0; + unsigned cursor = 1; + int val = 0; + unsigned n = ids[0]; + + while (n > 0) { + unsigned pivot = n >> 1; + cursor = base + pivot + 1; + val = pid - ids[cursor]; + + if (val < 0) { + n = pivot; + } else if (val > 0) { + base = cursor; + n -= pivot + 1; + } else { + /* found, so it's a duplicate */ + return -1; + } + } + + if (val > 0) + ++cursor; + + ids[0]++; + for (n = ids[0]; n > cursor; n--) + ids[n] = ids[n - 1]; + ids[n] = pid; + return 0; +} + +int __cold mdbx_reader_check(MDBX_env *env, int *dead) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (dead) + *dead = 0; + return mdbx_reader_check0(env, false, dead); +} + +/* Return: + * MDBX_RESULT_TRUE - done and mutex recovered + * MDBX_SUCCESS - done + * Otherwise errcode. */ +int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) { + mdbx_assert(env, rdt_locked >= 0); + +#if MDBX_TXN_CHECKPID + if (unlikely(env->me_pid != mdbx_getpid())) { + env->me_flags |= MDBX_FATAL_ERROR; + return MDBX_PANIC; + } +#endif /* MDBX_TXN_CHECKPID */ + + MDBX_lockinfo *const lck = env->me_lck; + if (unlikely(lck == NULL)) { + /* exclusive mode */ + if (dead) + *dead = 0; + return MDBX_SUCCESS; + } + + const unsigned snap_nreaders = lck->mti_numreaders; + mdbx_pid_t pidsbuf_onstask[142]; + mdbx_pid_t *const pids = + (snap_nreaders < ARRAY_LENGTH(pidsbuf_onstask)) + ? pidsbuf_onstask + : mdbx_malloc((snap_nreaders + 1) * sizeof(mdbx_pid_t)); + if (unlikely(!pids)) + return MDBX_ENOMEM; + + pids[0] = 0; + + int rc = MDBX_SUCCESS, count = 0; + for (unsigned i = 0; i < snap_nreaders; i++) { + const mdbx_pid_t pid = lck->mti_readers[i].mr_pid; + if (pid == 0) + continue /* skip empty */; + if (pid == env->me_pid) + continue /* skip self */; + if (mdbx_pid_insert(pids, pid) != 0) + continue /* such pid already processed */; + + int err = mdbx_rpid_check(env, pid); + if (err == MDBX_RESULT_TRUE) + continue /* reader is live */; + + if (err != MDBX_SUCCESS) { + rc = err; + break /* mdbx_rpid_check() failed */; + } + + /* stale reader found */ + if (!rdt_locked) { + err = mdbx_rdt_lock(env); + if (MDBX_IS_ERROR(err)) { + rc = err; + break; + } + + rdt_locked = -1; + if (err == MDBX_RESULT_TRUE) { + /* mutex recovered, the mdbx_mutex_failed() checked all readers */ + rc = MDBX_RESULT_TRUE; + break; + } + + /* a other process may have clean and reused slot, recheck */ + if (lck->mti_readers[i].mr_pid != pid) + continue; + + err = mdbx_rpid_check(env, pid); + if (MDBX_IS_ERROR(err)) { + rc = err; + break; + } + + if (err != MDBX_SUCCESS) + continue /* the race with other process, slot reused */; + } + + /* clean it */ + for (unsigned j = i; j < snap_nreaders; j++) { + if (lck->mti_readers[j].mr_pid == pid) { + mdbx_debug("clear stale reader pid %" PRIuPTR " txn %" PRIaTXN, + (size_t)pid, lck->mti_readers[j].mr_txnid); + lck->mti_readers[j].mr_pid = 0; + lck->mti_readers_refresh_flag = true; + count++; + } + } + } + + if (rdt_locked < 0) + mdbx_rdt_unlock(env); + + if (pids != pidsbuf_onstask) + mdbx_free(pids); + + if (dead) + *dead = count; + return rc; +} + +int __cold mdbx_setup_debug(int flags, MDBX_debug_func *logger) { + const int rc = mdbx_runtime_flags; + if (flags != -1) { +#if !MDBX_DEBUG + flags &= MDBX_DBG_DUMP | MDBX_DBG_LEGACY_MULTIOPEN; +#else + flags &= MDBX_DBG_ASSERT | MDBX_DBG_PRINT | MDBX_DBG_TRACE | + MDBX_DBG_EXTRA | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | MDBX_DBG_DUMP | + MDBX_DBG_LEGACY_MULTIOPEN; +#endif +#if defined(__linux__) || defined(__gnu_linux__) + if ((mdbx_runtime_flags ^ flags) & MDBX_DBG_DUMP) { + /* http://man7.org/linux/man-pages/man5/core.5.html */ + const unsigned long dump_bits = + 1 << 3 /* Dump file-backed shared mappings */ + | 1 << 6 /* Dump shared huge pages */ + | 1 << 8 /* Dump shared DAX pages */; + const int core_filter_fd = + open("/proc/self/coredump_filter", O_TRUNC | O_RDWR); + if (core_filter_fd != -1) { + char buf[32]; + intptr_t bytes = pread(core_filter_fd, buf, sizeof(buf), 0); + if (bytes > 0 && (size_t)bytes < sizeof(buf)) { + buf[bytes] = 0; + const unsigned long present_mask = strtoul(buf, NULL, 16); + const unsigned long wanna_mask = (flags & MDBX_DBG_DUMP) + ? present_mask | dump_bits + : present_mask & ~dump_bits; + if (wanna_mask != present_mask) { + bytes = snprintf(buf, sizeof(buf), "0x%lx\n", wanna_mask); + if (bytes > 0 && (size_t)bytes < sizeof(buf)) { + bytes = pwrite(core_filter_fd, buf, bytes, 0); + (void)bytes; + } + } + } + close(core_filter_fd); + } + } +#endif /* Linux */ + mdbx_runtime_flags = flags; + } + + if (-1 != (intptr_t)logger) + mdbx_debug_logger = logger; + return rc; +} + +static txnid_t __cold mdbx_oomkick(MDBX_env *env, const txnid_t laggard) { + mdbx_debug("DB size maxed out"); + + int retry; + for (retry = 0; retry < INT_MAX; ++retry) { + txnid_t oldest = mdbx_reclaiming_detent(env); + mdbx_assert(env, oldest < env->me_txn0->mt_txnid); + mdbx_assert(env, oldest >= laggard); + mdbx_assert(env, oldest >= *env->me_oldest); + if (oldest == laggard || unlikely(env->me_lck == NULL /* exclusive mode */)) + return oldest; + + if (MDBX_IS_ERROR(mdbx_reader_check0(env, false, NULL))) + break; + + MDBX_reader *const rtbl = env->me_lck->mti_readers; + MDBX_reader *asleep = nullptr; + for (int i = env->me_lck->mti_numreaders; --i >= 0;) { + if (rtbl[i].mr_pid) { + mdbx_jitter4testing(true); + const txnid_t snap = rtbl[i].mr_txnid; + if (oldest > snap && laggard <= /* ignore pending updates */ snap) { + oldest = snap; + asleep = &rtbl[i]; + } + } + } + + if (laggard < oldest || !asleep) { + if (retry && env->me_oom_func) { + /* LY: notify end of oom-loop */ + const txnid_t gap = oldest - laggard; + env->me_oom_func(env, 0, 0, laggard, + (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, -retry); + } + mdbx_notice("oom-kick: update oldest %" PRIaTXN " -> %" PRIaTXN, + *env->me_oldest, oldest); + mdbx_assert(env, *env->me_oldest <= oldest); + return *env->me_oldest = oldest; + } + + mdbx_tid_t tid; + mdbx_pid_t pid; + int rc; + + if (!env->me_oom_func) + break; + + pid = asleep->mr_pid; + tid = asleep->mr_tid; + if (asleep->mr_txnid != laggard || pid <= 0) + continue; + + const txnid_t gap = + mdbx_meta_txnid_stable(env, mdbx_meta_head(env)) - laggard; + rc = env->me_oom_func(env, pid, tid, laggard, + (gap < UINT_MAX) ? (unsigned)gap : UINT_MAX, retry); + if (rc < 0) + break; + + if (rc) { + asleep->mr_txnid = ~(txnid_t)0; + env->me_lck->mti_readers_refresh_flag = true; + if (rc > 1) { + asleep->mr_tid = 0; + asleep->mr_pid = 0; + mdbx_flush_noncoherent_cpu_writeback(); + } + } + } + + if (retry && env->me_oom_func) { + /* LY: notify end of oom-loop */ + env->me_oom_func(env, 0, 0, laggard, 0, -retry); + } + return mdbx_find_oldest(env->me_txn); +} + +int __cold mdbx_env_set_syncbytes(MDBX_env *env, size_t bytes) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) + return MDBX_EACCESS; + + if (unlikely(!env->me_map)) + return MDBX_EPERM; + + *env->me_autosync_threshold = bytes2pgno(env, bytes + env->me_psize - 1); + return bytes ? mdbx_env_sync(env, false) : MDBX_SUCCESS; +} + +int __cold mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(env->me_flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) + return MDBX_EACCESS; + + if (unlikely(!env->me_map)) + return MDBX_EPERM; + + *env->me_autosync_period = mdbx_osal_16dot16_to_monotime(seconds_16dot16); + return seconds_16dot16 ? mdbx_env_sync(env, false) : MDBX_SUCCESS; +} + +int __cold mdbx_env_set_oomfunc(MDBX_env *env, MDBX_oom_func *oomfunc) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + env->me_oom_func = oomfunc; + return MDBX_SUCCESS; +} + +MDBX_oom_func *__cold mdbx_env_get_oomfunc(MDBX_env *env) { + return likely(env && env->me_signature == MDBX_ME_SIGNATURE) + ? env->me_oom_func + : NULL; +} + +#ifdef __SANITIZE_THREAD__ +/* LY: avoid tsan-trap by me_txn, mm_last_pg and mt_next_pgno */ +__attribute__((__no_sanitize_thread__, __noinline__)) +#endif +int mdbx_txn_straggler(MDBX_txn *txn, int *percent) +{ + if (unlikely(!txn)) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + MDBX_env *env = txn->mt_env; + if (unlikely((txn->mt_flags & MDBX_RDONLY) == 0)) { + if (percent) + *percent = + (int)((txn->mt_next_pgno * UINT64_C(100) + txn->mt_end_pgno / 2) / + txn->mt_end_pgno); + return 0; + } + + txnid_t recent; + MDBX_meta *meta; + do { + meta = mdbx_meta_head(env); + recent = mdbx_meta_txnid_fluid(env, meta); + if (percent) { + const pgno_t maxpg = meta->mm_geo.now; + *percent = (int)((meta->mm_geo.next * UINT64_C(100) + maxpg / 2) / maxpg); + } + } while (unlikely(recent != mdbx_meta_txnid_fluid(env, meta))); + + txnid_t lag = recent - txn->mt_ro_reader->mr_txnid; + return (lag > INT_MAX) ? INT_MAX : (int)lag; +} + +typedef struct mdbx_walk_ctx { + void *mw_user; + MDBX_pgvisitor_func *mw_visitor; + MDBX_cursor mw_cursor; +} mdbx_walk_ctx_t; + +/* Depth-first tree traversal. */ +static int __cold mdbx_env_walk(mdbx_walk_ctx_t *ctx, const char *dbi, + pgno_t pgno, int deep) { + if (unlikely(pgno == P_INVALID)) + return MDBX_SUCCESS; /* empty db */ + + MDBX_page *mp; + int rc = mdbx_page_get(&ctx->mw_cursor, pgno, &mp, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + const int nkeys = NUMKEYS(mp); + size_t header_size = IS_LEAF2(mp) ? PAGEHDRSZ : PAGEHDRSZ + mp->mp_lower; + size_t unused_size = SIZELEFT(mp); + size_t payload_size = 0; + size_t align_bytes = 0; + MDBX_page_type_t type; + + /* LY: Don't use mask here, e.g bitwise + * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP). + * Pages should not me marked dirty/loose or otherwise. */ + switch (mp->mp_flags) { + case P_BRANCH: + type = MDBX_page_branch; + if (unlikely(nkeys < 2)) + return MDBX_CORRUPTED; + break; + case P_LEAF: + type = MDBX_page_leaf; + break; + case P_LEAF | P_LEAF2: + type = MDBX_page_dupfixed_leaf; + break; + default: + return MDBX_CORRUPTED; + } + + for (int i = 0; i < nkeys; + align_bytes += ((payload_size + align_bytes) & 1), i++) { + if (type == MDBX_page_dupfixed_leaf) { + /* LEAF2 pages have no mp_ptrs[] or node headers */ + payload_size += mp->mp_leaf2_ksize; + continue; + } + + MDBX_node *node = NODEPTR(mp, i); + payload_size += NODESIZE + NODEKSZ(node); + + if (type == MDBX_page_branch) + continue; + + assert(type == MDBX_page_leaf); + switch (node->mn_flags) { + case 0 /* usual node */: { + payload_size += NODEDSZ(node); + } break; + + case F_BIGDATA /* long data on the large/overflow page */: { + payload_size += sizeof(pgno_t); + + MDBX_page *op; + pgno_t large_pgno; + memcpy(&large_pgno, NODEDATA(node), sizeof(pgno_t)); + rc = mdbx_page_get(&ctx->mw_cursor, large_pgno, &op, NULL); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + /* LY: Don't use mask here, e.g bitwise + * (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP). + * Pages should not me marked dirty/loose or otherwise. */ + if (unlikely(P_OVERFLOW != op->mp_flags)) + return MDBX_CORRUPTED; + + const size_t over_header = PAGEHDRSZ; + const size_t over_payload = NODEDSZ(node); + const size_t over_unused = + pgno2bytes(ctx->mw_cursor.mc_txn->mt_env, op->mp_pages) - + over_payload - over_header; + + rc = ctx->mw_visitor( + large_pgno, op->mp_pages, ctx->mw_user, deep, dbi, + pgno2bytes(ctx->mw_cursor.mc_txn->mt_env, op->mp_pages), + MDBX_page_large, 1, over_payload, over_header, over_unused); + } break; + + case F_SUBDATA /* sub-db */: { + const size_t namelen = NODEKSZ(node); + if (unlikely(namelen == 0 || NODEDSZ(node) != sizeof(MDBX_db))) + return MDBX_CORRUPTED; + payload_size += sizeof(MDBX_db); + } break; + + case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: { + if (unlikely(NODEDSZ(node) != sizeof(MDBX_db))) + return MDBX_CORRUPTED; + payload_size += sizeof(MDBX_db); + } break; + + case F_DUPDATA /* short sub-page */: { + if (unlikely(NODEDSZ(node) < PAGEHDRSZ)) + return MDBX_CORRUPTED; + + MDBX_page *sp = NODEDATA(node); + const int nsubkeys = NUMKEYS(sp); + size_t subheader_size = + IS_LEAF2(sp) ? PAGEHDRSZ : PAGEHDRSZ + sp->mp_lower; + size_t subunused_size = SIZELEFT(sp); + size_t subpayload_size = 0; + size_t subalign_bytes = 0; + MDBX_page_type_t subtype; + + switch (sp->mp_flags & ~P_DIRTY /* ignore for sub-pages */) { + case P_LEAF | P_SUBP: + subtype = MDBX_subpage_leaf; + break; + case P_LEAF | P_LEAF2 | P_SUBP: + subtype = MDBX_subpage_dupfixed_leaf; + break; + default: + return MDBX_CORRUPTED; + } + + for (int j = 0; j < nsubkeys; + subalign_bytes += ((subpayload_size + subalign_bytes) & 1), j++) { + + if (subtype == MDBX_subpage_dupfixed_leaf) { + /* LEAF2 pages have no mp_ptrs[] or node headers */ + subpayload_size += sp->mp_leaf2_ksize; + } else { + assert(subtype == MDBX_subpage_leaf); + MDBX_node *subnode = NODEPTR(sp, j); + subpayload_size += NODESIZE + NODEKSZ(subnode) + NODEDSZ(subnode); + if (unlikely(subnode->mn_flags != 0)) + return MDBX_CORRUPTED; + } + } + + rc = ctx->mw_visitor(pgno, 0, ctx->mw_user, deep + 1, dbi, NODEDSZ(node), + subtype, nsubkeys, subpayload_size, subheader_size, + subunused_size + subalign_bytes); + header_size += subheader_size; + unused_size += subunused_size; + payload_size += subpayload_size; + align_bytes += subalign_bytes; + } break; + + default: + return MDBX_CORRUPTED; + } + + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + rc = ctx->mw_visitor(mp->mp_pgno, 1, ctx->mw_user, deep, dbi, + ctx->mw_cursor.mc_txn->mt_env->me_psize, type, nkeys, + payload_size, header_size, unused_size + align_bytes); + + if (unlikely(rc != MDBX_SUCCESS)) + return (rc == MDBX_RESULT_TRUE) ? MDBX_SUCCESS : rc; + + for (int i = 0; i < nkeys; i++) { + if (type == MDBX_page_dupfixed_leaf) + continue; + + MDBX_node *node = NODEPTR(mp, i); + if (type == MDBX_page_branch) { + rc = mdbx_env_walk(ctx, dbi, NODEPGNO(node), deep + 1); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_RESULT_TRUE) + return rc; + break; + } + continue; + } + + assert(type == MDBX_page_leaf); + MDBX_db db; + switch (node->mn_flags) { + default: + continue; + + case F_SUBDATA /* sub-db */: { + const size_t namelen = NODEKSZ(node); + if (unlikely(namelen == 0 || NODEDSZ(node) != sizeof(MDBX_db))) + return MDBX_CORRUPTED; + + char namebuf_onstask[142]; + char *const name = (namelen < sizeof(namebuf_onstask)) + ? namebuf_onstask + : mdbx_malloc(namelen + 1); + if (name) { + memcpy(name, NODEKEY(node), namelen); + name[namelen] = 0; + memcpy(&db, NODEDATA(node), sizeof(db)); + rc = mdbx_env_walk(ctx, name, db.md_root, deep + 1); + if (name != namebuf_onstask) + mdbx_free(name); + } else { + rc = MDBX_ENOMEM; + } + } break; + + case F_SUBDATA | F_DUPDATA /* dupsorted sub-tree */: + if (unlikely(NODEDSZ(node) != sizeof(MDBX_db))) + return MDBX_CORRUPTED; + + memcpy(&db, NODEDATA(node), sizeof(db)); + rc = mdbx_env_walk(ctx, dbi, db.md_root, deep + 1); + break; + } + + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + return MDBX_SUCCESS; +} + +int __cold mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor, + void *user) { + if (unlikely(!txn)) + return MDBX_BAD_TXN; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + mdbx_walk_ctx_t ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.mw_cursor.mc_snum = 1; + ctx.mw_cursor.mc_txn = txn; + ctx.mw_user = user; + ctx.mw_visitor = visitor; + + int rc = visitor( + 0, NUM_METAS, user, 0, MDBX_PGWALK_META, + pgno2bytes(txn->mt_env, NUM_METAS), MDBX_page_meta, NUM_METAS, + sizeof(MDBX_meta) * NUM_METAS, PAGEHDRSZ * NUM_METAS, + (txn->mt_env->me_psize - sizeof(MDBX_meta) - PAGEHDRSZ) * NUM_METAS); + if (!MDBX_IS_ERROR(rc)) + rc = mdbx_env_walk(&ctx, MDBX_PGWALK_GC, txn->mt_dbs[FREE_DBI].md_root, 0); + if (!MDBX_IS_ERROR(rc)) + rc = + mdbx_env_walk(&ctx, MDBX_PGWALK_MAIN, txn->mt_dbs[MAIN_DBI].md_root, 0); + if (!MDBX_IS_ERROR(rc)) + rc = visitor(P_INVALID, 0, user, INT_MIN, NULL, 0, MDBX_page_void, 0, 0, 0, + 0); + return rc; +} + +int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))) + return MDBX_EACCESS; + + if (likely(canary)) { + if (txn->mt_canary.x == canary->x && txn->mt_canary.y == canary->y && + txn->mt_canary.z == canary->z) + return MDBX_SUCCESS; + txn->mt_canary.x = canary->x; + txn->mt_canary.y = canary->y; + txn->mt_canary.z = canary->z; + } + txn->mt_canary.v = txn->mt_txnid; + + if ((txn->mt_flags & MDBX_TXN_DIRTY) == 0) { + txn->mt_flags |= MDBX_TXN_DIRTY; + *txn->mt_env->me_unsynced_pages += 1; + } + return MDBX_SUCCESS; +} + +int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary) { + if (unlikely(txn == NULL || canary == NULL)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + *canary = txn->mt_canary; + return MDBX_SUCCESS; +} + +int mdbx_cursor_on_first(MDBX_cursor *mc) { + if (unlikely(mc == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (!(mc->mc_flags & C_INITIALIZED)) + return MDBX_RESULT_FALSE; + + for (unsigned i = 0; i < mc->mc_snum; ++i) { + if (mc->mc_ki[i]) + return MDBX_RESULT_FALSE; + } + + return MDBX_RESULT_TRUE; +} + +int mdbx_cursor_on_last(MDBX_cursor *mc) { + if (unlikely(mc == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (!(mc->mc_flags & C_INITIALIZED)) + return MDBX_RESULT_FALSE; + + for (unsigned i = 0; i < mc->mc_snum; ++i) { + unsigned nkeys = NUMKEYS(mc->mc_pg[i]); + if (mc->mc_ki[i] < nkeys - 1) + return MDBX_RESULT_FALSE; + } + + return MDBX_RESULT_TRUE; +} + +int mdbx_cursor_eof(MDBX_cursor *mc) { + if (unlikely(mc == NULL)) + return MDBX_EINVAL; + + if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if ((mc->mc_flags & C_INITIALIZED) == 0) + return MDBX_RESULT_TRUE; + + if (mc->mc_snum == 0) + return MDBX_RESULT_TRUE; + + if ((mc->mc_flags & C_EOF) && + mc->mc_ki[mc->mc_top] >= NUMKEYS(mc->mc_pg[mc->mc_top])) + return MDBX_RESULT_TRUE; + + return MDBX_RESULT_FALSE; +} + +//------------------------------------------------------------------------------ + +struct diff_result { + ptrdiff_t diff; + int level; + int root_nkeys; +}; + +/* calculates: r = x - y */ +__hot static int cursor_diff(const MDBX_cursor *const __restrict x, + const MDBX_cursor *const __restrict y, + struct diff_result *const __restrict r) { + r->diff = 0; + r->level = 0; + r->root_nkeys = 0; + + if (unlikely(y->mc_signature != MDBX_MC_SIGNATURE || + x->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(y->mc_dbi != x->mc_dbi)) + return MDBX_EINVAL; + + if (unlikely(!(y->mc_flags & x->mc_flags & C_INITIALIZED))) + return MDBX_ENODATA; + + while (likely(r->level < y->mc_snum && r->level < x->mc_snum)) { + if (unlikely(y->mc_pg[r->level] != x->mc_pg[r->level])) + return MDBX_PROBLEM; + + int nkeys = NUMKEYS(y->mc_pg[r->level]); + assert(nkeys > 0); + if (r->level == 0) + r->root_nkeys = nkeys; + + const int limit_ki = nkeys - 1; + const int x_ki = x->mc_ki[r->level]; + const int y_ki = y->mc_ki[r->level]; + r->diff = ((x_ki < limit_ki) ? x_ki : limit_ki) - + ((y_ki < limit_ki) ? y_ki : limit_ki); + if (r->diff == 0) { + r->level += 1; + continue; + } + + while (unlikely(r->diff == 1) && + likely(r->level + 1 < y->mc_snum && r->level + 1 < x->mc_snum)) { + r->level += 1; + /* DB'PAGEs: 0------------------>MAX + * + * CURSORs: y < x + * STACK[i ]: | + * STACK[+1]: ...y++N|0++x... + */ + nkeys = NUMKEYS(y->mc_pg[r->level]); + r->diff = (nkeys - y->mc_ki[r->level]) + x->mc_ki[r->level]; + assert(r->diff > 0); + } + + while (unlikely(r->diff == -1) && + likely(r->level + 1 < y->mc_snum && r->level + 1 < x->mc_snum)) { + r->level += 1; + /* DB'PAGEs: 0------------------>MAX + * + * CURSORs: x < y + * STACK[i ]: | + * STACK[+1]: ...x--N|0--y... + */ + nkeys = NUMKEYS(x->mc_pg[r->level]); + r->diff = -(nkeys - x->mc_ki[r->level]) - y->mc_ki[r->level]; + assert(r->diff < 0); + } + + return MDBX_SUCCESS; + } + + r->diff = mdbx_cmp2int(x->mc_flags & C_EOF, y->mc_flags & C_EOF); + return MDBX_SUCCESS; +} + +__hot static ptrdiff_t estimate(const MDBX_db *db, + struct diff_result *const __restrict dr) { + /* root: branch-page => scale = leaf-factor * branch-factor^(N-1) + * level-1: branch-page(s) => scale = leaf-factor * branch-factor^2 + * level-2: branch-page(s) => scale = leaf-factor * branch-factor + * level-N: branch-page(s) => scale = leaf-factor + * last-level: leaf-page(s) => scale = 1 + */ + ptrdiff_t btree_power = db->md_depth - 2 - dr->level; + if (btree_power < 0) + return dr->diff; + + ptrdiff_t estimated = + (ptrdiff_t)db->md_entries * dr->diff / (ptrdiff_t)db->md_leaf_pages; + if (btree_power == 0) + return estimated; + + if (db->md_depth < 4) { + assert(dr->level == 0 && btree_power == 1); + return (ptrdiff_t)db->md_entries * dr->diff / (ptrdiff_t)dr->root_nkeys; + } + + /* average_branchpage_fillfactor = total(branch_entries) / branch_pages + total(branch_entries) = leaf_pages + branch_pages - 1 (root page) */ + const size_t log2_fixedpoint = sizeof(size_t) - 1; + const size_t half = UINT64_C(1) << (log2_fixedpoint - 1); + const size_t factor = + ((db->md_leaf_pages + db->md_branch_pages - 1) << log2_fixedpoint) / + db->md_branch_pages; + while (1) { + switch ((size_t)btree_power) { + default: { + const size_t square = (factor * factor + half) >> log2_fixedpoint; + const size_t quad = (square * square + half) >> log2_fixedpoint; + do { + estimated = estimated * quad + half; + estimated >>= log2_fixedpoint; + btree_power -= 4; + } while (btree_power >= 4); + continue; + } + case 3: + estimated = estimated * factor + half; + estimated >>= log2_fixedpoint; + __fallthrough /* fall through */; + case 2: + estimated = estimated * factor + half; + estimated >>= log2_fixedpoint; + __fallthrough /* fall through */; + case 1: + estimated = estimated * factor + half; + estimated >>= log2_fixedpoint; + __fallthrough /* fall through */; + case 0: + if (unlikely(estimated > (ptrdiff_t)db->md_entries)) + return (ptrdiff_t)db->md_entries; + if (unlikely(estimated < -(ptrdiff_t)db->md_entries)) + return -(ptrdiff_t)db->md_entries; + return estimated; + } + } +} + +__hot int mdbx_estimate_distance(const MDBX_cursor *first, + const MDBX_cursor *last, + ptrdiff_t *distance_items) { + if (unlikely(first == NULL || last == NULL || distance_items == NULL)) + return MDBX_EINVAL; + + *distance_items = 0; + struct diff_result dr; + int rc = cursor_diff(last, first, &dr); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + if (unlikely(dr.diff == 0) && + F_ISSET(first->mc_db->md_flags & first->mc_db->md_flags, + MDBX_DUPSORT | C_INITIALIZED)) { + first = &first->mc_xcursor->mx_cursor; + last = &last->mc_xcursor->mx_cursor; + rc = cursor_diff(first, last, &dr); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + if (likely(dr.diff != 0)) + *distance_items = estimate(first->mc_db, &dr); + + return MDBX_SUCCESS; +} + +int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, + MDBX_cursor_op move_op, ptrdiff_t *distance_items) { + if (unlikely(cursor == NULL || distance_items == NULL || + move_op == MDBX_GET_CURRENT || move_op == MDBX_GET_MULTIPLE)) + return MDBX_EINVAL; + + if (unlikely(cursor->mc_signature != MDBX_MC_SIGNATURE)) + return MDBX_EBADSIGN; + + if (!(cursor->mc_flags & C_INITIALIZED)) + return MDBX_ENODATA; + + MDBX_cursor_couple next; + mdbx_cursor_copy(cursor, &next.outer); + next.outer.mc_xcursor = NULL; + if (cursor->mc_db->md_flags & MDBX_DUPSORT) { + next.outer.mc_xcursor = &next.inner; + int rc = mdbx_xcursor_init0(&next.outer); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + MDBX_xcursor *mx = &container_of(cursor, MDBX_cursor_couple, outer)->inner; + mdbx_cursor_copy(&mx->mx_cursor, &next.inner.mx_cursor); + } + + MDBX_val stub = {0, 0}; + if (data == NULL) { + const unsigned mask = + 1 << MDBX_GET_BOTH | 1 << MDBX_GET_BOTH_RANGE | 1 << MDBX_SET_KEY; + if (unlikely(mask & (1 << move_op))) + return MDBX_EINVAL; + data = &stub; + } + + if (key == NULL) { + const unsigned mask = 1 << MDBX_GET_BOTH | 1 << MDBX_GET_BOTH_RANGE | + 1 << MDBX_SET_KEY | 1 << MDBX_SET | + 1 << MDBX_SET_RANGE; + if (unlikely(mask & (1 << move_op))) + return MDBX_EINVAL; + key = &stub; + } + + int rc = mdbx_cursor_get(&next.outer, key, data, move_op); + if (unlikely(rc != MDBX_SUCCESS && + (rc != MDBX_NOTFOUND || !(next.outer.mc_flags & C_INITIALIZED)))) + return rc; + + return mdbx_estimate_distance(cursor, &next.outer, distance_items); +} + +static int mdbx_is_samedata(const MDBX_val *a, const MDBX_val *b) { + return a->iov_len == b->iov_len && + memcmp(a->iov_base, b->iov_base, a->iov_len) == 0; +} + +int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key, + MDBX_val *begin_data, MDBX_val *end_key, + MDBX_val *end_data, ptrdiff_t *size_items) { + + if (unlikely(!txn || !size_items)) + return MDBX_EINVAL; + + if (unlikely(begin_data && (begin_key == NULL || begin_key == MDBX_EPSILON))) + return MDBX_EINVAL; + + if (unlikely(end_data && (end_key == NULL || end_key == MDBX_EPSILON))) + return MDBX_EINVAL; + + if (unlikely(begin_key == MDBX_EPSILON && end_key == MDBX_EPSILON)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + MDBX_cursor_couple begin; + /* LY: first, initialize cursor to refresh a DB in case it have DB_STALE */ + int rc = mdbx_cursor_init(&begin.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + if (unlikely(begin.outer.mc_db->md_entries == 0)) { + *size_items = 0; + return MDBX_SUCCESS; + } + + if (!begin_key) { + if (unlikely(!end_key)) { + /* LY: FIRST..LAST case */ + *size_items = (ptrdiff_t)begin.outer.mc_db->md_entries; + return MDBX_SUCCESS; + } + MDBX_val stub = {0, 0}; + rc = mdbx_cursor_first(&begin.outer, &stub, &stub); + if (unlikely(end_key == MDBX_EPSILON)) { + /* LY: FIRST..+epsilon case */ + return (rc == MDBX_SUCCESS) + ? mdbx_cursor_count(&begin.outer, (size_t *)size_items) + : rc; + } + } else { + if (unlikely(begin_key == MDBX_EPSILON)) { + if (end_key == NULL) { + /* LY: -epsilon..LAST case */ + MDBX_val stub = {0, 0}; + rc = mdbx_cursor_last(&begin.outer, &stub, &stub); + return (rc == MDBX_SUCCESS) + ? mdbx_cursor_count(&begin.outer, (size_t *)size_items) + : rc; + } + /* LY: -epsilon..value case */ + assert(end_key != MDBX_EPSILON); + begin_key = end_key; + } else if (unlikely(end_key == MDBX_EPSILON)) { + /* LY: value..+epsilon case */ + assert(begin_key != MDBX_EPSILON); + end_key = begin_key; + } + if (end_key && !begin_data && !end_data && + (begin_key == end_key || mdbx_is_samedata(begin_key, end_key))) { + /* LY: single key case */ + int exact = 0; + rc = mdbx_cursor_set(&begin.outer, begin_key, NULL, MDBX_SET, &exact); + if (unlikely(rc != MDBX_SUCCESS)) { + *size_items = 0; + return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; + } + *size_items = 1; + if (begin.outer.mc_xcursor != NULL) { + MDBX_node *leaf = NODEPTR(begin.outer.mc_pg[begin.outer.mc_top], + begin.outer.mc_ki[begin.outer.mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + /* LY: return the number of duplicates for given key */ + mdbx_tassert(txn, + begin.outer.mc_xcursor == &begin.inner && + (begin.inner.mx_cursor.mc_flags & C_INITIALIZED)); + *size_items = + (sizeof(*size_items) >= sizeof(begin.inner.mx_db.md_entries) || + begin.inner.mx_db.md_entries <= PTRDIFF_MAX) + ? (size_t)begin.inner.mx_db.md_entries + : PTRDIFF_MAX; + } + } + return MDBX_SUCCESS; + } else { + rc = mdbx_cursor_set(&begin.outer, begin_key, begin_data, + begin_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE, + NULL); + } + } + + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_NOTFOUND || !(begin.outer.mc_flags & C_INITIALIZED)) + return rc; + } + + MDBX_cursor_couple end; + rc = mdbx_cursor_init(&end.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (!end_key) { + MDBX_val stub = {0, 0}; + rc = mdbx_cursor_last(&end.outer, &stub, &stub); + } else { + rc = mdbx_cursor_set(&end.outer, end_key, end_data, + end_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE, NULL); + } + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc != MDBX_NOTFOUND || !(end.outer.mc_flags & C_INITIALIZED)) + return rc; + } + + rc = mdbx_estimate_distance(&begin.outer, &end.outer, size_items); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + assert(*size_items >= -(ptrdiff_t)begin.outer.mc_db->md_entries && + *size_items <= (ptrdiff_t)begin.outer.mc_db->md_entries); + +#if 0 /* LY: Was decided to returns as-is (i.e. negative) the estimation \ + * results for an inverted ranges. */ + + /* Commit 8ddfd1f34ad7cf7a3c4aa75d2e248ca7e639ed63 + Change-Id: If59eccf7311123ab6384c4b93f9b1fed5a0a10d1 */ + + if (*size_items < 0) { + /* LY: inverted range case */ + *size_items += (ptrdiff_t)begin.outer.mc_db->md_entries; + } else if (*size_items == 0 && begin_key && end_key) { + int cmp = begin.outer.mc_dbx->md_cmp(&origin_begin_key, &origin_end_key); + if (cmp == 0 && (begin.inner.mx_cursor.mc_flags & C_INITIALIZED) && + begin_data && end_data) + cmp = begin.outer.mc_dbx->md_dcmp(&origin_begin_data, &origin_end_data); + if (cmp > 0) { + /* LY: inverted range case with empty scope */ + *size_items = (ptrdiff_t)begin.outer.mc_db->md_entries; + } + } + assert(*size_items >= 0 && + *size_items <= (ptrdiff_t)begin.outer.mc_db->md_entries); +#endif + + return MDBX_SUCCESS; +} + +//------------------------------------------------------------------------------ + +/* Позволяет обновить или удалить существующую запись с получением + * в old_data предыдущего значения данных. При этом если new_data равен + * нулю, то выполняется удаление, иначе обновление/вставка. + * + * Текущее значение может находиться в уже измененной (грязной) странице. + * В этом случае страница будет перезаписана при обновлении, а само старое + * значение утрачено. Поэтому исходно в old_data должен быть передан + * дополнительный буфер для копирования старого значения. + * Если переданный буфер слишком мал, то функция вернет -1, установив + * old_data->iov_len в соответствующее значение. + * + * Для не-уникальных ключей также возможен второй сценарий использования, + * когда посредством old_data из записей с одинаковым ключом для + * удаления/обновления выбирается конкретная. Для выбора этого сценария + * во flags следует одновременно указать MDBX_CURRENT и MDBX_NOOVERWRITE. + * Именно эта комбинация выбрана, так как она лишена смысла, и этим позволяет + * идентифицировать запрос такого сценария. + * + * Функция может быть замещена соответствующими операциями с курсорами + * после двух доработок (TODO): + * - внешняя аллокация курсоров, в том числе на стеке (без malloc). + * - получения статуса страницы по адресу (знать о P_DIRTY). + */ +int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *new_data, + MDBX_val *old_data, unsigned flags) { + if (unlikely(!key || !old_data || !txn || old_data == new_data)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(old_data->iov_base == NULL && old_data->iov_len)) + return MDBX_EINVAL; + + if (unlikely(new_data == NULL && !(flags & MDBX_CURRENT))) + return MDBX_EINVAL; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(flags & ~(MDBX_NOOVERWRITE | MDBX_NODUPDATA | MDBX_RESERVE | + MDBX_APPEND | MDBX_APPENDDUP | MDBX_CURRENT))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + cx.outer.mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = &cx.outer; + + MDBX_val present_key = *key; + if (F_ISSET(flags, MDBX_CURRENT | MDBX_NOOVERWRITE)) { + /* в old_data значение для выбора конкретного дубликата */ + if (unlikely(!(txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT))) { + rc = MDBX_EINVAL; + goto bailout; + } + + /* убираем лишний бит, он был признаком запрошенного режима */ + flags -= MDBX_NOOVERWRITE; + + rc = mdbx_cursor_get(&cx.outer, &present_key, old_data, MDBX_GET_BOTH); + if (rc != MDBX_SUCCESS) + goto bailout; + + if (new_data) { + /* обновление конкретного дубликата */ + if (mdbx_is_samedata(old_data, new_data)) + /* если данные совпадают, то ничего делать не надо */ + goto bailout; + } + } else { + /* в old_data буфер для сохранения предыдущего значения */ + if (unlikely(new_data && old_data->iov_base == new_data->iov_base)) + return MDBX_EINVAL; + MDBX_val present_data; + rc = mdbx_cursor_get(&cx.outer, &present_key, &present_data, MDBX_SET_KEY); + if (unlikely(rc != MDBX_SUCCESS)) { + old_data->iov_base = NULL; + old_data->iov_len = 0; + if (rc != MDBX_NOTFOUND || (flags & MDBX_CURRENT)) + goto bailout; + } else if (flags & MDBX_NOOVERWRITE) { + rc = MDBX_KEYEXIST; + *old_data = present_data; + goto bailout; + } else { + MDBX_page *page = cx.outer.mc_pg[cx.outer.mc_top]; + if (txn->mt_dbs[dbi].md_flags & MDBX_DUPSORT) { + if (flags & MDBX_CURRENT) { + /* для не-уникальных ключей позволяем update/delete только если ключ + * один */ + MDBX_node *leaf = NODEPTR(page, cx.outer.mc_ki[cx.outer.mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdbx_tassert(txn, XCURSOR_INITED(&cx.outer) && + cx.outer.mc_xcursor->mx_db.md_entries > 1); + if (cx.outer.mc_xcursor->mx_db.md_entries > 1) { + rc = MDBX_EMULTIVAL; + goto bailout; + } + } + /* если данные совпадают, то ничего делать не надо */ + if (new_data && mdbx_is_samedata(&present_data, new_data)) { + *old_data = *new_data; + goto bailout; + } + /* В оригинальной LMDB фладок MDBX_CURRENT здесь приведет + * к замене данных без учета MDBX_DUPSORT сортировки, + * но здесь это в любом случае допустимо, так как мы + * проверили что для ключа есть только одно значение. */ + } else if ((flags & MDBX_NODUPDATA) && + mdbx_is_samedata(&present_data, new_data)) { + /* если данные совпадают и установлен MDBX_NODUPDATA */ + rc = MDBX_KEYEXIST; + goto bailout; + } + } else { + /* если данные совпадают, то ничего делать не надо */ + if (new_data && mdbx_is_samedata(&present_data, new_data)) { + *old_data = *new_data; + goto bailout; + } + flags |= MDBX_CURRENT; + } + + if (IS_DIRTY(page)) { + if (unlikely(old_data->iov_len < present_data.iov_len)) { + old_data->iov_base = NULL; + old_data->iov_len = present_data.iov_len; + rc = MDBX_RESULT_TRUE; + goto bailout; + } + memcpy(old_data->iov_base, present_data.iov_base, present_data.iov_len); + old_data->iov_len = present_data.iov_len; + } else { + *old_data = present_data; + } + } + } + + if (likely(new_data)) + rc = mdbx_cursor_put(&cx.outer, key, new_data, flags); + else + rc = mdbx_cursor_del(&cx.outer, 0); + +bailout: + txn->mt_cursors[dbi] = cx.outer.mc_next; + return rc; +} + +int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + size_t *values_count) { + DKBUF; + mdbx_debug("===> get db %u key [%s]", dbi, DKEY(key)); + + if (unlikely(!key || !data || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + int exact = 0; + rc = mdbx_cursor_set(&cx.outer, key, data, MDBX_SET_KEY, &exact); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc == MDBX_NOTFOUND && values_count) + *values_count = 0; + return rc; + } + + if (values_count) { + *values_count = 1; + if (cx.outer.mc_xcursor != NULL) { + MDBX_node *leaf = NODEPTR(cx.outer.mc_pg[cx.outer.mc_top], + cx.outer.mc_ki[cx.outer.mc_top]); + if (F_ISSET(leaf->mn_flags, F_DUPDATA)) { + mdbx_tassert(txn, cx.outer.mc_xcursor == &cx.inner && + (cx.inner.mx_cursor.mc_flags & C_INITIALIZED)); + *values_count = + (sizeof(*values_count) >= sizeof(cx.inner.mx_db.md_entries) || + cx.inner.mx_db.md_entries <= PTRDIFF_MAX) + ? (size_t)cx.inner.mx_db.md_entries + : PTRDIFF_MAX; + } + } + } + return MDBX_SUCCESS; +} + +/* Функция сообщает находится ли указанный адрес в "грязной" странице у + * заданной пишущей транзакции. В конечном счете это позволяет избавиться от + * лишнего копирования данных из НЕ-грязных страниц. + * + * "Грязные" страницы - это те, которые уже были изменены в ходе пишущей + * транзакции. Соответственно, какие-либо дальнейшие изменения могут привести + * к перезаписи таких страниц. Поэтому все функции, выполняющие изменения, в + * качестве аргументов НЕ должны получать указатели на данные в таких + * страницах. В свою очередь "НЕ грязные" страницы перед модификацией будут + * скопированы. + * + * Другими словами, данные из "грязных" страниц должны быть либо скопированы + * перед передачей в качестве аргументов для дальнейших модификаций, либо + * отвергнуты на стадии проверки корректности аргументов. + * + * Таким образом, функция позволяет как избавится от лишнего копирования, + * так и выполнить более полную проверку аргументов. + * + * ВАЖНО: Передаваемый указатель должен указывать на начало данных. Только + * так гарантируется что актуальный заголовок страницы будет физически + * расположен в той-же странице памяти, в том числе для многостраничных + * P_OVERFLOW страниц с длинными данными. */ +int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(txn->mt_flags & MDBX_TXN_RDONLY)) + return MDBX_RESULT_FALSE; + + const MDBX_env *env = txn->mt_env; + const uintptr_t mask = ~(uintptr_t)(env->me_psize - 1); + const MDBX_page *page = (const MDBX_page *)((uintptr_t)ptr & mask); + + /* LY: Тут не всё хорошо с абсолютной достоверностью результата, + * так как флажок P_DIRTY в LMDB может означать не совсем то, + * что было исходно задумано, детали см в логике кода mdbx_page_touch(). + * + * Более того, в режиме БЕЗ WRITEMAP грязные страницы выделяются через + * malloc(), т.е. находятся вне mmap-диапазона и тогда чтобы отличить + * действительно грязную страницу от указателя на данные пользователя + * следует сканировать dirtylist, что накладно. + * + * Тем не менее, однозначно страница "не грязная" (не будет переписана + * во время транзакции) если адрес находится внутри mmap-диапазона + * и в заголовке страницы нет флажка P_DIRTY. */ + if (env->me_map < (uint8_t *)page) { + const size_t usedbytes = pgno2bytes(env, txn->mt_next_pgno); + if ((uint8_t *)page < env->me_map + usedbytes) { + /* страница внутри диапазона, смотрим на флажки */ + return (page->mp_flags & (P_DIRTY | P_LOOSE | P_KEEP)) + ? MDBX_RESULT_TRUE + : MDBX_RESULT_FALSE; + } + /* Гипотетически здесь возможна ситуация, когда указатель адресует что-то + * в пределах mmap, но за границей распределенных страниц. Это тяжелая + * ошибка, к которой не возможно прийти без каких-то больших нарушений. + * Поэтому не проверяем этот случай кроме как assert-ом, на то что + * страница вне mmap-диаппазона. */ + mdbx_tassert(txn, (uint8_t *)page >= env->me_map + env->me_mapsize); + } + + /* Страница вне используемого mmap-диапазона, т.е. либо в функцию был + * передан некорректный адрес, либо адрес в теневой странице, которая была + * выделена посредством malloc(). + * + * Для WRITE_MAP режима такая страница однозначно "не грязная", + * а для режимов без WRITE_MAP следует просматривать списки dirty + * и spilled страниц у каких-либо транзакций (в том числе дочерних). + * + * Поэтому для WRITE_MAP возвращаем false, а для остальных режимов + * всегда true. Такая логика имеет ряд преимуществ: + * - не тратим время на просмотр списков; + * - результат всегда безопасен (может быть ложно-положительным, + * но не ложно-отрицательным); + * - результат не зависит от вложенности транзакций и от относительного + * положения переданной транзакции в этой рекурсии. */ + return (env->me_flags & MDBX_WRITEMAP) ? MDBX_RESULT_FALSE : MDBX_RESULT_TRUE; +} + +int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, + uint64_t increment) { + if (unlikely(!txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(txn->mt_owner != mdbx_thread_self())) + return MDBX_THREAD_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(TXN_DBI_CHANGED(txn, dbi))) + return MDBX_BAD_DBI; + + if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) { + MDBX_cursor_couple cx; + /* Stale, must read the DB's root. cursor_init does it for us. */ + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + } + + MDBX_db *dbs = &txn->mt_dbs[dbi]; + if (likely(result)) + *result = dbs->md_seq; + + if (likely(increment > 0)) { + if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) + return MDBX_BAD_TXN; + + if (unlikely(F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))) + return MDBX_EACCESS; + + uint64_t new = dbs->md_seq + increment; + if (unlikely(new < increment)) + return MDBX_RESULT_TRUE; + + mdbx_tassert(txn, new > dbs->md_seq); + dbs->md_seq = new; + txn->mt_flags |= MDBX_TXN_DIRTY; + txn->mt_dbflags[dbi] |= DB_DIRTY; + } + + return MDBX_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ + +__cold intptr_t mdbx_limits_keysize_max(intptr_t pagesize) { + if (pagesize < 1) + pagesize = (intptr_t)mdbx_syspagesize(); + else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || + pagesize > (intptr_t)MAX_PAGESIZE || + !mdbx_is_power2((size_t)pagesize))) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + return mdbx_maxkey(mdbx_nodemax(pagesize)); +} + +__cold int mdbx_limits_pgsize_min(void) { return MIN_PAGESIZE; } + +__cold int mdbx_limits_pgsize_max(void) { return MAX_PAGESIZE; } + +__cold intptr_t mdbx_limits_dbsize_min(intptr_t pagesize) { + if (pagesize < 1) + pagesize = (intptr_t)mdbx_syspagesize(); + else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || + pagesize > (intptr_t)MAX_PAGESIZE || + !mdbx_is_power2((size_t)pagesize))) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + return MIN_PAGENO * pagesize; +} + +__cold intptr_t mdbx_limits_dbsize_max(intptr_t pagesize) { + if (pagesize < 1) + pagesize = (intptr_t)mdbx_syspagesize(); + else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || + pagesize > (intptr_t)MAX_PAGESIZE || + !mdbx_is_power2((size_t)pagesize))) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + const uint64_t limit = MAX_PAGENO * (uint64_t)pagesize; + return (limit < (intptr_t)MAX_MAPSIZE) ? (intptr_t)limit + : (intptr_t)MAX_MAPSIZE; +} + +__cold intptr_t mdbx_limits_txnsize_max(intptr_t pagesize) { + if (pagesize < 1) + pagesize = (intptr_t)mdbx_syspagesize(); + else if (unlikely(pagesize < (intptr_t)MIN_PAGESIZE || + pagesize > (intptr_t)MAX_PAGESIZE || + !mdbx_is_power2((size_t)pagesize))) + return (MDBX_EINVAL > 0) ? -MDBX_EINVAL : MDBX_EINVAL; + + return pagesize * (MDBX_DPL_TXNFULL - 1); +} + +/*----------------------------------------------------------------------------*/ +/* attribute support functions for Nexenta */ + +static __inline int mdbx_attr_peek(MDBX_val *data, mdbx_attr_t *attrptr) { + if (unlikely(data->iov_len < sizeof(mdbx_attr_t))) + return MDBX_INCOMPATIBLE; + + if (likely(attrptr != NULL)) + *attrptr = *(mdbx_attr_t *)data->iov_base; + data->iov_len -= sizeof(mdbx_attr_t); + data->iov_base = + likely(data->iov_len > 0) ? ((mdbx_attr_t *)data->iov_base) + 1 : NULL; + + return MDBX_SUCCESS; +} + +static __inline int mdbx_attr_poke(MDBX_val *reserved, MDBX_val *data, + mdbx_attr_t attr, unsigned flags) { + mdbx_attr_t *space = reserved->iov_base; + if (flags & MDBX_RESERVE) { + if (likely(data != NULL)) { + data->iov_base = data->iov_len ? space + 1 : NULL; + } + } else { + *space = attr; + if (likely(data != NULL)) { + memcpy(space + 1, data->iov_base, data->iov_len); + } + } + + return MDBX_SUCCESS; +} + +int mdbx_cursor_get_attr(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, + mdbx_attr_t *attrptr, MDBX_cursor_op op) { + int rc = mdbx_cursor_get(mc, key, data, op); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + return mdbx_attr_peek(data, attrptr); +} + +int mdbx_get_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + uint64_t *attrptr) { + int rc = mdbx_get(txn, dbi, key, data); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + return mdbx_attr_peek(data, attrptr); +} + +int mdbx_put_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + mdbx_attr_t attr, unsigned flags) { + MDBX_val reserve; + reserve.iov_base = NULL; + reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t); + + int rc = mdbx_put(txn, dbi, key, &reserve, flags | MDBX_RESERVE); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + return mdbx_attr_poke(&reserve, data, attr, flags); +} + +int mdbx_cursor_put_attr(MDBX_cursor *cursor, MDBX_val *key, MDBX_val *data, + mdbx_attr_t attr, unsigned flags) { + MDBX_val reserve; + reserve.iov_base = NULL; + reserve.iov_len = (data ? data->iov_len : 0) + sizeof(mdbx_attr_t); + + int rc = mdbx_cursor_put(cursor, key, &reserve, flags | MDBX_RESERVE); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + return mdbx_attr_poke(&reserve, data, attr, flags); +} + +int mdbx_set_attr(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data, + mdbx_attr_t attr) { + if (unlikely(!key || !txn)) + return MDBX_EINVAL; + + if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) + return MDBX_VERSION_MISMATCH; + + if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) + return MDBX_EINVAL; + + if (unlikely(txn->mt_flags & (MDBX_TXN_RDONLY | MDBX_TXN_BLOCKED))) + return (txn->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EACCESS : MDBX_BAD_TXN; + + MDBX_cursor_couple cx; + MDBX_val old_data; + int rc = mdbx_cursor_init(&cx.outer, txn, dbi); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + rc = mdbx_cursor_set(&cx.outer, key, &old_data, MDBX_SET, NULL); + if (unlikely(rc != MDBX_SUCCESS)) { + if (rc == MDBX_NOTFOUND && data) { + cx.outer.mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = &cx.outer; + rc = mdbx_cursor_put_attr(&cx.outer, key, data, attr, 0); + txn->mt_cursors[dbi] = cx.outer.mc_next; + } + return rc; + } + + mdbx_attr_t old_attr = 0; + rc = mdbx_attr_peek(&old_data, &old_attr); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + if (old_attr == attr && (!data || (data->iov_len == old_data.iov_len && + memcmp(data->iov_base, old_data.iov_base, + old_data.iov_len) == 0))) + return MDBX_SUCCESS; + + cx.outer.mc_next = txn->mt_cursors[dbi]; + txn->mt_cursors[dbi] = &cx.outer; + rc = mdbx_cursor_put_attr(&cx.outer, key, data ? data : &old_data, attr, + MDBX_CURRENT); + txn->mt_cursors[dbi] = cx.outer.mc_next; + return rc; +} + +//---------------------------------------------------------------------------- + +#ifdef __SANITIZE_ADDRESS__ +LIBMDBX_API __attribute__((__weak__)) const char *__asan_default_options() { + return "symbolize=1:allow_addr2line=1:" +#ifdef _DEBUG + "debug=1:" +#endif /* _DEBUG */ + "report_globals=1:" + "replace_str=1:replace_intrin=1:" + "malloc_context_size=9:" + "detect_leaks=1:" + "check_printf=1:" + "detect_deadlocks=1:" +#ifndef LTO_ENABLED + "check_initialization_order=1:" +#endif + "detect_stack_use_after_return=1:" + "intercept_tls_get_addr=1:" + "decorate_proc_maps=1:" + "abort_on_error=1"; +} +#endif /* __SANITIZE_ADDRESS__ */ diff --git a/contrib/db/libmdbx/src/ntdll.def b/contrib/db/libmdbx/src/ntdll.def new file mode 100644 index 00000000..e3a6e33c --- /dev/null +++ b/contrib/db/libmdbx/src/ntdll.def @@ -0,0 +1,1244 @@ +LIBRARY ntdll +EXPORTS +CsrAllocateCaptureBuffer +CsrAllocateMessagePointer +CsrCaptureMessageBuffer +CsrCaptureMessageMultiUnicodeStringsInPlace +CsrCaptureMessageString +CsrCaptureTimeout +CsrClientCallServer +CsrClientConnectToServer +CsrFreeCaptureBuffer +CsrGetProcessId +CsrIdentifyAlertableThread +CsrSetPriorityClass +DbgBreakPoint +DbgPrint +DbgPrintEx +DbgPrintReturnControlC +DbgPrompt +DbgQueryDebugFilterState +DbgSetDebugFilterState +DbgUiConnectToDbg +DbgUiContinue +DbgUiConvertStateChangeStructure +DbgUiDebugActiveProcess +DbgUiGetThreadDebugObject +DbgUiIssueRemoteBreakin +DbgUiRemoteBreakin +DbgUiSetThreadDebugObject +DbgUiStopDebugging +DbgUiWaitStateChange +DbgUserBreakPoint +KiRaiseUserExceptionDispatcher +KiUserApcDispatcher +KiUserCallbackDispatcher +KiUserExceptionDispatcher +LdrAccessResource +LdrAddRefDll +LdrDisableThreadCalloutsForDll +LdrEnumResources +LdrEnumerateLoadedModules +LdrFindEntryForAddress +LdrFindResourceDirectory_U +LdrFindResourceEx_U +LdrFindResource_U +LdrFlushAlternateResourceModules +LdrGetDllHandle +LdrGetDllHandleEx +LdrGetProcedureAddress +LdrInitShimEngineDynamic +LdrInitializeThunk +LdrLoadAlternateResourceModule +LdrLoadDll +LdrLockLoaderLock +LdrProcessRelocationBlock +LdrQueryImageFileExecutionOptions +LdrQueryProcessModuleInformation +LdrSetAppCompatDllRedirectionCallback +LdrSetDllManifestProber +LdrShutdownProcess +LdrShutdownThread +LdrUnloadAlternateResourceModule +LdrUnloadDll +LdrUnlockLoaderLock +LdrVerifyImageMatchesChecksum +NlsAnsiCodePage +NlsMbCodePageTag +NlsMbOemCodePageTag +NtAcceptConnectPort +NtAccessCheck +NtAccessCheckAndAuditAlarm +NtAccessCheckByType +NtAccessCheckByTypeAndAuditAlarm +NtAccessCheckByTypeResultList +NtAccessCheckByTypeResultListAndAuditAlarm +NtAccessCheckByTypeResultListAndAuditAlarmByHandle +NtAddAtom +NtAddBootEntry +NtAdjustGroupsToken +NtAdjustPrivilegesToken +NtAlertResumeThread +NtAlertThread +NtAllocateLocallyUniqueId +NtAllocateUserPhysicalPages +NtAllocateUuids +NtAllocateVirtualMemory +NtAreMappedFilesTheSame +NtAssignProcessToJobObject +NtCallbackReturn +NtCancelIoFile +NtCancelTimer +NtClearEvent +NtClose +NtCloseObjectAuditAlarm +NtCompactKeys +NtCompareTokens +NtCompleteConnectPort +NtCompressKey +NtConnectPort +NtContinue +NtCreateDebugObject +NtCreateDirectoryObject +NtCreateEvent +NtCreateEventPair +NtCreateFile +NtCreateIoCompletion +NtCreateJobObject +NtCreateJobSet +NtCreateKey +NtCreateKeyedEvent +NtCreateMailslotFile +NtCreateMutant +NtCreateNamedPipeFile +NtCreatePagingFile +NtCreatePort +NtCreateProcess +NtCreateProcessEx +NtCreateProfile +NtCreateSection +NtCreateSemaphore +NtCreateSymbolicLinkObject +NtCreateThread +NtCreateTimer +NtCreateToken +NtCreateWaitablePort +NtDebugActiveProcess +NtDebugContinue +NtDelayExecution +NtDeleteAtom +NtDeleteBootEntry +NtDeleteFile +NtDeleteKey +NtDeleteObjectAuditAlarm +NtDeleteValueKey +NtDeviceIoControlFile +NtDisplayString +NtDuplicateObject +NtDuplicateToken +NtEnumerateBootEntries +NtEnumerateKey +NtEnumerateSystemEnvironmentValuesEx +NtEnumerateValueKey +NtExtendSection +NtFilterToken +NtFindAtom +NtFlushBuffersFile +NtFlushInstructionCache +NtFlushKey +NtFlushVirtualMemory +NtFlushWriteBuffer +NtFreeUserPhysicalPages +NtFreeVirtualMemory +NtFsControlFile +NtGetContextThread +NtGetDevicePowerState +NtGetWriteWatch +NtImpersonateAnonymousToken +NtImpersonateClientOfPort +NtImpersonateThread +NtInitializeRegistry +NtInitiatePowerAction +NtIsProcessInJob +NtIsSystemResumeAutomatic +NtListenPort +NtLoadDriver +NtLoadKey +NtLoadKey2 +NtLockFile +NtLockProductActivationKeys +NtLockRegistryKey +NtLockVirtualMemory +NtMakePermanentObject +NtMakeTemporaryObject +NtMapUserPhysicalPages +NtMapUserPhysicalPagesScatter +NtMapViewOfSection +NtModifyBootEntry +NtNotifyChangeDirectoryFile +NtNotifyChangeKey +NtNotifyChangeMultipleKeys +NtOpenDirectoryObject +NtOpenEvent +NtOpenEventPair +NtOpenFile +NtOpenIoCompletion +NtOpenJobObject +NtOpenKey +NtOpenKeyedEvent +NtOpenMutant +NtOpenObjectAuditAlarm +NtOpenProcess +NtOpenProcessToken +NtOpenProcessTokenEx +NtOpenSection +NtOpenSemaphore +NtOpenSymbolicLinkObject +NtOpenThread +NtOpenThreadToken +NtOpenThreadTokenEx +NtOpenTimer +NtPlugPlayControl +NtPowerInformation +NtPrivilegeCheck +NtPrivilegeObjectAuditAlarm +NtPrivilegedServiceAuditAlarm +NtProtectVirtualMemory +NtPulseEvent +NtQueryAttributesFile +NtQueryBootEntryOrder +NtQueryBootOptions +NtQueryDebugFilterState +NtQueryDefaultLocale +NtQueryDefaultUILanguage +NtQueryDirectoryFile +NtQueryDirectoryObject +NtQueryEaFile +NtQueryEvent +NtQueryFullAttributesFile +NtQueryInformationAtom +NtQueryInformationFile +NtQueryInformationJobObject +NtQueryInformationPort +NtQueryInformationProcess +NtQueryInformationThread +NtQueryInformationToken +NtQueryInstallUILanguage +NtQueryIntervalProfile +NtQueryIoCompletion +NtQueryKey +NtQueryMultipleValueKey +NtQueryMutant +NtQueryObject +NtQueryOpenSubKeys +NtQueryPerformanceCounter +NtQueryPortInformationProcess +NtQueryQuotaInformationFile +NtQuerySection +NtQuerySecurityObject +NtQuerySemaphore +NtQuerySymbolicLinkObject +NtQuerySystemEnvironmentValue +NtQuerySystemEnvironmentValueEx +NtQuerySystemInformation +NtQuerySystemTime +NtQueryTimer +NtQueryTimerResolution +NtQueryValueKey +NtQueryVirtualMemory +NtQueryVolumeInformationFile +NtQueueApcThread +NtRaiseException +NtRaiseHardError +NtReadFile +NtReadFileScatter +NtReadRequestData +NtReadVirtualMemory +NtRegisterThreadTerminatePort +NtReleaseKeyedEvent +NtReleaseMutant +NtReleaseSemaphore +NtRemoveIoCompletion +NtRemoveProcessDebug +NtRenameKey +NtReplaceKey +NtReplyPort +NtReplyWaitReceivePort +NtReplyWaitReceivePortEx +NtReplyWaitReplyPort +NtRequestPort +NtRequestWaitReplyPort +NtResetEvent +NtResetWriteWatch +NtRestoreKey +NtResumeProcess +NtResumeThread +NtSaveKey +NtSaveKeyEx +NtSaveMergedKeys +NtSecureConnectPort +NtSetBootEntryOrder +NtSetBootOptions +NtSetContextThread +NtSetDebugFilterState +NtSetDefaultHardErrorPort +NtSetDefaultLocale +NtSetDefaultUILanguage +NtSetEaFile +NtSetEvent +NtSetEventBoostPriority +NtSetHighEventPair +NtSetHighWaitLowEventPair +NtSetInformationDebugObject +NtSetInformationFile +NtSetInformationJobObject +NtSetInformationKey +NtSetInformationObject +NtSetInformationProcess +NtSetInformationThread +NtSetInformationToken +NtSetIntervalProfile +NtSetIoCompletion +NtSetLdtEntries +NtSetLowEventPair +NtSetLowWaitHighEventPair +NtSetQuotaInformationFile +NtSetSecurityObject +NtSetSystemEnvironmentValue +NtSetSystemEnvironmentValueEx +NtSetSystemInformation +NtSetSystemPowerState +NtSetSystemTime +NtSetThreadExecutionState +NtSetTimer +NtSetTimerResolution +NtSetUuidSeed +NtSetValueKey +NtSetVolumeInformationFile +NtShutdownSystem +NtSignalAndWaitForSingleObject +NtStartProfile +NtStopProfile +NtSuspendProcess +NtSuspendThread +NtSystemDebugControl +NtTerminateJobObject +NtTerminateProcess +NtTerminateThread +NtTestAlert +NtTraceEvent +NtTranslateFilePath +NtUnloadDriver +NtUnloadKey +NtUnloadKeyEx +NtUnlockFile +NtUnlockVirtualMemory +NtUnmapViewOfSection +NtVdmControl +NtWaitForDebugEvent +NtWaitForKeyedEvent +NtWaitForMultipleObjects +NtWaitForSingleObject +NtWaitHighEventPair +NtWaitLowEventPair +NtWriteFile +NtWriteFileGather +NtWriteRequestData +NtWriteVirtualMemory +NtYieldExecution +PfxFindPrefix +PfxInitialize +PfxInsertPrefix +PfxRemovePrefix +RtlAbortRXact +RtlAbsoluteToSelfRelativeSD +RtlAcquirePebLock +RtlAcquireResourceExclusive +RtlAcquireResourceShared +RtlActivateActivationContext +RtlActivateActivationContextEx +RtlActivateActivationContextUnsafeFast +RtlAddAccessAllowedAce +RtlAddAccessAllowedAceEx +RtlAddAccessAllowedObjectAce +RtlAddAccessDeniedAce +RtlAddAccessDeniedAceEx +RtlAddAccessDeniedObjectAce +RtlAddAce +RtlAddActionToRXact +RtlAddAtomToAtomTable +RtlAddAttributeActionToRXact +RtlAddAuditAccessAce +RtlAddAuditAccessAceEx +RtlAddAuditAccessObjectAce +RtlAddCompoundAce +RtlAddRefActivationContext +RtlAddRefMemoryStream +RtlAddVectoredExceptionHandler +RtlAddressInSectionTable +RtlAdjustPrivilege +RtlAllocateAndInitializeSid +RtlAllocateHandle +RtlAllocateHeap +RtlAnsiCharToUnicodeChar +RtlAnsiStringToUnicodeSize +RtlAnsiStringToUnicodeString +RtlAppendAsciizToString +RtlAppendPathElement +RtlAppendStringToString +RtlAppendUnicodeStringToString +RtlAppendUnicodeToString +RtlApplicationVerifierStop +RtlApplyRXact +RtlApplyRXactNoFlush +RtlAreAllAccessesGranted +RtlAreAnyAccessesGranted +RtlAreBitsClear +RtlAreBitsSet +RtlAssert +RtlCancelTimer +RtlCaptureContext +RtlCaptureStackBackTrace +RtlCharToInteger +RtlCheckForOrphanedCriticalSections +RtlCheckRegistryKey +RtlClearAllBits +RtlClearBits +RtlCloneMemoryStream +RtlCommitMemoryStream +RtlCompactHeap +RtlCompareMemory +RtlCompareMemoryUlong +RtlCompareString +RtlCompareUnicodeString +RtlCompressBuffer +RtlComputeCrc32 +RtlComputeImportTableHash +RtlComputePrivatizedDllName_U +RtlConsoleMultiByteToUnicodeN +RtlConvertExclusiveToShared +RtlConvertSharedToExclusive +RtlConvertSidToUnicodeString +RtlConvertToAutoInheritSecurityObject +RtlCopyLuid +RtlCopyLuidAndAttributesArray +RtlCopyMemoryStreamTo +RtlCopyOutOfProcessMemoryStreamTo +RtlCopySecurityDescriptor +RtlCopySid +RtlCopySidAndAttributesArray +RtlCopyString +RtlCopyUnicodeString +RtlCreateAcl +RtlCreateActivationContext +RtlCreateAndSetSD +RtlCreateAtomTable +RtlCreateBootStatusDataFile +RtlCreateEnvironment +RtlCreateHeap +RtlCreateProcessParameters +RtlCreateQueryDebugBuffer +RtlCreateRegistryKey +RtlCreateSecurityDescriptor +RtlCreateServiceSid +RtlCreateSystemVolumeInformationFolder +RtlCreateTagHeap +RtlCreateTimer +RtlCreateTimerQueue +RtlCreateUnicodeString +RtlCreateUnicodeStringFromAsciiz +RtlCreateUserProcess +RtlCreateUserSecurityObject +RtlCreateUserThread +RtlCustomCPToUnicodeN +RtlCutoverTimeToSystemTime +RtlDeNormalizeProcessParams +RtlDeactivateActivationContext +RtlDeactivateActivationContextUnsafeFast +RtlDebugPrintTimes +RtlDecodePointer +RtlDecodeSystemPointer +RtlDecompressBuffer +RtlDecompressFragment +RtlDefaultNpAcl +RtlDelete +RtlDeleteAce +RtlDeleteAtomFromAtomTable +RtlDeleteCriticalSection +RtlDeleteElementGenericTable +RtlDeleteElementGenericTableAvl +RtlDeleteNoSplay +RtlDeleteRegistryValue +RtlDeleteResource +RtlDeleteSecurityObject +RtlDeleteTimer +RtlDeleteTimerQueue +RtlDeleteTimerQueueEx +RtlDeregisterWait +RtlDeregisterWaitEx +RtlDestroyAtomTable +RtlDestroyEnvironment +RtlDestroyHandleTable +RtlDestroyHeap +RtlDestroyProcessParameters +RtlDestroyQueryDebugBuffer +RtlDetermineDosPathNameType_U +RtlDllShutdownInProgress +RtlDnsHostNameToComputerName +RtlDoesFileExists_U +RtlDosApplyFileIsolationRedirection_Ustr +RtlDosPathNameToNtPathName_U +RtlDosSearchPath_U +RtlDosSearchPath_Ustr +RtlDowncaseUnicodeChar +RtlDowncaseUnicodeString +RtlDumpResource +RtlDuplicateUnicodeString +RtlEmptyAtomTable +RtlEnableEarlyCriticalSectionEventCreation +RtlEncodePointer +RtlEncodeSystemPointer +RtlEnterCriticalSection +RtlEnumProcessHeaps +RtlEnumerateGenericTable +RtlEnumerateGenericTableAvl +RtlEnumerateGenericTableLikeADirectory +RtlEnumerateGenericTableWithoutSplaying +RtlEnumerateGenericTableWithoutSplayingAvl +RtlEqualComputerName +RtlEqualDomainName +RtlEqualLuid +RtlEqualPrefixSid +RtlEqualSid +RtlEqualString +RtlEqualUnicodeString +RtlEraseUnicodeString +RtlExitUserThread +RtlExpandEnvironmentStrings_U +RtlFillMemory +RtlFinalReleaseOutOfProcessMemoryStream +RtlFindActivationContextSectionGuid +RtlFindActivationContextSectionString +RtlFindCharInUnicodeString +RtlFindClearBits +RtlFindClearBitsAndSet +RtlFindClearRuns +RtlFindLastBackwardRunClear +RtlFindLeastSignificantBit +RtlFindLongestRunClear +RtlFindMessage +RtlFindMostSignificantBit +RtlFindNextForwardRunClear +RtlFindSetBits +RtlFindSetBitsAndClear +RtlFirstEntrySList +RtlFirstFreeAce +RtlFlushSecureMemoryCache +RtlFormatCurrentUserKeyPath +RtlFormatMessage +RtlFreeAnsiString +RtlFreeHandle +RtlFreeHeap +RtlFreeOemString +RtlFreeSid +RtlFreeThreadActivationContextStack +RtlFreeUnicodeString +RtlGUIDFromString +RtlGenerate8dot3Name +RtlGetAce +RtlGetActiveActivationContext +RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize +RtlGetControlSecurityDescriptor +RtlGetCurrentDirectory_U +RtlGetCurrentPeb +RtlGetDaclSecurityDescriptor +RtlGetElementGenericTable +RtlGetElementGenericTableAvl +RtlGetFrame +RtlGetFullPathName_U +RtlGetGroupSecurityDescriptor +RtlGetLastNtStatus +RtlGetLastWin32Error +RtlGetLengthWithoutLastFullDosOrNtPathElement +RtlGetLengthWithoutTrailingPathSeperators +RtlGetLongestNtPathLength +RtlGetNativeSystemInformation +RtlGetNtGlobalFlags +RtlGetNtProductType +RtlGetNtVersionNumbers +RtlGetOwnerSecurityDescriptor +RtlGetProcessHeaps +RtlGetSaclSecurityDescriptor +RtlGetSecurityDescriptorRMControl +RtlGetSetBootStatusData +RtlGetUnloadEventTrace +RtlGetUserInfoHeap +RtlGetVersion +RtlHashUnicodeString +RtlIdentifierAuthoritySid +RtlImageDirectoryEntryToData +RtlImageNtHeader +RtlImageRvaToSection +RtlImageRvaToVa +RtlImpersonateSelf +RtlInitAnsiString +RtlInitCodePageTable +RtlInitMemoryStream +RtlInitNlsTables +RtlInitOutOfProcessMemoryStream +RtlInitString +RtlInitUnicodeString +RtlInitUnicodeStringEx +RtlInitializeAtomPackage +RtlInitializeBitMap +RtlInitializeContext +RtlInitializeCriticalSection +RtlInitializeCriticalSectionAndSpinCount +RtlInitializeGenericTable +RtlInitializeGenericTableAvl +RtlInitializeHandleTable +RtlInitializeRXact +RtlInitializeResource +RtlInitializeSListHead +RtlInitializeSid +RtlInsertElementGenericTable +RtlInsertElementGenericTableAvl +RtlInt64ToUnicodeString +RtlIntegerToChar +RtlIntegerToUnicodeString +RtlInterlockedFlushSList +RtlInterlockedPopEntrySList +RtlInterlockedPushEntrySList +RtlInterlockedPushListSList +RtlIpv4AddressToStringA +RtlIpv4AddressToStringExA +RtlIpv4AddressToStringExW +RtlIpv4AddressToStringW +RtlIpv4StringToAddressA +RtlIpv4StringToAddressExA +RtlIpv4StringToAddressExW +RtlIpv4StringToAddressW +RtlIpv6AddressToStringA +RtlIpv6AddressToStringExA +RtlIpv6AddressToStringExW +RtlIpv6AddressToStringW +RtlIpv6StringToAddressA +RtlIpv6StringToAddressExA +RtlIpv6StringToAddressExW +RtlIpv6StringToAddressW +RtlIsActivationContextActive +RtlIsDosDeviceName_U +RtlIsGenericTableEmpty +RtlIsGenericTableEmptyAvl +RtlIsNameLegalDOS8Dot3 +RtlIsTextUnicode +RtlIsThreadWithinLoaderCallout +RtlIsValidHandle +RtlIsValidIndexHandle +RtlLargeIntegerToChar +RtlLeaveCriticalSection +RtlLengthRequiredSid +RtlLengthSecurityDescriptor +RtlLengthSid +RtlLocalTimeToSystemTime +RtlLockBootStatusData +RtlLockHeap +RtlLockMemoryStreamRegion +RtlLogStackBackTrace +RtlLookupAtomInAtomTable +RtlLookupElementGenericTable +RtlLookupElementGenericTableAvl +RtlMakeSelfRelativeSD +RtlMapGenericMask +RtlMapSecurityErrorToNtStatus +RtlMoveMemory +RtlMultiAppendUnicodeStringBuffer +RtlMultiByteToUnicodeN +RtlMultiByteToUnicodeSize +RtlNewInstanceSecurityObject +RtlNewSecurityGrantedAccess +RtlNewSecurityObject +RtlNewSecurityObjectEx +RtlNewSecurityObjectWithMultipleInheritance +RtlNormalizeProcessParams +RtlNtPathNameToDosPathName +RtlNtStatusToDosError +RtlNtStatusToDosErrorNoTeb +RtlNumberGenericTableElements +RtlNumberGenericTableElementsAvl +RtlNumberOfClearBits +RtlNumberOfSetBits +RtlOemStringToUnicodeSize +RtlOemStringToUnicodeString +RtlOemToUnicodeN +RtlOpenCurrentUser +RtlPcToFileHeader +RtlPinAtomInAtomTable +RtlPopFrame +RtlPrefixString +RtlPrefixUnicodeString +RtlProtectHeap +RtlPushFrame +RtlQueryAtomInAtomTable +RtlQueryDepthSList +RtlQueryEnvironmentVariable_U +RtlQueryHeapInformation +RtlQueryInformationAcl +RtlQueryInformationActivationContext +RtlQueryInformationActiveActivationContext +RtlQueryInterfaceMemoryStream +RtlQueryProcessBackTraceInformation +RtlQueryProcessDebugInformation +RtlQueryProcessHeapInformation +RtlQueryProcessLockInformation +RtlQueryRegistryValues +RtlQuerySecurityObject +RtlQueryTagHeap +RtlQueryTimeZoneInformation +RtlQueueApcWow64Thread +RtlQueueWorkItem +RtlRaiseException +RtlRaiseStatus +RtlRandom +RtlRandomEx +RtlReAllocateHeap +RtlReadMemoryStream +RtlReadOutOfProcessMemoryStream +RtlRealPredecessor +RtlRealSuccessor +RtlRegisterSecureMemoryCacheCallback +RtlRegisterWait +RtlReleaseActivationContext +RtlReleaseMemoryStream +RtlReleasePebLock +RtlReleaseResource +RtlRemoteCall +RtlRemoveVectoredExceptionHandler +RtlResetRtlTranslations +RtlRestoreLastWin32Error +RtlRevertMemoryStream +RtlRunDecodeUnicodeString +RtlRunEncodeUnicodeString +RtlSecondsSince1970ToTime +RtlSecondsSince1980ToTime +RtlSeekMemoryStream +RtlSelfRelativeToAbsoluteSD +RtlSelfRelativeToAbsoluteSD2 +RtlSetAllBits +RtlSetAttributesSecurityDescriptor +RtlSetBits +RtlSetControlSecurityDescriptor +RtlSetCriticalSectionSpinCount +RtlSetCurrentDirectory_U +RtlSetCurrentEnvironment +RtlSetDaclSecurityDescriptor +RtlSetEnvironmentVariable +RtlSetGroupSecurityDescriptor +RtlSetHeapInformation +RtlSetInformationAcl +RtlSetIoCompletionCallback +RtlSetLastWin32Error +RtlSetLastWin32ErrorAndNtStatusFromNtStatus +RtlSetMemoryStreamSize +RtlSetOwnerSecurityDescriptor +RtlSetProcessIsCritical +RtlSetSaclSecurityDescriptor +RtlSetSecurityDescriptorRMControl +RtlSetSecurityObject +RtlSetSecurityObjectEx +RtlSetThreadIsCritical +RtlSetThreadPoolStartFunc +RtlSetTimeZoneInformation +RtlSetTimer +RtlSetUserFlagsHeap +RtlSetUserValueHeap +RtlSizeHeap +RtlSplay +RtlStartRXact +RtlStatMemoryStream +RtlStringFromGUID +RtlSubAuthorityCountSid +RtlSubAuthoritySid +RtlSubtreePredecessor +RtlSubtreeSuccessor +RtlSystemTimeToLocalTime +RtlTimeFieldsToTime +RtlTimeToElapsedTimeFields +RtlTimeToSecondsSince1970 +RtlTimeToSecondsSince1980 +RtlTimeToTimeFields +RtlTraceDatabaseAdd +RtlTraceDatabaseCreate +RtlTraceDatabaseDestroy +RtlTraceDatabaseEnumerate +RtlTraceDatabaseFind +RtlTraceDatabaseLock +RtlTraceDatabaseUnlock +RtlTraceDatabaseValidate +RtlTryEnterCriticalSection +RtlUnhandledExceptionFilter +RtlUnhandledExceptionFilter2 +RtlUnicodeStringToAnsiSize +RtlUnicodeStringToAnsiString +RtlUnicodeStringToCountedOemString +RtlUnicodeStringToInteger +RtlUnicodeStringToOemSize +RtlUnicodeStringToOemString +RtlUnicodeToCustomCPN +RtlUnicodeToMultiByteN +RtlUnicodeToMultiByteSize +RtlUnicodeToOemN +RtlUniform +RtlUnlockBootStatusData +RtlUnlockHeap +RtlUnlockMemoryStreamRegion +RtlUnwind +RtlUpcaseUnicodeChar +RtlUpcaseUnicodeString +RtlUpcaseUnicodeStringToAnsiString +RtlUpcaseUnicodeStringToCountedOemString +RtlUpcaseUnicodeStringToOemString +RtlUpcaseUnicodeToCustomCPN +RtlUpcaseUnicodeToMultiByteN +RtlUpcaseUnicodeToOemN +RtlUpdateTimer +RtlUpperChar +RtlUpperString +RtlValidAcl +RtlValidRelativeSecurityDescriptor +RtlValidSecurityDescriptor +RtlValidSid +RtlValidateHeap +RtlValidateProcessHeaps +RtlValidateUnicodeString +RtlVerifyVersionInfo +RtlWalkFrameChain +RtlWalkHeap +RtlWriteMemoryStream +RtlWriteRegistryValue +RtlZeroHeap +RtlZeroMemory +RtlZombifyActivationContext +RtlpApplyLengthFunction +RtlpEnsureBufferSize +RtlpNotOwnerCriticalSection +RtlpNtCreateKey +RtlpNtEnumerateSubKey +RtlpNtMakeTemporaryKey +RtlpNtOpenKey +RtlpNtQueryValueKey +RtlpNtSetValueKey +RtlpUnWaitCriticalSection +RtlpWaitForCriticalSection +RtlxAnsiStringToUnicodeSize +RtlxOemStringToUnicodeSize +RtlxUnicodeStringToAnsiSize +RtlxUnicodeStringToOemSize +VerSetConditionMask +ZwAcceptConnectPort +ZwAccessCheck +ZwAccessCheckAndAuditAlarm +ZwAccessCheckByType +ZwAccessCheckByTypeAndAuditAlarm +ZwAccessCheckByTypeResultList +ZwAccessCheckByTypeResultListAndAuditAlarm +ZwAccessCheckByTypeResultListAndAuditAlarmByHandle +ZwAddAtom +ZwAddBootEntry +ZwAdjustGroupsToken +ZwAdjustPrivilegesToken +ZwAlertResumeThread +ZwAlertThread +ZwAllocateLocallyUniqueId +ZwAllocateUserPhysicalPages +ZwAllocateUuids +ZwAllocateVirtualMemory +ZwAreMappedFilesTheSame +ZwAssignProcessToJobObject +ZwCallbackReturn +ZwCancelIoFile +ZwCancelTimer +ZwClearEvent +ZwClose +ZwCloseObjectAuditAlarm +ZwCompactKeys +ZwCompareTokens +ZwCompleteConnectPort +ZwCompressKey +ZwConnectPort +ZwContinue +ZwCreateDebugObject +ZwCreateDirectoryObject +ZwCreateEvent +ZwCreateEventPair +ZwCreateFile +ZwCreateIoCompletion +ZwCreateJobObject +ZwCreateJobSet +ZwCreateKey +ZwCreateKeyedEvent +ZwCreateMailslotFile +ZwCreateMutant +ZwCreateNamedPipeFile +ZwCreatePagingFile +ZwCreatePort +ZwCreateProcess +ZwCreateProcessEx +ZwCreateProfile +ZwCreateSection +ZwCreateSemaphore +ZwCreateSymbolicLinkObject +ZwCreateThread +ZwCreateTimer +ZwCreateToken +ZwCreateWaitablePort +ZwDebugActiveProcess +ZwDebugContinue +ZwDelayExecution +ZwDeleteAtom +ZwDeleteBootEntry +ZwDeleteFile +ZwDeleteKey +ZwDeleteObjectAuditAlarm +ZwDeleteValueKey +ZwDeviceIoControlFile +ZwDisplayString +ZwDuplicateObject +ZwDuplicateToken +ZwEnumerateBootEntries +ZwEnumerateKey +ZwEnumerateSystemEnvironmentValuesEx +ZwEnumerateValueKey +ZwExtendSection +ZwFilterToken +ZwFindAtom +ZwFlushBuffersFile +ZwFlushInstructionCache +ZwFlushKey +ZwFlushVirtualMemory +ZwFlushWriteBuffer +ZwFreeUserPhysicalPages +ZwFreeVirtualMemory +ZwFsControlFile +ZwGetContextThread +ZwGetDevicePowerState +ZwGetWriteWatch +ZwImpersonateAnonymousToken +ZwImpersonateClientOfPort +ZwImpersonateThread +ZwInitializeRegistry +ZwInitiatePowerAction +ZwIsProcessInJob +ZwIsSystemResumeAutomatic +ZwListenPort +ZwLoadDriver +ZwLoadKey +ZwLoadKey2 +ZwLockFile +ZwLockProductActivationKeys +ZwLockRegistryKey +ZwLockVirtualMemory +ZwMakePermanentObject +ZwMakeTemporaryObject +ZwMapUserPhysicalPages +ZwMapUserPhysicalPagesScatter +ZwMapViewOfSection +ZwModifyBootEntry +ZwNotifyChangeDirectoryFile +ZwNotifyChangeKey +ZwNotifyChangeMultipleKeys +ZwOpenDirectoryObject +ZwOpenEvent +ZwOpenEventPair +ZwOpenFile +ZwOpenIoCompletion +ZwOpenJobObject +ZwOpenKey +ZwOpenKeyedEvent +ZwOpenMutant +ZwOpenObjectAuditAlarm +ZwOpenProcess +ZwOpenProcessToken +ZwOpenProcessTokenEx +ZwOpenSection +ZwOpenSemaphore +ZwOpenSymbolicLinkObject +ZwOpenThread +ZwOpenThreadToken +ZwOpenThreadTokenEx +ZwOpenTimer +ZwPlugPlayControl +ZwPowerInformation +ZwPrivilegeCheck +ZwPrivilegeObjectAuditAlarm +ZwPrivilegedServiceAuditAlarm +ZwProtectVirtualMemory +ZwPulseEvent +ZwQueryAttributesFile +ZwQueryBootEntryOrder +ZwQueryBootOptions +ZwQueryDebugFilterState +ZwQueryDefaultLocale +ZwQueryDefaultUILanguage +ZwQueryDirectoryFile +ZwQueryDirectoryObject +ZwQueryEaFile +ZwQueryEvent +ZwQueryFullAttributesFile +ZwQueryInformationAtom +ZwQueryInformationFile +ZwQueryInformationJobObject +ZwQueryInformationPort +ZwQueryInformationProcess +ZwQueryInformationThread +ZwQueryInformationToken +ZwQueryInstallUILanguage +ZwQueryIntervalProfile +ZwQueryIoCompletion +ZwQueryKey +ZwQueryMultipleValueKey +ZwQueryMutant +ZwQueryObject +ZwQueryOpenSubKeys +ZwQueryPerformanceCounter +ZwQueryPortInformationProcess +ZwQueryQuotaInformationFile +ZwQuerySection +ZwQuerySecurityObject +ZwQuerySemaphore +ZwQuerySymbolicLinkObject +ZwQuerySystemEnvironmentValue +ZwQuerySystemEnvironmentValueEx +ZwQuerySystemInformation +ZwQuerySystemTime +ZwQueryTimer +ZwQueryTimerResolution +ZwQueryValueKey +ZwQueryVirtualMemory +ZwQueryVolumeInformationFile +ZwQueueApcThread +ZwRaiseException +ZwRaiseHardError +ZwReadFile +ZwReadFileScatter +ZwReadRequestData +ZwReadVirtualMemory +ZwRegisterThreadTerminatePort +ZwReleaseKeyedEvent +ZwReleaseMutant +ZwReleaseSemaphore +ZwRemoveIoCompletion +ZwRemoveProcessDebug +ZwRenameKey +ZwReplaceKey +ZwReplyPort +ZwReplyWaitReceivePort +ZwReplyWaitReceivePortEx +ZwReplyWaitReplyPort +ZwRequestPort +ZwRequestWaitReplyPort +ZwResetEvent +ZwResetWriteWatch +ZwRestoreKey +ZwResumeProcess +ZwResumeThread +ZwSaveKey +ZwSaveKeyEx +ZwSaveMergedKeys +ZwSecureConnectPort +ZwSetBootEntryOrder +ZwSetBootOptions +ZwSetContextThread +ZwSetDebugFilterState +ZwSetDefaultHardErrorPort +ZwSetDefaultLocale +ZwSetDefaultUILanguage +ZwSetEaFile +ZwSetEvent +ZwSetEventBoostPriority +ZwSetHighEventPair +ZwSetHighWaitLowEventPair +ZwSetInformationDebugObject +ZwSetInformationFile +ZwSetInformationJobObject +ZwSetInformationKey +ZwSetInformationObject +ZwSetInformationProcess +ZwSetInformationThread +ZwSetInformationToken +ZwSetIntervalProfile +ZwSetIoCompletion +ZwSetLdtEntries +ZwSetLowEventPair +ZwSetLowWaitHighEventPair +ZwSetQuotaInformationFile +ZwSetSecurityObject +ZwSetSystemEnvironmentValue +ZwSetSystemEnvironmentValueEx +ZwSetSystemInformation +ZwSetSystemPowerState +ZwSetSystemTime +ZwSetThreadExecutionState +ZwSetTimer +ZwSetTimerResolution +ZwSetUuidSeed +ZwSetValueKey +ZwSetVolumeInformationFile +ZwShutdownSystem +ZwSignalAndWaitForSingleObject +ZwStartProfile +ZwStopProfile +ZwSuspendProcess +ZwSuspendThread +ZwSystemDebugControl +ZwTerminateJobObject +ZwTerminateProcess +ZwTerminateThread +ZwTestAlert +ZwTraceEvent +ZwTranslateFilePath +ZwUnloadDriver +ZwUnloadKey +ZwUnloadKeyEx +ZwUnlockFile +ZwUnlockVirtualMemory +ZwUnmapViewOfSection +ZwVdmControl +ZwWaitForDebugEvent +ZwWaitForKeyedEvent +ZwWaitForMultipleObjects +ZwWaitForSingleObject +ZwWaitHighEventPair +ZwWaitLowEventPair +ZwWriteFile +ZwWriteFileGather +ZwWriteRequestData +ZwWriteVirtualMemory +ZwYieldExecution +__isascii +__iscsym +__iscsymf +__toascii +_alldiv +_alldvrm +_allmul +_allrem +_allshl +_allshr +_atoi64 +_aulldiv +_aulldvrm +_aullrem +_aullshr +_fltused +_i64toa +_i64tow +_itoa +_itow +_lfind +_ltoa +_ltow +_memccpy +_memicmp +_snprintf +_snwprintf +_splitpath +_strcmpi +_stricmp +_strlwr +_strnicmp +_strupr +_ui64toa +_ui64tow +_ultoa +_ultow +_vsnprintf +_vsnwprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsupr +_wtoi +_wtoi64 +_wtol +abs +atan +atoi +atol +bsearch +ceil +cos +fabs +floor +isalnum +isalpha +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +iswalpha +iswctype +iswdigit +iswlower +iswspace +iswxdigit +isxdigit +labs +log +mbstowcs +memchr +memcmp +memcpy +memmove +memset +pow +qsort +sin +sprintf +sqrt +sscanf +strcat +strchr +strcmp +strcpy +strcspn +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtol +strtoul +swprintf +tan +tolower +toupper +towlower +towupper +vDbgPrintEx +vDbgPrintExWithPrefix +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsrchr +wcsspn +wcsstr +wcstol +wcstombs +wcstoul diff --git a/contrib/db/libmdbx/src/osal.c b/contrib/db/libmdbx/src/osal.c new file mode 100644 index 00000000..993d83b0 --- /dev/null +++ b/contrib/db/libmdbx/src/osal.c @@ -0,0 +1,1319 @@ +/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "./bits.h" + +#if defined(_WIN32) || defined(_WIN64) + +static int waitstatus2errcode(DWORD result) { + switch (result) { + case WAIT_OBJECT_0: + return MDBX_SUCCESS; + case WAIT_FAILED: + return GetLastError(); + case WAIT_ABANDONED: + return ERROR_ABANDONED_WAIT_0; + case WAIT_IO_COMPLETION: + return ERROR_USER_APC; + case WAIT_TIMEOUT: + return ERROR_TIMEOUT; + default: + return ERROR_UNHANDLED_ERROR; + } +} + +/* Map a result from an NTAPI call to WIN32 error code. */ +static int ntstatus2errcode(NTSTATUS status) { + DWORD dummy; + OVERLAPPED ov; + memset(&ov, 0, sizeof(ov)); + ov.Internal = status; + return GetOverlappedResult(NULL, &ov, &dummy, FALSE) ? MDBX_SUCCESS + : GetLastError(); +} + +/* We use native NT APIs to setup the memory map, so that we can + * let the DB file grow incrementally instead of always preallocating + * the full size. These APIs are defined in and + * but those headers are meant for driver-level development and + * conflict with the regular user-level headers, so we explicitly + * declare them here. Using these APIs also means we must link to + * ntdll.dll, which is not linked by default in user code. */ +#pragma comment(lib, "ntdll.lib") +#ifdef MDBX_AVOID_CRT +#pragma comment(lib, "mdbx_ntdll_extra.lib") +#endif + +extern NTSTATUS NTAPI NtCreateSection( + OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, + IN OPTIONAL POBJECT_ATTRIBUTES ObjectAttributes, + IN OPTIONAL PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, IN OPTIONAL HANDLE FileHandle); + +typedef struct _SECTION_BASIC_INFORMATION { + ULONG Unknown; + ULONG SectionAttributes; + LARGE_INTEGER SectionSize; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, + SectionImageInformation, + SectionRelocationInformation, // name:wow64:whNtQuerySection_SectionRelocationInformation + MaxSectionInfoClass +} SECTION_INFORMATION_CLASS; + +extern NTSTATUS NTAPI NtQuerySection( + IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS InformationClass, + OUT PVOID InformationBuffer, IN ULONG InformationBufferSize, + OUT PULONG ResultLength OPTIONAL); + +extern NTSTATUS NTAPI NtExtendSection(IN HANDLE SectionHandle, + IN PLARGE_INTEGER NewSectionSize); + +typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT; + +extern NTSTATUS NTAPI NtMapViewOfSection( + IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, + IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, + IN OUT OPTIONAL PLARGE_INTEGER SectionOffset, IN OUT PSIZE_T ViewSize, + IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, + IN ULONG Win32Protect); + +extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, + IN OPTIONAL PVOID BaseAddress); + +extern NTSTATUS NTAPI NtClose(HANDLE Handle); + +extern NTSTATUS NTAPI NtAllocateVirtualMemory( + IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, + IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect); + +extern NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN OUT PSIZE_T RegionSize, + IN ULONG FreeType); + +#ifndef WOF_CURRENT_VERSION +typedef struct _WOF_EXTERNAL_INFO { + DWORD Version; + DWORD Provider; +} WOF_EXTERNAL_INFO, *PWOF_EXTERNAL_INFO; +#endif /* WOF_CURRENT_VERSION */ + +#ifndef WIM_PROVIDER_CURRENT_VERSION +#define WIM_PROVIDER_HASH_SIZE 20 + +typedef struct _WIM_PROVIDER_EXTERNAL_INFO { + DWORD Version; + DWORD Flags; + LARGE_INTEGER DataSourceId; + BYTE ResourceHash[WIM_PROVIDER_HASH_SIZE]; +} WIM_PROVIDER_EXTERNAL_INFO, *PWIM_PROVIDER_EXTERNAL_INFO; +#endif /* WIM_PROVIDER_CURRENT_VERSION */ + +#ifndef FILE_PROVIDER_CURRENT_VERSION +typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 { + ULONG Version; + ULONG Algorithm; + ULONG Flags; +} FILE_PROVIDER_EXTERNAL_INFO_V1, *PFILE_PROVIDER_EXTERNAL_INFO_V1; +#endif /* FILE_PROVIDER_CURRENT_VERSION */ + +#ifndef STATUS_OBJECT_NOT_EXTERNALLY_BACKED +#define STATUS_OBJECT_NOT_EXTERNALLY_BACKED ((NTSTATUS)0xC000046DL) +#endif +#ifndef STATUS_INVALID_DEVICE_REQUEST +#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L) +#endif + +#ifndef FILE_DEVICE_FILE_SYSTEM +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#endif + +#ifndef FSCTL_GET_EXTERNAL_BACKING +#define FSCTL_GET_EXTERNAL_BACKING \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 196, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif + +#endif /* _WIN32 || _WIN64 */ + +/*----------------------------------------------------------------------------*/ + +#if _POSIX_C_SOURCE > 200212 && \ + /* workaround for avoid musl libc wrong prototype */ ( \ + defined(__GLIBC__) || defined(__GNU_LIBRARY__)) +/* Prototype should match libc runtime. ISO POSIX (2003) & LSB 1.x-3.x */ +__extern_C void __assert_fail(const char *assertion, const char *file, + unsigned line, const char *function) +#ifdef __THROW + __THROW +#else + __nothrow +#endif /* __THROW */ + __noreturn; + +#elif defined(__APPLE__) || defined(__MACH__) +__extern_C void __assert_rtn(const char *function, const char *file, int line, + const char *assertion) /* __nothrow */ +#ifdef __dead2 + __dead2 +#else + __noreturn +#endif /* __dead2 */ +#ifdef __disable_tail_calls + __disable_tail_calls +#endif /* __disable_tail_calls */ + ; + +#define __assert_fail(assertion, file, line, function) \ + __assert_rtn(function, file, line, assertion) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \ + defined(__DragonFly__) +__extern_C void __assert(const char *function, const char *file, int line, + const char *assertion) /* __nothrow */ +#ifdef __dead2 + __dead2 +#else + __noreturn +#endif /* __dead2 */ +#ifdef __disable_tail_calls + __disable_tail_calls +#endif /* __disable_tail_calls */ + ; +#define __assert_fail(assertion, file, line, function) \ + __assert(function, file, line, assertion) + +#endif /* __assert_fail */ + +void __cold mdbx_assert_fail(const MDBX_env *env, const char *msg, + const char *func, int line) { +#if MDBX_DEBUG + if (env && env->me_assert_func) { + env->me_assert_func(env, msg, func, line); + return; + } +#else + (void)env; +#endif /* MDBX_DEBUG */ + + if (mdbx_debug_logger) + mdbx_debug_log(MDBX_DBG_ASSERT, func, line, "assert: %s\n", msg); + else { +#if defined(_WIN32) || defined(_WIN64) + char *message = nullptr; + const int num = mdbx_asprintf(&message, "\r\nMDBX-ASSERTION: %s, %s:%u", + msg, func ? func : "unknown", line); + if (num < 1 || !message) + message = ""; + OutputDebugStringA(message); + if (IsDebuggerPresent()) + DebugBreak(); +#else + __assert_fail(msg, "mdbx", line, func); +#endif + } + +#if defined(_WIN32) || defined(_WIN64) + FatalExit(ERROR_UNHANDLED_ERROR); +#else + abort(); +#endif +} + +__cold void mdbx_panic(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + + char *message = nullptr; + const int num = mdbx_vasprintf(&message, fmt, ap); + va_end(ap); + if (num < 1 || !message) + message = ""; + +#if defined(_WIN32) || defined(_WIN64) + OutputDebugStringA("\r\nMDBX-PANIC: "); + OutputDebugStringA(message); + if (IsDebuggerPresent()) + DebugBreak(); + FatalExit(ERROR_UNHANDLED_ERROR); +#else + __assert_fail(message, "mdbx", 0, "panic"); + abort(); +#endif +} + +/*----------------------------------------------------------------------------*/ + +#ifndef mdbx_vasprintf +int mdbx_vasprintf(char **strp, const char *fmt, va_list ap) { + va_list ones; + va_copy(ones, ap); + int needed = vsnprintf(nullptr, 0, fmt, ap); + + if (unlikely(needed < 0 || needed >= INT_MAX)) { + *strp = nullptr; + va_end(ones); + return needed; + } + + *strp = mdbx_malloc(needed + 1); + if (unlikely(*strp == nullptr)) { + va_end(ones); +#if defined(_WIN32) || defined(_WIN64) + SetLastError(MDBX_ENOMEM); +#else + errno = MDBX_ENOMEM; +#endif + return -1; + } + + int actual = vsnprintf(*strp, needed + 1, fmt, ones); + va_end(ones); + + assert(actual == needed); + if (unlikely(actual < 0)) { + mdbx_free(*strp); + *strp = nullptr; + } + return actual; +} +#endif /* mdbx_vasprintf */ + +#ifndef mdbx_asprintf +int mdbx_asprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int rc = mdbx_vasprintf(strp, fmt, ap); + va_end(ap); + return rc; +} +#endif /* mdbx_asprintf */ + +#ifndef mdbx_memalign_alloc +int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result) { +#if defined(_WIN32) || defined(_WIN64) + (void)alignment; + *result = VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + return *result ? MDBX_SUCCESS : MDBX_ENOMEM /* ERROR_OUTOFMEMORY */; +#elif defined(_ISOC11_SOURCE) + *result = aligned_alloc(alignment, bytes); + return *result ? MDBX_SUCCESS : errno; +#elif _POSIX_VERSION >= 200112L + *result = nullptr; + return posix_memalign(result, alignment, bytes); +#elif __GLIBC_PREREQ(2, 16) || __STDC_VERSION__ >= 201112L + *result = memalign(alignment, bytes); + return *result ? MDBX_SUCCESS : errno; +#else +#error FIXME +#endif +} +#endif /* mdbx_memalign_alloc */ + +#ifndef mdbx_memalign_free +void mdbx_memalign_free(void *ptr) { +#if defined(_WIN32) || defined(_WIN64) + VirtualFree(ptr, 0, MEM_RELEASE); +#else + mdbx_free(ptr); +#endif +} +#endif /* mdbx_memalign_free */ + +#ifndef mdbx_strdup +char *mdbx_strdup(const char *str) { + if (!str) + return NULL; + size_t bytes = strlen(str) + 1; + char *dup = mdbx_malloc(bytes); + if (dup) + memcpy(dup, str, bytes); + return dup; +} +#endif /* mdbx_strdup */ + +/*----------------------------------------------------------------------------*/ + +int mdbx_condmutex_init(mdbx_condmutex_t *condmutex) { +#if defined(_WIN32) || defined(_WIN64) + int rc = MDBX_SUCCESS; + condmutex->event = NULL; + condmutex->mutex = CreateMutex(NULL, FALSE, NULL); + if (!condmutex->mutex) + return GetLastError(); + + condmutex->event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!condmutex->event) { + rc = GetLastError(); + (void)CloseHandle(condmutex->mutex); + condmutex->mutex = NULL; + } + return rc; +#else + memset(condmutex, 0, sizeof(mdbx_condmutex_t)); + int rc = pthread_mutex_init(&condmutex->mutex, NULL); + if (rc == 0) { + rc = pthread_cond_init(&condmutex->cond, NULL); + if (rc != 0) + (void)pthread_mutex_destroy(&condmutex->mutex); + } + return rc; +#endif +} + +static bool is_allzeros(const void *ptr, size_t bytes) { + const uint8_t *u8 = ptr; + for (size_t i = 0; i < bytes; ++i) + if (u8[i] != 0) + return false; + return true; +} + +int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex) { + int rc = MDBX_EINVAL; +#if defined(_WIN32) || defined(_WIN64) + if (condmutex->event) { + rc = CloseHandle(condmutex->event) ? MDBX_SUCCESS : GetLastError(); + if (rc == MDBX_SUCCESS) + condmutex->event = NULL; + } + if (condmutex->mutex) { + rc = CloseHandle(condmutex->mutex) ? MDBX_SUCCESS : GetLastError(); + if (rc == MDBX_SUCCESS) + condmutex->mutex = NULL; + } +#else + if (!is_allzeros(&condmutex->cond, sizeof(condmutex->cond))) { + rc = pthread_cond_destroy(&condmutex->cond); + if (rc == 0) + memset(&condmutex->cond, 0, sizeof(condmutex->cond)); + } + if (!is_allzeros(&condmutex->mutex, sizeof(condmutex->mutex))) { + rc = pthread_mutex_destroy(&condmutex->mutex); + if (rc == 0) + memset(&condmutex->mutex, 0, sizeof(condmutex->mutex)); + } +#endif + return rc; +} + +int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex) { +#if defined(_WIN32) || defined(_WIN64) + DWORD code = WaitForSingleObject(condmutex->mutex, INFINITE); + return waitstatus2errcode(code); +#else + return pthread_mutex_lock(&condmutex->mutex); +#endif +} + +int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex) { +#if defined(_WIN32) || defined(_WIN64) + return ReleaseMutex(condmutex->mutex) ? MDBX_SUCCESS : GetLastError(); +#else + return pthread_mutex_unlock(&condmutex->mutex); +#endif +} + +int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex) { +#if defined(_WIN32) || defined(_WIN64) + return SetEvent(condmutex->event) ? MDBX_SUCCESS : GetLastError(); +#else + return pthread_cond_signal(&condmutex->cond); +#endif +} + +int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex) { +#if defined(_WIN32) || defined(_WIN64) + DWORD code = + SignalObjectAndWait(condmutex->mutex, condmutex->event, INFINITE, FALSE); + if (code == WAIT_OBJECT_0) + code = WaitForSingleObject(condmutex->mutex, INFINITE); + return waitstatus2errcode(code); +#else + return pthread_cond_wait(&condmutex->cond, &condmutex->mutex); +#endif +} + +/*----------------------------------------------------------------------------*/ + +int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex) { +#if defined(_WIN32) || defined(_WIN64) + InitializeCriticalSection(fastmutex); + return MDBX_SUCCESS; +#else + return pthread_mutex_init(fastmutex, NULL); +#endif +} + +int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex) { +#if defined(_WIN32) || defined(_WIN64) + DeleteCriticalSection(fastmutex); + return MDBX_SUCCESS; +#else + return pthread_mutex_destroy(fastmutex); +#endif +} + +int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex) { +#if defined(_WIN32) || defined(_WIN64) + EnterCriticalSection(fastmutex); + return MDBX_SUCCESS; +#else + return pthread_mutex_lock(fastmutex); +#endif +} + +int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) { +#if defined(_WIN32) || defined(_WIN64) + LeaveCriticalSection(fastmutex); + return MDBX_SUCCESS; +#else + return pthread_mutex_unlock(fastmutex); +#endif +} + +/*----------------------------------------------------------------------------*/ + +int mdbx_removefile(const char *pathname) { +#if defined(_WIN32) || defined(_WIN64) + return DeleteFileA(pathname) ? MDBX_SUCCESS : GetLastError(); +#else + return unlink(pathname) ? errno : MDBX_SUCCESS; +#endif +} +int mdbx_openfile(const char *pathname, int flags, mode_t mode, + mdbx_filehandle_t *fd, bool exclusive) { + *fd = INVALID_HANDLE_VALUE; +#if defined(_WIN32) || defined(_WIN64) + (void)mode; + + DWORD DesiredAccess, ShareMode; + DWORD FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { + default: + return ERROR_INVALID_PARAMETER; + case O_RDONLY: + DesiredAccess = GENERIC_READ; + ShareMode = + exclusive ? FILE_SHARE_READ : (FILE_SHARE_READ | FILE_SHARE_WRITE); + break; + case O_WRONLY: /* assume for MDBX_env_copy() and friends output */ + DesiredAccess = GENERIC_WRITE; + ShareMode = 0; + FlagsAndAttributes |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; + break; + case O_RDWR: + DesiredAccess = GENERIC_READ | GENERIC_WRITE; + ShareMode = exclusive ? 0 : (FILE_SHARE_READ | FILE_SHARE_WRITE); + break; + } + + DWORD CreationDisposition; + switch (flags & (O_EXCL | O_CREAT)) { + default: + return ERROR_INVALID_PARAMETER; + case 0: + CreationDisposition = OPEN_EXISTING; + break; + case O_EXCL | O_CREAT: + CreationDisposition = CREATE_NEW; + FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + break; + case O_CREAT: + CreationDisposition = OPEN_ALWAYS; + FlagsAndAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + break; + } + + *fd = CreateFileA(pathname, DesiredAccess, ShareMode, NULL, + CreationDisposition, FlagsAndAttributes, NULL); + + if (*fd == INVALID_HANDLE_VALUE) + return GetLastError(); + if ((flags & O_CREAT) && GetLastError() != ERROR_ALREADY_EXISTS) { + /* set FILE_ATTRIBUTE_NOT_CONTENT_INDEXED for new file */ + DWORD FileAttributes = GetFileAttributesA(pathname); + if (FileAttributes == INVALID_FILE_ATTRIBUTES || + !SetFileAttributesA(pathname, FileAttributes | + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) { + int rc = GetLastError(); + CloseHandle(*fd); + *fd = INVALID_HANDLE_VALUE; + return rc; + } + } +#else + (void)exclusive; +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif /* O_CLOEXEC */ + *fd = open(pathname, flags, mode); + if (*fd < 0) + return errno; + +#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC) + int fd_flags = fcntl(*fd, F_GETFD); + if (fd_flags != -1) + (void)fcntl(*fd, F_SETFD, fd_flags | FD_CLOEXEC); +#endif /* FD_CLOEXEC && !O_CLOEXEC */ + + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) { + /* assume for MDBX_env_copy() and friends output */ +#if defined(O_DIRECT) + int fd_flags = fcntl(*fd, F_GETFD); + if (fd_flags != -1) + (void)fcntl(*fd, F_SETFL, fd_flags | O_DIRECT); +#endif /* O_DIRECT */ +#if defined(F_NOCACHE) + (void)fcntl(*fd, F_NOCACHE, 1); +#endif /* F_NOCACHE */ + } +#endif + + return MDBX_SUCCESS; +} + +int mdbx_closefile(mdbx_filehandle_t fd) { +#if defined(_WIN32) || defined(_WIN64) + return CloseHandle(fd) ? MDBX_SUCCESS : GetLastError(); +#else + return (close(fd) == 0) ? MDBX_SUCCESS : errno; +#endif +} + +int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t bytes, uint64_t offset) { + if (bytes > MAX_WRITE) + return MDBX_EINVAL; +#if defined(_WIN32) || defined(_WIN64) + OVERLAPPED ov; + ov.hEvent = 0; + ov.Offset = (DWORD)offset; + ov.OffsetHigh = HIGH_DWORD(offset); + + DWORD read = 0; + if (unlikely(!ReadFile(fd, buf, (DWORD)bytes, &read, &ov))) { + int rc = GetLastError(); + return (rc == MDBX_SUCCESS) ? /* paranoia */ ERROR_READ_FAULT : rc; + } +#else + STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + intptr_t read = pread(fd, buf, bytes, offset); + if (read < 0) { + int rc = errno; + return (rc == MDBX_SUCCESS) ? /* paranoia */ MDBX_EIO : rc; + } +#endif + return (bytes == (size_t)read) ? MDBX_SUCCESS : MDBX_ENODATA; +} + +int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t bytes, + uint64_t offset) { + while (true) { +#if defined(_WIN32) || defined(_WIN64) + OVERLAPPED ov; + ov.hEvent = 0; + ov.Offset = (DWORD)offset; + ov.OffsetHigh = HIGH_DWORD(offset); + + DWORD written; + if (unlikely(!WriteFile(fd, buf, + (bytes <= MAX_WRITE) ? (DWORD)bytes : MAX_WRITE, + &written, &ov))) + return GetLastError(); + if (likely(bytes == written)) + return MDBX_SUCCESS; +#else + STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + const intptr_t written = + pwrite(fd, buf, (bytes <= MAX_WRITE) ? bytes : MAX_WRITE, offset); + if (likely(bytes == (size_t)written)) + return MDBX_SUCCESS; + if (written < 0) { + const int rc = errno; + if (rc != EINTR) + return rc; + continue; + } +#endif + bytes -= written; + offset += written; + buf = (char *)buf + written; + } +} + +int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt, + uint64_t offset, size_t expected_written) { +#if defined(_WIN32) || defined(_WIN64) || defined(__APPLE__) + size_t written = 0; + for (int i = 0; i < iovcnt; ++i) { + int rc = mdbx_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + written += iov[i].iov_len; + offset += iov[i].iov_len; + } + return (expected_written == written) ? MDBX_SUCCESS + : MDBX_EIO /* ERROR_WRITE_FAULT */; +#else + int rc; + intptr_t written; + do { + STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + written = pwritev(fd, iov, iovcnt, offset); + if (likely(expected_written == (size_t)written)) + return MDBX_SUCCESS; + rc = errno; + } while (rc == EINTR); + return (written < 0) ? rc : MDBX_EIO /* Use which error code? */; +#endif +} + +int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits) { +#if defined(_WIN32) || defined(_WIN64) + return ((mode_bits & (MDBX_SYNC_DATA | MDBX_SYNC_IODQ)) == 0 || + FlushFileBuffers(fd)) + ? MDBX_SUCCESS + : GetLastError(); +#else + +#if defined(__APPLE__) && \ + MDBX_OSX_SPEED_INSTEADOF_DURABILITY == MDBX_OSX_WANNA_DURABILITY + if (mode_bits & MDBX_SYNC_IODQ) + return likely(fcntl(fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno; +#endif /* MacOS */ +#if defined(__linux__) || defined(__gnu_linux__) + if (mode_bits == MDBX_SYNC_SIZE && mdbx_linux_kernel_version >= 0x03060000) + return MDBX_SUCCESS; +#endif /* Linux */ + int rc; + do { +#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 + /* LY: This code is always safe and without appreciable performance + * degradation, even on a kernel with fdatasync's bug. + * + * For more info about of a corresponding fdatasync() bug + * see http://www.spinics.net/lists/linux-ext4/msg33714.html */ + if ((mode_bits & MDBX_SYNC_SIZE) == 0) { + if (fdatasync(fd) == 0) + return MDBX_SUCCESS; + } else +#else + (void)mode_bits; +#endif + if (fsync(fd) == 0) + return MDBX_SUCCESS; + rc = errno; + } while (rc == EINTR); + return rc; +#endif +} + +int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length) { +#if defined(_WIN32) || defined(_WIN64) + BY_HANDLE_FILE_INFORMATION info; + if (!GetFileInformationByHandle(fd, &info)) + return GetLastError(); + *length = info.nFileSizeLow | (uint64_t)info.nFileSizeHigh << 32; +#else + struct stat st; + + STATIC_ASSERT_MSG(sizeof(off_t) <= sizeof(uint64_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + if (fstat(fd, &st)) + return errno; + + *length = st.st_size; +#endif + return MDBX_SUCCESS; +} + +int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length) { +#if defined(_WIN32) || defined(_WIN64) + if (mdbx_SetFileInformationByHandle) { + FILE_END_OF_FILE_INFO EndOfFileInfo; + EndOfFileInfo.EndOfFile.QuadPart = length; + return mdbx_SetFileInformationByHandle(fd, FileEndOfFileInfo, + &EndOfFileInfo, + sizeof(FILE_END_OF_FILE_INFO)) + ? MDBX_SUCCESS + : GetLastError(); + } else { + LARGE_INTEGER li; + li.QuadPart = length; + return (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) && SetEndOfFile(fd)) + ? MDBX_SUCCESS + : GetLastError(); + } +#else + STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + return ftruncate(fd, length) == 0 ? MDBX_SUCCESS : errno; +#endif +} + +int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos) { +#if defined(_WIN32) || defined(_WIN64) + LARGE_INTEGER li; + li.QuadPart = pos; + return SetFilePointerEx(fd, li, NULL, FILE_BEGIN) ? MDBX_SUCCESS + : GetLastError(); +#else + STATIC_ASSERT_MSG(sizeof(off_t) >= sizeof(size_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + return (lseek(fd, pos, SEEK_SET) < 0) ? errno : MDBX_SUCCESS; +#endif +} + +/*----------------------------------------------------------------------------*/ + +int mdbx_thread_create(mdbx_thread_t *thread, + THREAD_RESULT(THREAD_CALL *start_routine)(void *), + void *arg) { +#if defined(_WIN32) || defined(_WIN64) + *thread = CreateThread(NULL, 0, start_routine, arg, 0, NULL); + return *thread ? MDBX_SUCCESS : GetLastError(); +#else + return pthread_create(thread, NULL, start_routine, arg); +#endif +} + +int mdbx_thread_join(mdbx_thread_t thread) { +#if defined(_WIN32) || defined(_WIN64) + DWORD code = WaitForSingleObject(thread, INFINITE); + return waitstatus2errcode(code); +#else + void *unused_retval = &unused_retval; + return pthread_join(thread, &unused_retval); +#endif +} + +/*----------------------------------------------------------------------------*/ + +int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async) { + uint8_t *ptr = (uint8_t *)map->address + offset; +#if defined(_WIN32) || defined(_WIN64) + if (FlushViewOfFile(ptr, length) && (async || FlushFileBuffers(map->fd))) + return MDBX_SUCCESS; + return GetLastError(); +#else +#ifdef __linux__ + if (async && mdbx_linux_kernel_version > 0x02061300) + /* Since Linux 2.6.19, MS_ASYNC is in fact a no-op, + since the kernel properly tracks dirty pages and flushes them to storage + as necessary. */ + return MDBX_SUCCESS; +#endif /* Linux */ + const int mode = async ? MS_ASYNC : MS_SYNC; + int rc = (msync(ptr, length, mode) == 0) ? MDBX_SUCCESS : errno; +#if defined(__APPLE__) && \ + MDBX_OSX_SPEED_INSTEADOF_DURABILITY == MDBX_OSX_WANNA_DURABILITY + if (rc == MDBX_SUCCESS && mode == MS_SYNC) + rc = likely(fcntl(map->fd, F_FULLFSYNC) != -1) ? MDBX_SUCCESS : errno; +#endif /* MacOS */ + return rc; +#endif +} + +int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags) { +#if defined(_WIN32) || defined(_WIN64) + if (GetFileType(handle) != FILE_TYPE_DISK) + return ERROR_FILE_OFFLINE; + + if (mdbx_GetFileInformationByHandleEx) { + FILE_REMOTE_PROTOCOL_INFO RemoteProtocolInfo; + if (mdbx_GetFileInformationByHandleEx(handle, FileRemoteProtocolInfo, + &RemoteProtocolInfo, + sizeof(RemoteProtocolInfo))) { + + if ((RemoteProtocolInfo.Flags & REMOTE_PROTOCOL_INFO_FLAG_OFFLINE) && + !(flags & MDBX_RDONLY)) + return ERROR_FILE_OFFLINE; + if (!(RemoteProtocolInfo.Flags & REMOTE_PROTOCOL_INFO_FLAG_LOOPBACK) && + !(flags & MDBX_EXCLUSIVE)) + return ERROR_REMOTE_STORAGE_MEDIA_ERROR; + } + } + + if (mdbx_NtFsControlFile) { + NTSTATUS rc; + struct { + WOF_EXTERNAL_INFO wof_info; + union { + WIM_PROVIDER_EXTERNAL_INFO wim_info; + FILE_PROVIDER_EXTERNAL_INFO_V1 file_info; + }; + size_t reserved_for_microsoft_madness[42]; + } GetExternalBacking_OutputBuffer; + IO_STATUS_BLOCK StatusBlock; + rc = mdbx_NtFsControlFile(handle, NULL, NULL, NULL, &StatusBlock, + FSCTL_GET_EXTERNAL_BACKING, NULL, 0, + &GetExternalBacking_OutputBuffer, + sizeof(GetExternalBacking_OutputBuffer)); + if (NT_SUCCESS(rc)) { + if (!(flags & MDBX_EXCLUSIVE)) + return ERROR_REMOTE_STORAGE_MEDIA_ERROR; + } else if (rc != STATUS_OBJECT_NOT_EXTERNALLY_BACKED && + rc != STATUS_INVALID_DEVICE_REQUEST) + return ntstatus2errcode(rc); + } + + if (mdbx_GetVolumeInformationByHandleW && mdbx_GetFinalPathNameByHandleW) { + WCHAR *PathBuffer = mdbx_malloc(sizeof(WCHAR) * INT16_MAX); + if (!PathBuffer) + return MDBX_ENOMEM; + + int rc = MDBX_SUCCESS; + DWORD VolumeSerialNumber, FileSystemFlags; + if (!mdbx_GetVolumeInformationByHandleW(handle, PathBuffer, INT16_MAX, + &VolumeSerialNumber, NULL, + &FileSystemFlags, NULL, 0)) { + rc = GetLastError(); + goto bailout; + } + + if ((flags & MDBX_RDONLY) == 0) { + if (FileSystemFlags & + (FILE_SEQUENTIAL_WRITE_ONCE | FILE_READ_ONLY_VOLUME | + FILE_VOLUME_IS_COMPRESSED)) { + rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; + goto bailout; + } + } + + if (!mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX, + FILE_NAME_NORMALIZED | + VOLUME_NAME_NT)) { + rc = GetLastError(); + goto bailout; + } + + if (_wcsnicmp(PathBuffer, L"\\Device\\Mup\\", 12) == 0) { + if (!(flags & MDBX_EXCLUSIVE)) { + rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; + goto bailout; + } + } else if (mdbx_GetFinalPathNameByHandleW(handle, PathBuffer, INT16_MAX, + FILE_NAME_NORMALIZED | + VOLUME_NAME_DOS)) { + UINT DriveType = GetDriveTypeW(PathBuffer); + if (DriveType == DRIVE_NO_ROOT_DIR && + _wcsnicmp(PathBuffer, L"\\\\?\\", 4) == 0 && + _wcsnicmp(PathBuffer + 5, L":\\", 2) == 0) { + PathBuffer[7] = 0; + DriveType = GetDriveTypeW(PathBuffer + 4); + } + switch (DriveType) { + case DRIVE_CDROM: + if (flags & MDBX_RDONLY) + break; + // fall through + case DRIVE_UNKNOWN: + case DRIVE_NO_ROOT_DIR: + case DRIVE_REMOTE: + default: + if (!(flags & MDBX_EXCLUSIVE)) + rc = ERROR_REMOTE_STORAGE_MEDIA_ERROR; + // fall through + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + case DRIVE_RAMDISK: + break; + } + } + bailout: + mdbx_free(PathBuffer); + return rc; + } +#else + (void)handle; + /* TODO: check for NFS handle ? */ + (void)flags; +#endif + return MDBX_SUCCESS; +} + +int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t size, size_t limit) { + assert(size <= limit); +#if defined(_WIN32) || defined(_WIN64) + map->length = 0; + map->current = 0; + map->section = NULL; + map->address = nullptr; + + NTSTATUS rc = mdbx_check4nonlocal(map->fd, flags); + if (rc != MDBX_SUCCESS) + return rc; + + rc = mdbx_filesize(map->fd, &map->filesize); + if (rc != MDBX_SUCCESS) + return rc; + if ((flags & MDBX_RDONLY) == 0 && map->filesize != size) { + rc = mdbx_ftruncate(map->fd, size); + if (rc == MDBX_SUCCESS) + map->filesize = size; + /* ignore error, because Windows unable shrink file + * that already mapped (by another process) */ + } + + LARGE_INTEGER SectionSize; + SectionSize.QuadPart = size; + rc = NtCreateSection( + &map->section, + /* DesiredAccess */ + (flags & MDBX_WRITEMAP) + ? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE | + SECTION_MAP_WRITE + : SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE, + /* ObjectAttributes */ NULL, /* MaximumSize (InitialSize) */ &SectionSize, + /* SectionPageProtection */ + (flags & MDBX_RDONLY) ? PAGE_READONLY : PAGE_READWRITE, + /* AllocationAttributes */ SEC_RESERVE, map->fd); + if (!NT_SUCCESS(rc)) + return ntstatus2errcode(rc); + + SIZE_T ViewSize = (flags & MDBX_RDONLY) ? 0 : limit; + rc = NtMapViewOfSection( + map->section, GetCurrentProcess(), &map->address, + /* ZeroBits */ 0, + /* CommitSize */ 0, + /* SectionOffset */ NULL, &ViewSize, + /* InheritDisposition */ ViewUnmap, + /* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE, + /* Win32Protect */ + (flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY); + if (!NT_SUCCESS(rc)) { + NtClose(map->section); + map->section = 0; + map->address = nullptr; + return ntstatus2errcode(rc); + } + assert(map->address != MAP_FAILED); + + map->current = (size_t)SectionSize.QuadPart; + map->length = ViewSize; + return MDBX_SUCCESS; +#else + (void)size; + map->address = mmap( + NULL, limit, (flags & MDBX_WRITEMAP) ? PROT_READ | PROT_WRITE : PROT_READ, + MAP_SHARED, map->fd, 0); + if (likely(map->address != MAP_FAILED)) { + map->length = limit; + return MDBX_SUCCESS; + } + map->length = 0; + map->address = nullptr; + return errno; +#endif +} + +int mdbx_munmap(mdbx_mmap_t *map) { +#if defined(_WIN32) || defined(_WIN64) + if (map->section) + NtClose(map->section); + NTSTATUS rc = NtUnmapViewOfSection(GetCurrentProcess(), map->address); + if (!NT_SUCCESS(rc)) + ntstatus2errcode(rc); + + map->length = 0; + map->current = 0; + map->address = nullptr; +#else + if (unlikely(munmap(map->address, map->length))) + return errno; + map->length = 0; + map->address = nullptr; +#endif + return MDBX_SUCCESS; +} + +int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size, size_t limit) { + assert(size <= limit); +#if defined(_WIN32) || defined(_WIN64) + assert(size != map->current || limit != map->length || size < map->filesize); + + NTSTATUS status; + LARGE_INTEGER SectionSize; + int err, rc = MDBX_SUCCESS; + + if (!(flags & MDBX_RDONLY) && limit == map->length && size > map->current) { + /* growth rw-section */ + SectionSize.QuadPart = size; + status = NtExtendSection(map->section, &SectionSize); + if (NT_SUCCESS(status)) { + map->current = size; + if (map->filesize < size) + map->filesize = size; + } + return ntstatus2errcode(status); + } + + if (limit > map->length) { + /* check ability of address space for growth before umnap */ + PVOID BaseAddress = (PBYTE)map->address + map->length; + SIZE_T RegionSize = limit - map->length; + status = NtAllocateVirtualMemory(GetCurrentProcess(), &BaseAddress, 0, + &RegionSize, MEM_RESERVE, PAGE_NOACCESS); + if (!NT_SUCCESS(status)) + return ntstatus2errcode(status); + + status = NtFreeVirtualMemory(GetCurrentProcess(), &BaseAddress, &RegionSize, + MEM_RELEASE); + if (!NT_SUCCESS(status)) + return ntstatus2errcode(status); + } + + /* Windows unable: + * - shrink a mapped file; + * - change size of mapped view; + * - extend read-only mapping; + * Therefore we should unmap/map entire section. */ + status = NtUnmapViewOfSection(GetCurrentProcess(), map->address); + if (!NT_SUCCESS(status)) + return ntstatus2errcode(status); + status = NtClose(map->section); + map->section = NULL; + PVOID ReservedAddress = NULL; + SIZE_T ReservedSize = limit; + + if (!NT_SUCCESS(status)) { + bailout_ntstatus: + err = ntstatus2errcode(status); + bailout: + map->address = NULL; + map->current = map->length = 0; + if (ReservedAddress) + (void)NtFreeVirtualMemory(GetCurrentProcess(), &ReservedAddress, + &ReservedSize, MEM_RELEASE); + return err; + } + + /* resizing of the file may take a while, + * therefore we reserve address space to avoid occupy it by other threads */ + ReservedAddress = map->address; + status = NtAllocateVirtualMemory(GetCurrentProcess(), &ReservedAddress, 0, + &ReservedSize, MEM_RESERVE, PAGE_NOACCESS); + if (!NT_SUCCESS(status)) { + ReservedAddress = NULL; + if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018) + goto bailout_ntstatus /* no way to recovery */; + + /* assume we can change base address if mapping size changed or prev address + * couldn't be used */ + map->address = NULL; + } + +retry_file_and_section: + err = mdbx_filesize(map->fd, &map->filesize); + if (err != MDBX_SUCCESS) + goto bailout; + + if ((flags & MDBX_RDONLY) == 0 && map->filesize != size) { + err = mdbx_ftruncate(map->fd, size); + if (err == MDBX_SUCCESS) + map->filesize = size; + /* ignore error, because Windows unable shrink file + * that already mapped (by another process) */ + } + + SectionSize.QuadPart = size; + status = NtCreateSection( + &map->section, + /* DesiredAccess */ + (flags & MDBX_WRITEMAP) + ? SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE | + SECTION_MAP_WRITE + : SECTION_QUERY | SECTION_MAP_READ | SECTION_EXTEND_SIZE, + /* ObjectAttributes */ NULL, + /* MaximumSize (InitialSize) */ &SectionSize, + /* SectionPageProtection */ + (flags & MDBX_RDONLY) ? PAGE_READONLY : PAGE_READWRITE, + /* AllocationAttributes */ SEC_RESERVE, map->fd); + + if (!NT_SUCCESS(status)) + goto bailout_ntstatus; + + if (ReservedAddress) { + /* release reserved address space */ + status = NtFreeVirtualMemory(GetCurrentProcess(), &ReservedAddress, + &ReservedSize, MEM_RELEASE); + ReservedAddress = NULL; + if (!NT_SUCCESS(status)) + goto bailout_ntstatus; + } + +retry_mapview:; + SIZE_T ViewSize = (flags & MDBX_RDONLY) ? size : limit; + status = NtMapViewOfSection( + map->section, GetCurrentProcess(), &map->address, + /* ZeroBits */ 0, + /* CommitSize */ 0, + /* SectionOffset */ NULL, &ViewSize, + /* InheritDisposition */ ViewUnmap, + /* AllocationType */ (flags & MDBX_RDONLY) ? 0 : MEM_RESERVE, + /* Win32Protect */ + (flags & MDBX_WRITEMAP) ? PAGE_READWRITE : PAGE_READONLY); + + if (!NT_SUCCESS(status)) { + if (status == /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 && + map->address) { + /* try remap at another base address */ + map->address = NULL; + goto retry_mapview; + } + NtClose(map->section); + map->section = NULL; + + if (map->address && (size != map->current || limit != map->length)) { + /* try remap with previously size and limit, + * but will return MDBX_RESULT_TRUE on success */ + rc = MDBX_RESULT_TRUE; + size = map->current; + limit = map->length; + goto retry_file_and_section; + } + + /* no way to recovery */ + goto bailout_ntstatus; + } + assert(map->address != MAP_FAILED); + + map->current = (size_t)SectionSize.QuadPart; + map->length = ViewSize; + return rc; +#else + if (limit != map->length) { +#if defined(_GNU_SOURCE) && \ + !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \ + defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__)) + void *ptr = mremap(map->address, map->length, limit, + /* LY: in case changing the mapping size calling code + must guarantees the absence of competing threads, and + a willingness to another base address */ + MREMAP_MAYMOVE); + if (ptr == MAP_FAILED) { + int err = errno; + return (err == EAGAIN || err == ENOMEM) ? MDBX_RESULT_TRUE : err; + } + map->address = ptr; + map->length = limit; +#else + return MDBX_RESULT_TRUE; +#endif /* mremap() <= _GNU_SOURCE && !__FreeBSD__ */ + } + return (flags & MDBX_RDONLY) ? MDBX_SUCCESS : mdbx_ftruncate(map->fd, size); +#endif +} + +/*----------------------------------------------------------------------------*/ + +__cold void mdbx_osal_jitter(bool tiny) { + for (;;) { +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ + defined(__x86_64__) + const unsigned salt = 277u * (unsigned)__rdtsc(); +#else + const unsigned salt = rand(); +#endif + + const unsigned coin = salt % (tiny ? 29u : 43u); + if (coin < 43 / 3) + break; +#if defined(_WIN32) || defined(_WIN64) + SwitchToThread(); + if (coin > 43 * 2 / 3) + Sleep(1); +#else + sched_yield(); + if (coin > 43 * 2 / 3) + usleep(coin); +#endif + } +} + +#if defined(_WIN32) || defined(_WIN64) +#elif defined(__APPLE__) || defined(__MACH__) +#include +#elif defined(__linux__) || defined(__gnu_linux__) +static __cold clockid_t choice_monoclock() { + struct timespec probe; +#if defined(CLOCK_BOOTTIME) + if (clock_gettime(CLOCK_BOOTTIME, &probe) == 0) + return CLOCK_BOOTTIME; +#elif defined(CLOCK_MONOTONIC_RAW) + if (clock_gettime(CLOCK_MONOTONIC_RAW, &probe) == 0) + return CLOCK_MONOTONIC_RAW; +#elif defined(CLOCK_MONOTONIC_COARSE) + if (clock_gettime(CLOCK_MONOTONIC_COARSE, &probe) == 0) + return CLOCK_MONOTONIC_COARSE; +#endif + return CLOCK_MONOTONIC; +} +#endif + +uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16) { +#if defined(_WIN32) || defined(_WIN64) + static LARGE_INTEGER performance_frequency; + if (performance_frequency.QuadPart == 0) + QueryPerformanceFrequency(&performance_frequency); + const uint64_t ratio = performance_frequency.QuadPart; +#elif defined(__APPLE__) || defined(__MACH__) + static uint64_t ratio; + if (!ratio) { + mach_timebase_info_data_t ti; + mach_timebase_info(&ti); + ratio = UINT64_C(1000000000) * ti.denom / ti.numer; + } +#else + const uint64_t ratio = UINT64_C(1000000000); +#endif + return (ratio * seconds_16dot16 + 32768) >> 16; +} + +uint64_t mdbx_osal_monotime(void) { +#if defined(_WIN32) || defined(_WIN64) + LARGE_INTEGER counter; + counter.QuadPart = 0; + QueryPerformanceCounter(&counter); + return counter.QuadPart; +#elif defined(__APPLE__) || defined(__MACH__) + return mach_absolute_time(); +#else + +#if defined(__linux__) || defined(__gnu_linux__) + static clockid_t posix_clockid = -1; + if (unlikely(posix_clockid < 0)) + posix_clockid = choice_monoclock(); +#elif defined(CLOCK_MONOTONIC) +#define posix_clockid CLOCK_MONOTONIC +#else +#define posix_clockid CLOCK_REALTIME +#endif + + struct timespec ts; + if (unlikely(clock_gettime(posix_clockid, &ts) != 0)) { + ts.tv_nsec = 0; + ts.tv_sec = 0; + } + return ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec; +#endif +} diff --git a/contrib/db/libmdbx/src/osal.h b/contrib/db/libmdbx/src/osal.h new file mode 100644 index 00000000..b690a5a5 --- /dev/null +++ b/contrib/db/libmdbx/src/osal.h @@ -0,0 +1,899 @@ +/* https://en.wikipedia.org/wiki/Operating_system_abstraction_layer */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +/*----------------------------------------------------------------------------*/ +/* Microsoft compiler generates a lot of warning for self includes... */ + +#ifdef _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable : 4548) /* expression before comma has no effect; \ + expected expression with side - effect */ +#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ + * semantics are not enabled. Specify /EHsc */ +#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ + * mode specified; termination on exception is \ + * not guaranteed. Specify /EHsc */ +#endif /* _MSC_VER (warnings) */ + +#if defined(_WIN32) || defined(_WIN64) +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif +#if !defined(_NO_CRT_STDIO_INLINE) && defined(MDBX_BUILD_DLL) +#define _NO_CRT_STDIO_INLINE +#endif +#endif /* Windows */ + +/*----------------------------------------------------------------------------*/ +/* C99 includes */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* C11 stdalign.h */ +#if __has_include() +#include +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define alignas(N) _Alignas(N) +#elif defined(_MSC_VER) +#define alignas(N) __declspec(align(N)) +#elif __has_attribute(__aligned__) || defined(__GNUC__) +#define alignas(N) __attribute__((__aligned__(N))) +#else +#error "FIXME: Required _alignas() or equivalent." +#endif + +/*----------------------------------------------------------------------------*/ +/* Systems includes */ + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__BSD__) || defined(__NETBSD__) || defined(__bsdi__) || \ + defined(__DragonFly__) || defined(__APPLE__) || defined(__MACH__) +#include +#else +#include +#ifndef _POSIX_C_SOURCE +#ifdef _POSIX_SOURCE +#define _POSIX_C_SOURCE 1 +#else +#define _POSIX_C_SOURCE 0 +#endif +#endif +#endif /* !xBSD */ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 0 +#endif + +#if defined(_WIN32) || defined(_WIN64) +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#define HAVE_SYS_STAT_H +#define HAVE_SYS_TYPES_H +typedef HANDLE mdbx_thread_t; +typedef unsigned mdbx_thread_key_t; +#define MDBX_OSAL_SECTION HANDLE +#define MAP_FAILED NULL +#define HIGH_DWORD(v) ((DWORD)((sizeof(v) > 4) ? ((uint64_t)(v) >> 32) : 0)) +#define THREAD_CALL WINAPI +#define THREAD_RESULT DWORD +typedef struct { + HANDLE mutex; + HANDLE event; +} mdbx_condmutex_t; +typedef CRITICAL_SECTION mdbx_fastmutex_t; + +#ifdef MDBX_AVOID_CRT +#ifndef mdbx_malloc +static inline void *mdbx_malloc(size_t bytes) { + return LocalAlloc(LMEM_FIXED, bytes); +} +#endif /* mdbx_malloc */ + +#ifndef mdbx_calloc +static inline void *mdbx_calloc(size_t nelem, size_t size) { + return LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, nelem * size); +} +#endif /* mdbx_calloc */ + +#ifndef mdbx_realloc +static inline void *mdbx_realloc(void *ptr, size_t bytes) { + return LocalReAlloc(ptr, bytes, LMEM_MOVEABLE); +} +#endif /* mdbx_realloc */ + +#ifndef mdbx_free +#define mdbx_free LocalFree +#endif /* mdbx_free */ +#else +#define mdbx_malloc malloc +#define mdbx_calloc calloc +#define mdbx_realloc realloc +#define mdbx_free free +#define mdbx_strdup _strdup +#endif /* MDBX_AVOID_CRT */ + +#ifndef snprintf +#define snprintf _snprintf /* ntdll */ +#endif + +#ifndef vsnprintf +#define vsnprintf _vsnprintf /* ntdll */ +#endif + +#else /*----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +typedef pthread_t mdbx_thread_t; +typedef pthread_key_t mdbx_thread_key_t; +#define INVALID_HANDLE_VALUE (-1) +#define THREAD_CALL +#define THREAD_RESULT void * +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; +} mdbx_condmutex_t; +typedef pthread_mutex_t mdbx_fastmutex_t; +#define mdbx_malloc malloc +#define mdbx_calloc calloc +#define mdbx_realloc realloc +#define mdbx_free free +#define mdbx_strdup strdup +#endif /* Platform */ + +/* *INDENT-OFF* */ +/* clang-format off */ +#if defined(HAVE_SYS_STAT_H) || __has_include() +#include +#endif +#if defined(HAVE_SYS_TYPES_H) || __has_include() +#include +#endif +#if defined(HAVE_SYS_FILE_H) || __has_include() +#include +#endif +/* *INDENT-ON* */ +/* clang-format on */ + +#ifndef SSIZE_MAX +#define SSIZE_MAX INTPTR_MAX +#endif + +#if !defined(MADV_DODUMP) && defined(MADV_CORE) +#define MADV_DODUMP MADV_CORE +#endif /* MADV_CORE -> MADV_DODUMP */ + +#if !defined(MADV_DONTDUMP) && defined(MADV_NOCORE) +#define MADV_DONTDUMP MADV_NOCORE +#endif /* MADV_NOCORE -> MADV_DONTDUMP */ + +#ifndef MADV_REMOVE_OR_FREE +#ifdef MADV_REMOVE +#define MADV_REMOVE_OR_FREE MADV_REMOVE +#elif defined(MADV_FREE) +#define MADV_REMOVE_OR_FREE MADV_FREE +#endif +#endif /* MADV_REMOVE_OR_FREE */ + +#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \ + defined(i486) || defined(__i486) || defined(__i486__) || \ + defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \ + defined(__i686) || defined(__i686__) || defined(_M_IX86) || \ + defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \ + defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \ + defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__) +#ifndef __ia32__ +/* LY: define neutral __ia32__ for x86 and x86-64 archs */ +#define __ia32__ 1 +#endif /* __ia32__ */ +#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64) || defined(_M_X64)) +/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */ +#define __amd64__ 1 +#endif /* __amd64__ */ +#endif /* all x86 */ + +#if !defined(UNALIGNED_OK) +#if (defined(__ia32__) || defined(__e2k__) || \ + defined(__ARM_FEATURE_UNALIGNED)) && \ + !defined(__ALIGNED__) +#define UNALIGNED_OK 1 +#else +#define UNALIGNED_OK 0 +#endif +#endif /* UNALIGNED_OK */ + +#if (-6 & 5) || CHAR_BIT != 8 || UINT_MAX < 0xffffffff || ULONG_MAX % 0xFFFF +#error \ + "Sanity checking failed: Two's complement, reasonably sized integer types" +#endif + +/*----------------------------------------------------------------------------*/ +/* Compiler's includes for builtins/intrinsics */ + +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#include +#elif __GNUC_PREREQ(4, 4) || defined(__clang__) +#if defined(__ia32__) || defined(__e2k__) +#include +#endif /* __ia32__ */ +#if defined(__ia32__) +#include +#endif /* __ia32__ */ +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) +#include +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ + (defined(HP_IA64) || defined(__ia64)) +#include +#elif defined(__IBMC__) && defined(__powerpc) +#include +#elif defined(_AIX) +#include +#include +#elif (defined(__osf__) && defined(__DECC)) || defined(__alpha) +#include +#include +#elif defined(__MWERKS__) +/* CodeWarrior - troubles ? */ +#pragma gcc_extensions +#elif defined(__SNC__) +/* Sony PS3 - troubles ? */ +#elif defined(__hppa__) || defined(__hppa) +#include +#else +#error Unsupported C compiler, please use GNU C 4.4 or newer +#endif /* Compiler */ + +/*----------------------------------------------------------------------------*/ +/* Byteorder */ + +#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ + !defined(__ORDER_BIG_ENDIAN__) + +/* *INDENT-OFF* */ +/* clang-format off */ +#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \ + defined(HAVE_ENDIAN_H) || __has_include() +#include +#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \ + defined(HAVE_MACHINE_ENDIAN_H) || __has_include() +#include +#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include() +#include +#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \ + (__has_include() && __has_include()) +#include +#include +#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__NETBSD__) || defined(__NetBSD__) || \ + defined(HAVE_SYS_PARAM_H) || __has_include() +#include +#endif /* OS */ +/* *INDENT-ON* */ +/* clang-format on */ + +#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) +#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN +#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN +#define __BYTE_ORDER__ __BYTE_ORDER +#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN +#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN +#define __BYTE_ORDER__ _BYTE_ORDER +#else +#define __ORDER_LITTLE_ENDIAN__ 1234 +#define __ORDER_BIG_ENDIAN__ 4321 + +#if defined(__LITTLE_ENDIAN__) || \ + (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ + defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ + defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL) || \ + defined(_M_ARM) || defined(_M_ARM64) || defined(__e2k__) || \ + defined(__elbrus_4c__) || defined(__elbrus_8c__) || defined(__bfin__) || \ + defined(__BFIN__) || defined(__ia64__) || defined(_IA64) || \ + defined(__IA64__) || defined(__ia64) || defined(_M_IA64) || \ + defined(__itanium__) || defined(__ia32__) || defined(__CYGWIN__) || \ + defined(_WIN64) || defined(_WIN32) || defined(__TOS_WIN__) || \ + defined(__WINDOWS__) +#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + +#elif defined(__BIG_ENDIAN__) || \ + (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \ + defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(__MIPSEB__) || defined(_MIPSEB) || defined(__MIPSEB) || \ + defined(__m68k__) || defined(M68000) || defined(__hppa__) || \ + defined(__hppa) || defined(__HPPA__) || defined(__sparc__) || \ + defined(__sparc) || defined(__370__) || defined(__THW_370__) || \ + defined(__s390__) || defined(__s390x__) || defined(__SYSC_ZARCH__) +#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ + +#else +#error __BYTE_ORDER__ should be defined. +#endif /* Arch */ + +#endif +#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */ + +/*----------------------------------------------------------------------------*/ +/* Memory/Compiler barriers, cache coherence */ + +static __inline void mdbx_compiler_barrier(void) { +#if defined(__clang__) || defined(__GNUC__) + __asm__ __volatile__("" ::: "memory"); +#elif defined(_MSC_VER) + _ReadWriteBarrier(); +#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ + __memory_barrier(); + if (type > MDBX_BARRIER_COMPILER) +#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) + __mf(); +#elif defined(__i386__) || defined(__x86_64__) + _mm_mfence(); +#else +#error "Unknown target for Intel Compiler, please report to us." +#endif +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) + __compiler_barrier(); +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ + (defined(HP_IA64) || defined(__ia64)) + _Asm_sched_fence(/* LY: no-arg meaning 'all expect ALU', e.g. 0x3D3D */); +#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ + defined(__ppc64__) || defined(__powerpc64__) + __fence(); +#else +#error "Could not guess the kind of compiler, please report to us." +#endif +} + +static __inline void mdbx_memory_barrier(void) { +#if __has_extension(c_atomic) || __has_extension(cxx_atomic) + __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); +#elif defined(__ATOMIC_SEQ_CST) + __atomic_thread_fence(__ATOMIC_SEQ_CST); +#elif defined(__clang__) || defined(__GNUC__) + __sync_synchronize(); +#elif defined(_MSC_VER) + MemoryBarrier(); +#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ +#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) + __mf(); +#elif defined(__i386__) || defined(__x86_64__) + _mm_mfence(); +#else +#error "Unknown target for Intel Compiler, please report to us." +#endif +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) + __machine_rw_barrier(); +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ + (defined(HP_IA64) || defined(__ia64)) + _Asm_mf(); +#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ + defined(__ppc64__) || defined(__powerpc64__) + __lwsync(); +#else +#error "Could not guess the kind of compiler, please report to us." +#endif +} + +/*----------------------------------------------------------------------------*/ +/* Cache coherence and invalidation */ + +#ifndef MDBX_CPU_WRITEBACK_IS_COHERENT +#if defined(__ia32__) || defined(__e2k__) || defined(__hppa) || \ + defined(__hppa__) +#define MDBX_CPU_WRITEBACK_IS_COHERENT 1 +#else +#define MDBX_CPU_WRITEBACK_IS_COHERENT 0 +#endif +#endif /* MDBX_CPU_WRITEBACK_IS_COHERENT */ + +#ifndef MDBX_CACHELINE_SIZE +#if defined(SYSTEM_CACHE_ALIGNMENT_SIZE) +#define MDBX_CACHELINE_SIZE SYSTEM_CACHE_ALIGNMENT_SIZE +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +#define MDBX_CACHELINE_SIZE 128 +#else +#define MDBX_CACHELINE_SIZE 64 +#endif +#endif /* MDBX_CACHELINE_SIZE */ + +#if MDBX_CPU_WRITEBACK_IS_COHERENT +#define mdbx_flush_noncoherent_cpu_writeback() mdbx_compiler_barrier() +#else +#define mdbx_flush_noncoherent_cpu_writeback() mdbx_memory_barrier() +#endif + +#if __has_include() +#include +#elif defined(__mips) || defined(__mips__) || defined(__mips64) || \ + defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \ + defined(__MWERKS__) || defined(__sgi) +/* MIPS should have explicit cache control */ +#include +#endif + +#ifndef MDBX_CPU_CACHE_MMAP_NONCOHERENT +#if defined(__mips) || defined(__mips__) || defined(__mips64) || \ + defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \ + defined(__MWERKS__) || defined(__sgi) +/* MIPS has cache coherency issues. */ +#define MDBX_CPU_CACHE_MMAP_NONCOHERENT 1 +#else +/* LY: assume no relevant mmap/dcache issues. */ +#define MDBX_CPU_CACHE_MMAP_NONCOHERENT 0 +#endif +#endif /* ndef MDBX_CPU_CACHE_MMAP_NONCOHERENT */ + +static __inline void mdbx_invalidate_mmap_noncoherent_cache(void *addr, + size_t nbytes) { +#if MDBX_CPU_CACHE_MMAP_NONCOHERENT +#ifdef DCACHE + /* MIPS has cache coherency issues. + * Note: for any nbytes >= on-chip cache size, entire is flushed. */ + cacheflush(addr, nbytes, DCACHE); +#else +#error "Oops, cacheflush() not available" +#endif /* DCACHE */ +#else /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ + (void)addr; + (void)nbytes; +#endif /* MDBX_CPU_CACHE_MMAP_NONCOHERENT */ +} + +/*----------------------------------------------------------------------------*/ +/* libc compatibility stuff */ + +#if (!defined(__GLIBC__) && __GLIBC_PREREQ(2, 1)) && \ + (defined(_GNU_SOURCE) || defined(_BSD_SOURCE)) +#define mdbx_asprintf asprintf +#define mdbx_vasprintf vasprintf +#else +__printf_args(2, 3) int mdbx_asprintf(char **strp, const char *fmt, ...); +int mdbx_vasprintf(char **strp, const char *fmt, va_list ap); +#endif + +/*----------------------------------------------------------------------------*/ +/* OS abstraction layer stuff */ + +/* max bytes to write in one call */ +#define MAX_WRITE UINT32_C(0x3fff0000) + +#if defined(__linux__) || defined(__gnu_linux__) +extern uint32_t mdbx_linux_kernel_version; +#endif /* Linux */ + +/* Get the size of a memory page for the system. + * This is the basic size that the platform's memory manager uses, and is + * fundamental to the use of memory-mapped files. */ +static __inline size_t mdbx_syspagesize(void) { +#if defined(_WIN32) || defined(_WIN64) + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + return sysconf(_SC_PAGE_SIZE); +#endif +} + +#ifndef mdbx_strdup +LIBMDBX_API char *mdbx_strdup(const char *str); +#endif + +static __inline int mdbx_get_errno(void) { +#if defined(_WIN32) || defined(_WIN64) + DWORD rc = GetLastError(); +#else + int rc = errno; +#endif + return rc; +} + +#ifndef mdbx_memalign_alloc +int mdbx_memalign_alloc(size_t alignment, size_t bytes, void **result); +#endif +#ifndef mdbx_memalign_free +void mdbx_memalign_free(void *ptr); +#endif + +int mdbx_condmutex_init(mdbx_condmutex_t *condmutex); +int mdbx_condmutex_lock(mdbx_condmutex_t *condmutex); +int mdbx_condmutex_unlock(mdbx_condmutex_t *condmutex); +int mdbx_condmutex_signal(mdbx_condmutex_t *condmutex); +int mdbx_condmutex_wait(mdbx_condmutex_t *condmutex); +int mdbx_condmutex_destroy(mdbx_condmutex_t *condmutex); + +int mdbx_fastmutex_init(mdbx_fastmutex_t *fastmutex); +int mdbx_fastmutex_acquire(mdbx_fastmutex_t *fastmutex); +int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex); +int mdbx_fastmutex_destroy(mdbx_fastmutex_t *fastmutex); + +int mdbx_pwritev(mdbx_filehandle_t fd, struct iovec *iov, int iovcnt, + uint64_t offset, size_t expected_written); +int mdbx_pread(mdbx_filehandle_t fd, void *buf, size_t count, uint64_t offset); +int mdbx_pwrite(mdbx_filehandle_t fd, const void *buf, size_t count, + uint64_t offset); + +int mdbx_thread_create(mdbx_thread_t *thread, + THREAD_RESULT(THREAD_CALL *start_routine)(void *), + void *arg); +int mdbx_thread_join(mdbx_thread_t thread); + +enum mdbx_syncmode_bits { + MDBX_SYNC_DATA = 1, + MDBX_SYNC_SIZE = 2, + MDBX_SYNC_IODQ = 4 +}; + +int mdbx_filesync(mdbx_filehandle_t fd, enum mdbx_syncmode_bits mode_bits); +int mdbx_filesize_sync(mdbx_filehandle_t fd); +int mdbx_ftruncate(mdbx_filehandle_t fd, uint64_t length); +int mdbx_fseek(mdbx_filehandle_t fd, uint64_t pos); +int mdbx_filesize(mdbx_filehandle_t fd, uint64_t *length); +int mdbx_openfile(const char *pathname, int flags, mode_t mode, + mdbx_filehandle_t *fd, bool exclusive); +int mdbx_closefile(mdbx_filehandle_t fd); +int mdbx_removefile(const char *pathname); + +typedef struct mdbx_mmap_param { + union { + void *address; + uint8_t *dxb; + struct MDBX_lockinfo *lck; + }; + mdbx_filehandle_t fd; + size_t length; /* mapping length, but NOT a size of file or DB */ +#if defined(_WIN32) || defined(_WIN64) + size_t current; /* mapped region size, e.g. file and DB */ + uint64_t filesize; +#endif +#ifdef MDBX_OSAL_SECTION + MDBX_OSAL_SECTION section; +#endif +} mdbx_mmap_t; + +int mdbx_mmap(int flags, mdbx_mmap_t *map, size_t must, size_t limit); +int mdbx_munmap(mdbx_mmap_t *map); +int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t current, size_t wanna); +#if defined(_WIN32) || defined(_WIN64) +typedef struct { + unsigned limit, count; + HANDLE handles[31]; +} mdbx_handle_array_t; +int mdbx_suspend_threads_before_remap(MDBX_env *env, + mdbx_handle_array_t **array); +int mdbx_resume_threads_after_remap(mdbx_handle_array_t *array); +#endif /* Windows */ +int mdbx_msync(mdbx_mmap_t *map, size_t offset, size_t length, int async); +int mdbx_check4nonlocal(mdbx_filehandle_t handle, int flags); + +static __inline mdbx_pid_t mdbx_getpid(void) { +#if defined(_WIN32) || defined(_WIN64) + return GetCurrentProcessId(); +#else + return getpid(); +#endif +} + +static __inline mdbx_tid_t mdbx_thread_self(void) { +#if defined(_WIN32) || defined(_WIN64) + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +void mdbx_osal_jitter(bool tiny); +uint64_t mdbx_osal_monotime(void); +uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); + +/*----------------------------------------------------------------------------*/ +/* lck stuff */ + +#if defined(_WIN32) || defined(_WIN64) +#undef MDBX_OSAL_LOCK +#define MDBX_OSAL_LOCK_SIGN UINT32_C(0xF10C) +#else +#define MDBX_OSAL_LOCK pthread_mutex_t +#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017) +#endif /* MDBX_OSAL_LOCK */ + +/// \brief Инициализация объектов синхронизации внутри текущего процесса +/// связанных с экземпляром MDBX_env. +/// \return Код ошибки или 0 в случае успеха. +int mdbx_lck_init(MDBX_env *env); + +/// \brief Отключение от общих межпроцесных объектов и разрушение объектов +/// синхронизации внутри текущего процесса связанных с экземпляром MDBX_env. +void mdbx_lck_destroy(MDBX_env *env); + +/// \brief Подключение к общим межпроцесным объектам блокировки с попыткой +/// захвата блокировки максимального уровня (разделяемой при недоступности +/// эксклюзивной). +/// В зависимости от реализации и/или платформы (Windows) может +/// захватывать блокировку не-операционного супер-уровня (например, для +/// инициализации разделяемых объектов синхронизации), которая затем будет +/// понижена до операционно-эксклюзивной или разделяемой посредством +/// явного вызова mdbx_lck_downgrade(). +/// \return +/// MDBX_RESULT_TRUE (-1) - если удалось захватить эксклюзивную блокировку и, +/// следовательно, текущий процесс является первым и единственным +/// после предыдущего использования БД. +/// MDBX_RESULT_FALSE (0) - если удалось захватить только разделяемую +/// блокировку и, следовательно, БД уже открыта и используется другими +/// процессами. +/// Иначе (не 0 и не -1) - код ошибки. +int mdbx_lck_seize(MDBX_env *env); + +/// \brief Снижает уровень первоначальной захваченной блокировки до +/// операционного уровня определяемого аргументом. +/// \param +/// complete = TRUE - понижение до разделяемой блокировки. +/// complete = FALSE - понижение до эксклюзивной операционной блокировки. +/// \return Код ошибки или 0 в случае успеха. +int mdbx_lck_downgrade(MDBX_env *env, bool complete); + +/// \brief Блокирует lck-файл и/или таблицу читателей для (де)регистрации. +/// \return Код ошибки или 0 в случае успеха. +int mdbx_rdt_lock(MDBX_env *env); + +/// \brief Разблокирует lck-файл и/или таблицу читателей после (де)регистрации. +void mdbx_rdt_unlock(MDBX_env *env); + +/// \brief Захватывает блокировку для изменения БД (при старте пишущей +/// транзакции). Транзакции чтения при этом никак не блокируются. +/// \return Код ошибки или 0 в случае успеха. +LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dontwait); + +/// \brief Освобождает блокировку по окончанию изменения БД (после завершения +/// пишущей транзакции). +LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env); + +/// \brief Устанавливает alive-флажок присутствия (индицирующую блокировку) +/// читателя для pid текущего процесса. Функции может выполнить не более +/// необходимого минимума для корректной работы mdbx_rpid_check() в других +/// процессах. +/// \return Код ошибки или 0 в случае успеха. +int mdbx_rpid_set(MDBX_env *env); + +/// \brief Снимает alive-флажок присутствия (индицирующую блокировку) +/// читателя для pid текущего процесса. Функции может выполнить не более +/// необходимого минимума для корректной работы mdbx_rpid_check() в других +/// процессах. +/// \return Код ошибки или 0 в случае успеха. +int mdbx_rpid_clear(MDBX_env *env); + +/// \brief Проверяет жив ли процесс-читатель с заданным pid +/// по alive-флажку присутствия (индицирующей блокировку), +/// либо любым другим способом. +/// \return +/// MDBX_RESULT_TRUE (-1) - если процесс-читатель с соответствующим pid жив +/// и работает с БД (индицирующая блокировка присутствует). +/// MDBX_RESULT_FALSE (0) - если процесс-читатель с соответствующим pid +/// отсутствует или не работает с БД (индицирующая блокировка отсутствует). +/// Иначе (не 0 и не -1) - код ошибки. +int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid); + +#if defined(_WIN32) || defined(_WIN64) +typedef union MDBX_srwlock { + struct { + long volatile readerCount; + long volatile writerCount; + }; + RTL_SRWLOCK native; +} MDBX_srwlock; + +typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *); +extern MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared, + mdbx_srwlock_ReleaseShared, mdbx_srwlock_AcquireExclusive, + mdbx_srwlock_ReleaseExclusive; + +typedef BOOL(WINAPI *MDBX_GetFileInformationByHandleEx)( + _In_ HANDLE hFile, _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + _Out_ LPVOID lpFileInformation, _In_ DWORD dwBufferSize); +extern MDBX_GetFileInformationByHandleEx mdbx_GetFileInformationByHandleEx; + +typedef BOOL(WINAPI *MDBX_GetVolumeInformationByHandleW)( + _In_ HANDLE hFile, _Out_opt_ LPWSTR lpVolumeNameBuffer, + _In_ DWORD nVolumeNameSize, _Out_opt_ LPDWORD lpVolumeSerialNumber, + _Out_opt_ LPDWORD lpMaximumComponentLength, + _Out_opt_ LPDWORD lpFileSystemFlags, + _Out_opt_ LPWSTR lpFileSystemNameBuffer, _In_ DWORD nFileSystemNameSize); +extern MDBX_GetVolumeInformationByHandleW mdbx_GetVolumeInformationByHandleW; + +typedef DWORD(WINAPI *MDBX_GetFinalPathNameByHandleW)(_In_ HANDLE hFile, + _Out_ LPWSTR lpszFilePath, + _In_ DWORD cchFilePath, + _In_ DWORD dwFlags); +extern MDBX_GetFinalPathNameByHandleW mdbx_GetFinalPathNameByHandleW; + +typedef BOOL(WINAPI *MDBX_SetFileInformationByHandle)( + _In_ HANDLE hFile, _In_ FILE_INFO_BY_HANDLE_CLASS FileInformationClass, + _Out_ LPVOID lpFileInformation, _In_ DWORD dwBufferSize); +extern MDBX_SetFileInformationByHandle mdbx_SetFileInformationByHandle; + +typedef NTSTATUS(NTAPI *MDBX_NtFsControlFile)( + IN HANDLE FileHandle, IN OUT HANDLE Event, + IN OUT PVOID /* PIO_APC_ROUTINE */ ApcRoutine, IN OUT PVOID ApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG FsControlCode, + IN OUT PVOID InputBuffer, IN ULONG InputBufferLength, + OUT OPTIONAL PVOID OutputBuffer, IN ULONG OutputBufferLength); +extern MDBX_NtFsControlFile mdbx_NtFsControlFile; + +#ifndef _WIN32_WINNT_WIN8 +typedef struct _WIN32_MEMORY_RANGE_ENTRY { + PVOID VirtualAddress; + SIZE_T NumberOfBytes; +} WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY; +#endif + +typedef BOOL(WINAPI *MDBX_PrefetchVirtualMemory)( + HANDLE hProcess, ULONG_PTR NumberOfEntries, + PWIN32_MEMORY_RANGE_ENTRY VirtualAddresses, ULONG Flags); +extern MDBX_PrefetchVirtualMemory mdbx_PrefetchVirtualMemory; + +#endif /* Windows */ + +/*----------------------------------------------------------------------------*/ +/* Atomics */ + +#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \ + !defined(__STDC_NO_ATOMICS__) && \ + (__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \ + !(defined(__GNUC__) || defined(__clang__))) +#include +#elif defined(__GNUC__) || defined(__clang__) +/* LY: nothing required */ +#elif defined(_MSC_VER) +#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */ +#pragma warning(disable : 4133) /* 'function': incompatible types - from \ + 'size_t' to 'LONGLONG' */ +#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \ + 'std::size_t', possible loss of data */ +#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \ + 'long', possible loss of data */ +#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange) +#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64) +#elif defined(__APPLE__) +#include +#else +#error FIXME atomic-ops +#endif + +static __inline uint32_t mdbx_atomic_add32(volatile uint32_t *p, uint32_t v) { +#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT) + assert(atomic_is_lock_free(p)); + return atomic_fetch_add((_Atomic uint32_t *)p, v); +#elif defined(__GNUC__) || defined(__clang__) + return __sync_fetch_and_add(p, v); +#else +#ifdef _MSC_VER + STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t)); + return _InterlockedExchangeAdd((volatile long *)p, v); +#endif +#ifdef __APPLE__ + return OSAtomicAdd32(v, (volatile int32_t *)p); +#endif +#endif +} + +static __inline uint64_t mdbx_atomic_add64(volatile uint64_t *p, uint64_t v) { +#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT) + assert(atomic_is_lock_free(p)); + return atomic_fetch_add((_Atomic uint64_t *)p, v); +#elif defined(__GNUC__) || defined(__clang__) + return __sync_fetch_and_add(p, v); +#else +#ifdef _MSC_VER +#ifdef _WIN64 + return _InterlockedExchangeAdd64((volatile int64_t *)p, v); +#else + return InterlockedExchangeAdd64((volatile int64_t *)p, v); +#endif +#endif /* _MSC_VER */ +#ifdef __APPLE__ + return OSAtomicAdd64(v, (volatile int64_t *)p); +#endif +#endif +} + +#define mdbx_atomic_sub32(p, v) mdbx_atomic_add32(p, 0 - (v)) +#define mdbx_atomic_sub64(p, v) mdbx_atomic_add64(p, 0 - (v)) + +static __inline bool mdbx_atomic_compare_and_swap32(volatile uint32_t *p, + uint32_t c, uint32_t v) { +#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT) + assert(atomic_is_lock_free(p)); + return atomic_compare_exchange_strong((_Atomic uint32_t *)p, &c, v); +#elif defined(__GNUC__) || defined(__clang__) + return __sync_bool_compare_and_swap(p, c, v); +#else +#ifdef _MSC_VER + STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t)); + return c == _InterlockedCompareExchange((volatile long *)p, v, c); +#endif +#ifdef __APPLE__ + return c == OSAtomicCompareAndSwap32Barrier(c, v, (volatile int32_t *)p); +#endif +#endif +} + +static __inline bool mdbx_atomic_compare_and_swap64(volatile uint64_t *p, + uint64_t c, uint64_t v) { +#if !defined(__cplusplus) && defined(ATOMIC_VAR_INIT) + assert(atomic_is_lock_free(p)); + return atomic_compare_exchange_strong((_Atomic uint64_t *)p, &c, v); +#elif defined(__GNUC__) || defined(__clang__) + return __sync_bool_compare_and_swap(p, c, v); +#else +#ifdef _MSC_VER + return c == _InterlockedCompareExchange64((volatile int64_t *)p, v, c); +#endif +#ifdef __APPLE__ + return c == OSAtomicCompareAndSwap64Barrier(c, v, (volatile uint64_t *)p); +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ + +#if defined(_MSC_VER) && _MSC_VER >= 1900 +/* LY: MSVC 2015/2017/2019 has buggy/inconsistent PRIuPTR/PRIxPTR macros + * for internal format-args checker. */ +#undef PRIuPTR +#undef PRIiPTR +#undef PRIdPTR +#undef PRIxPTR +#define PRIuPTR "Iu" +#define PRIiPTR "Ii" +#define PRIdPTR "Id" +#define PRIxPTR "Ix" +#define PRIuSIZE "zu" +#define PRIiSIZE "zi" +#define PRIdSIZE "zd" +#define PRIxSIZE "zx" +#endif /* fix PRI*PTR for _MSC_VER */ + +#ifndef PRIuSIZE +#define PRIuSIZE PRIuPTR +#define PRIiSIZE PRIiPTR +#define PRIdSIZE PRIdPTR +#define PRIxSIZE PRIxPTR +#endif /* PRI*SIZE macros for MSVC */ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/contrib/db/libmdbx/src/tools/CMakeLists.txt b/contrib/db/libmdbx/src/tools/CMakeLists.txt new file mode 100644 index 00000000..3e200098 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/CMakeLists.txt @@ -0,0 +1,19 @@ +project(mdbx_tools) + +set(MDBX_TOOLS + mdbx_chk + mdbx_copy + mdbx_dump + mdbx_load + mdbx_stat + ) + +foreach (TOOL ${MDBX_TOOLS}) + add_executable(${TOOL} ${TOOL}.c) + + target_link_libraries(${TOOL} mdbx) + install(TARGETS ${TOOL} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT mdbx) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${TOOL}.1) + install(FILES ${TOOL}.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man1 COMPONENT mdbx) + endif() +endforeach() diff --git a/contrib/db/libmdbx/src/tools/mdbx_chk.c b/contrib/db/libmdbx/src/tools/mdbx_chk.c new file mode 100644 index 00000000..9d3b9e06 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_chk.c @@ -0,0 +1,1417 @@ +/* mdbx_chk.c - memory-mapped database check tool */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#ifdef _MSC_VER +#if _MSC_VER > 1800 +#pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ +#endif /* _MSC_VER (warnings) */ + +/* Avoid reference to mdbx_runtime_flags from assert() */ +#define mdbx_runtime_flags (~0u) +#include "../bits.h" + +typedef struct flagbit { + int bit; + char *name; +} flagbit; + +flagbit dbflags[] = {{MDBX_DUPSORT, "dupsort"}, + {MDBX_INTEGERKEY, "integerkey"}, + {MDBX_REVERSEKEY, "reversekey"}, + {MDBX_DUPFIXED, "dupfixed"}, + {MDBX_REVERSEDUP, "reversedup"}, + {MDBX_INTEGERDUP, "integerdup"}, + {0, NULL}}; + +#if defined(_WIN32) || defined(_WIN64) +#include "wingetopt.h" + +static volatile BOOL user_break; +static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { + (void)dwCtrlType; + user_break = true; + return true; +} + +#else /* WINDOWS */ + +static volatile sig_atomic_t user_break; +static void signal_handler(int sig) { + (void)sig; + user_break = 1; +} + +#endif /* !WINDOWS */ + +#define EXIT_INTERRUPTED (EXIT_FAILURE + 4) +#define EXIT_FAILURE_SYS (EXIT_FAILURE + 3) +#define EXIT_FAILURE_MDB (EXIT_FAILURE + 2) +#define EXIT_FAILURE_CHECK_MAJOR (EXIT_FAILURE + 1) +#define EXIT_FAILURE_CHECK_MINOR EXIT_FAILURE + +typedef struct { + const char *name; + struct { + uint64_t branch, large_count, large_volume, leaf; + uint64_t subleaf_dupsort, leaf_dupfixed, subleaf_dupfixed; + uint64_t total, empty, other; + } pages; + uint64_t payload_bytes; + uint64_t lost_bytes; +} walk_dbi_t; + +struct { + short *pagemap; + uint64_t total_payload_bytes; + uint64_t pgcount; + walk_dbi_t dbi[MAX_DBI]; +} walk; + +#define dbi_free walk.dbi[FREE_DBI] +#define dbi_main walk.dbi[MAIN_DBI] +#define dbi_meta walk.dbi[CORE_DBS] + +uint64_t total_unused_bytes; +int envflags = MDBX_RDONLY | MDBX_EXCLUSIVE; + +MDBX_env *env; +MDBX_txn *txn; +MDBX_envinfo envinfo; +MDBX_stat envstat; +size_t maxkeysize, userdb_count, skipped_subdb; +uint64_t reclaimable_pages, gc_pages, alloc_pages, unused_pages, backed_pages; +unsigned verbose; +char ignore_wrong_order, quiet; +const char *only_subdb; + +struct problem { + struct problem *pr_next; + size_t count; + const char *caption; +}; + +struct problem *problems_list; +uint64_t total_problems; + +static void __printf_args(1, 2) print(const char *msg, ...) { + if (!quiet) { + va_list args; + + fflush(stderr); + va_start(args, msg); + vfprintf(stdout, msg, args); + va_end(args); + } +} + +static void __printf_args(1, 2) error(const char *msg, ...) { + total_problems++; + + if (!quiet) { + va_list args; + + fflush(stdout); + va_start(args, msg); + fputs(" ! ", stderr); + vfprintf(stderr, msg, args); + va_end(args); + fflush(NULL); + } +} + +static void pagemap_cleanup(void) { + for (int i = CORE_DBS; ++i < MAX_DBI;) { + if (walk.dbi[i].name) { + mdbx_free((void *)walk.dbi[i].name); + walk.dbi[i].name = NULL; + } + } + + mdbx_free(walk.pagemap); + walk.pagemap = NULL; +} + +static walk_dbi_t *pagemap_lookup_dbi(const char *dbi_name, bool silent) { + static walk_dbi_t *last; + + if (dbi_name == MDBX_PGWALK_MAIN) + return &dbi_main; + if (dbi_name == MDBX_PGWALK_GC) + return &dbi_free; + if (dbi_name == MDBX_PGWALK_META) + return &dbi_meta; + + if (last && strcmp(last->name, dbi_name) == 0) + return last; + + walk_dbi_t *dbi = walk.dbi + CORE_DBS; + for (dbi = walk.dbi + CORE_DBS; (++dbi)->name;) { + if (strcmp(dbi->name, dbi_name) == 0) + return last = dbi; + if (dbi == walk.dbi + MAX_DBI) + return NULL; + } + + dbi->name = mdbx_strdup(dbi_name); + if (verbose > 0 && !silent) { + print(" - found '%s' area\n", dbi_name); + fflush(NULL); + } + + return last = dbi; +} + +static void __printf_args(4, 5) + + problem_add(const char *object, uint64_t entry_number, const char *msg, + const char *extra, ...) { + total_problems++; + + if (!quiet) { + int need_fflush = 0; + struct problem *p; + + for (p = problems_list; p; p = p->pr_next) + if (p->caption == msg) + break; + + if (!p) { + p = mdbx_calloc(1, sizeof(*p)); + p->caption = msg; + p->pr_next = problems_list; + problems_list = p; + need_fflush = 1; + } + + p->count++; + if (verbose > 1) { + print(" %s #%" PRIu64 ": %s", object, entry_number, msg); + if (extra) { + va_list args; + printf(" ("); + va_start(args, extra); + vfprintf(stdout, extra, args); + va_end(args); + printf(")"); + } + printf("\n"); + if (need_fflush) + fflush(NULL); + } + } +} + +static struct problem *problems_push(void) { + struct problem *p = problems_list; + problems_list = NULL; + return p; +} + +static size_t problems_pop(struct problem *list) { + size_t count = 0; + + if (problems_list) { + int i; + + print(" - problems: "); + for (i = 0; problems_list; ++i) { + struct problem *p = problems_list->pr_next; + count += problems_list->count; + print("%s%s (%" PRIuPTR ")", i ? ", " : "", problems_list->caption, + problems_list->count); + mdbx_free(problems_list); + problems_list = p; + } + print("\n"); + fflush(NULL); + } + + problems_list = list; + return count; +} + +static int pgvisitor(const uint64_t pgno, const unsigned pgnumber, + void *const ctx, const int deep, + const char *const dbi_name_or_tag, const size_t page_size, + const MDBX_page_type_t pagetype, const size_t nentries, + const size_t payload_bytes, const size_t header_bytes, + const size_t unused_bytes) { + (void)ctx; + if (deep > 42) { + problem_add("deep", deep, "too large", nullptr); + return MDBX_CORRUPTED /* avoid infinite loop/recursion */; + } + + if (pagetype == MDBX_page_void) + return MDBX_SUCCESS; + + walk_dbi_t *dbi = pagemap_lookup_dbi(dbi_name_or_tag, false); + if (!dbi) + return MDBX_ENOMEM; + + const size_t page_bytes = payload_bytes + header_bytes + unused_bytes; + walk.pgcount += pgnumber; + + const char *pagetype_caption; + bool branch = false; + switch (pagetype) { + default: + problem_add("page", pgno, "unknown page-type", "type %u, deep %i", + (unsigned)pagetype, deep); + pagetype_caption = "unknown"; + dbi->pages.other += pgnumber; + break; + case MDBX_page_meta: + pagetype_caption = "meta"; + dbi->pages.other += pgnumber; + break; + case MDBX_page_large: + pagetype_caption = "large"; + dbi->pages.large_volume += pgnumber; + dbi->pages.large_count += 1; + break; + case MDBX_page_branch: + pagetype_caption = "branch"; + dbi->pages.branch += pgnumber; + branch = true; + break; + case MDBX_page_leaf: + pagetype_caption = "leaf"; + dbi->pages.leaf += pgnumber; + break; + case MDBX_page_dupfixed_leaf: + pagetype_caption = "leaf-dupfixed"; + dbi->pages.leaf_dupfixed += pgnumber; + break; + case MDBX_subpage_leaf: + pagetype_caption = "subleaf-dupsort"; + dbi->pages.subleaf_dupsort += 1; + break; + case MDBX_subpage_dupfixed_leaf: + pagetype_caption = "subleaf-dupfixed"; + dbi->pages.subleaf_dupfixed += 1; + break; + } + + if (pgnumber) { + if (verbose > 3 && (!only_subdb || strcmp(only_subdb, dbi->name) == 0)) { + if (pgnumber == 1) + print(" %s-page %" PRIu64, pagetype_caption, pgno); + else + print(" %s-span %" PRIu64 "[%u]", pagetype_caption, pgno, pgnumber); + print(" of %s: header %" PRIiPTR ", payload %" PRIiPTR + ", unused %" PRIiPTR ", deep %i\n", + dbi->name, header_bytes, payload_bytes, unused_bytes, deep); + } + + bool already_used = false; + for (unsigned n = 0; n < pgnumber; ++n) { + uint64_t spanpgno = pgno + n; + if (spanpgno >= alloc_pages) + problem_add("page", spanpgno, "wrong page-no", + "%s-page: %" PRIu64 " > %" PRIu64 ", deep %i", + pagetype_caption, spanpgno, alloc_pages, deep); + else if (walk.pagemap[spanpgno]) { + walk_dbi_t *coll_dbi = &walk.dbi[walk.pagemap[spanpgno] - 1]; + problem_add("page", spanpgno, + (branch && coll_dbi == dbi) ? "loop" : "already used", + "%s-page: by %s, deep %i", pagetype_caption, coll_dbi->name, + deep); + already_used = true; + } else { + walk.pagemap[spanpgno] = (short)(dbi - walk.dbi + 1); + dbi->pages.total += 1; + } + } + + if (already_used) + return branch ? MDBX_RESULT_TRUE /* avoid infinite loop/recursion */ + : MDBX_SUCCESS; + } + + if (unused_bytes > page_size) + problem_add("page", pgno, "illegal unused-bytes", + "%s-page: %u < %" PRIuPTR " < %u", pagetype_caption, 0, + unused_bytes, envstat.ms_psize); + + if (header_bytes < (int)sizeof(long) || + (size_t)header_bytes >= envstat.ms_psize - sizeof(long)) + problem_add("page", pgno, "illegal header-length", + "%s-page: %" PRIuPTR " < %" PRIuPTR " < %" PRIuPTR, + pagetype_caption, sizeof(long), header_bytes, + envstat.ms_psize - sizeof(long)); + if (payload_bytes < 1) { + if (nentries > 1) { + problem_add("page", pgno, "zero size-of-entry", + "%s-page: payload %" PRIuPTR " bytes, %" PRIuPTR " entries", + pagetype_caption, payload_bytes, nentries); + /* if ((size_t)header_bytes + unused_bytes < page_size) { + // LY: hush a misuse error + page_bytes = page_size; + } */ + } else { + problem_add("page", pgno, "empty", + "%s-page: payload %" PRIuPTR " bytes, %" PRIuPTR + " entries, deep %i", + pagetype_caption, payload_bytes, nentries, deep); + dbi->pages.empty += 1; + } + } + + if (pgnumber) { + if (page_bytes != page_size) { + problem_add("page", pgno, "misused", + "%s-page: %" PRIuPTR " != %" PRIuPTR " (%" PRIuPTR + "h + %" PRIuPTR "p + %" PRIuPTR "u), deep %i", + pagetype_caption, page_size, page_bytes, header_bytes, + payload_bytes, unused_bytes, deep); + if (page_size > page_bytes) + dbi->lost_bytes += page_size - page_bytes; + } else { + dbi->payload_bytes += payload_bytes + header_bytes; + walk.total_payload_bytes += payload_bytes + header_bytes; + } + } + + return user_break ? MDBX_EINTR : MDBX_SUCCESS; +} + +typedef int(visitor)(const uint64_t record_number, const MDBX_val *key, + const MDBX_val *data); +static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler, + bool silent); + +static int handle_userdb(const uint64_t record_number, const MDBX_val *key, + const MDBX_val *data) { + (void)record_number; + (void)key; + (void)data; + return MDBX_SUCCESS; +} + +static int handle_freedb(const uint64_t record_number, const MDBX_val *key, + const MDBX_val *data) { + char *bad = ""; + pgno_t *iptr = data->iov_base; + txnid_t txnid = *(txnid_t *)key->iov_base; + + if (key->iov_len != sizeof(txnid_t)) + problem_add("entry", record_number, "wrong txn-id size", + "key-size %" PRIiPTR, key->iov_len); + else if (txnid < 1 || txnid > envinfo.mi_recent_txnid) + problem_add("entry", record_number, "wrong txn-id", "%" PRIaTXN, txnid); + else { + if (data->iov_len < sizeof(pgno_t) || data->iov_len % sizeof(pgno_t)) + problem_add("entry", txnid, "wrong idl size", "%" PRIuPTR, data->iov_len); + size_t number = (data->iov_len >= sizeof(pgno_t)) ? *iptr++ : 0; + if (number < 1 || number > MDBX_PNL_MAX) + problem_add("entry", txnid, "wrong idl length", "%" PRIuPTR, number); + else if ((number + 1) * sizeof(pgno_t) > data->iov_len) { + problem_add("entry", txnid, "trimmed idl", + "%" PRIuSIZE " > %" PRIuSIZE " (corruption)", + (number + 1) * sizeof(pgno_t), data->iov_len); + number = data->iov_len / sizeof(pgno_t) - 1; + } else if (data->iov_len - (number + 1) * sizeof(pgno_t) >= + /* LY: allow gap upto one page. it is ok + * and better than shink-and-retry inside mdbx_update_gc() */ + envstat.ms_psize) + problem_add("entry", txnid, "extra idl space", + "%" PRIuSIZE " < %" PRIuSIZE " (minor, not a trouble)", + (number + 1) * sizeof(pgno_t), data->iov_len); + + gc_pages += number; + if (envinfo.mi_latter_reader_txnid > txnid) + reclaimable_pages += number; + + pgno_t prev = MDBX_PNL_ASCENDING ? NUM_METAS - 1 : txn->mt_next_pgno; + pgno_t span = 1; + for (unsigned i = 0; i < number; ++i) { + const pgno_t pgno = iptr[i]; + if (pgno < NUM_METAS) + problem_add("entry", txnid, "wrong idl entry", + "pgno %" PRIaPGNO " < meta-pages %u", pgno, NUM_METAS); + else if (pgno >= backed_pages) + problem_add("entry", txnid, "wrong idl entry", + "pgno %" PRIaPGNO " > backed-pages %" PRIu64, pgno, + backed_pages); + else if (pgno >= alloc_pages) + problem_add("entry", txnid, "wrong idl entry", + "pgno %" PRIaPGNO " > alloc-pages %" PRIu64, pgno, + alloc_pages - 1); + else { + if (MDBX_PNL_DISORDERED(prev, pgno)) { + bad = " [bad sequence]"; + problem_add("entry", txnid, "bad sequence", + "%" PRIaPGNO " %c [%u].%" PRIaPGNO, prev, + (prev == pgno) ? '=' : (MDBX_PNL_ASCENDING ? '>' : '<'), + i, pgno); + } + if (walk.pagemap) { + int idx = walk.pagemap[pgno]; + if (idx == 0) + walk.pagemap[pgno] = -1; + else if (idx > 0) + problem_add("page", pgno, "already used", "by %s", + walk.dbi[idx - 1].name); + else + problem_add("page", pgno, "already listed in GC", nullptr); + } + } + prev = pgno; + while (i + span < number && + iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pgno, span) + : pgno_sub(pgno, span))) + ++span; + } + if (verbose > 3 && !only_subdb) { + print(" transaction %" PRIaTXN ", %" PRIuPTR + " pages, maxspan %" PRIaPGNO "%s\n", + txnid, number, span, bad); + if (verbose > 4) { + for (unsigned i = 0; i < number; i += span) { + const pgno_t pgno = iptr[i]; + for (span = 1; + i + span < number && + iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pgno, span) + : pgno_sub(pgno, span)); + ++span) + ; + if (span > 1) { + print(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pgno, span); + } else + print(" %9" PRIaPGNO "\n", pgno); + } + } + } + } + + return MDBX_SUCCESS; +} + +static int handle_maindb(const uint64_t record_number, const MDBX_val *key, + const MDBX_val *data) { + char *name; + int rc; + size_t i; + + name = key->iov_base; + for (i = 0; i < key->iov_len; ++i) { + if (name[i] < ' ') + return handle_userdb(record_number, key, data); + } + + name = mdbx_malloc(key->iov_len + 1); + memcpy(name, key->iov_base, key->iov_len); + name[key->iov_len] = '\0'; + userdb_count++; + + rc = process_db(~0u, name, handle_userdb, false); + mdbx_free(name); + if (rc != MDBX_INCOMPATIBLE) + return rc; + + return handle_userdb(record_number, key, data); +} + +static int process_db(MDBX_dbi dbi_handle, char *dbi_name, visitor *handler, + bool silent) { + MDBX_cursor *mc; + MDBX_stat ms; + MDBX_val key, data; + MDBX_val prev_key, prev_data; + unsigned flags; + int rc, i; + struct problem *saved_list; + uint64_t problems_count; + + uint64_t record_count = 0, dups = 0; + uint64_t key_bytes = 0, data_bytes = 0; + + if (dbi_handle == ~0u) { + rc = mdbx_dbi_open(txn, dbi_name, 0, &dbi_handle); + if (rc) { + if (!dbi_name || + rc != + MDBX_INCOMPATIBLE) /* LY: mainDB's record is not a user's DB. */ { + error("mdbx_open '%s' failed, error %d %s\n", + dbi_name ? dbi_name : "main", rc, mdbx_strerror(rc)); + } + return rc; + } + } + + if (dbi_handle >= CORE_DBS && dbi_name && only_subdb && + strcmp(only_subdb, dbi_name)) { + if (verbose) { + print("Skip processing '%s'...\n", dbi_name); + fflush(NULL); + } + skipped_subdb++; + return MDBX_SUCCESS; + } + + if (!silent && verbose) { + print("Processing '%s'...\n", dbi_name ? dbi_name : "@MAIN"); + fflush(NULL); + } + + rc = mdbx_dbi_flags(txn, dbi_handle, &flags); + if (rc) { + error("mdbx_dbi_flags failed, error %d %s\n", rc, mdbx_strerror(rc)); + return rc; + } + + rc = mdbx_dbi_stat(txn, dbi_handle, &ms, sizeof(ms)); + if (rc) { + error("mdbx_dbi_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); + return rc; + } + + if (!silent && verbose) { + print(" - dbi-id %d, flags:", dbi_handle); + if (!flags) + print(" none"); + else { + for (i = 0; dbflags[i].bit; i++) + if (flags & dbflags[i].bit) + print(" %s", dbflags[i].name); + } + print(" (0x%02X)\n", flags); + if (verbose > 1) { + print(" - page size %u, entries %" PRIu64 "\n", ms.ms_psize, + ms.ms_entries); + print(" - b-tree depth %u, pages: branch %" PRIu64 ", leaf %" PRIu64 + ", overflow %" PRIu64 "\n", + ms.ms_depth, ms.ms_branch_pages, ms.ms_leaf_pages, + ms.ms_overflow_pages); + } + } + + walk_dbi_t *dbi = (dbi_handle < CORE_DBS) + ? &walk.dbi[dbi_handle] + : pagemap_lookup_dbi(dbi_name, true); + if (!dbi) { + error("too many DBIs or out of memory\n"); + return MDBX_ENOMEM; + } + const uint64_t subtotal_pages = + ms.ms_branch_pages + ms.ms_leaf_pages + ms.ms_overflow_pages; + if (subtotal_pages != dbi->pages.total) + error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "subtotal", + subtotal_pages, dbi->pages.total); + if (ms.ms_branch_pages != dbi->pages.branch) + error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "branch", + ms.ms_branch_pages, dbi->pages.branch); + const uint64_t allleaf_pages = dbi->pages.leaf + dbi->pages.leaf_dupfixed; + if (ms.ms_leaf_pages != allleaf_pages) + error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", "all-leaf", + ms.ms_leaf_pages, allleaf_pages); + if (ms.ms_overflow_pages != dbi->pages.large_volume) + error("%s pages mismatch (%" PRIu64 " != walked %" PRIu64 ")\n", + "large/overlow", ms.ms_overflow_pages, dbi->pages.large_volume); + + rc = mdbx_cursor_open(txn, dbi_handle, &mc); + if (rc) { + error("mdbx_cursor_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + return rc; + } + + saved_list = problems_push(); + prev_key.iov_base = NULL; + prev_key.iov_len = 0; + prev_data.iov_base = NULL; + prev_data.iov_len = 0; + rc = mdbx_cursor_get(mc, &key, &data, MDBX_FIRST); + while (rc == MDBX_SUCCESS) { + if (user_break) { + print(" - interrupted by signal\n"); + fflush(NULL); + rc = MDBX_EINTR; + goto bailout; + } + + bool bad_key = false; + if (key.iov_len > maxkeysize) { + problem_add("entry", record_count, "key length exceeds max-key-size", + "%" PRIuPTR " > %" PRIuPTR, key.iov_len, maxkeysize); + bad_key = true; + } else if ((flags & MDBX_INTEGERKEY) && key.iov_len != sizeof(uint64_t) && + key.iov_len != sizeof(uint32_t)) { + problem_add("entry", record_count, "wrong key length", + "%" PRIuPTR " != 4or8", key.iov_len); + bad_key = true; + } + + bool bad_data = false; + if ((flags & MDBX_INTEGERDUP) && data.iov_len != sizeof(uint64_t) && + data.iov_len != sizeof(uint32_t)) { + problem_add("entry", record_count, "wrong data length", + "%" PRIuPTR " != 4or8", data.iov_len); + bad_data = true; + } + + if (prev_key.iov_base && !bad_data) { + if ((flags & MDBX_DUPFIXED) && prev_data.iov_len != data.iov_len) { + problem_add("entry", record_count, "different data length", + "%" PRIuPTR " != %" PRIuPTR, prev_data.iov_len, + data.iov_len); + bad_data = true; + } + + if (!bad_key) { + int cmp = mdbx_cmp(txn, dbi_handle, &prev_key, &key); + if (cmp == 0) { + ++dups; + if ((flags & MDBX_DUPSORT) == 0) { + problem_add("entry", record_count, "duplicated entries", NULL); + if (data.iov_len == prev_data.iov_len && + memcmp(data.iov_base, prev_data.iov_base, data.iov_len) == 0) { + problem_add("entry", record_count, "complete duplicate", NULL); + } + } else if (!bad_data) { + cmp = mdbx_dcmp(txn, dbi_handle, &prev_data, &data); + if (cmp == 0) { + problem_add("entry", record_count, "complete duplicate", NULL); + } else if (cmp > 0 && !ignore_wrong_order) { + problem_add("entry", record_count, "wrong order of multi-values", + NULL); + } + } + } else if (cmp > 0 && !ignore_wrong_order) { + problem_add("entry", record_count, "wrong order of entries", NULL); + } + } + } else if (verbose) { + if (flags & MDBX_INTEGERKEY) + print(" - fixed key-size %" PRIuPTR "\n", key.iov_len); + if (flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) + print(" - fixed data-size %" PRIuPTR "\n", data.iov_len); + } + + if (handler) { + rc = handler(record_count, &key, &data); + if (MDBX_IS_ERROR(rc)) + goto bailout; + } + + record_count++; + key_bytes += key.iov_len; + data_bytes += data.iov_len; + + if (!bad_key) + prev_key = key; + if (!bad_data) + prev_data = data; + rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT); + } + if (rc != MDBX_NOTFOUND) + error("mdbx_cursor_get failed, error %d %s\n", rc, mdbx_strerror(rc)); + else + rc = 0; + + if (record_count != ms.ms_entries) + problem_add("entry", record_count, "differentent number of entries", + "%" PRIu64 " != %" PRIu64, record_count, ms.ms_entries); +bailout: + problems_count = problems_pop(saved_list); + if (!silent && verbose) { + print(" - summary: %" PRIu64 " records, %" PRIu64 " dups, %" PRIu64 + " key's bytes, %" PRIu64 " data's " + "bytes, %" PRIu64 " problems\n", + record_count, dups, key_bytes, data_bytes, problems_count); + fflush(NULL); + } + + mdbx_cursor_close(mc); + return (rc || problems_count) ? MDBX_RESULT_TRUE : MDBX_SUCCESS; +} + +static void usage(char *prog) { + fprintf(stderr, + "usage: %s dbpath [-V] [-v] [-n] [-q] [-w] [-c] [-d] [-s subdb]\n" + " -V\t\tshow version\n" + " -v\t\tmore verbose, could be used multiple times\n" + " -n\t\tNOSUBDIR mode for open\n" + " -q\t\tbe quiet\n" + " -w\t\tlock DB for writing while checking\n" + " -d\t\tdisable page-by-page traversal of b-tree\n" + " -s subdb\tprocess a specific subdatabase only\n" + " -c\t\tforce cooperative mode (don't try exclusive)\n" + " -i\t\tignore wrong order errors (for custom comparators case)\n", + prog); + exit(EXIT_INTERRUPTED); +} + +const char *meta_synctype(uint64_t sign) { + switch (sign) { + case MDBX_DATASIGN_NONE: + return "no-sync/legacy"; + case MDBX_DATASIGN_WEAK: + return "weak"; + default: + return "steady"; + } +} + +static __inline bool meta_ot(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b, + uint64_t sign_b, const bool roolback2steady) { + if (txn_a == txn_b) + return SIGN_IS_STEADY(sign_b); + + if (roolback2steady && SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b)) + return SIGN_IS_STEADY(sign_b); + + return txn_a < txn_b; +} + +static __inline bool meta_eq(txnid_t txn_a, uint64_t sign_a, txnid_t txn_b, + uint64_t sign_b) { + if (txn_a != txn_b) + return false; + + if (SIGN_IS_STEADY(sign_a) != SIGN_IS_STEADY(sign_b)) + return false; + + return true; +} + +static __inline int meta_recent(const bool roolback2steady) { + + if (meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, + envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, roolback2steady)) + return meta_ot(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, + envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, + roolback2steady) + ? 1 + : 2; + + return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, + envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, roolback2steady) + ? 2 + : 0; +} + +static __inline int meta_tail(int head) { + + if (head == 0) + return meta_ot(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, + envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true) + ? 1 + : 2; + if (head == 1) + return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, + envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, true) + ? 0 + : 2; + if (head == 2) + return meta_ot(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, + envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, true) + ? 0 + : 1; + assert(false); + return -1; +} + +static int meta_steady(void) { return meta_recent(true); } + +static int meta_head(void) { return meta_recent(false); } + +void verbose_meta(int num, txnid_t txnid, uint64_t sign) { + print(" - meta-%d: %s %" PRIu64, num, meta_synctype(sign), txnid); + bool stay = true; + + const int steady = meta_steady(); + const int head = meta_head(); + if (num == steady && num == head) { + print(", head"); + stay = false; + } else if (num == steady) { + print(", head-steady"); + stay = false; + } else if (num == head) { + print(", head-weak"); + stay = false; + } + if (num == meta_tail(head)) { + print(", tail"); + stay = false; + } + if (stay) + print(", stay"); + + if (txnid > envinfo.mi_recent_txnid && + (envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) == MDBX_EXCLUSIVE) + print(", rolled-back %" PRIu64 " (%" PRIu64 " >>> %" PRIu64 ")", + txnid - envinfo.mi_recent_txnid, txnid, envinfo.mi_recent_txnid); + print("\n"); +} + +static int check_meta_head(bool steady) { + switch (meta_recent(steady)) { + default: + assert(false); + error("unexpected internal error (%s)\n", + steady ? "meta_steady_head" : "meta_weak_head"); + __fallthrough; + case 0: + if (envinfo.mi_meta0_txnid != envinfo.mi_recent_txnid) { + print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 + ")\n", + 0, envinfo.mi_meta0_txnid, envinfo.mi_recent_txnid); + return 1; + } + break; + case 1: + if (envinfo.mi_meta1_txnid != envinfo.mi_recent_txnid) { + print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 + ")\n", + 1, envinfo.mi_meta1_txnid, envinfo.mi_recent_txnid); + return 1; + } + break; + case 2: + if (envinfo.mi_meta2_txnid != envinfo.mi_recent_txnid) { + print(" - meta-%d txn-id mismatch recent-txn-id (%" PRIi64 " != %" PRIi64 + ")\n", + 2, envinfo.mi_meta2_txnid, envinfo.mi_recent_txnid); + return 1; + } + } + return 0; +} + +static void print_size(const char *prefix, const uint64_t value, + const char *suffix) { + const char sf[] = + "KMGTPEZY"; /* LY: Kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta! */ + double k = 1024.0; + size_t i; + for (i = 0; sf[i + 1] && value / k > 1000.0; ++i) + k *= 1024; + print("%s%" PRIu64 " (%.2f %cb)%s", prefix, value, value / k, sf[i], suffix); +} + +int main(int argc, char *argv[]) { + int rc; + char *prog = argv[0]; + char *envname; + int problems_maindb = 0, problems_freedb = 0, problems_meta = 0; + int dont_traversal = 0; + bool locked = false; + + double elapsed; +#if defined(_WIN32) || defined(_WIN64) + uint64_t timestamp_start, timestamp_finish; + timestamp_start = GetTickCount64(); +#else + struct timespec timestamp_start, timestamp_finish; + if (clock_gettime(CLOCK_MONOTONIC, ×tamp_start)) { + rc = errno; + error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); + return EXIT_FAILURE_SYS; + } +#endif + + dbi_meta.name = "@META"; + dbi_free.name = "@GC"; + dbi_main.name = "@MAIN"; + atexit(pagemap_cleanup); + + if (argc < 2) { + usage(prog); + } + + for (int i; (i = getopt(argc, argv, "Vvqnwcdsi:")) != EOF;) { + switch (i) { + case 'V': + printf("%s (%s, build %s)\n", mdbx_version.git.describe, + mdbx_version.git.datetime, mdbx_build.datetime); + exit(EXIT_SUCCESS); + break; + case 'v': + verbose++; + break; + case 'q': + quiet = 1; + break; + case 'n': + envflags |= MDBX_NOSUBDIR; + break; + case 'w': + envflags &= ~MDBX_RDONLY; + break; + case 'c': + envflags &= ~MDBX_EXCLUSIVE; + break; + case 'd': + dont_traversal = 1; + break; + case 's': + if (only_subdb && strcmp(only_subdb, optarg)) + usage(prog); + only_subdb = optarg; + break; + case 'i': + ignore_wrong_order = 1; + break; + default: + usage(prog); + } + } + + if (optind != argc - 1) + usage(prog); + +#if defined(_WIN32) || defined(_WIN64) + SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); +#else +#ifdef SIGPIPE + signal(SIGPIPE, signal_handler); +#endif +#ifdef SIGHUP + signal(SIGHUP, signal_handler); +#endif + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#endif /* !WINDOWS */ + + envname = argv[optind]; + print("Running mdbx_chk for %s in 'read-%s' mode...\n", envname, + (envflags & MDBX_RDONLY) ? "only" : "write"); + fflush(NULL); + + rc = mdbx_env_create(&env); + if (rc) { + error("mdbx_env_create failed, error %d %s\n", rc, mdbx_strerror(rc)); + return rc < 0 ? EXIT_FAILURE_MDB : EXIT_FAILURE_SYS; + } + + rc = mdbx_env_set_maxdbs(env, MAX_DBI); + if (rc) { + error("mdbx_env_set_maxdbs failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + rc = mdbx_env_open(env, envname, envflags, 0664); + if ((envflags & MDBX_EXCLUSIVE) && + (rc == MDBX_BUSY || +#if defined(_WIN32) || defined(_WIN64) + rc == ERROR_LOCK_VIOLATION || rc == ERROR_SHARING_VIOLATION +#else + rc == EBUSY || rc == EAGAIN +#endif + )) { + envflags &= ~MDBX_EXCLUSIVE; + rc = mdbx_env_open(env, envname, envflags, 0664); + } + + if (rc) { + error("mdbx_env_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + if (rc == MDBX_WANNA_RECOVERY && (envflags & MDBX_RDONLY)) + print("Please run %s in the read-write mode (with '-w' option).\n", prog); + goto bailout; + } + if (verbose) + print(" - %s mode\n", + (envflags & MDBX_EXCLUSIVE) ? "monopolistic" : "cooperative"); + + if ((envflags & MDBX_RDONLY) == 0) { + rc = mdbx_txn_lock(env, false); + if (rc != MDBX_SUCCESS) { + error("mdbx_txn_lock failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + locked = true; + } + + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); + if (rc) { + error("mdbx_txn_begin() failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + rc = mdbx_env_get_maxkeysize(env); + if (rc < 0) { + error("mdbx_env_get_maxkeysize failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto bailout; + } + maxkeysize = rc; + + rc = mdbx_env_info2(env, txn, &envinfo, sizeof(envinfo)); + if (rc) { + error("mdbx_env_info failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + rc = mdbx_env_stat2(env, txn, &envstat, sizeof(envstat)); + if (rc) { + error("mdbx_env_stat failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + mdbx_filehandle_t dxb_fd; + rc = mdbx_env_get_fd(env, &dxb_fd); + if (rc) { + error("mdbx_env_get_fd failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + uint64_t dxb_filesize = 0; +#if defined(_WIN32) || defined(_WIN64) + { + BY_HANDLE_FILE_INFORMATION info; + if (!GetFileInformationByHandle(dxb_fd, &info)) + rc = GetLastError(); + else + dxb_filesize = info.nFileSizeLow | (uint64_t)info.nFileSizeHigh << 32; + } +#else + { + struct stat st; + STATIC_ASSERT_MSG(sizeof(off_t) <= sizeof(uint64_t), + "libmdbx requires 64-bit file I/O on 64-bit systems"); + if (fstat(dxb_fd, &st)) + rc = errno; + else + dxb_filesize = st.st_size; + } +#endif + if (rc) { + error("mdbx_filesize failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + errno = 0; + const uint64_t dxbfile_pages = dxb_filesize / envinfo.mi_dxb_pagesize; + alloc_pages = txn->mt_next_pgno; + backed_pages = envinfo.mi_geo.current / envinfo.mi_dxb_pagesize; +#if !(defined(_WIN32) || defined(_WIN64)) + if ((envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) != MDBX_RDONLY && + backed_pages != dxbfile_pages) { + print(" ! backed-pages %" PRIu64 " != file-pages %" PRIu64 "\n", + backed_pages, dxbfile_pages); + ++problems_meta; + } +#endif /* !Windows */ + if (dxbfile_pages < NUM_METAS) + print(" ! file-pages %" PRIu64 " < %u\n", dxbfile_pages, NUM_METAS); + if (backed_pages < NUM_METAS) + print(" ! backed-pages %" PRIu64 " < %u\n", backed_pages, NUM_METAS); + if (backed_pages < NUM_METAS || dxbfile_pages < NUM_METAS) + goto bailout; + if (backed_pages > MAX_PAGENO) { + print(" ! backed-pages %" PRIu64 " > max-pages %" PRIaPGNO "\n", + backed_pages, MAX_PAGENO); + ++problems_meta; + backed_pages = MAX_PAGENO; + } + + if ((envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) != MDBX_RDONLY) { + if (backed_pages > dxbfile_pages) { + print(" ! backed-pages %" PRIu64 " > file-pages %" PRIu64 "\n", + backed_pages, dxbfile_pages); + ++problems_meta; + backed_pages = dxbfile_pages; + } + if (alloc_pages > backed_pages) { + print(" ! alloc-pages %" PRIu64 " > backed-pages %" PRIu64 "\n", + alloc_pages, backed_pages); + ++problems_meta; + alloc_pages = backed_pages; + } + } else { + /* LY: DB may be shrinked by writer downto the allocated pages. */ + if (alloc_pages > backed_pages) { + print(" ! alloc-pages %" PRIu64 " > backed-pages %" PRIu64 "\n", + alloc_pages, backed_pages); + ++problems_meta; + alloc_pages = backed_pages; + } + if (alloc_pages > dxbfile_pages) { + print(" ! alloc-pages %" PRIu64 " > file-pages %" PRIu64 "\n", + alloc_pages, dxbfile_pages); + ++problems_meta; + alloc_pages = dxbfile_pages; + } + if (backed_pages > dxbfile_pages) + backed_pages = dxbfile_pages; + } + + if (verbose) { + print(" - pagesize %u (%u system), max keysize %" PRIuPTR + ", max readers %u\n", + envinfo.mi_dxb_pagesize, envinfo.mi_sys_pagesize, maxkeysize, + envinfo.mi_maxreaders); + print_size(" - mapsize ", envinfo.mi_mapsize, "\n"); + if (envinfo.mi_geo.lower == envinfo.mi_geo.upper) + print_size(" - fixed datafile: ", envinfo.mi_geo.current, ""); + else { + print_size(" - dynamic datafile: ", envinfo.mi_geo.lower, ""); + print_size(" .. ", envinfo.mi_geo.upper, ", "); + print_size("+", envinfo.mi_geo.grow, ", "); + print_size("-", envinfo.mi_geo.shrink, "\n"); + print_size(" - current datafile: ", envinfo.mi_geo.current, ""); + } + printf(", %" PRIu64 " pages\n", + envinfo.mi_geo.current / envinfo.mi_dxb_pagesize); + print(" - transactions: recent %" PRIu64 ", latter reader %" PRIu64 + ", lag %" PRIi64 "\n", + envinfo.mi_recent_txnid, envinfo.mi_latter_reader_txnid, + envinfo.mi_recent_txnid - envinfo.mi_latter_reader_txnid); + + verbose_meta(0, envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign); + verbose_meta(1, envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign); + verbose_meta(2, envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign); + } + + if (verbose) + print(" - performs check for meta-pages clashes\n"); + if (meta_eq(envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign, + envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign)) { + print(" ! meta-%d and meta-%d are clashed\n", 0, 1); + ++problems_meta; + } + if (meta_eq(envinfo.mi_meta1_txnid, envinfo.mi_meta1_sign, + envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign)) { + print(" ! meta-%d and meta-%d are clashed\n", 1, 2); + ++problems_meta; + } + if (meta_eq(envinfo.mi_meta2_txnid, envinfo.mi_meta2_sign, + envinfo.mi_meta0_txnid, envinfo.mi_meta0_sign)) { + print(" ! meta-%d and meta-%d are clashed\n", 2, 0); + ++problems_meta; + } + + if (envflags & MDBX_EXCLUSIVE) { + if (verbose) + print(" - performs full check recent-txn-id with meta-pages\n"); + problems_meta += check_meta_head(true); + } else if (locked) { + if (verbose) + print(" - performs lite check recent-txn-id with meta-pages (not a " + "monopolistic mode)\n"); + problems_meta += check_meta_head(false); + } else if (verbose) { + print(" - skip check recent-txn-id with meta-pages (monopolistic or " + "read-write mode only)\n"); + } + + if (!dont_traversal) { + struct problem *saved_list; + size_t traversal_problems; + uint64_t empty_pages, lost_bytes; + + print("Traversal b-tree by txn#%" PRIaTXN "...\n", txn->mt_txnid); + fflush(NULL); + walk.pagemap = mdbx_calloc((size_t)backed_pages, sizeof(*walk.pagemap)); + if (!walk.pagemap) { + rc = errno ? errno : MDBX_ENOMEM; + error("calloc failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + saved_list = problems_push(); + rc = mdbx_env_pgwalk(txn, pgvisitor, NULL); + traversal_problems = problems_pop(saved_list); + + if (rc) { + if (rc == MDBX_EINTR && user_break) { + print(" - interrupted by signal\n"); + fflush(NULL); + } else { + error("mdbx_env_pgwalk failed, error %d %s\n", rc, mdbx_strerror(rc)); + } + goto bailout; + } + + for (uint64_t n = 0; n < alloc_pages; ++n) + if (!walk.pagemap[n]) + unused_pages += 1; + + empty_pages = lost_bytes = 0; + for (walk_dbi_t *dbi = &dbi_main; dbi < walk.dbi + MAX_DBI && dbi->name; + ++dbi) { + empty_pages += dbi->pages.empty; + lost_bytes += dbi->lost_bytes; + } + + if (verbose) { + uint64_t total_page_bytes = walk.pgcount * envstat.ms_psize; + print(" - pages: total %" PRIu64 ", unused %" PRIu64 "\n", walk.pgcount, + unused_pages); + if (verbose > 1) { + for (walk_dbi_t *dbi = walk.dbi; dbi < walk.dbi + MAX_DBI && dbi->name; + ++dbi) { + print(" %s: subtotal %" PRIu64, dbi->name, dbi->pages.total); + if (dbi->pages.other && dbi->pages.other != dbi->pages.total) + print(", other %" PRIu64, dbi->pages.other); + if (dbi->pages.branch) + print(", branch %" PRIu64, dbi->pages.branch); + if (dbi->pages.large_count) + print(", large %" PRIu64, dbi->pages.large_count); + uint64_t all_leaf = dbi->pages.leaf + dbi->pages.leaf_dupfixed; + if (all_leaf) { + print(", leaf %" PRIu64, all_leaf); + if (verbose > 2 && + (dbi->pages.leaf_dupfixed | dbi->pages.subleaf_dupsort | + dbi->pages.subleaf_dupsort)) + print(" (usual %" PRIu64 ", sub-dupsort %" PRIu64 + ", dupfixed %" PRIu64 ", sub-dupfixed %" PRIu64 ")", + dbi->pages.leaf, dbi->pages.subleaf_dupsort, + dbi->pages.leaf_dupfixed, dbi->pages.subleaf_dupfixed); + } + print("\n"); + } + } + + if (verbose > 1) + print(" - usage: total %" PRIu64 " bytes, payload %" PRIu64 + " (%.1f%%), unused " + "%" PRIu64 " (%.1f%%)\n", + total_page_bytes, walk.total_payload_bytes, + walk.total_payload_bytes * 100.0 / total_page_bytes, + total_page_bytes - walk.total_payload_bytes, + (total_page_bytes - walk.total_payload_bytes) * 100.0 / + total_page_bytes); + if (verbose > 2) { + for (walk_dbi_t *dbi = walk.dbi; dbi < walk.dbi + MAX_DBI && dbi->name; + ++dbi) + if (dbi->pages.total) { + uint64_t dbi_bytes = dbi->pages.total * envstat.ms_psize; + print(" %s: subtotal %" PRIu64 " bytes (%.1f%%)," + " payload %" PRIu64 " (%.1f%%), unused %" PRIu64 " (%.1f%%)", + dbi->name, dbi_bytes, dbi_bytes * 100.0 / total_page_bytes, + dbi->payload_bytes, dbi->payload_bytes * 100.0 / dbi_bytes, + dbi_bytes - dbi->payload_bytes, + (dbi_bytes - dbi->payload_bytes) * 100.0 / dbi_bytes); + if (dbi->pages.empty) + print(", %" PRIu64 " empty pages", dbi->pages.empty); + if (dbi->lost_bytes) + print(", %" PRIu64 " bytes lost", dbi->lost_bytes); + print("\n"); + } else + print(" %s: empty\n", dbi->name); + } + print(" - summary: average fill %.1f%%", + walk.total_payload_bytes * 100.0 / total_page_bytes); + if (empty_pages) + print(", %" PRIu64 " empty pages", empty_pages); + if (lost_bytes) + print(", %" PRIu64 " bytes lost", lost_bytes); + print(", %" PRIuPTR " problems\n", traversal_problems); + } + } else if (verbose) { + print("Skipping b-tree walk...\n"); + fflush(NULL); + } + + if (!verbose) + print("Iterating DBIs...\n"); + problems_maindb = process_db(~0u, /* MAIN_DBI */ NULL, NULL, false); + problems_freedb = process_db(FREE_DBI, "@GC", handle_freedb, false); + + if (verbose) { + uint64_t value = envinfo.mi_mapsize / envstat.ms_psize; + double percent = value / 100.0; + print(" - space: %" PRIu64 " total pages", value); + print(", backed %" PRIu64 " (%.1f%%)", backed_pages, + backed_pages / percent); + print(", allocated %" PRIu64 " (%.1f%%)", alloc_pages, + alloc_pages / percent); + + if (verbose > 1) { + value = envinfo.mi_mapsize / envstat.ms_psize - alloc_pages; + print(", remained %" PRIu64 " (%.1f%%)", value, value / percent); + + value = alloc_pages - gc_pages; + print(", used %" PRIu64 " (%.1f%%)", value, value / percent); + + print(", gc %" PRIu64 " (%.1f%%)", gc_pages, gc_pages / percent); + + value = gc_pages - reclaimable_pages; + print(", detained %" PRIu64 " (%.1f%%)", value, value / percent); + + print(", reclaimable %" PRIu64 " (%.1f%%)", reclaimable_pages, + reclaimable_pages / percent); + } + + value = + envinfo.mi_mapsize / envstat.ms_psize - alloc_pages + reclaimable_pages; + print(", available %" PRIu64 " (%.1f%%)\n", value, value / percent); + } + + if (problems_maindb == 0 && problems_freedb == 0) { + if (!dont_traversal && + (envflags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) != MDBX_RDONLY) { + if (walk.pgcount != alloc_pages - gc_pages) { + error("used pages mismatch (%" PRIu64 " != %" PRIu64 ")\n", + walk.pgcount, alloc_pages - gc_pages); + } + if (unused_pages != gc_pages) { + error("gc pages mismatch (%" PRIu64 " != %" PRIu64 ")\n", unused_pages, + gc_pages); + } + } else if (verbose) { + print(" - skip check used and gc pages (btree-traversal with " + "monopolistic or read-write mode only)\n"); + } + + if (!process_db(MAIN_DBI, NULL, handle_maindb, true)) { + if (!userdb_count && verbose) + print(" - does not contain multiple databases\n"); + } + } + +bailout: + if (txn) + mdbx_txn_abort(txn); + if (locked) + mdbx_txn_unlock(env); + if (env) + mdbx_env_close(env); + fflush(NULL); + if (rc) { + if (rc < 0) + return (user_break) ? EXIT_INTERRUPTED : EXIT_FAILURE_SYS; + return EXIT_FAILURE_MDB; + } + +#if defined(_WIN32) || defined(_WIN64) + timestamp_finish = GetTickCount64(); + elapsed = (timestamp_finish - timestamp_start) * 1e-3; +#else + if (clock_gettime(CLOCK_MONOTONIC, ×tamp_finish)) { + rc = errno; + error("clock_gettime failed, error %d %s\n", rc, mdbx_strerror(rc)); + return EXIT_FAILURE_SYS; + } + elapsed = timestamp_finish.tv_sec - timestamp_start.tv_sec + + (timestamp_finish.tv_nsec - timestamp_start.tv_nsec) * 1e-9; +#endif /* !WINDOWS */ + + total_problems += problems_meta; + if (total_problems || problems_maindb || problems_freedb) { + print("Total %" PRIu64 " error%s detected, elapsed %.3f seconds.\n", + total_problems, (total_problems > 1) ? "s are" : " is", elapsed); + if (problems_meta || problems_maindb || problems_freedb) + return EXIT_FAILURE_CHECK_MAJOR; + return EXIT_FAILURE_CHECK_MINOR; + } + print("No error is detected, elapsed %.3f seconds\n", elapsed); + return EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/src/tools/mdbx_chk.vcxproj b/contrib/db/libmdbx/src/tools/mdbx_chk.vcxproj new file mode 100644 index 00000000..e6c26862 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_chk.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {15030120-5F7F-48F9-ABE5-DFC814F2A4BE} + Win32Proj + mdbx_chk + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + EnableAllWarnings + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + + + EnableAllWarnings + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + EnableAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + EnableAllWarnings + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/src/tools/mdbx_copy.1 b/contrib/db/libmdbx/src/tools/mdbx_copy.1 new file mode 100644 index 00000000..74d94b6b --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_copy.1 @@ -0,0 +1,57 @@ +.\" Copyright 2015-2019 Leonid Yuriev . +.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2015,2016 Peter-Service R&D LLC . +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.TH MDBX_COPY 1 "2014/06/20" "LMDB 0.9.14" +.SH NAME +mdbx_copy \- MDBX environment copy tool +.SH SYNOPSIS +.B mdbx_copy +[\c +.BR \-V ] +[\c +.BR \-c ] +[\c +.BR \-n ] +.B srcpath +[\c +.BR dstpath ] +.SH DESCRIPTION +The +.B mdbx_copy +utility copies an MDBX environment. The environment can +be copied regardless of whether it is currently in use. +No lockfile is created, since it gets recreated at need. + +If +.I dstpath +is specified it must be the path of an empty directory +for storing the backup. Otherwise, the backup will be +written to stdout. + +.SH OPTIONS +.TP +.BR \-V +Write the library version number to the standard output, and exit. +.TP +.BR \-c +Compact while copying. Only current data pages will be copied; freed +or unused pages will be omitted from the copy. This option will +slow down the backup process as it is more CPU-intensive. +Currently it fails if the environment has suffered a page leak. +.TP +.BR \-n +Open LDMB environment(s) which do not use subdirectories. + +.SH DIAGNOSTICS +Exit status is zero if no errors occur. +Errors result in a non-zero exit status and +a diagnostic message being written to standard error. +.SH CAVEATS +This utility can trigger significant file size growth if run +in parallel with write transactions, because pages which they +free during copying cannot be reused until the copy is done. +.SH "SEE ALSO" +.BR mdbx_stat (1) +.SH AUTHOR +Howard Chu of Symas Corporation diff --git a/contrib/db/libmdbx/src/tools/mdbx_copy.c b/contrib/db/libmdbx/src/tools/mdbx_copy.c new file mode 100644 index 00000000..f700b178 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_copy.c @@ -0,0 +1,109 @@ +/* mdbx_copy.c - memory-mapped database backup tool */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#ifdef _MSC_VER +#if _MSC_VER > 1800 +#pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ +#endif /* _MSC_VER (warnings) */ + +/* Avoid reference to mdbx_runtime_flags from assert() */ +#define mdbx_runtime_flags (~0u) +#include "../bits.h" + +#if defined(_WIN32) || defined(_WIN64) +#include "wingetopt.h" + +static volatile BOOL user_break; +static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { + (void)dwCtrlType; + user_break = true; + return true; +} + +#else /* WINDOWS */ + +static volatile sig_atomic_t user_break; +static void signal_handler(int sig) { + (void)sig; + user_break = 1; +} + +#endif /* !WINDOWS */ + +int main(int argc, char *argv[]) { + int rc; + MDBX_env *env = NULL; + const char *progname = argv[0], *act; + unsigned flags = MDBX_RDONLY; + unsigned cpflags = 0; + + for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) { + if (argv[1][1] == 'n' && argv[1][2] == '\0') + flags |= MDBX_NOSUBDIR; + else if (argv[1][1] == 'c' && argv[1][2] == '\0') + cpflags |= MDBX_CP_COMPACT; + else if (argv[1][1] == 'V' && argv[1][2] == '\0') { + printf("%s (%s, build %s)\n", mdbx_version.git.describe, + mdbx_version.git.datetime, mdbx_build.datetime); + exit(EXIT_SUCCESS); + } else + argc = 0; + } + + if (argc < 2 || argc > 3) { + fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname); + exit(EXIT_FAILURE); + } + +#if defined(_WIN32) || defined(_WIN64) + SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); +#else +#ifdef SIGPIPE + signal(SIGPIPE, signal_handler); +#endif +#ifdef SIGHUP + signal(SIGHUP, signal_handler); +#endif + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#endif /* !WINDOWS */ + + act = "opening environment"; + rc = mdbx_env_create(&env); + if (rc == MDBX_SUCCESS) { + rc = mdbx_env_open(env, argv[1], flags, 0640); + } + if (rc == MDBX_SUCCESS) { + act = "copying"; + if (argc == 2) { + mdbx_filehandle_t fd; +#if defined(_WIN32) || defined(_WIN64) + fd = GetStdHandle(STD_OUTPUT_HANDLE); +#else + fd = fileno(stdout); +#endif + rc = mdbx_env_copy2fd(env, fd, cpflags); + } else + rc = mdbx_env_copy(env, argv[2], cpflags); + } + if (rc) + fprintf(stderr, "%s: %s failed, error %d (%s)\n", progname, act, rc, + mdbx_strerror(rc)); + mdbx_env_close(env); + + return rc ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/src/tools/mdbx_copy.vcxproj b/contrib/db/libmdbx/src/tools/mdbx_copy.vcxproj new file mode 100644 index 00000000..d47513c2 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_copy.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {15030120-5F7F-48F9-ABE5-DFC814F2A4BD} + Win32Proj + mdbx_copy + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + EnableAllWarnings + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + + + EnableAllWarnings + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + EnableAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + EnableAllWarnings + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/src/tools/mdbx_dump.1 b/contrib/db/libmdbx/src/tools/mdbx_dump.1 new file mode 100644 index 00000000..93d29a7c --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_dump.1 @@ -0,0 +1,77 @@ +.\" Copyright 2015-2019 Leonid Yuriev . +.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2015,2016 Peter-Service R&D LLC . +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.TH MDBX_DUMP 1 "2014/06/20" "LMDB 0.9.14" +.SH NAME +mdbx_dump \- MDBX environment export tool +.SH SYNOPSIS +.B mdbx_dump +[\c +.BR \-V ] +[\c +.BI \-f \ file\fR] +[\c +.BR \-l ] +[\c +.BR \-n ] +[\c +.BR \-p ] +[\c +.BR \-a \ | +.BI \-s \ subdb\fR] +.BR \ envpath +.SH DESCRIPTION +The +.B mdbx_dump +utility reads a database and writes its contents to the +standard output using a portable flat-text format +understood by the +.BR mdbx_load (1) +utility. +.SH OPTIONS +.TP +.BR \-V +Write the library version number to the standard output, and exit. +.TP +.BR \-f \ file +Write to the specified file instead of to the standard output. +.TP +.BR \-l +List the databases stored in the environment. Just the +names will be listed, no data will be output. +.TP +.BR \-n +Dump an MDBX database which does not use subdirectories. +.TP +.BR \-p +If characters in either the key or data items are printing characters (as +defined by isprint(3)), output them directly. This option permits users to +use standard text editors and tools to modify the contents of databases. + +Note: different systems may have different notions about what characters +are considered printing characters, and databases dumped in this manner may +be less portable to external systems. +.TP +.BR \-a +Dump all of the subdatabases in the environment. +.TP +.BR \-s \ subdb +Dump a specific subdatabase. If no database is specified, only the main database is dumped. +.SH DIAGNOSTICS +Exit status is zero if no errors occur. +Errors result in a non-zero exit status and +a diagnostic message being written to standard error. + +Dumping and reloading databases that use user-defined comparison functions +will result in new databases that use the default comparison functions. +\fBIn this case it is quite likely that the reloaded database will be +damaged beyond repair permitting neither record storage nor retrieval.\fP + +The only available workaround is to modify the source for the +.BR mdbx_load (1) +utility to load the database using the correct comparison functions. +.SH "SEE ALSO" +.BR mdbx_load (1) +.SH AUTHOR +Howard Chu of Symas Corporation diff --git a/contrib/db/libmdbx/src/tools/mdbx_dump.c b/contrib/db/libmdbx/src/tools/mdbx_dump.c new file mode 100644 index 00000000..8cb9c86e --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_dump.c @@ -0,0 +1,340 @@ +/* mdbx_dump.c - memory-mapped database dump tool */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#ifdef _MSC_VER +#if _MSC_VER > 1800 +#pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ +#endif /* _MSC_VER (warnings) */ + +/* Avoid reference to mdbx_runtime_flags from assert() */ +#define mdbx_runtime_flags (~0u) +#include "../bits.h" + +#include + +#define PRINT 1 +static int mode; + +typedef struct flagbit { + int bit; + char *name; +} flagbit; + +flagbit dbflags[] = {{MDBX_REVERSEKEY, "reversekey"}, + {MDBX_DUPSORT, "dupsort"}, + {MDBX_INTEGERKEY, "integerkey"}, + {MDBX_DUPFIXED, "dupfixed"}, + {MDBX_INTEGERDUP, "integerdup"}, + {MDBX_REVERSEDUP, "reversedup"}, + {0, NULL}}; + +#if defined(_WIN32) || defined(_WIN64) +#include "wingetopt.h" + +static volatile BOOL user_break; +static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { + (void)dwCtrlType; + user_break = true; + return true; +} + +#else /* WINDOWS */ + +static volatile sig_atomic_t user_break; +static void signal_handler(int sig) { + (void)sig; + user_break = 1; +} + +#endif /* !WINDOWS */ + +static const char hexc[] = "0123456789abcdef"; + +static void dumpbyte(unsigned char c) { + putchar(hexc[c >> 4]); + putchar(hexc[c & 0xf]); +} + +static void text(MDBX_val *v) { + unsigned char *c, *end; + + putchar(' '); + c = v->iov_base; + end = c + v->iov_len; + while (c < end) { + if (isprint(*c) && *c != '\\') { + putchar(*c); + } else { + putchar('\\'); + dumpbyte(*c); + } + c++; + } + putchar('\n'); +} + +static void dumpval(MDBX_val *v) { + unsigned char *c, *end; + + putchar(' '); + c = v->iov_base; + end = c + v->iov_len; + while (c < end) { + dumpbyte(*c++); + } + putchar('\n'); +} + +/* Dump in BDB-compatible format */ +static int dumpit(MDBX_txn *txn, MDBX_dbi dbi, char *name) { + MDBX_cursor *mc; + MDBX_stat ms; + MDBX_val key, data; + MDBX_envinfo info; + unsigned int flags; + int rc, i; + + rc = mdbx_dbi_flags(txn, dbi, &flags); + if (rc) + return rc; + + rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms)); + if (rc) + return rc; + + rc = mdbx_env_info(mdbx_txn_env(txn), &info, sizeof(info)); + if (rc) + return rc; + + printf("VERSION=3\n"); + printf("format=%s\n", mode & PRINT ? "print" : "bytevalue"); + if (name) + printf("database=%s\n", name); + printf("type=btree\n"); + printf("mapsize=%" PRIu64 "\n", info.mi_mapsize); + printf("maxreaders=%u\n", info.mi_maxreaders); + + for (i = 0; dbflags[i].bit; i++) + if (flags & dbflags[i].bit) + printf("%s=1\n", dbflags[i].name); + + printf("db_pagesize=%d\n", ms.ms_psize); + printf("HEADER=END\n"); + + rc = mdbx_cursor_open(txn, dbi, &mc); + if (rc) + return rc; + + while ((rc = mdbx_cursor_get(mc, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) { + if (user_break) { + rc = MDBX_EINTR; + break; + } + if (mode & PRINT) { + text(&key); + text(&data); + } else { + dumpval(&key); + dumpval(&data); + } + } + printf("DATA=END\n"); + if (rc == MDBX_NOTFOUND) + rc = MDBX_SUCCESS; + + return rc; +} + +static void usage(char *prog) { + fprintf(stderr, + "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", + prog); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) { + int i, rc; + MDBX_env *env; + MDBX_txn *txn; + MDBX_dbi dbi; + char *prog = argv[0]; + char *envname; + char *subname = NULL; + int alldbs = 0, envflags = 0, list = 0; + + if (argc < 2) { + usage(prog); + } + + /* -a: dump main DB and all subDBs + * -s: dump only the named subDB + * -n: use NOSUBDIR flag on env_open + * -p: use printable characters + * -f: write to file instead of stdout + * -V: print version and exit + * (default) dump only the main DB + */ + while ((i = getopt(argc, argv, "af:lnps:V")) != EOF) { + switch (i) { + case 'V': + printf("%s (%s, build %s)\n", mdbx_version.git.describe, + mdbx_version.git.datetime, mdbx_build.datetime); + exit(EXIT_SUCCESS); + break; + case 'l': + list = 1; + /*FALLTHROUGH*/; + __fallthrough; + case 'a': + if (subname) + usage(prog); + alldbs++; + break; + case 'f': + if (freopen(optarg, "w", stdout) == NULL) { + fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, + mdbx_strerror(errno)); + exit(EXIT_FAILURE); + } + break; + case 'n': + envflags |= MDBX_NOSUBDIR; + break; + case 'p': + mode |= PRINT; + break; + case 's': + if (alldbs) + usage(prog); + subname = optarg; + break; + default: + usage(prog); + } + } + + if (optind != argc - 1) + usage(prog); + +#if defined(_WIN32) || defined(_WIN64) + SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); +#else +#ifdef SIGPIPE + signal(SIGPIPE, signal_handler); +#endif +#ifdef SIGHUP + signal(SIGHUP, signal_handler); +#endif + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#endif /* !WINDOWS */ + + envname = argv[optind]; + rc = mdbx_env_create(&env); + if (rc) { + fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, + mdbx_strerror(rc)); + return EXIT_FAILURE; + } + + if (alldbs || subname) { + mdbx_env_set_maxdbs(env, 2); + } + + rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664); + if (rc) { + fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); + if (rc) { + fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + rc = mdbx_dbi_open(txn, subname, 0, &dbi); + if (rc) { + fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto txn_abort; + } + + if (alldbs) { + MDBX_cursor *cursor; + MDBX_val key; + int count = 0; + + rc = mdbx_cursor_open(txn, dbi, &cursor); + if (rc) { + fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) { + if (user_break) { + rc = MDBX_EINTR; + break; + } + char *str; + MDBX_dbi db2; + if (memchr(key.iov_base, '\0', key.iov_len)) + continue; + count++; + str = mdbx_malloc(key.iov_len + 1); + memcpy(str, key.iov_base, key.iov_len); + str[key.iov_len] = '\0'; + rc = mdbx_dbi_open(txn, str, 0, &db2); + if (rc == MDBX_SUCCESS) { + if (list) { + printf("%s\n", str); + list++; + } else { + rc = dumpit(txn, db2, str); + if (rc) + break; + } + mdbx_dbi_close(env, db2); + } + mdbx_free(str); + if (rc) + continue; + } + mdbx_cursor_close(cursor); + if (!count) { + fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, + envname); + rc = MDBX_NOTFOUND; + } else if (rc == MDBX_INCOMPATIBLE) { + /* LY: the record it not a named sub-db. */ + rc = MDBX_SUCCESS; + } + } else { + rc = dumpit(txn, dbi, subname); + } + if (rc && rc != MDBX_NOTFOUND) + fprintf(stderr, "%s: %s: %s\n", prog, envname, mdbx_strerror(rc)); + + mdbx_dbi_close(env, dbi); +txn_abort: + mdbx_txn_abort(txn); +env_close: + mdbx_env_close(env); + + return rc ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/src/tools/mdbx_dump.vcxproj b/contrib/db/libmdbx/src/tools/mdbx_dump.vcxproj new file mode 100644 index 00000000..6978a2c2 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_dump.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {15030120-5F7F-48F9-ABE5-DFC814F2A4BC} + Win32Proj + mdbx_dump + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + EnableAllWarnings + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + + + EnableAllWarnings + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + EnableAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + EnableAllWarnings + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/src/tools/mdbx_load.1 b/contrib/db/libmdbx/src/tools/mdbx_load.1 new file mode 100644 index 00000000..e23ec78e --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_load.1 @@ -0,0 +1,86 @@ +.\" Copyright 2015-2019 Leonid Yuriev . +.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2015,2016 Peter-Service R&D LLC . +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.TH MDBX_LOAD 1 "2014/06/20" "LMDB 0.9.14" +.SH NAME +mdbx_load \- MDBX environment import tool +.SH SYNOPSIS +.B mdbx_load +[\c +.BR \-V ] +[\c +.BI \-f \ file\fR] +[\c +.BR \-n ] +[\c +.BI \-s \ subdb\fR] +[\c +.BR \-N ] +[\c +.BR \-T ] +.BR \ envpath +.SH DESCRIPTION +The +.B mdbx_load +utility reads from the standard input and loads it into the +MDBX environment +.BR envpath . + +The input to +.B mdbx_load +must be in the output format specified by the +.BR mdbx_dump (1) +utility or as specified by the +.B -T +option below. +.SH OPTIONS +.TP +.BR \-V +Write the library version number to the standard output, and exit. +.TP +.BR \-a +Append all records in the order they appear in the input. The input is assumed to already be +in correctly sorted order and no sorting or checking for redundant values will be performed. +This option must be used to reload data that was produced by running +.B mdbx_dump +on a database that uses custom compare functions. +.TP +.BR \-f \ file +Read from the specified file instead of from the standard input. +.TP +.BR \-n +Load an MDBX database which does not use subdirectories. +.TP +.BR \-s \ subdb +Load a specific subdatabase. If no database is specified, data is loaded into the main database. +.TP +.BR \-N +Don't overwrite existing records when loading into an already existing database; just skip them. +.TP +.BR \-T +Load data from simple text files. The input must be paired lines of text, where the first +line of the pair is the key item, and the second line of the pair is its corresponding +data item. + +A simple escape mechanism, where newline and backslash (\\) characters are special, is +applied to the text input. Newline characters are interpreted as record separators. +Backslash characters in the text will be interpreted in one of two ways: If the backslash +character precedes another backslash character, the pair will be interpreted as a literal +backslash. If the backslash character precedes any other character, the two characters +following the backslash will be interpreted as a hexadecimal specification of a single +character; for example, \\0a is a newline character in the ASCII character set. + +For this reason, any backslash or newline characters that naturally occur in the text +input must be escaped to avoid misinterpretation by +.BR mdbx_load . + +.SH DIAGNOSTICS +Exit status is zero if no errors occur. +Errors result in a non-zero exit status and +a diagnostic message being written to standard error. + +.SH "SEE ALSO" +.BR mdbx_dump (1) +.SH AUTHOR +Howard Chu of Symas Corporation diff --git a/contrib/db/libmdbx/src/tools/mdbx_load.c b/contrib/db/libmdbx/src/tools/mdbx_load.c new file mode 100644 index 00000000..7bbc52b8 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_load.c @@ -0,0 +1,554 @@ +/* mdbx_load.c - memory-mapped database load tool */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#ifdef _MSC_VER +#if _MSC_VER > 1800 +#pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ +#endif /* _MSC_VER (warnings) */ + +/* Avoid reference to mdbx_runtime_flags from assert() */ +#define mdbx_runtime_flags (~0u) +#include "../bits.h" + +#include + +#if defined(_WIN32) || defined(_WIN64) +#include "wingetopt.h" + +static volatile BOOL user_break; +static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { + (void)dwCtrlType; + user_break = true; + return true; +} + +#else /* WINDOWS */ + +static volatile sig_atomic_t user_break; +static void signal_handler(int sig) { + (void)sig; + user_break = 1; +} + +#endif /* !WINDOWS */ + +#define PRINT 1 +#define NOHDR 2 +static int mode; + +static char *subname = NULL; +static size_t lineno; +static int version; + +static int dbi_flags; +static char *prog; +static int Eof; + +static MDBX_envinfo envinfo; +static MDBX_val kbuf, dbuf; +static MDBX_val k0buf; + +#define STRLENOF(s) (sizeof(s) - 1) + +typedef struct flagbit { + int bit; + char *name; + int len; +} flagbit; + +#define S(s) s, STRLENOF(s) + +flagbit dbflags[] = {{MDBX_REVERSEKEY, S("reversekey")}, + {MDBX_DUPSORT, S("dupsort")}, + {MDBX_INTEGERKEY, S("integerkey")}, + {MDBX_DUPFIXED, S("dupfixed")}, + {MDBX_INTEGERDUP, S("integerdup")}, + {MDBX_REVERSEDUP, S("reversedup")}, + {0, NULL, 0}}; + +static void readhdr(void) { + char *ptr; + + dbi_flags = 0; + while (fgets(dbuf.iov_base, (int)dbuf.iov_len, stdin) != NULL) { + lineno++; + if (!strncmp(dbuf.iov_base, "db_pagesize=", STRLENOF("db_pagesize=")) || + !strncmp(dbuf.iov_base, "duplicates=", STRLENOF("duplicates="))) { + /* LY: silently ignore information fields. */ + continue; + } else if (!strncmp(dbuf.iov_base, "VERSION=", STRLENOF("VERSION="))) { + version = atoi((char *)dbuf.iov_base + STRLENOF("VERSION=")); + if (version > 3) { + fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported VERSION %d\n", + prog, lineno, version); + exit(EXIT_FAILURE); + } + } else if (!strncmp(dbuf.iov_base, "HEADER=END", STRLENOF("HEADER=END"))) { + break; + } else if (!strncmp(dbuf.iov_base, "format=", STRLENOF("format="))) { + if (!strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "print", + STRLENOF("print"))) + mode |= PRINT; + else if (strncmp((char *)dbuf.iov_base + STRLENOF("FORMAT="), "bytevalue", + STRLENOF("bytevalue"))) { + fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported FORMAT %s\n", prog, + lineno, (char *)dbuf.iov_base + STRLENOF("FORMAT=")); + exit(EXIT_FAILURE); + } + } else if (!strncmp(dbuf.iov_base, "database=", STRLENOF("database="))) { + ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); + if (ptr) + *ptr = '\0'; + if (subname) + mdbx_free(subname); + subname = mdbx_strdup((char *)dbuf.iov_base + STRLENOF("database=")); + } else if (!strncmp(dbuf.iov_base, "type=", STRLENOF("type="))) { + if (strncmp((char *)dbuf.iov_base + STRLENOF("type="), "btree", + STRLENOF("btree"))) { + fprintf(stderr, "%s: line %" PRIiSIZE ": unsupported type %s\n", prog, + lineno, (char *)dbuf.iov_base + STRLENOF("type=")); + exit(EXIT_FAILURE); + } + } else if (!strncmp(dbuf.iov_base, "mapaddr=", STRLENOF("mapaddr="))) { + int i; + ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); + if (ptr) + *ptr = '\0'; + void *unused; + i = sscanf((char *)dbuf.iov_base + STRLENOF("mapaddr="), "%p", &unused); + if (i != 1) { + fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapaddr %s\n", prog, + lineno, (char *)dbuf.iov_base + STRLENOF("mapaddr=")); + exit(EXIT_FAILURE); + } + } else if (!strncmp(dbuf.iov_base, "mapsize=", STRLENOF("mapsize="))) { + int i; + ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); + if (ptr) + *ptr = '\0'; + i = sscanf((char *)dbuf.iov_base + STRLENOF("mapsize="), "%" PRIu64, + &envinfo.mi_mapsize); + if (i != 1) { + fprintf(stderr, "%s: line %" PRIiSIZE ": invalid mapsize %s\n", prog, + lineno, (char *)dbuf.iov_base + STRLENOF("mapsize=")); + exit(EXIT_FAILURE); + } + } else if (!strncmp(dbuf.iov_base, + "maxreaders=", STRLENOF("maxreaders="))) { + int i; + ptr = memchr(dbuf.iov_base, '\n', dbuf.iov_len); + if (ptr) + *ptr = '\0'; + i = sscanf((char *)dbuf.iov_base + STRLENOF("maxreaders="), "%u", + &envinfo.mi_maxreaders); + if (i != 1) { + fprintf(stderr, "%s: line %" PRIiSIZE ": invalid maxreaders %s\n", prog, + lineno, (char *)dbuf.iov_base + STRLENOF("maxreaders=")); + exit(EXIT_FAILURE); + } + } else { + int i; + for (i = 0; dbflags[i].bit; i++) { + if (!strncmp(dbuf.iov_base, dbflags[i].name, dbflags[i].len) && + ((char *)dbuf.iov_base)[dbflags[i].len] == '=') { + if (((char *)dbuf.iov_base)[dbflags[i].len + 1] == '1') + dbi_flags |= dbflags[i].bit; + break; + } + } + if (!dbflags[i].bit) { + ptr = memchr(dbuf.iov_base, '=', dbuf.iov_len); + if (!ptr) { + fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected format\n", prog, + lineno); + exit(EXIT_FAILURE); + } else { + *ptr = '\0'; + fprintf(stderr, + "%s: line %" PRIiSIZE ": unrecognized keyword ignored: %s\n", + prog, lineno, (char *)dbuf.iov_base); + } + } + } + } +} + +static void badend(void) { + fprintf(stderr, "%s: line %" PRIiSIZE ": unexpected end of input\n", prog, + lineno); +} + +static int unhex(unsigned char *c2) { + int x, c; + x = *c2++ & 0x4f; + if (x & 0x40) + x -= 55; + c = x << 4; + x = *c2 & 0x4f; + if (x & 0x40) + x -= 55; + c |= x; + return c; +} + +static int readline(MDBX_val *out, MDBX_val *buf) { + unsigned char *c1, *c2, *end; + size_t len, l2; + int c; + + if (!(mode & NOHDR)) { + c = fgetc(stdin); + if (c == EOF) { + Eof = 1; + return EOF; + } + if (c != ' ') { + lineno++; + if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) { + badend: + Eof = 1; + badend(); + return EOF; + } + if (c == 'D' && !strncmp(buf->iov_base, "ATA=END", STRLENOF("ATA=END"))) + return EOF; + goto badend; + } + } + if (fgets(buf->iov_base, (int)buf->iov_len, stdin) == NULL) { + Eof = 1; + return EOF; + } + lineno++; + + c1 = buf->iov_base; + len = strlen((char *)c1); + l2 = len; + + /* Is buffer too short? */ + while (c1[len - 1] != '\n') { + buf->iov_base = mdbx_realloc(buf->iov_base, buf->iov_len * 2); + if (!buf->iov_base) { + Eof = 1; + fprintf(stderr, "%s: line %" PRIiSIZE ": out of memory, line too long\n", + prog, lineno); + return EOF; + } + c1 = buf->iov_base; + c1 += l2; + if (fgets((char *)c1, (int)buf->iov_len + 1, stdin) == NULL) { + Eof = 1; + badend(); + return EOF; + } + buf->iov_len *= 2; + len = strlen((char *)c1); + l2 += len; + } + c1 = c2 = buf->iov_base; + len = l2; + c1[--len] = '\0'; + end = c1 + len; + + if (mode & PRINT) { + while (c2 < end) { + if (unlikely(*c2 == '\\')) { + if (c2[1] == '\\') { + *c1++ = '\\'; + } else { + if (c2 + 3 > end || !isxdigit(c2[1]) || !isxdigit(c2[2])) { + Eof = 1; + badend(); + return EOF; + } + *c1++ = (char)unhex(++c2); + } + c2 += 2; + } else { + /* copies are redundant when no escapes were used */ + *c1++ = *c2++; + } + } + } else { + /* odd length not allowed */ + if (len & 1) { + Eof = 1; + badend(); + return EOF; + } + while (c2 < end) { + if (!isxdigit(*c2) || !isxdigit(c2[1])) { + Eof = 1; + badend(); + return EOF; + } + *c1++ = (char)unhex(c2); + c2 += 2; + } + } + c2 = out->iov_base = buf->iov_base; + out->iov_len = c1 - c2; + + return 0; +} + +static void usage(void) { + fprintf(stderr, + "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", + prog); + exit(EXIT_FAILURE); +} + +static int anyway_greater(const MDBX_val *a, const MDBX_val *b) { + (void)a; + (void)b; + return 1; +} + +int main(int argc, char *argv[]) { + int i, rc; + MDBX_env *env = NULL; + MDBX_txn *txn = NULL; + MDBX_cursor *mc = NULL; + MDBX_dbi dbi; + char *envname = NULL; + int envflags = MDBX_UTTERLY_NOSYNC, putflags = 0; + int append = 0; + MDBX_val prevk; + + prog = argv[0]; + if (argc < 2) + usage(); + + /* -a: append records in input order + * -f: load file instead of stdin + * -n: use NOSUBDIR flag on env_open + * -s: load into named subDB + * -N: use NOOVERWRITE on puts + * -T: read plaintext + * -V: print version and exit + */ + while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) { + switch (i) { + case 'V': + printf("%s (%s, build %s)\n", mdbx_version.git.describe, + mdbx_version.git.datetime, mdbx_build.datetime); + exit(EXIT_SUCCESS); + break; + case 'a': + append = 1; + break; + case 'f': + if (freopen(optarg, "r", stdin) == NULL) { + fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, + mdbx_strerror(errno)); + exit(EXIT_FAILURE); + } + break; + case 'n': + envflags |= MDBX_NOSUBDIR; + break; + case 's': + subname = mdbx_strdup(optarg); + break; + case 'N': + putflags = MDBX_NOOVERWRITE | MDBX_NODUPDATA; + break; + case 'T': + mode |= NOHDR | PRINT; + break; + default: + usage(); + } + } + + if (optind != argc - 1) + usage(); + +#if defined(_WIN32) || defined(_WIN64) + SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); +#else +#ifdef SIGPIPE + signal(SIGPIPE, signal_handler); +#endif +#ifdef SIGHUP + signal(SIGHUP, signal_handler); +#endif + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#endif /* !WINDOWS */ + + dbuf.iov_len = 4096; + dbuf.iov_base = mdbx_malloc(dbuf.iov_len); + + /* read first header for mapsize= */ + if (!(mode & NOHDR)) + readhdr(); + + envname = argv[optind]; + rc = mdbx_env_create(&env); + if (rc) { + fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, + mdbx_strerror(rc)); + return EXIT_FAILURE; + } + + mdbx_env_set_maxdbs(env, 2); + + if (envinfo.mi_maxreaders) + mdbx_env_set_maxreaders(env, envinfo.mi_maxreaders); + + if (envinfo.mi_mapsize) { + if (envinfo.mi_mapsize > SIZE_MAX) { + fprintf(stderr, "mdbx_env_set_mapsize failed, error %d %s\n", rc, + mdbx_strerror(MDBX_TOO_LARGE)); + return EXIT_FAILURE; + } + mdbx_env_set_mapsize(env, (size_t)envinfo.mi_mapsize); + } + +#ifdef MDBX_FIXEDMAP + if (info.mi_mapaddr) + envflags |= MDBX_FIXEDMAP; +#endif + + rc = mdbx_env_open(env, envname, envflags, 0664); + if (rc) { + fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + kbuf.iov_len = mdbx_env_get_maxkeysize(env); + if (kbuf.iov_len >= SIZE_MAX / 4) { + fprintf(stderr, "mdbx_env_get_maxkeysize failed, returns %zu\n", + kbuf.iov_len); + goto env_close; + } + kbuf.iov_len = (kbuf.iov_len + 1) * 2; + kbuf.iov_base = malloc(kbuf.iov_len * 2); + k0buf.iov_len = kbuf.iov_len; + k0buf.iov_base = (char *)kbuf.iov_base + kbuf.iov_len; + prevk.iov_base = k0buf.iov_base; + + while (!Eof) { + if (user_break) { + rc = MDBX_EINTR; + break; + } + + rc = mdbx_txn_begin(env, NULL, 0, &txn); + if (rc) { + fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + rc = mdbx_dbi_open_ex(txn, subname, dbi_flags | MDBX_CREATE, &dbi, + append ? anyway_greater : NULL, + append ? anyway_greater : NULL); + if (rc) { + fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto txn_abort; + } + + rc = mdbx_cursor_open(txn, dbi, &mc); + if (rc) { + fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + + int batch = 0; + prevk.iov_len = 0; + while (1) { + MDBX_val key; + rc = readline(&key, &kbuf); + if (rc) /* rc == EOF */ + break; + + MDBX_val data; + rc = readline(&data, &dbuf); + if (rc) { + fprintf(stderr, "%s: line %" PRIiSIZE ": failed to read key value\n", + prog, lineno); + goto txn_abort; + } + + int appflag = 0; + if (append) { + appflag = MDBX_APPEND; + if (dbi_flags & MDBX_DUPSORT) { + if (prevk.iov_len == key.iov_len && + memcmp(prevk.iov_base, key.iov_base, key.iov_len) == 0) + appflag = MDBX_APPEND | MDBX_APPENDDUP; + else + memcpy(prevk.iov_base, key.iov_base, prevk.iov_len = key.iov_len); + } + } + rc = mdbx_cursor_put(mc, &key, &data, putflags | appflag); + if (rc == MDBX_KEYEXIST && putflags) + continue; + if (rc) { + fprintf(stderr, "mdbx_cursor_put failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + batch++; + if (batch == 100) { + rc = mdbx_txn_commit(txn); + if (rc) { + fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, + lineno, mdbx_strerror(rc)); + goto env_close; + } + rc = mdbx_txn_begin(env, NULL, 0, &txn); + if (rc) { + fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + rc = mdbx_cursor_open(txn, dbi, &mc); + if (rc) { + fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + batch = 0; + } + } + rc = mdbx_txn_commit(txn); + txn = NULL; + if (rc) { + fprintf(stderr, "%s: line %" PRIiSIZE ": txn_commit: %s\n", prog, lineno, + mdbx_strerror(rc)); + goto env_close; + } + mdbx_dbi_close(env, dbi); + + /* try read next header */ + if (!(mode & NOHDR)) + readhdr(); + } + +txn_abort: + mdbx_txn_abort(txn); +env_close: + mdbx_env_close(env); + + return rc ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/src/tools/mdbx_load.vcxproj b/contrib/db/libmdbx/src/tools/mdbx_load.vcxproj new file mode 100644 index 00000000..05a100fc --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_load.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {15030120-5F7F-48F9-ABE5-DFC814F2A4BB} + Win32Proj + mdbx_load + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + EnableAllWarnings + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + + + EnableAllWarnings + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + EnableAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + EnableAllWarnings + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/src/tools/mdbx_stat.1 b/contrib/db/libmdbx/src/tools/mdbx_stat.1 new file mode 100644 index 00000000..50a30b4f --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_stat.1 @@ -0,0 +1,66 @@ +.\" Copyright 2015-2019 Leonid Yuriev . +.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved. +.\" Copyright 2015,2016 Peter-Service R&D LLC . +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.TH MDBX_STAT 1 "2014/06/20" "LMDB 0.9.14" +.SH NAME +mdbx_stat \- MDBX environment status tool +.SH SYNOPSIS +.B mdbx_stat +[\c +.BR \-V ] +[\c +.BR \-e ] +[\c +.BR \-f [ f [ f ]]] +[\c +.BR \-n ] +[\c +.BR \-r [ r ]] +[\c +.BR \-a \ | +.BI \-s \ subdb\fR] +.BR \ envpath +.SH DESCRIPTION +The +.B mdbx_stat +utility displays the status of an MDBX environment. +.SH OPTIONS +.TP +.BR \-V +Write the library version number to the standard output, and exit. +.TP +.BR \-e +Display information about the database environment. +.TP +.BR \-f +Display information about the environment freelist. +If \fB\-ff\fP is given, summarize each freelist entry. +If \fB\-fff\fP is given, display the full list of page IDs in the freelist. +.TP +.BR \-n +Display the status of an MDBX database which does not use subdirectories. +.TP +.BR \-r +Display information about the environment reader table. +Shows the process ID, thread ID, and transaction ID for each active +reader slot. The process ID and transaction ID are in decimal, the +thread ID is in hexadecimal. The transaction ID is displayed as "-" +if the reader does not currently have a read transaction open. +If \fB\-rr\fP is given, check for stale entries in the reader +table and clear them. The reader table will be printed again +after the check is performed. +.TP +.BR \-a +Display the status of all of the subdatabases in the environment. +.TP +.BR \-s \ subdb +Display the status of a specific subdatabase. +.SH DIAGNOSTICS +Exit status is zero if no errors occur. +Errors result in a non-zero exit status and +a diagnostic message being written to standard error. +.SH "SEE ALSO" +.BR mdbx_copy (1) +.SH AUTHOR +Howard Chu of Symas Corporation diff --git a/contrib/db/libmdbx/src/tools/mdbx_stat.c b/contrib/db/libmdbx/src/tools/mdbx_stat.c new file mode 100644 index 00000000..d4ebc2e6 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_stat.c @@ -0,0 +1,392 @@ +/* mdbx_stat.c - memory-mapped database status tool */ + +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ + +#ifdef _MSC_VER +#if _MSC_VER > 1800 +#pragma warning(disable : 4464) /* relative include path contains '..' */ +#endif +#pragma warning(disable : 4996) /* The POSIX name is deprecated... */ +#endif /* _MSC_VER (warnings) */ + +/* Avoid reference to mdbx_runtime_flags from assert() */ +#define mdbx_runtime_flags (~0u) +#include "../bits.h" + +#if defined(_WIN32) || defined(_WIN64) +#include "wingetopt.h" + +static volatile BOOL user_break; +static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) { + (void)dwCtrlType; + user_break = true; + return true; +} + +#else /* WINDOWS */ + +static volatile sig_atomic_t user_break; +static void signal_handler(int sig) { + (void)sig; + user_break = 1; +} + +#endif /* !WINDOWS */ + +static void prstat(MDBX_stat *ms) { + printf(" Pagesize: %u\n", ms->ms_psize); + printf(" Tree depth: %u\n", ms->ms_depth); + printf(" Branch pages: %" PRIu64 "\n", ms->ms_branch_pages); + printf(" Leaf pages: %" PRIu64 "\n", ms->ms_leaf_pages); + printf(" Overflow pages: %" PRIu64 "\n", ms->ms_overflow_pages); + printf(" Entries: %" PRIu64 "\n", ms->ms_entries); +} + +static void usage(char *prog) { + fprintf(stderr, + "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", + prog); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) { + int o, rc; + MDBX_env *env; + MDBX_txn *txn; + MDBX_dbi dbi; + MDBX_stat mst; + MDBX_envinfo mei; + char *prog = argv[0]; + char *envname; + char *subname = NULL; + int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; + + if (argc < 2) { + usage(prog); + } + + /* -a: print stat of main DB and all subDBs + * -s: print stat of only the named subDB + * -e: print env info + * -f: print freelist info + * -r: print reader info + * -n: use NOSUBDIR flag on env_open + * -V: print version and exit + * (default) print stat of only the main DB + */ + while ((o = getopt(argc, argv, "Vaefnrs:")) != EOF) { + switch (o) { + case 'V': + printf("%s (%s, build %s)\n", mdbx_version.git.describe, + mdbx_version.git.datetime, mdbx_build.datetime); + exit(EXIT_SUCCESS); + break; + case 'a': + if (subname) + usage(prog); + alldbs++; + break; + case 'e': + envinfo++; + break; + case 'f': + freinfo++; + break; + case 'n': + envflags |= MDBX_NOSUBDIR; + break; + case 'r': + rdrinfo++; + break; + case 's': + if (alldbs) + usage(prog); + subname = optarg; + break; + default: + usage(prog); + } + } + + if (optind != argc - 1) + usage(prog); + +#if defined(_WIN32) || defined(_WIN64) + SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true); +#else +#ifdef SIGPIPE + signal(SIGPIPE, signal_handler); +#endif +#ifdef SIGHUP + signal(SIGHUP, signal_handler); +#endif + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#endif /* !WINDOWS */ + + envname = argv[optind]; + rc = mdbx_env_create(&env); + if (rc) { + fprintf(stderr, "mdbx_env_create failed, error %d %s\n", rc, + mdbx_strerror(rc)); + return EXIT_FAILURE; + } + + if (alldbs || subname) { + mdbx_env_set_maxdbs(env, 4); + } + + rc = mdbx_env_open(env, envname, envflags | MDBX_RDONLY, 0664); + if (rc) { + fprintf(stderr, "mdbx_env_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + if (envinfo || freinfo) { + (void)mdbx_env_info(env, &mei, sizeof(mei)); + } else { + /* LY: zap warnings from gcc */ + memset(&mei, 0, sizeof(mei)); + } + + if (envinfo) { + (void)mdbx_env_stat(env, &mst, sizeof(mst)); + printf("Environment Info\n"); + printf(" Pagesize: %u\n", mst.ms_psize); + if (mei.mi_geo.lower != mei.mi_geo.upper) { + printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64 + "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64 + "/-%" PRIu64 ")\n", + mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow, + mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize, + mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize, + mei.mi_geo.shrink / mst.ms_psize); + printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", + mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); + } else { + printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", + mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); + } + printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n", + mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize); + printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1); + printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid); + printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n", + mei.mi_latter_reader_txnid, + mei.mi_latter_reader_txnid - mei.mi_recent_txnid); + printf(" Max readers: %u\n", mei.mi_maxreaders); + printf(" Number of readers used: %u\n", mei.mi_numreaders); + } else { + /* LY: zap warnings from gcc */ + memset(&mst, 0, sizeof(mst)); + } + + if (rdrinfo) { + printf("Reader Table Status\n"); + rc = mdbx_reader_list(env, (MDBX_msg_func *)fputs, stdout); + if (rdrinfo > 1) { + int dead; + mdbx_reader_check(env, &dead); + printf(" %d stale readers cleared.\n", dead); + rc = mdbx_reader_list(env, (MDBX_msg_func *)fputs, stdout); + } + if (!(subname || alldbs || freinfo)) + goto env_close; + } + + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); + if (rc) { + fprintf(stderr, "mdbx_txn_begin failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto env_close; + } + + if (freinfo) { + MDBX_cursor *cursor; + MDBX_val key, data; + pgno_t pages = 0, *iptr; + pgno_t reclaimable = 0; + + printf("Freelist Status\n"); + dbi = 0; + rc = mdbx_cursor_open(txn, dbi, &cursor); + if (rc) { + fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); + if (rc) { + fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + prstat(&mst); + while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == + MDBX_SUCCESS) { + if (user_break) { + rc = MDBX_EINTR; + break; + } + iptr = data.iov_base; + const pgno_t number = *iptr++; + + pages += number; + if (envinfo && mei.mi_latter_reader_txnid > *(size_t *)key.iov_base) + reclaimable += number; + + if (freinfo > 1) { + char *bad = ""; + pgno_t prev = + MDBX_PNL_ASCENDING ? NUM_METAS - 1 : (pgno_t)mei.mi_last_pgno + 1; + pgno_t span = 1; + for (unsigned i = 0; i < number; ++i) { + pgno_t pg = iptr[i]; + if (MDBX_PNL_DISORDERED(prev, pg)) + bad = " [bad sequence]"; + prev = pg; + while (i + span < number && + iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span) + : pgno_sub(pg, span))) + ++span; + } + printf(" Transaction %" PRIaTXN ", %" PRIaPGNO + " pages, maxspan %" PRIaPGNO "%s\n", + *(txnid_t *)key.iov_base, number, span, bad); + if (freinfo > 2) { + for (unsigned i = 0; i < number; i += span) { + const pgno_t pg = iptr[i]; + for (span = 1; + i + span < number && + iptr[i + span] == (MDBX_PNL_ASCENDING ? pgno_add(pg, span) + : pgno_sub(pg, span)); + ++span) + ; + if (span > 1) + printf(" %9" PRIaPGNO "[%" PRIaPGNO "]\n", pg, span); + else + printf(" %9" PRIaPGNO "\n", pg); + } + } + } + } + mdbx_cursor_close(cursor); + + switch (rc) { + case MDBX_SUCCESS: + case MDBX_NOTFOUND: + break; + case MDBX_EINTR: + fprintf(stderr, "Interrupted by signal/user\n"); + goto txn_abort; + default: + fprintf(stderr, "mdbx_cursor_get failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + + if (envinfo) { + uint64_t value = mei.mi_mapsize / mst.ms_psize; + double percent = value / 100.0; + printf("Page Allocation Info\n"); + printf(" Max pages: %" PRIu64 " 100%%\n", value); + + value = mei.mi_last_pgno + 1; + printf(" Pages used: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1); + printf(" Remained: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = mei.mi_last_pgno + 1 - pages; + printf(" Used now: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = pages; + printf(" Unallocated: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = pages - reclaimable; + printf(" Detained: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = reclaimable; + printf(" Reclaimable: %" PRIu64 " %.1f%%\n", value, value / percent); + + value = + mei.mi_mapsize / mst.ms_psize - (mei.mi_last_pgno + 1) + reclaimable; + printf(" Available: %" PRIu64 " %.1f%%\n", value, value / percent); + } else + printf(" Free pages: %" PRIaPGNO "\n", pages); + } + + rc = mdbx_dbi_open(txn, subname, 0, &dbi); + if (rc) { + fprintf(stderr, "mdbx_open failed, error %d %s\n", rc, mdbx_strerror(rc)); + goto txn_abort; + } + + rc = mdbx_dbi_stat(txn, dbi, &mst, sizeof(mst)); + if (rc) { + fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + printf("Status of %s\n", subname ? subname : "Main DB"); + prstat(&mst); + + if (alldbs) { + MDBX_cursor *cursor; + MDBX_val key; + + rc = mdbx_cursor_open(txn, dbi, &cursor); + if (rc) { + fprintf(stderr, "mdbx_cursor_open failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + while ((rc = mdbx_cursor_get(cursor, &key, NULL, MDBX_NEXT_NODUP)) == 0) { + char *str; + MDBX_dbi db2; + if (memchr(key.iov_base, '\0', key.iov_len)) + continue; + str = mdbx_malloc(key.iov_len + 1); + memcpy(str, key.iov_base, key.iov_len); + str[key.iov_len] = '\0'; + rc = mdbx_dbi_open(txn, str, 0, &db2); + if (rc == MDBX_SUCCESS) + printf("Status of %s\n", str); + mdbx_free(str); + if (rc) + continue; + rc = mdbx_dbi_stat(txn, db2, &mst, sizeof(mst)); + if (rc) { + fprintf(stderr, "mdbx_dbi_stat failed, error %d %s\n", rc, + mdbx_strerror(rc)); + goto txn_abort; + } + prstat(&mst); + mdbx_dbi_close(env, db2); + } + mdbx_cursor_close(cursor); + } + + if (rc == MDBX_NOTFOUND) + rc = MDBX_SUCCESS; + + mdbx_dbi_close(env, dbi); +txn_abort: + mdbx_txn_abort(txn); +env_close: + mdbx_env_close(env); + + return rc ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/src/tools/mdbx_stat.vcxproj b/contrib/db/libmdbx/src/tools/mdbx_stat.vcxproj new file mode 100644 index 00000000..4027491d --- /dev/null +++ b/contrib/db/libmdbx/src/tools/mdbx_stat.vcxproj @@ -0,0 +1,166 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {15030120-5F7F-48F9-ABE5-DFC814F2A4BF} + Win32Proj + mdbx_stat + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + + + + + + EnableAllWarnings + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + + + EnableAllWarnings + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + + + Console + + + + + EnableAllWarnings + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + EnableAllWarnings + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + + + Console + true + true + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + + + + + + + + + + + diff --git a/contrib/db/libmdbx/src/tools/wingetopt.c b/contrib/db/libmdbx/src/tools/wingetopt.c new file mode 100644 index 00000000..7feb223f --- /dev/null +++ b/contrib/db/libmdbx/src/tools/wingetopt.c @@ -0,0 +1,95 @@ +/* + * POSIX getopt for Windows + * + * AT&T Public License + * + * Code given out at the 1985 UNIFORUM conference in Dallas. + */ + +/*----------------------------------------------------------------------------*/ +/* Microsoft compiler generates a lot of warning for self includes... */ + +#ifdef _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable : 4548) /* expression before comma has no effect; \ + expected expression with side - effect */ +#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ + * semantics are not enabled. Specify /EHsc */ +#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ + * mode specified; termination on exception is \ + * not guaranteed. Specify /EHsc */ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif +#endif /* _MSC_VER (warnings) */ + +#include "wingetopt.h" +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +/*----------------------------------------------------------------------------*/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef EOF +#define EOF (-1) +#endif + +#define ERR(s, c) \ + if (opterr) { \ + fputs(argv[0], stderr); \ + fputs(s, stderr); \ + fputc(c, stderr); \ + } + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int getopt(int argc, char *const argv[], const char *opts) { + static int sp = 1; + int c; + const char *cp; + + if (sp == 1) { + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') + return EOF; + else if (strcmp(argv[optind], "--") == 0) { + optind++; + return EOF; + } + } + optopt = c = argv[optind][sp]; + if (c == ':' || (cp = strchr(opts, c)) == NULL) { + ERR(": illegal option -- ", c); + if (argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return '?'; + } + if (*++cp == ':') { + if (argv[optind][sp + 1] != '\0') + optarg = &argv[optind++][sp + 1]; + else if (++optind >= argc) { + ERR(": option requires an argument -- ", c); + sp = 1; + return '?'; + } else + optarg = argv[optind++]; + sp = 1; + } else { + if (argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return c; +} diff --git a/contrib/db/libmdbx/src/tools/wingetopt.h b/contrib/db/libmdbx/src/tools/wingetopt.h new file mode 100644 index 00000000..fdff3683 --- /dev/null +++ b/contrib/db/libmdbx/src/tools/wingetopt.h @@ -0,0 +1,26 @@ +/* + * POSIX getopt for Windows + * + * AT&T Public License + * + * Code given out at the 1985 UNIFORUM conference in Dallas. + */ + +#ifndef _WINGETOPT_H_ +#define _WINGETOPT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int opterr; +extern int optind; +extern int optopt; +extern char *optarg; +int getopt(int argc, char *const argv[], const char *optstring); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H_ */ diff --git a/contrib/db/libmdbx/src/version.c b/contrib/db/libmdbx/src/version.c new file mode 100644 index 00000000..a0f7b4f5 --- /dev/null +++ b/contrib/db/libmdbx/src/version.c @@ -0,0 +1,34 @@ +/* + * Copyright 2015-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "./bits.h" + +#if MDBX_VERSION_MAJOR != 0 || MDBX_VERSION_MINOR != 3 +#error "API version mismatch!" +#endif + +#define MDBX_VERSION_RELEASE 0 +#define MDBX_VERSION_REVISION 0 + +/*LIBMDBX_EXPORTS*/ const mdbx_version_info mdbx_version = { + MDBX_VERSION_MAJOR, + MDBX_VERSION_MINOR, + MDBX_VERSION_RELEASE, + MDBX_VERSION_REVISION, + {"@MDBX_GIT_TIMESTAMP@", "@MDBX_GIT_TREE@", "@MDBX_GIT_COMMIT@", + "@MDBX_GIT_DESCRIBE@"}}; + +/*LIBMDBX_EXPORTS*/ const mdbx_build_info mdbx_build = { + "@MDBX_BUILD_TIMESTAMP@", "@MDBX_BUILD_TARGET@", "@MDBX_BUILD_OPTIONS@", + "@MDBX_BUILD_COMPILER@", "@MDBX_BUILD_FLAGS@"}; diff --git a/contrib/db/libmdbx/test/CMakeLists.txt b/contrib/db/libmdbx/test/CMakeLists.txt new file mode 100644 index 00000000..bb4abd5d --- /dev/null +++ b/contrib/db/libmdbx/test/CMakeLists.txt @@ -0,0 +1,37 @@ +set(TARGET mdbx_test) +project(${TARGET}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-declarations") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-cast-qual") + +add_executable(${TARGET} + base.h + cases.cc + chrono.cc + chrono.h + config.cc + config.h + copy.cc + dead.cc + hill.cc + jitter.cc + keygen.cc + keygen.h + log.cc + log.h + main.cc + osal.h + osal-unix.cc + test.cc + test.h + try.cc + utils.cc + utils.h + append.cc + ttl.cc + ) + +target_link_libraries(${TARGET} + mdbx + ) + diff --git a/contrib/db/libmdbx/test/append.cc b/contrib/db/libmdbx/test/append.cc new file mode 100644 index 00000000..273f68b8 --- /dev/null +++ b/contrib/db/libmdbx/test/append.cc @@ -0,0 +1,165 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +bool testcase_append::run() { + MDBX_dbi dbi; + int err = db_open__begin__table_create_open_clean(dbi); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("append: bailout-prepare due '%s'", mdbx_strerror(err)); + return true; + } + + keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); + /* LY: тест наполнения таблиц в append-режиме, + * при котором записи добавляются строго в конец (в порядке сортировки) */ + const unsigned flags = (config.params.table_flags & MDBX_DUPSORT) + ? MDBX_APPEND | MDBX_APPENDDUP + : MDBX_APPEND; + keyvalue_maker.make_ordered(); + + key = keygen::alloc(config.params.keylen_max); + data = keygen::alloc(config.params.datalen_max); + keygen::buffer last_key = keygen::alloc(config.params.keylen_max); + keygen::buffer last_data = keygen::alloc(config.params.datalen_max); + last_key->value.iov_base = last_key->bytes; + last_key->value.iov_len = 0; + last_data->value.iov_base = last_data->bytes; + last_data->value.iov_len = 0; + + simple_checksum inserted_checksum; + uint64_t inserted_number = 0; + uint64_t serial_count = 0; + + unsigned txn_nops = 0; + uint64_t commited_inserted_number = inserted_number; + simple_checksum commited_inserted_checksum = inserted_checksum; + while (should_continue()) { + const keygen::serial_t serial = serial_count; + if (!keyvalue_maker.increment(serial_count, 1)) { + // дошли до границы пространства ключей + break; + } + + log_trace("append: append-a %" PRIu64, serial); + generate_pair(serial, key, data); + int cmp = inserted_number ? mdbx_cmp(txn_guard.get(), dbi, &key->value, + &last_key->value) + : 1; + if (cmp == 0 && (config.params.table_flags & MDBX_DUPSORT)) + cmp = mdbx_dcmp(txn_guard.get(), dbi, &data->value, &last_data->value); + + err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value, flags); + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("append: bailout-insert due '%s'", mdbx_strerror(err)); + txn_end(true); + inserted_number = commited_inserted_number; + inserted_checksum = commited_inserted_checksum; + break; + } + + if (cmp > 0) { + if (unlikely(err != MDBX_SUCCESS)) + failure_perror("mdbx_put(appenda-a)", err); + + memcpy(last_key->value.iov_base, key->value.iov_base, + last_key->value.iov_len = key->value.iov_len); + memcpy(last_data->value.iov_base, data->value.iov_base, + last_data->value.iov_len = data->value.iov_len); + ++inserted_number; + inserted_checksum.push((uint32_t)inserted_number, key->value); + inserted_checksum.push(10639, data->value); + } else { + if (unlikely(err != MDBX_EKEYMISMATCH)) + failure_perror("mdbx_put(appenda-a) != MDBX_EKEYMISMATCH", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("append: bailout-commit due '%s'", mdbx_strerror(err)); + inserted_number = commited_inserted_number; + inserted_checksum = commited_inserted_checksum; + break; + } + commited_inserted_number = inserted_number; + commited_inserted_checksum = inserted_checksum; + txn_nops = 0; + } + + report(1); + } + + if (txn_guard) { + err = breakable_commit(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("append: bailout-commit due '%s'", mdbx_strerror(err)); + inserted_number = commited_inserted_number; + inserted_checksum = commited_inserted_checksum; + } + } + //---------------------------------------------------------------------------- + txn_begin(true); + cursor_open(dbi); + + MDBX_val check_key, check_data; + err = + mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, MDBX_FIRST); + if (likely(inserted_number)) { + if (unlikely(err != MDBX_SUCCESS)) + failure_perror("mdbx_cursor_get(MDBX_FIRST)", err); + } + + simple_checksum read_checksum; + uint64_t read_count = 0; + while (err == MDBX_SUCCESS) { + ++read_count; + read_checksum.push((uint32_t)read_count, check_key); + read_checksum.push(10639, check_data); + + err = + mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, MDBX_NEXT); + } + + if (unlikely(err != MDBX_NOTFOUND)) + failure_perror("mdbx_cursor_get(MDBX_NEXT) != EOF", err); + + if (unlikely(read_count != inserted_number)) + failure("read_count(%" PRIu64 ") != inserted_number(%" PRIu64 ")", + read_count, inserted_number); + + if (unlikely(read_checksum.value != inserted_checksum.value)) + failure("read_checksum(0x%016" PRIu64 ") " + "!= inserted_checksum(0x%016" PRIu64 ")", + read_checksum.value, inserted_checksum.value); + + cursor_close(); + txn_end(true); + //---------------------------------------------------------------------------- + + if (dbi) { + if (config.params.drop_table && !mode_readonly()) { + txn_begin(false); + db_table_drop(dbi); + err = breakable_commit(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("append: bailout-clean due '%s'", mdbx_strerror(err)); + return true; + } + } else + db_table_close(dbi); + } + return true; +} diff --git a/contrib/db/libmdbx/test/base.h b/contrib/db/libmdbx/test/base.h new file mode 100644 index 00000000..5ca134a8 --- /dev/null +++ b/contrib/db/libmdbx/test/base.h @@ -0,0 +1,113 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#pragma warning(push, 1) +#pragma warning(disable : 4548) /* expression before comma has no effect; \ + expected expression with side - effect */ +#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \ + semantics are not enabled. Specify /EHsc */ +#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ + mode specified; termination on exception \ + is not guaranteed. Specify /EHsc */ +#endif /* _MSC_VER (warnings) */ + +/* If you wish to build your application for a previous Windows platform, + * include WinSDKVer.h and set the _WIN32_WINNT macro to the platform you + * wish to support before including SDKDDKVer.h. + * + * TODO: #define _WIN32_WINNT WIN32_MUSTDIE */ +#include +#endif /* WINDOWS */ + +#ifdef __APPLE__ +#define _DARWIN_C_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) +#include +#else +#include +#include +#include +#include +#include +#include +#endif + +#ifdef _BSD_SOURCE +#include +#endif + +#include +#include +#include // for PRId64, PRIu64 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../mdbx.h" +#include "../src/defs.h" +#include "../src/osal.h" + +#if !defined(__thread) && (defined(_MSC_VER) || defined(__DMC__)) +#define __thread __declspec(thread) +#endif /* __thread */ + +#ifdef _MSC_VER +#pragma warning(pop) +#pragma warning(disable : 4201) /* nonstandard extension used : \ + nameless struct / union */ +#pragma warning(disable : 4127) /* conditional expression is constant */ +#if _MSC_VER < 1900 +#pragma warning(disable : 4510) /* default constructor could \ + not be generated */ +#pragma warning(disable : 4512) /* assignment operator could \ + not be generated */ +#pragma warning(disable : 4610) /* user-defined constructor required */ +#ifndef snprintf +#define snprintf(buffer, buffer_size, format, ...) \ + _snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__) +#endif +#ifndef vsnprintf +#define vsnprintf(buffer, buffer_size, format, args) \ + _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args) +#endif +#pragma warning(disable : 4996) /* 'vsnprintf': This function or variable \ + may be unsafe */ +#endif +#endif /* _MSC_VER */ diff --git a/contrib/db/libmdbx/test/cases.cc b/contrib/db/libmdbx/test/cases.cc new file mode 100644 index 00000000..a98834a4 --- /dev/null +++ b/contrib/db/libmdbx/test/cases.cc @@ -0,0 +1,99 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +void configure_actor(unsigned &last_space_id, const actor_testcase testcase, + const char *space_id_cstr, const actor_params ¶ms) { + unsigned wait4id = 0; + + if (params.waitfor_nops) { + for (auto i = global::actors.rbegin(); i != global::actors.rend(); ++i) { + if (i->is_waitable(params.waitfor_nops)) { + if (i->signal_nops && i->signal_nops != params.waitfor_nops) + failure("Previous waitable actor (id=%u) already linked on %u-ops\n", + i->actor_id, i->signal_nops); + wait4id = i->actor_id; + i->signal_nops = params.waitfor_nops; + break; + } + } + if (!wait4id) + failure("No previous waitable actor for %u-ops\n", params.waitfor_nops); + } + + unsigned space_id = 0; + if (!space_id_cstr || strcmp(space_id_cstr, "auto") == 0) + space_id = last_space_id + 1; + else { + char *end = nullptr; + errno = 0; + space_id = strtoul(space_id_cstr, &end, 0); + if (errno) + failure_perror("Expects an integer value for space-id\n", errno); + if (end && *end) + failure("The '%s' is unexpected for space-id\n", end); + } + + if (space_id > ACTOR_ID_MAX) + failure("Invalid space-id %u\n", space_id); + last_space_id = space_id; + + log_trace("configure_actor: space %u for %s", space_id, + testcase2str(testcase)); + global::actors.emplace_back( + actor_config(testcase, params, space_id, wait4id)); + global::databases.insert(params.pathname_db); +} + +void testcase_setup(const char *casename, actor_params ¶ms, + unsigned &last_space_id) { + if (strcmp(casename, "basic") == 0) { + log_notice(">>> testcase_setup(%s)", casename); + configure_actor(last_space_id, ac_jitter, nullptr, params); + configure_actor(last_space_id, ac_hill, nullptr, params); + configure_actor(last_space_id, ac_ttl, nullptr, params); + configure_actor(last_space_id, ac_jitter, nullptr, params); + configure_actor(last_space_id, ac_hill, nullptr, params); + configure_actor(last_space_id, ac_ttl, nullptr, params); + configure_actor(last_space_id, ac_try, nullptr, params); + configure_actor(last_space_id, ac_copy, nullptr, params); + configure_actor(last_space_id, ac_append, nullptr, params); + log_notice("<<< testcase_setup(%s): done", casename); + } else { + failure("unknown testcase `%s`", casename); + } +} + +void keycase_setup(const char *casename, actor_params ¶ms) { + if (strcmp(casename, "random") == 0 || strcmp(casename, "prng") == 0) { + log_notice(">>> keycase_setup(%s)", casename); + params.keygen.keycase = kc_random; + // TODO + log_notice("<<< keycase_setup(%s): done", casename); + } else if (strcmp(casename, "dashes") == 0 || + strcmp(casename, "aside") == 0) { + log_notice(">>> keycase_setup(%s)", casename); + params.keygen.keycase = kc_dashes; + // TODO + log_notice("<<< keycase_setup(%s): done", casename); + } else if (strcmp(casename, "custom") == 0) { + log_notice("=== keycase_setup(%s): skip", casename); + params.keygen.keycase = kc_custom; + } else { + failure("unknown keycase `%s`", casename); + } +} + +/* TODO */ diff --git a/contrib/db/libmdbx/test/chrono.cc b/contrib/db/libmdbx/test/chrono.cc new file mode 100644 index 00000000..38cb321a --- /dev/null +++ b/contrib/db/libmdbx/test/chrono.cc @@ -0,0 +1,129 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +namespace chrono { + +#define NSEC_PER_SEC 1000000000u +uint32_t ns2fractional(uint32_t ns) { + assert(ns < NSEC_PER_SEC); + /* LY: здесь и далее используется "длинное деление", которое + * для ясности кода оставлено как есть (без ручной оптимизации). Так как + * GCC, Clang и даже MSVC сами давно умеют конвертировать деление на + * константу в быструю reciprocal-форму. */ + return ((uint64_t)ns << 32) / NSEC_PER_SEC; +} + +uint32_t fractional2ns(uint32_t fractional) { + return (fractional * (uint64_t)NSEC_PER_SEC) >> 32; +} + +#define USEC_PER_SEC 1000000u +uint32_t us2fractional(uint32_t us) { + assert(us < USEC_PER_SEC); + return ((uint64_t)us << 32) / USEC_PER_SEC; +} + +uint32_t fractional2us(uint32_t fractional) { + return (fractional * (uint64_t)USEC_PER_SEC) >> 32; +} + +#define MSEC_PER_SEC 1000u +uint32_t ms2fractional(uint32_t ms) { + assert(ms < MSEC_PER_SEC); + return ((uint64_t)ms << 32) / MSEC_PER_SEC; +} + +uint32_t fractional2ms(uint32_t fractional) { + return (fractional * (uint64_t)MSEC_PER_SEC) >> 32; +} + +time from_ns(uint64_t ns) { + time result; + result.fixedpoint = ((ns / NSEC_PER_SEC) << 32) | + ns2fractional((uint32_t)(ns % NSEC_PER_SEC)); + return result; +} + +time from_us(uint64_t us) { + time result; + result.fixedpoint = ((us / USEC_PER_SEC) << 32) | + us2fractional((uint32_t)(us % USEC_PER_SEC)); + return result; +} + +time from_ms(uint64_t ms) { + time result; + result.fixedpoint = ((ms / MSEC_PER_SEC) << 32) | + ms2fractional((uint32_t)(ms % MSEC_PER_SEC)); + return result; +} + +time now_realtime() { +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + static void(WINAPI * query_time)(LPFILETIME); + if (!query_time) { + query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), + "GetSystemTimePreciseAsFileTime"); + if (!query_time) + query_time = GetSystemTimeAsFileTime; + } + + FILETIME filetime; + query_time(&filetime); + uint64_t ns100 = + (uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime; + return from_ns((ns100 - UINT64_C(116444736000000000)) * 100u); +#else + struct timespec ts; + if (unlikely(clock_gettime(CLOCK_REALTIME, &ts))) + failure_perror("clock_gettime(CLOCK_REALTIME", errno); + + return from_timespec(ts); +#endif +} + +time now_motonic() { +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + static uint64_t reciprocal; + static LARGE_INTEGER Frequency; + if (reciprocal == 0) { + if (!QueryPerformanceFrequency(&Frequency)) + failure_perror("QueryPerformanceFrequency()", GetLastError()); + reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) / + Frequency.QuadPart); + assert(reciprocal); + } + + LARGE_INTEGER Counter; + if (!QueryPerformanceCounter(&Counter)) + failure_perror("QueryPerformanceCounter()", GetLastError()); + + time result; + result.fixedpoint = (Counter.QuadPart / Frequency.QuadPart) << 32; + uint64_t mod = Counter.QuadPart % Frequency.QuadPart; + result.fixedpoint += (mod * reciprocal) >> 16; + return result; +#else + struct timespec ts; + if (unlikely(clock_gettime(CLOCK_MONOTONIC, &ts))) + failure_perror("clock_gettime(CLOCK_MONOTONIC)", errno); + + return from_timespec(ts); +#endif +} + +} /* namespace chrono */ diff --git a/contrib/db/libmdbx/test/chrono.h b/contrib/db/libmdbx/test/chrono.h new file mode 100644 index 00000000..11675195 --- /dev/null +++ b/contrib/db/libmdbx/test/chrono.h @@ -0,0 +1,100 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" +#include "log.h" +#include "utils.h" + +namespace chrono { + +#pragma pack(push, 1) + +typedef union time { + uint64_t fixedpoint; + struct { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + uint32_t fractional; + union { + uint32_t utc; + uint32_t integer; + }; +#else + union { + uint32_t utc; + uint32_t integer; + }; + uint32_t fractional; +#endif + }; + + void reset() { fixedpoint = 0; } + uint32_t seconds() const { return utc; } +} time; + +#pragma pack(pop) + +uint32_t ns2fractional(uint32_t); +uint32_t fractional2ns(uint32_t); +uint32_t us2fractional(uint32_t); +uint32_t fractional2us(uint32_t); +uint32_t ms2fractional(uint32_t); +uint32_t fractional2ms(uint32_t); + +time from_ns(uint64_t us); +time from_us(uint64_t ns); +time from_ms(uint64_t ms); + +inline time from_seconds(uint64_t seconds) { + assert(seconds < UINT32_MAX); + time result; + result.fixedpoint = seconds << 32; + return result; +} + +inline time from_utc(time_t utc) { + assert(utc >= 0); + return from_seconds((uint64_t)utc); +} + +inline time infinite() { + time result; + result.fixedpoint = UINT64_MAX; + return result; +} + +#if defined(HAVE_TIMESPEC_TV_NSEC) || defined(__timespec_defined) || \ + defined(CLOCK_REALTIME) +inline time from_timespec(const struct timespec &ts) { + time result; + result.fixedpoint = + ((uint64_t)ts.tv_sec << 32) | ns2fractional((uint32_t)ts.tv_nsec); + return result; +} +#endif /* HAVE_TIMESPEC_TV_NSEC */ + +#if defined(HAVE_TIMEVAL_TV_USEC) || defined(_STRUCT_TIMEVAL) +inline time from_timeval(const struct timeval &tv) { + time result; + result.fixedpoint = + ((uint64_t)tv.tv_sec << 32) | us2fractional((uint32_t)tv.tv_usec); + return result; +} +#endif /* HAVE_TIMEVAL_TV_USEC */ + +time now_realtime(); +time now_motonic(); + +} /* namespace chrono */ diff --git a/contrib/db/libmdbx/test/config.cc b/contrib/db/libmdbx/test/config.cc new file mode 100644 index 00000000..dd150e9a --- /dev/null +++ b/contrib/db/libmdbx/test/config.cc @@ -0,0 +1,576 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +#if defined(_MSC_VER) && !defined(strcasecmp) +#define strcasecmp(str, len) _stricmp(str, len) +#endif /* _MSC_VER && strcasecmp() */ + +namespace config { + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + const char **value, const char *default_value) { + assert(narg < argc); + const char *current = argv[narg]; + const size_t optlen = strlen(option); + + if (strncmp(current, "--", 2) || strncmp(current + 2, option, optlen)) + return false; + + if (!value) { + if (current[optlen + 2] == '=') + failure("Option '--%s' doen't accept any value\n", option); + return true; + } + + *value = nullptr; + if (current[optlen + 2] == '=') { + *value = ¤t[optlen + 3]; + return true; + } + + if (narg + 1 < argc && strncmp("--", argv[narg + 1], 2) != 0) { + *value = argv[narg + 1]; + if (strcmp(*value, "default") == 0) { + if (!default_value) + failure("Option '--%s' doen't accept default value\n", option); + *value = default_value; + } + ++narg; + return true; + } + + if (default_value) { + *value = default_value; + return true; + } + + failure("No value given for '--%s' option\n", option); +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + std::string &value, bool allow_empty) { + return parse_option(argc, argv, narg, option, value, allow_empty, + allow_empty ? "" : nullptr); +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + std::string &value, bool allow_empty, + const char *default_value) { + const char *value_cstr; + if (!parse_option(argc, argv, narg, option, &value_cstr, default_value)) + return false; + + if (!allow_empty && strlen(value_cstr) == 0) + failure("Value for option '--%s' could't be empty\n", option); + + value = value_cstr; + return true; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + unsigned &mask, const option_verb *verbs) { + const char *list; + if (!parse_option(argc, argv, narg, option, &list)) + return false; + + unsigned clear = 0; + while (*list) { + if (*list == ',' || *list == ' ' || *list == '\t') { + ++list; + continue; + } + + const char *const comma = strchr(list, ','); + const bool strikethrough = *list == '-' || *list == '~'; + if (strikethrough || *list == '+') + ++list; + else + mask = clear; + const size_t len = (comma) ? comma - list : strlen(list); + const option_verb *scan = verbs; + + while (true) { + if (!scan->verb) + failure("Unknown verb '%.*s', for option '==%s'\n", (int)len, list, + option); + if (strlen(scan->verb) == len && strncmp(list, scan->verb, len) == 0) { + mask = strikethrough ? mask & ~scan->mask : mask | scan->mask; + clear = strikethrough ? clear & ~scan->mask : clear | scan->mask; + list += len; + break; + } + ++scan; + } + } + + return true; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + uint64_t &value, const scale_mode scale, + const uint64_t minval, const uint64_t maxval, + const uint64_t default_value) { + + const char *value_cstr; + if (!parse_option(argc, argv, narg, option, &value_cstr)) + return false; + + if (default_value && strcmp(value_cstr, "default") == 0) { + value = default_value; + return true; + } + + if (strcmp(value_cstr, "min") == 0 || strcmp(value_cstr, "minimal") == 0) { + value = minval; + return true; + } + + if (strcmp(value_cstr, "max") == 0 || strcmp(value_cstr, "maximal") == 0) { + value = maxval; + return true; + } + + char *suffix = nullptr; + errno = 0; + unsigned long long raw = strtoull(value_cstr, &suffix, 0); + if ((suffix && *suffix) || errno) { + suffix = nullptr; + errno = 0; + raw = strtoull(value_cstr, &suffix, 10); + } + if (errno) + failure("Option '--%s' expects a numeric value (%s)\n", option, + test_strerror(errno)); + + uint64_t multipler = 1; + if (suffix && *suffix) { + if (scale == no_scale) + failure("Option '--%s' doen't accepts suffixes, so '%s' is unexpected\n", + option, suffix); + if (strcmp(suffix, "K") == 0 || strcasecmp(suffix, "Kilo") == 0) + multipler = (scale == decimal) ? UINT64_C(1000) : UINT64_C(1024); + else if (strcmp(suffix, "M") == 0 || strcasecmp(suffix, "Mega") == 0) + multipler = + (scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024; + else if (strcmp(suffix, "G") == 0 || strcasecmp(suffix, "Giga") == 0) + multipler = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 + : UINT64_C(1024) * 1024 * 1024; + else if (strcmp(suffix, "T") == 0 || strcasecmp(suffix, "Tera") == 0) + multipler = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 * 1000 + : UINT64_C(1024) * 1024 * 1024 * 1024; + else if (scale == duration && + (strcmp(suffix, "s") == 0 || strcasecmp(suffix, "Seconds") == 0)) + multipler = 1; + else if (scale == duration && + (strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0)) + multipler = 60; + else if (scale == duration && + (strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0)) + multipler = 3600; + else if (scale == duration && + (strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0)) + multipler = 3600 * 24; + else + failure( + "Option '--%s' expects a numeric value with Kilo/Mega/Giga/Tera %s" + "suffixes, but '%s' is unexpected\n", + option, (scale == duration) ? "or Seconds/Minutes/Hours/Days " : "", + suffix); + } + + if (raw >= UINT64_MAX / multipler) + failure("The value for option '--%s' is too huge\n", option); + + value = raw * multipler; + if (maxval && value > maxval) + failure("The maximal value for option '--%s' is %" PRIu64 "\n", option, + maxval); + if (value < minval) + failure("The minimal value for option '--%s' is %" PRIu64 "\n", option, + minval); + return true; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + unsigned &value, const scale_mode scale, + const unsigned minval, const unsigned maxval, + const unsigned default_value) { + + uint64_t huge; + if (!parse_option(argc, argv, narg, option, huge, scale, minval, maxval, + default_value)) + return false; + value = (unsigned)huge; + return true; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + uint8_t &value, const uint8_t minval, const uint8_t maxval, + const uint8_t default_value) { + + uint64_t huge; + if (!parse_option(argc, argv, narg, option, huge, no_scale, minval, maxval, + default_value)) + return false; + value = (uint8_t)huge; + return true; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + int64_t &value, const int64_t minval, const int64_t maxval, + const int64_t default_value) { + uint64_t proxy = (uint64_t)value; + if (parse_option(argc, argv, narg, option, proxy, config::binary, + (uint64_t)minval, (uint64_t)maxval, + (uint64_t)default_value)) { + value = (int64_t)proxy; + return true; + } + return false; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + int32_t &value, const int32_t minval, const int32_t maxval, + const int32_t default_value) { + uint64_t proxy = (uint64_t)value; + if (parse_option(argc, argv, narg, option, proxy, config::binary, + (uint64_t)minval, (uint64_t)maxval, + (uint64_t)default_value)) { + value = (int32_t)proxy; + return true; + } + return false; +} + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + bool &value) { + const char *value_cstr = nullptr; + if (!parse_option(argc, argv, narg, option, &value_cstr, "yes")) { + const char *current = argv[narg]; + if (strncmp(current, "--no-", 5) == 0 && strcmp(current + 5, option) == 0) { + value = false; + return true; + } + if (strncmp(current, "--dont-", 7) == 0 && + strcmp(current + 7, option) == 0) { + value = false; + return true; + } + return false; + } + + if (!value_cstr) { + value = true; + return true; + } + + if (strcasecmp(value_cstr, "yes") == 0 || strcasecmp(value_cstr, "1") == 0) { + value = true; + return true; + } + + if (strcasecmp(value_cstr, "no") == 0 || strcasecmp(value_cstr, "0") == 0) { + value = false; + return true; + } + + failure( + "Option '--%s' expects a 'boolean' value Yes/No, so '%s' is unexpected\n", + option, value_cstr); +} + +//----------------------------------------------------------------------------- + +const struct option_verb mode_bits[] = { + {"rdonly", MDBX_RDONLY}, {"mapasync", MDBX_MAPASYNC}, + {"utterly", MDBX_UTTERLY_NOSYNC}, {"nosubdir", MDBX_NOSUBDIR}, + {"nosync", MDBX_NOSYNC}, {"nometasync", MDBX_NOMETASYNC}, + {"writemap", MDBX_WRITEMAP}, {"notls", MDBX_NOTLS}, + {"nordahead", MDBX_NORDAHEAD}, {"nomeminit", MDBX_NOMEMINIT}, + {"coalesce", MDBX_COALESCE}, {"lifo", MDBX_LIFORECLAIM}, + {"perturb", MDBX_PAGEPERTURB}, {nullptr, 0}}; + +const struct option_verb table_bits[] = { + {"key.reverse", MDBX_REVERSEKEY}, + {"key.integer", MDBX_INTEGERKEY}, + {"data.integer", MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT}, + {"data.fixed", MDBX_DUPFIXED | MDBX_DUPSORT}, + {"data.reverse", MDBX_REVERSEDUP | MDBX_DUPSORT}, + {"data.dups", MDBX_DUPSORT}, + {nullptr, 0}}; + +static void dump_verbs(const char *caption, size_t bits, + const struct option_verb *verbs) { + log_info("%s: 0x%" PRIx64 " = ", caption, (uint64_t)bits); + + const char *comma = ""; + while (verbs->mask && bits) { + if ((bits & verbs->mask) == verbs->mask) { + logging::feed("%s%s", comma, verbs->verb); + bits -= verbs->mask; + comma = ", "; + } + ++verbs; + } + + logging::feed("%s\n", (*comma == '\0') ? "none" : ""); +} + +static void dump_duration(const char *caption, unsigned duration) { + log_info("%s: ", caption); + if (duration) { + if (duration > 24 * 3600) + logging::feed("%u_", duration / (24 * 3600)); + if (duration > 3600) + logging::feed("%02u:", (duration % (24 * 3600)) / 3600); + logging::feed("%02u:%02u", (duration % 3600) / 60, duration % 60); + } else { + logging::feed("INFINITE"); + } + logging::feed("\n"); +} + +void dump(const char *title) { + logging::local_suffix indent(title); + + for (auto i = global::actors.begin(); i != global::actors.end(); ++i) { + log_info("#%u, testcase %s, space_id/table %u\n", i->actor_id, + testcase2str(i->testcase), i->space_id); + indent.push(); + + if (i->params.loglevel) { + log_info("log: level %u, %s\n", i->params.loglevel, + i->params.pathname_log.empty() ? "console" + : i->params.pathname_log.c_str()); + } + + log_info("database: %s, size %" PRIuPTR "[%" PRIiPTR "..%" PRIiPTR + ", %i %i, %i]\n", + i->params.pathname_db.c_str(), i->params.size_now, + i->params.size_lower, i->params.size_upper, + i->params.shrink_threshold, i->params.growth_step, + i->params.pagesize); + + dump_verbs("mode", i->params.mode_flags, mode_bits); + dump_verbs("table", i->params.table_flags, table_bits); + + if (i->params.test_nops) + log_info("iterations/records %u\n", i->params.test_nops); + else + dump_duration("duration", i->params.test_duration); + + if (i->params.nrepeat) + log_info("repeat %u\n", i->params.nrepeat); + else + log_info("repeat ETERNALLY\n"); + + log_info("threads %u\n", i->params.nthreads); + + log_info( + "keygen.params: case %s, width %u, mesh %u, rotate %u, offset %" PRIu64 + ", split %u/%u\n", + keygencase2str(i->params.keygen.keycase), i->params.keygen.width, + i->params.keygen.mesh, i->params.keygen.rotate, i->params.keygen.offset, + i->params.keygen.split, + i->params.keygen.width - i->params.keygen.split); + log_info("keygen.seed: %u\n", i->params.keygen.seed); + log_info("key: minlen %u, maxlen %u\n", i->params.keylen_min, + i->params.keylen_max); + log_info("data: minlen %u, maxlen %u\n", i->params.datalen_min, + i->params.datalen_max); + + log_info("batch: read %u, write %u\n", i->params.batch_read, + i->params.batch_write); + + if (i->params.waitfor_nops) + log_info("wait: actor %u for %u ops\n", i->wait4id, + i->params.waitfor_nops); + else if (i->params.delaystart) + dump_duration("delay", i->params.delaystart); + else + log_info("no-delay\n"); + + if (i->params.inject_writefaultn) + log_info("inject-writefault on %u ops\n", i->params.inject_writefaultn); + else + log_info("no-inject-writefault\n"); + + log_info("limits: readers %u, tables %u\n", i->params.max_readers, + i->params.max_tables); + + log_info("drop table: %s\n", i->params.drop_table ? "Yes" : "No"); + log_info("ignore MDBX_MAP_FULL error: %s\n", + i->params.ignore_dbfull ? "Yes" : "No"); + indent.pop(); + } + + dump_duration("timeout", global::config::timeout_duration_seconds); + log_info("cleanup: before %s, after %s\n", + global::config::cleanup_before ? "Yes" : "No", + global::config::cleanup_after ? "Yes" : "No"); + + log_info("failfast: %s\n", global::config::failfast ? "Yes" : "No"); + log_info("progress indicator: %s\n", + global::config::progress_indicator ? "Yes" : "No"); +} + +} /* namespace config */ + +//----------------------------------------------------------------------------- + +using namespace config; + +actor_config::actor_config(actor_testcase testcase, const actor_params ¶ms, + unsigned space_id, unsigned wait4id) + : params(params) { + this->space_id = space_id; + this->actor_id = 1 + (unsigned)global::actors.size(); + this->testcase = testcase; + this->wait4id = wait4id; + signal_nops = 0; +} + +const std::string actor_config::serialize(const char *prefix) const { + simple_checksum checksum; + + std::string result; + if (prefix) + result.append(prefix); + + checksum.push(params.pathname_db); + result.append(params.pathname_db); + result.append("|"); + + checksum.push(params.pathname_log); + result.append(params.pathname_log); + result.append("|"); + + static_assert(std::is_pod::value, + "actor_params_pod should by POD"); + result.append(data2hex(static_cast(¶ms), + sizeof(actor_params_pod), checksum)); + result.append("|"); + + static_assert(std::is_pod::value, + "actor_config_pod should by POD"); + result.append(data2hex(static_cast(this), + sizeof(actor_config_pod), checksum)); + result.append("|"); + + result.append(osal_serialize(checksum)); + result.append("|"); + + result.append(std::to_string(checksum.value)); + return result; +} + +bool actor_config::deserialize(const char *str, actor_config &config) { + simple_checksum checksum; + + TRACE(">> actor_config::deserialize: %s\n", str); + + const char *slash = strchr(str, '|'); + if (!slash) { + TRACE("<< actor_config::deserialize: slash-1\n"); + return false; + } + config.params.pathname_db.assign(str, slash - str); + checksum.push(config.params.pathname_db); + str = slash + 1; + + slash = strchr(str, '|'); + if (!slash) { + TRACE("<< actor_config::deserialize: slash-2\n"); + return false; + } + config.params.pathname_log.assign(str, slash - str); + checksum.push(config.params.pathname_log); + str = slash + 1; + + slash = strchr(str, '|'); + if (!slash) { + TRACE("<< actor_config::deserialize: slash-3\n"); + return false; + } + static_assert(std::is_pod::value, + "actor_params_pod should by POD"); + if (!hex2data(str, slash, static_cast(&config.params), + sizeof(actor_params_pod), checksum)) { + TRACE("<< actor_config::deserialize: actor_params_pod(%.*s)\n", + (int)(slash - str), str); + return false; + } + str = slash + 1; + + slash = strchr(str, '|'); + if (!slash) { + TRACE("<< actor_config::deserialize: slash-4\n"); + return false; + } + static_assert(std::is_pod::value, + "actor_config_pod should by POD"); + if (!hex2data(str, slash, static_cast(&config), + sizeof(actor_config_pod), checksum)) { + TRACE("<< actor_config::deserialize: actor_config_pod(%.*s)\n", + (int)(slash - str), str); + return false; + } + str = slash + 1; + + slash = strchr(str, '|'); + if (!slash) { + TRACE("<< actor_config::deserialize: slash-5\n"); + return false; + } + if (!config.osal_deserialize(str, slash, checksum)) { + TRACE("<< actor_config::deserialize: osal\n"); + return false; + } + str = slash + 1; + + uint64_t verify = std::stoull(std::string(str)); + if (checksum.value != verify) { + TRACE("<< actor_config::deserialize: checksum mismatch\n"); + return false; + } + + TRACE("<< actor_config::deserialize: OK\n"); + return true; +} + +unsigned actor_params::mdbx_keylen_min() const { + return (table_flags & MDBX_INTEGERKEY) ? 4 : 0; +} + +unsigned actor_params::mdbx_keylen_max() const { + return (table_flags & MDBX_INTEGERKEY) + ? 8 + : std::min((unsigned)mdbx_limits_keysize_max(pagesize), + (unsigned)UINT16_MAX); +} + +unsigned actor_params::mdbx_datalen_min() const { + return (table_flags & MDBX_INTEGERDUP) ? 4 : 0; +} + +unsigned actor_params::mdbx_datalen_max() const { + return (table_flags & MDBX_INTEGERDUP) + ? 8 + : std::min((table_flags & MDBX_DUPSORT) + ? (unsigned)mdbx_limits_keysize_max(pagesize) + : (unsigned)MDBX_MAXDATASIZE, + (unsigned)UINT16_MAX); +} diff --git a/contrib/db/libmdbx/test/config.h b/contrib/db/libmdbx/test/config.h new file mode 100644 index 00000000..89889d8e --- /dev/null +++ b/contrib/db/libmdbx/test/config.h @@ -0,0 +1,326 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" +#include "log.h" +#include "utils.h" + +#define ACTOR_ID_MAX INT16_MAX + +enum actor_testcase { + ac_none, + ac_hill, + ac_deadread, + ac_deadwrite, + ac_jitter, + ac_try, + ac_copy, + ac_append, + ac_ttl +}; + +enum actor_status { + as_unknown, + as_debuging, + as_running, + as_successful, + as_killed, + as_failed, + as_coredump, +}; + +const char *testcase2str(const actor_testcase); +const char *status2str(actor_status status); + +enum keygen_case { + kc_random, /* [ 6.. 2.. 7.. 4.. 0.. 1.. 5.. 3.. ] */ + kc_dashes, /* [ 0123.. 4567.. ] */ + kc_custom, + /* TODO: more cases */ +}; + +const char *keygencase2str(const keygen_case); + +//----------------------------------------------------------------------------- + +namespace config { + +enum scale_mode { no_scale, decimal, binary, duration }; + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + const char **value, const char *default_value = nullptr); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + std::string &value, bool allow_empty = false); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + std::string &value, bool allow_empty, + const char *default_value); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + bool &value); + +struct option_verb { + const char *const verb; + unsigned mask; +}; + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + unsigned &mask, const option_verb *verbs); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + uint64_t &value, const scale_mode scale, + const uint64_t minval = 0, const uint64_t maxval = INT64_MAX, + const uint64_t default_value = 0); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + unsigned &value, const scale_mode scale, + const unsigned minval = 0, const unsigned maxval = INT32_MAX, + const unsigned default_value = 0); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + uint8_t &value, const uint8_t minval = 0, + const uint8_t maxval = 255, const uint8_t default_value = 0); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + int64_t &value, const int64_t minval, const int64_t maxval, + const int64_t default_value = -1); + +bool parse_option(int argc, char *const argv[], int &narg, const char *option, + int32_t &value, const int32_t minval, const int32_t maxval, + const int32_t default_value = -1); + +inline bool parse_option_intptr(int argc, char *const argv[], int &narg, + const char *option, intptr_t &value, + const intptr_t minval, const intptr_t maxval, + const intptr_t default_value = -1) { + static_assert(sizeof(intptr_t) == 4 || sizeof(intptr_t) == 8, "WTF?"); + if (sizeof(intptr_t) == 8) + return parse_option(argc, argv, narg, option, + *reinterpret_cast(&value), int64_t(minval), + int64_t(maxval), int64_t(default_value)); + else + return parse_option(argc, argv, narg, option, + *reinterpret_cast(&value), int32_t(minval), + int32_t(maxval), int32_t(default_value)); +} + +//----------------------------------------------------------------------------- + +#pragma pack(push, 1) + +struct keygen_params_pod { + keygen_case keycase; + + /* Параметры генератора пар key-value. + * + * Ключи и значения генерируются по задаваемым параметрам на основе "плоской" + * исходной координаты. При этом, в общем случае, в процессе тестов исходная + * координата последовательно итерируется в заданном диапазоне, а необходимые + * паттерны/последовательности/узоры получаются за счет преобразования + * исходной координаты, согласно описанным ниже параметрам. + * + * Стоит отметить, что порядок описания параметров для удобства совпадает с + * порядком их использования, т.е. с порядком соответствующих преобразований. + * + * Второе важное замечание касается ограничений одновременной координированной + * генерации паттеров как для ключей, так и для значений. Суть в том, что + * такая возможность не нужна по следующим причинам: + * - libmdbx поддерживает два существенно различающихся вида таблиц, + * "уникальные" (без дубликатов и без multi-value), и так называемые + * "с дубликатами" (c multi-value). + * - Для таблиц "без дубликатов" только размер связанных к ключами значений + * (данных) оказывает влияния на работу движка, непосредственно содержимое + * данных не анализируется движком и не оказывает влияния на его работу. + * - Для таблиц "с дубликатами", при наличии более одного значения для + * некоторого ключа, формируется дочернее btree-поддерево. Это дерево + * формируется в отдельном "кусте" страниц и обслуживается независимо + * от окружения родительского ключа. + * - Таким образом, паттерн генерации значений имеет смысл только для + * таблиц "с дубликатами" и только в контексте одного значения ключа. + * Иначе говоря, нет смысла в со-координации генерации паттернов для + * ключей и значений. Более того, генерацию значений всегда необходимо + * рассматривать в контексте связки с одним значением ключа. + * - Тем не менее, во всех случаях достаточно важным является равномерная + * всех возможных сочетаний длин ключей и данных. + * + * width: + * Большинство тестов предполагают создание или итерирование некоторого + * количества записей. При этом требуется итерирование или генерация + * значений и ключей из некоторого ограниченного пространства вариантов. + * + * Параметр width задает такую ширину пространства вариантов в битах. + * Таким образом мощность пространства вариантов (пока) всегда равна + * степени двойки. Это ограничение можно снять, но ценой увеличения + * вычислительной сложности, включая потерю простоты и прозрачности. + * + * С другой стороны, не-битовый width может быть полезен: + * - Позволит генерировать ключи/значения в точно задаваемом диапазоне. + * Например, перебрать в псевдо-случайном порядке 10001 значение. + * - Позволит поровну разделять заданное пространство (диапазон) + * ключей/значений между количеством потоков некратным степени двойки. + * + * mesh и seed: + * Позволяют получить псевдо-случайные последовательности ключей/значений. + * Параметр mesh задает сколько младших бит исходной плоской координаты + * будет "перемешано" (инъективно отображено), а параметр seed позволяет + * выбрать конкретный вариант "перемешивания". + * + * Перемешивание выполняется при ненулевом значении mesh. Перемешивание + * реализуется посредством применения двух инъективных функций для + * заданного количества бит: + * - применяется первая инъективная функция; + * - к результату добавляется salt полученный из seed; + * - применяется вторая инъективная функция; + * + * Следует отметить, что mesh умышленно позволяет перемешать только младшую + * часть, что при ненулевом значении split (см далее) не позволяет получать + * псевдо-случайные значений ключей без псевдо-случайности в значениях. + * + * Такое ограничение соответствуют внутренней алгоритмике libmdbx. Проще + * говоря, мы можем проверить движок псевдо-случайной последовательностью + * ключей на таблицах без дубликатов (без multi-value), а затем проверить + * корректность работу псевдо-случайной последовательностью значений на + * таблицах с дубликатами (с multi-value), опционально добавляя + * псевдо-случайности к последовательности ключей. Однако, нет смысла + * генерировать псевдо-случайные ключи, одновременно с формированием + * какого-либо паттерна в значениях, так как содержимое в данных либо + * не будет иметь значения (для таблиц без дубликатов), либо будет + * обрабатываться в отдельных btree-поддеревьях. + * + * rotate и offset: + * Для проверки слияния и разделения страниц внутри движка требуются + * генерация ключей/значений в виде не-смежных последовательностей, как-бы + * в виде "пунктира", который постепенно заполняет весь заданных диапазон. + * + * Параметры позволяют генерировать такой "пунктир". Соответственно rotate + * задает циклический сдвиг вправо, а offset задает смещение, точнее говоря + * сложение по модулю внутри диапазона заданного посредством width. + * + * Например, при rotate равном 1 (циклический сдвиг вправо на 1 бит), + * четные и нечетные исходные значения сложатся в две линейные + * последовательности, которые постепенно закроют старшую и младшую + * половины диапазона. + * + * split: + * Для таблиц без дубликатов (без multi-value ключей) фактически требуется + * генерация только ключей, а данные могут быть постоянным. Но для таблиц с + * дубликатами (с multi-value ключами) также требуется генерация значений. + * + * Ненулевое значение параметра split фактически включает генерацию значений, + * при этом значение split определяет сколько бит исходного абстрактного + * номера будет отрезано для генерации значения. + */ + + uint8_t width; + uint8_t mesh; + uint8_t rotate; + uint8_t split; + uint32_t seed; + uint64_t offset; +}; + +struct actor_params_pod { + unsigned loglevel; + + unsigned mode_flags; + unsigned table_flags; + intptr_t size_lower; + intptr_t size_now; + intptr_t size_upper; + int shrink_threshold; + int growth_step; + int pagesize; + + unsigned test_duration; + unsigned test_nops; + unsigned nrepeat; + unsigned nthreads; + + unsigned keylen_min, keylen_max; + unsigned datalen_min, datalen_max; + + unsigned batch_read; + unsigned batch_write; + + unsigned delaystart; + unsigned waitfor_nops; + unsigned inject_writefaultn; + + unsigned max_readers; + unsigned max_tables; + keygen_params_pod keygen; + + bool drop_table; + bool ignore_dbfull; +}; + +struct actor_config_pod { + unsigned actor_id, space_id; + actor_testcase testcase; + unsigned wait4id; + unsigned signal_nops; +}; + +#pragma pack(pop) + +extern const struct option_verb mode_bits[]; +extern const struct option_verb table_bits[]; +void dump(const char *title = "config-dump: "); + +} /* namespace config */ + +struct actor_params : public config::actor_params_pod { + std::string pathname_log; + std::string pathname_db; + void set_defaults(const std::string &tmpdir); + + unsigned mdbx_keylen_min() const; + unsigned mdbx_keylen_max() const; + unsigned mdbx_datalen_min() const; + unsigned mdbx_datalen_max() const; +}; + +struct actor_config : public config::actor_config_pod { + actor_params params; + + bool wanna_event4signalling() const { return true /* TODO ? */; } + + actor_config(actor_testcase testcase, const actor_params ¶ms, + unsigned space_id, unsigned wait4id); + + actor_config(const char *str) { + if (!deserialize(str, *this)) + failure("Invalid internal parameter '%s'\n", str); + } + + const std::string osal_serialize(simple_checksum &) const; + bool osal_deserialize(const char *str, const char *end, simple_checksum &); + + const std::string serialize(const char *prefix) const; + static bool deserialize(const char *str, actor_config &config); + + bool is_waitable(size_t nops) const { + switch (testcase) { + case ac_hill: + if (!params.test_nops || params.test_nops >= nops) + return true; + __fallthrough; + default: + return false; + } + } +}; diff --git a/contrib/db/libmdbx/test/copy.cc b/contrib/db/libmdbx/test/copy.cc new file mode 100644 index 00000000..e239d41e --- /dev/null +++ b/contrib/db/libmdbx/test/copy.cc @@ -0,0 +1,26 @@ +#include "test.h" + +void testcase_copy::copy_db(const bool with_compaction) { + int err = osal_removefile(copy_pathname); + if (err != MDBX_SUCCESS && err != MDBX_ENOFILE) + failure_perror("mdbx_removefile()", err); + + err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(), + with_compaction ? MDBX_CP_COMPACT : 0); + if (unlikely(err != MDBX_SUCCESS)) + failure_perror(with_compaction ? "mdbx_env_copy(MDBX_CP_COMPACT)" + : "mdbx_env_copy(MDBX_CP_ASIS)", + err); +} + +bool testcase_copy::run() { + jitter_delay(); + db_open(); + assert(!txn_guard); + const bool order = flipcoin(); + jitter_delay(); + copy_db(order); + jitter_delay(); + copy_db(!order); + return true; +} diff --git a/contrib/db/libmdbx/test/darwin/LICENSE b/contrib/db/libmdbx/test/darwin/LICENSE new file mode 100644 index 00000000..6a0dd306 --- /dev/null +++ b/contrib/db/libmdbx/test/darwin/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2015, Aleksey Demakov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/contrib/db/libmdbx/test/darwin/README.md b/contrib/db/libmdbx/test/darwin/README.md new file mode 100644 index 00000000..a6a8fd1a --- /dev/null +++ b/contrib/db/libmdbx/test/darwin/README.md @@ -0,0 +1,8 @@ +# DarwinPthreadBarrier + +A pthread_barrier_t implementation for Mac OS/X + +There is no pthread_barrier_t in Mac OS/X pthreads. This project fixes +this omission by providing a simple-minded barrier implementation based +on a pair of pthread_mutex_t and pthread_cond_t. + diff --git a/contrib/db/libmdbx/test/darwin/pthread_barrier.c b/contrib/db/libmdbx/test/darwin/pthread_barrier.c new file mode 100644 index 00000000..054aa007 --- /dev/null +++ b/contrib/db/libmdbx/test/darwin/pthread_barrier.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015, Aleksey Demakov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pthread_barrier.h" + +#include + +#ifdef __APPLE__ + +int pthread_barrierattr_init(pthread_barrierattr_t *attr) { + memset(attr, 0, sizeof(pthread_barrierattr_t)); + int m = pthread_mutexattr_init(&attr->mattr); + int c = pthread_condattr_init(&attr->cattr); + return m ? m : c; +} + +int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) { + int c = pthread_condattr_destroy(&attr->cattr); + int m = pthread_mutexattr_destroy(&attr->mattr); + return m ? m : c; +} + +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, + int *__restrict pshared) { + return pthread_condattr_getpshared(&attr->cattr, pshared); +} + +int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) { + int m = pthread_mutexattr_setpshared(&attr->mattr, pshared); + int c = pthread_condattr_setpshared(&attr->cattr, pshared); + return m ? m : c; +} + +int pthread_barrier_init(pthread_barrier_t *__restrict barrier, + const pthread_barrierattr_t *__restrict attr, + unsigned count) { + if (count == 0) + return errno = EINVAL; + + int rc = pthread_mutex_init(&barrier->mutex, attr ? &attr->mattr : 0); + if (rc) + return rc; + + rc = pthread_cond_init(&barrier->cond, attr ? &attr->cattr : 0); + if (rc) { + int errno_save = errno; + pthread_mutex_destroy(&barrier->mutex); + errno = errno_save; + return rc; + } + + barrier->limit = count; + barrier->count = 0; + barrier->phase = 0; + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *barrier) { + pthread_mutex_destroy(&barrier->mutex); + pthread_cond_destroy(&barrier->cond); + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t *barrier) { + int rc = pthread_mutex_lock(&barrier->mutex); + if (rc) + return rc; + + barrier->count++; + if (barrier->count >= barrier->limit) { + barrier->phase++; + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return PTHREAD_BARRIER_SERIAL_THREAD; + } else { + unsigned phase = barrier->phase; + do + pthread_cond_wait(&barrier->cond, &barrier->mutex); + while (phase == barrier->phase); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +#endif /* __APPLE__ */ diff --git a/contrib/db/libmdbx/test/darwin/pthread_barrier.h b/contrib/db/libmdbx/test/darwin/pthread_barrier.h new file mode 100644 index 00000000..efa9b9b7 --- /dev/null +++ b/contrib/db/libmdbx/test/darwin/pthread_barrier.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Aleksey Demakov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PTHREAD_BARRIER_H +#define PTHREAD_BARRIER_H + +#include + +#ifdef __APPLE__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(PTHREAD_BARRIER_SERIAL_THREAD) +#define PTHREAD_BARRIER_SERIAL_THREAD (1) +#endif + +#if !defined(PTHREAD_PROCESS_PRIVATE) +#define PTHREAD_PROCESS_PRIVATE (42) +#endif +#if !defined(PTHREAD_PROCESS_SHARED) +#define PTHREAD_PROCESS_SHARED (43) +#endif + +typedef struct { + pthread_mutexattr_t mattr; + pthread_condattr_t cattr; +} pthread_barrierattr_t; + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned int limit; + unsigned int count; + unsigned int phase; +} pthread_barrier_t; + +int pthread_barrierattr_init(pthread_barrierattr_t *attr); +int pthread_barrierattr_destroy(pthread_barrierattr_t *attr); + +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, + int *__restrict pshared); +int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared); + +int pthread_barrier_init(pthread_barrier_t *__restrict barrier, + const pthread_barrierattr_t *__restrict attr, + unsigned int count); +int pthread_barrier_destroy(pthread_barrier_t *barrier); + +int pthread_barrier_wait(pthread_barrier_t *barrier); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPLE__ */ + +#endif /* PTHREAD_BARRIER_H */ diff --git a/contrib/db/libmdbx/test/dead.cc b/contrib/db/libmdbx/test/dead.cc new file mode 100644 index 00000000..a1a8b5f9 --- /dev/null +++ b/contrib/db/libmdbx/test/dead.cc @@ -0,0 +1,35 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +bool testcase_deadread::run() { + db_open(); + txn_begin(true); + cursor_guard.reset(); + txn_guard.reset(); + db_guard.reset(); + return true; +} + +//----------------------------------------------------------------------------- + +bool testcase_deadwrite::run() { + db_open(); + txn_begin(false); + cursor_guard.reset(); + txn_guard.reset(); + db_guard.reset(); + return true; +} diff --git a/contrib/db/libmdbx/test/hill.cc b/contrib/db/libmdbx/test/hill.cc new file mode 100644 index 00000000..1b03ddf0 --- /dev/null +++ b/contrib/db/libmdbx/test/hill.cc @@ -0,0 +1,321 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +bool testcase_hill::run() { + MDBX_dbi dbi; + int err = db_open__begin__table_create_open_clean(dbi); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("hill: bailout-prepare due '%s'", mdbx_strerror(err)); + return true; + } + + /* LY: тест "холмиком": + * - сначала наполняем таблицу циклическими CRUD-манипуляциями, + * которые в каждом цикле делают несколько операций, включая удаление, + * но в результате добавляют записи. + * - затем очищаем таблицу также CRUD-манипуляциями, но уже с другой + * пропорцией удалений. + * + * При этом очень многое зависит от порядка перебора ключей: + * - (псевдо)случайное распределение требуется лишь для полноты картины, + * но в целом не покрывает важных кейсов. + * - кроме (псевдо)случайного перебора требуется последовательное + * итерирование ключей интервалами различной ширины, с тем чтобы + * проверить различные варианты как разделения, так и слияния страниц + * внутри движка. + * - при не-уникальных ключах (MDBX_DUPSORT с подвариантами), для каждого + * повтора внутри движка формируется вложенное btree-дерево, + * соответственно требуется соблюдение аналогичных принципов + * итерирования для значений. + */ + + /* TODO: работа в несколько потоков */ + keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); + + keygen::buffer a_key = keygen::alloc(config.params.keylen_max); + keygen::buffer a_data_0 = keygen::alloc(config.params.datalen_max); + keygen::buffer a_data_1 = keygen::alloc(config.params.datalen_max); + keygen::buffer b_key = keygen::alloc(config.params.keylen_max); + keygen::buffer b_data = keygen::alloc(config.params.datalen_max); + + const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) + ? MDBX_NODUPDATA + : MDBX_NODUPDATA | MDBX_NOOVERWRITE; + const unsigned update_flags = + (config.params.table_flags & MDBX_DUPSORT) + ? MDBX_CURRENT | MDBX_NODUPDATA | MDBX_NOOVERWRITE + : MDBX_NODUPDATA; + + uint64_t serial_count = 0; + uint64_t commited_serial = serial_count; + unsigned txn_nops = 0; + + while (should_continue()) { + const keygen::serial_t a_serial = serial_count; + if (unlikely(!keyvalue_maker.increment(serial_count, 1))) { + log_notice("uphill: unexpected key-space overflow"); + break; + } + + const keygen::serial_t b_serial = serial_count; + assert(b_serial > a_serial); + + // создаем первую запись из пары + const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); + log_trace("uphill: insert-a (age %" PRIu64 ") %" PRIu64, age_shift, + a_serial); + generate_pair(a_serial, a_key, a_data_1, age_shift); + err = mdbx_put(txn_guard.get(), dbi, &a_key->value, &a_data_1->value, + insert_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("uphill: bailout at insert-a due '%s'", mdbx_strerror(err)); + txn_restart(true, false); + serial_count = commited_serial; + break; + } + failure_perror("mdbx_put(insert-a.1)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); + serial_count = commited_serial; + break; + } + commited_serial = a_serial; + txn_nops = 0; + } + + // создаем вторую запись из пары + log_trace("uphill: insert-b %" PRIu64, b_serial); + generate_pair(b_serial, b_key, b_data, 0); + err = mdbx_put(txn_guard.get(), dbi, &b_key->value, &b_data->value, + insert_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("uphill: bailout at insert-b due '%s'", mdbx_strerror(err)); + txn_restart(true, false); + serial_count = commited_serial; + break; + } + failure_perror("mdbx_put(insert-b)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); + serial_count = commited_serial; + break; + } + commited_serial = a_serial; + txn_nops = 0; + } + + // обновляем данные в первой записи + log_trace("uphill: update-a (age %" PRIu64 "->0) %" PRIu64, age_shift, + a_serial); + generate_pair(a_serial, a_key, a_data_0, 0); + checkdata("uphill: update-a", dbi, a_key->value, a_data_1->value); + err = mdbx_replace(txn_guard.get(), dbi, &a_key->value, &a_data_0->value, + &a_data_1->value, update_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("uphill: bailout at update-a due '%s'", mdbx_strerror(err)); + txn_restart(true, false); + serial_count = commited_serial; + break; + } + failure_perror("mdbx_replace(update-a: 1->0)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); + serial_count = commited_serial; + break; + } + commited_serial = a_serial; + txn_nops = 0; + } + + // удаляем вторую запись + log_trace("uphill: delete-b %" PRIu64, b_serial); + checkdata("uphill: delete-b", dbi, b_key->value, b_data->value); + err = mdbx_del(txn_guard.get(), dbi, &b_key->value, &b_data->value); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("uphill: bailout at delete-b due '%s'", mdbx_strerror(err)); + txn_restart(true, false); + serial_count = commited_serial; + break; + } + failure_perror("mdbx_del(b)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err)); + serial_count = commited_serial; + break; + } + commited_serial = a_serial; + txn_nops = 0; + } + + report(1); + if (!keyvalue_maker.increment(serial_count, 1)) { + // дошли до границы пространства ключей + serial_count = a_serial; + goto overflow; + } + } + + while (serial_count > 1) { + if (unlikely(!keyvalue_maker.increment(serial_count, -2))) + failure("downhill: unexpected key-space underflow"); + + overflow: + const keygen::serial_t a_serial = serial_count; + const keygen::serial_t b_serial = a_serial + 1; + assert(b_serial > a_serial); + + // обновляем первую запись из пары + const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); + log_trace("downhill: update-a (age 0->%" PRIu64 ") %" PRIu64, age_shift, + a_serial); + generate_pair(a_serial, a_key, a_data_0, 0); + generate_pair(a_serial, a_key, a_data_1, age_shift); + checkdata("downhill: update-a", dbi, a_key->value, a_data_0->value); + err = mdbx_replace(txn_guard.get(), dbi, &a_key->value, &a_data_1->value, + &a_data_0->value, update_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("downhill: bailout at update-a due '%s'", + mdbx_strerror(err)); + txn_end(true); + break; + } + failure_perror("mdbx_put(update-a: 0->1)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); + break; + } + txn_nops = 0; + } + + // создаем вторую запись из пары + log_trace("downhill: insert-b %" PRIu64, b_serial); + generate_pair(b_serial, b_key, b_data, 0); + err = mdbx_put(txn_guard.get(), dbi, &b_key->value, &b_data->value, + insert_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("downhill: bailout at insert-a due '%s'", + mdbx_strerror(err)); + txn_end(true); + break; + } + failure_perror("mdbx_put(insert-b)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); + break; + } + txn_nops = 0; + } + + // удаляем первую запись + log_trace("downhill: delete-a (age %" PRIu64 ") %" PRIu64, age_shift, + a_serial); + checkdata("downhill: delete-a", dbi, a_key->value, a_data_1->value); + err = mdbx_del(txn_guard.get(), dbi, &a_key->value, &a_data_1->value); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("downhill: bailout at delete-a due '%s'", + mdbx_strerror(err)); + txn_end(true); + break; + } + failure_perror("mdbx_del(a)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); + break; + } + txn_nops = 0; + } + + // удаляем вторую запись + log_trace("downhill: delete-b %" PRIu64, b_serial); + checkdata("downhill: delete-b", dbi, b_key->value, b_data->value); + err = mdbx_del(txn_guard.get(), dbi, &b_key->value, &b_data->value); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("downhill: bailout at delete-b due '%s'", + mdbx_strerror(err)); + txn_end(true); + break; + } + failure_perror("mdbx_del(b)", err); + } + + if (++txn_nops >= config.params.batch_write) { + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); + break; + } + txn_nops = 0; + } + + report(1); + } + + if (txn_guard) { + err = breakable_commit(); + if (unlikely(err != MDBX_SUCCESS)) + log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err)); + } + + if (dbi) { + if (config.params.drop_table && !mode_readonly()) { + txn_begin(false); + db_table_drop(dbi); + err = breakable_commit(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("hill: bailout-clean due '%s'", mdbx_strerror(err)); + return true; + } + } else + db_table_close(dbi); + } + return true; +} diff --git a/contrib/db/libmdbx/test/jitter.cc b/contrib/db/libmdbx/test/jitter.cc new file mode 100644 index 00000000..82d1d764 --- /dev/null +++ b/contrib/db/libmdbx/test/jitter.cc @@ -0,0 +1,59 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +bool testcase_jitter::run() { + while (should_continue()) { + jitter_delay(); + db_open(); + + if (flipcoin()) { + jitter_delay(); + txn_begin(true); + fetch_canary(); + jitter_delay(); + txn_end(flipcoin()); + } + + jitter_delay(); + txn_begin(mode_readonly()); + jitter_delay(); + if (!mode_readonly()) { + fetch_canary(); + update_canary(1); + /* TODO: + * - db_setsize() + * ... + */ + } + txn_end(flipcoin()); + + if (flipcoin()) { + jitter_delay(); + txn_begin(true); + jitter_delay(); + txn_end(flipcoin()); + } + + jitter_delay(); + db_close(); + + /* just 'align' nops with other tests with batching */ + const auto batching = + std::max(config.params.batch_read, config.params.batch_write); + report(std::max(1u, batching / 2)); + } + return true; +} diff --git a/contrib/db/libmdbx/test/keygen.cc b/contrib/db/libmdbx/test/keygen.cc new file mode 100644 index 00000000..0110b049 --- /dev/null +++ b/contrib/db/libmdbx/test/keygen.cc @@ -0,0 +1,275 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +namespace keygen { + +static inline __pure_function serial_t mask(unsigned bits) { + assert(bits > 0 && bits <= serial_maxwith); + return serial_allones >> (serial_maxwith - bits); +} + +/* LY: https://en.wikipedia.org/wiki/Injective_function */ +serial_t injective(const serial_t serial, + const unsigned bits /* at least serial_minwith (8) */, + const serial_t salt) { + assert(bits > serial_minwith && bits <= serial_maxwith); + + /* LY: All these "magic" prime numbers were found + * and verified with a bit of brute force. */ + + static const uint64_t m[64 - serial_minwith + 1] = { + /* 8 - 24 */ + 113, 157, 397, 653, 1753, 5641, 9697, 23873, 25693, 80833, 105953, 316937, + 309277, 834497, 1499933, 4373441, 10184137, + /* 25 - 64 */ + 10184137, 17279209, 33990377, 67295161, 284404553, 1075238767, 6346721573, + 6924051577, 19204053433, 45840188887, 53625693977, 73447827913, + 141638870249, 745683604649, 1283334050489, 1100828289853, 2201656586197, + 5871903036137, 11238507001417, 45264020802263, 105008404482889, + 81921776907059, 199987980256399, 307207457507641, 946769023178273, + 2420886491930041, 3601632139991929, 11984491914483833, 21805846439714153, + 23171543400565993, 53353226456762893, 155627817337932409, + 227827205384840249, 816509268558278821, 576933057762605689, + 2623957345935638441, 5048241705479929949, 4634245581946485653, + 4613509448041658233, 4952535426879925961}; + static const uint8_t s[64 - serial_minwith + 1] = { + /* 8 - 24 */ + 2, 3, 4, 4, 2, 4, 3, 3, 7, 3, 3, 4, 8, 3, 10, 3, 11, + /* 25 - 64 */ + 11, 9, 9, 9, 11, 10, 5, 14, 11, 16, 14, 12, 13, 16, 19, 10, 10, 21, 7, 20, + 10, 14, 22, 19, 3, 21, 18, 19, 26, 24, 2, 21, 25, 29, 24, 10, 11, 14, 20, + 19}; + + const auto mult = m[bits - 8]; + const auto shift = s[bits - 8]; + serial_t result = serial * mult; + if (salt) { + const unsigned left = bits / 2; + const unsigned right = bits - left; + result = (result << left) | ((result & mask(bits)) >> right); + result = (result ^ salt) * mult; + } + + result ^= result << shift; + result &= mask(bits); + log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64 + " => %" PRIu64 "/%u", + serial, bits, mult, shift, salt, result, bits); + return result; +} + +void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, + serial_t value_age) { + assert(mapping.width >= serial_minwith && mapping.width <= serial_maxwith); + assert(mapping.split <= mapping.width); + assert(mapping.mesh <= mapping.width); + assert(mapping.rotate <= mapping.width); + assert(mapping.offset <= mask(mapping.width)); + assert(!(key_essentials.flags & + ~(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))); + assert(!(value_essentials.flags & ~(MDBX_INTEGERDUP | MDBX_REVERSEDUP))); + + log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial, + value_age); + + if (mapping.mesh >= serial_minwith) { + serial = + (serial & ~mask(mapping.mesh)) | injective(serial, mapping.mesh, salt); + log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial); + } + + if (mapping.rotate) { + const unsigned right = mapping.rotate; + const unsigned left = mapping.width - right; + serial = (serial << left) | ((serial & mask(mapping.width)) >> right); + log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64, + mapping.rotate, serial, serial); + } + + if (mapping.offset) { + serial = (serial + mapping.offset) & mask(mapping.width); + log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset, + serial); + } + if (base) { + serial += base; + log_trace("keygen-pair: base@%" PRIu64 " => %" PRIu64, base, serial); + } + + serial_t key_serial = serial; + serial_t value_serial = value_age << mapping.split; + if (mapping.split) { + if (key_essentials.flags & MDBX_DUPSORT) { + key_serial >>= mapping.split; + value_serial += serial & mask(mapping.split); + } else { + /* Без MDBX_DUPSORT требуется уникальность ключей, а для этого нельзя + * отбрасывать какие-либо биты serial после инъективного преобразования. + * Поэтому key_serial не трогаем, а в value_serial нелинейно вмешиваем + * запрошенное количество бит из serial */ + value_serial += + (serial ^ (serial >> mapping.split)) & mask(mapping.split); + } + + value_serial |= value_age << mapping.split; + log_trace("keygen-pair: split@%u => k%" PRIu64 ", v%" PRIu64, mapping.split, + key_serial, value_serial); + } + + log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial, + value_serial); + mk(key_serial, key_essentials, *key); + mk(value_serial, value_essentials, *value); + + if (log_enabled(logging::trace)) { + char dump_key[128], dump_value[128]; + log_trace("keygen-pair: key %s, value %s", + mdbx_dkey(&key->value, dump_key, sizeof(dump_key)), + mdbx_dkey(&value->value, dump_value, sizeof(dump_value))); + } +} + +void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, + unsigned thread_number) { + key_essentials.flags = + actor.table_flags & (MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT); + assert(actor.keylen_min <= UINT8_MAX); + key_essentials.minlen = (uint8_t)actor.keylen_min; + assert(actor.keylen_max <= UINT16_MAX); + key_essentials.maxlen = (uint16_t)actor.keylen_max; + + value_essentials.flags = + actor.table_flags & (MDBX_INTEGERDUP | MDBX_REVERSEDUP); + assert(actor.datalen_min <= UINT8_MAX); + value_essentials.minlen = (uint8_t)actor.datalen_min; + assert(actor.datalen_max <= UINT16_MAX); + value_essentials.maxlen = (uint16_t)actor.datalen_max; + + assert(thread_number < 2); + (void)thread_number; + mapping = actor.keygen; + salt = (actor.keygen.seed + actor_id) * UINT64_C(14653293970879851569); + + // FIXME: TODO + base = 0; +} + +void maker::make_ordered() { + mapping.mesh = 0; + mapping.rotate = 0; +} + +bool maker::is_unordered() const { + return (mapping.mesh >= serial_minwith || mapping.rotate) != 0; +} + +bool maker::increment(serial_t &serial, int delta) const { + if (serial > mask(mapping.width)) { + log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial, + mask(mapping.width)); + return false; + } + + serial_t target = serial + (int64_t)delta; + if (target > mask(mapping.width) || + ((delta > 0) ? target < serial : target > serial)) { + log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow", + serial, delta, target); + return false; + } + + log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", continue", serial, + delta, target); + serial = target; + return true; +} + +//----------------------------------------------------------------------------- + +static size_t length(serial_t serial) { + size_t n = 0; + if (serial > UINT32_MAX) { + n = 4; + serial >>= 32; + } + if (serial > UINT16_MAX) { + n += 2; + serial >>= 16; + } + if (serial > UINT8_MAX) { + n += 1; + serial >>= 8; + } + return (serial > 0) ? n + 1 : n; +} + +buffer alloc(size_t limit) { + result *ptr = (result *)malloc(sizeof(result) + limit); + if (unlikely(ptr == nullptr)) + failure_perror("malloc(keyvalue_buffer)", errno); + ptr->value.iov_base = ptr->bytes; + ptr->value.iov_len = 0; + ptr->limit = limit; + return buffer(ptr); +} + +void __hot maker::mk(const serial_t serial, const essentials ¶ms, + result &out) { + assert(out.limit >= params.maxlen); + assert(params.maxlen >= params.minlen); + assert(params.maxlen >= length(serial)); + + out.value.iov_base = out.bytes; + out.value.iov_len = + (params.maxlen > params.minlen) + ? params.minlen + serial % (params.maxlen - params.minlen) + : params.minlen; + + if (params.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) { + assert(params.maxlen == params.minlen); + assert(params.minlen == 4 || params.minlen == 8); + if (is_byteorder_le() || params.minlen == 8) + out.u64 = serial; + else + out.u32 = (uint32_t)serial; + } else if (params.flags & (MDBX_REVERSEKEY | MDBX_REVERSEDUP)) { + if (out.value.iov_len > 8) { + memset(out.bytes, '\0', out.value.iov_len - 8); + unaligned::store(out.bytes + out.value.iov_len - 8, htobe64(serial)); + } else { + out.u64 = htobe64(serial); + if (out.value.iov_len < 8) { + out.value.iov_len = std::max(length(serial), out.value.iov_len); + out.value.iov_base = out.bytes + 8 - out.value.iov_len; + } + } + } else { + out.u64 = htole64(serial); + if (out.value.iov_len > 8) + memset(out.bytes + 8, '\0', out.value.iov_len - 8); + else + out.value.iov_len = std::max(length(serial), out.value.iov_len); + } + + assert(out.value.iov_len >= params.minlen); + assert(out.value.iov_len <= params.maxlen); + assert(out.value.iov_len >= length(serial)); + assert(out.value.iov_base >= out.bytes); + assert((uint8_t *)out.value.iov_base + out.value.iov_len <= + out.bytes + out.limit); +} + +} /* namespace keygen */ diff --git a/contrib/db/libmdbx/test/keygen.h b/contrib/db/libmdbx/test/keygen.h new file mode 100644 index 00000000..d0299e1e --- /dev/null +++ b/contrib/db/libmdbx/test/keygen.h @@ -0,0 +1,130 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" +#include "config.h" +#include "log.h" +#include "utils.h" + +namespace keygen { + +/* Под "генерацией ключей" здесь понимается генерация обоих значений для + * пар key-value, т.е. не только ключей, но и ассоциированных с ними данных. + */ + +/* Генерацию ключей нельзя отнести к простым задачам, так как требования + * примерно следующие: + * - генерация разного количества уникальных ключей различной длины + * в задаваемом диапазоне; + * - возможность выбора как псевдо-случайного порядка ключей, + * так и по некоторым специфическим законам (ограниченными упорядоченными + * последовательностями, в шахматном порядке по граница диапазона и т.д.); + * - возможность генерации дубликатов с задаваемым законом распределения; + * - возможность генерации непересекающимися кластерами для параллельного + * использования в нескольких потоках; + * - использовать минимум ресурсов, как CPU, так и RAM, в том числе + * включая cache pollution и ram bandwidth. + * + * При этом заведомо известно, что для MDBX не имеет значения: + * - используемый алфавит (значения байтов); + * - частотное распределение по алфавиту; + * - абсолютное значение ключей или разность между отдельными значениями; + * + * Соответственно, в общих чертах, схема генерации следующая: + * - вводится плоская одномерная "координата" serial (uint64_t); + * - генерация специфических паттернов (последовательностей) + * реализуется посредством соответствующих преобразований "координат", при + * этом все подобные преобразования выполняются только над "координатой"; + * - итоговая "координата" преобразуется в 8-байтное суррогатное значение + * ключа; + * - для получения ключей длиной МЕНЕЕ 8 байт суррогат может усекаться + * до ненулевых байт, в том числе до нулевой длины; + * - для получения ключей длиной БОЛЕЕ 8 байт суррогат дополняется + * нулями или псевдослучайной последовательностью; + * + * Механизм генерации паттернов: + * - реализованный механизм является компромиссом между скоростью/простотой + * и гибкостью, необходимой для получения последовательностей, которых + * будет достаточно для проверки сценариев разделения и слияния страниц + * с данными внутри mdbx; + * - псевдо-случайные паттерны реализуются посредством набора инъективных + * отображающих функций; + * - не-псевдо-случайные паттерны реализуются посредством параметризируемого + * трех-этапного преобразования: + * 1) смещение (сложение) по модулю; + * 2) циклический сдвиг; + * 3) добавление абсолютного смещения (базы); + */ + +typedef uint64_t serial_t; + +enum : serial_t { + serial_minwith = 8, + serial_maxwith = sizeof(serial_t) * 8, + serial_allones = ~(serial_t)0u +}; + +struct result { + MDBX_val value; + size_t limit; + union { + uint8_t bytes[sizeof(uint64_t)]; + uint32_t u32; + uint64_t u64; + }; + + std::string as_string() const { + return std::string((const char *)value.iov_base, value.iov_len); + } +}; + +//----------------------------------------------------------------------------- + +struct buffer_deleter : public std::unary_function { + void operator()(result *buffer) const { free(buffer); } +}; + +typedef std::unique_ptr buffer; + +buffer alloc(size_t limit); + +class maker { + config::keygen_params_pod mapping; + serial_t base; + serial_t salt; + + struct essentials { + uint8_t minlen; + uint8_t flags; + uint16_t maxlen; + } key_essentials, value_essentials; + + static void mk(const serial_t serial, const essentials ¶ms, result &out); + +public: + maker() { memset(this, 0, sizeof(*this)); } + + void pair(serial_t serial, const buffer &key, buffer &value, + serial_t value_age); + void setup(const config::actor_params_pod &actor, unsigned actor_id, + unsigned thread_number); + void make_ordered(); + bool is_unordered() const; + + bool increment(serial_t &serial, int delta) const; +}; + +} /* namespace keygen */ diff --git a/contrib/db/libmdbx/test/log.cc b/contrib/db/libmdbx/test/log.cc new file mode 100644 index 00000000..79544e11 --- /dev/null +++ b/contrib/db/libmdbx/test/log.cc @@ -0,0 +1,325 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +static void fflushall() { fflush(nullptr); } + +void failure(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + fflushall(); + logging::output(logging::failure, fmt, ap); + va_end(ap); + fflushall(); + exit(EXIT_FAILURE); +} + +const char *test_strerror(int errnum) { + static __thread char buf[1024]; + return mdbx_strerror_r(errnum, buf, sizeof(buf)); +} + +void __noreturn failure_perror(const char *what, int errnum) { + failure("%s failed: %s (%d)\n", what, test_strerror(errnum), errnum); +} + +//----------------------------------------------------------------------------- + +static void mdbx_logger(int type, const char *function, int line, + const char *msg, va_list args) { + logging::loglevel level = logging::info; + if (type & MDBX_DBG_EXTRA) + level = logging::extra; + if (type & MDBX_DBG_TRACE) + level = logging::trace; + if (type & MDBX_DBG_PRINT) + level = logging::verbose; + + if (!function) + function = "unknown"; + if (type & MDBX_DBG_ASSERT) { + log_error("mdbx: assertion failure: %s, %d", function, line); + level = logging::failure; + } + + if (logging::output( + level, + strncmp(function, "mdbx_", 5) == 0 ? "%s: " : "mdbx: %s: ", function)) + logging::feed_ap(msg, args); + if (type & MDBX_DBG_ASSERT) + abort(); +} + +namespace logging { + +static std::string prefix; +static std::string suffix; +static loglevel level; +static FILE *last; + +void setlevel(loglevel _level) { + level = (_level > error) ? failure : _level; + int mdbx_dbg_opts = MDBX_DBG_ASSERT | MDBX_DBG_JITTER | MDBX_DBG_DUMP; + if (level <= trace) + mdbx_dbg_opts |= MDBX_DBG_TRACE; + if (level <= verbose) + mdbx_dbg_opts |= MDBX_DBG_PRINT; + int rc = mdbx_setup_debug(mdbx_dbg_opts, mdbx_logger); + log_trace("set mdbx debug-opts: 0x%02x", rc); +} + +void setup(loglevel _level, const std::string &_prefix) { + setlevel(_level); + prefix = _prefix; +} + +void setup(const std::string &_prefix) { prefix = _prefix; } + +const char *level2str(const loglevel alevel) { + switch (alevel) { + default: + return "invalid/unknown"; + case extra: + return "extra"; + case trace: + return "trace"; + case verbose: + return "verbose"; + case info: + return "info"; + case notice: + return "notice"; + case warning: + return "warning"; + case error: + return "error"; + case failure: + return "failure"; + } +} + +bool output(const loglevel priority, const char *format, ...) { + if (priority < level) + return false; + + va_list ap; + va_start(ap, format); + output(priority, format, ap); + va_end(ap); + return true; +} + +bool output(const logging::loglevel priority, const char *format, va_list ap) { + if (last) { + putc('\n', last); + fflush(last); + last = nullptr; + } + + if (priority < level) + return false; + + chrono::time now = chrono::now_realtime(); + struct tm tm; +#ifdef _MSC_VER + int rc = _localtime32_s(&tm, (const __time32_t *)&now.utc); +#else + time_t time = now.utc; + int rc = localtime_r(&time, &tm) ? MDBX_SUCCESS : errno; +#endif + if (rc != MDBX_SUCCESS) + failure_perror("localtime_r()", rc); + + last = stdout; + fprintf(last, + "[ %02d%02d%02d-%02d:%02d:%02d.%06d_%05u %-10s %.4s ] %s" /* TODO */, + tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, chrono::fractional2us(now.fractional), osal_getpid(), + prefix.c_str(), level2str(priority), suffix.c_str()); + + va_list ones; + memset(&ones, 0, sizeof(ones)) /* zap MSVC and other stupid compilers */; + if (priority >= error) + va_copy(ones, ap); + vfprintf(last, format, ap); + + size_t len = strlen(format); + char end = len ? format[len - 1] : '\0'; + + switch (end) { + default: + putc('\n', last); + // fall through + case '\n': + fflush(last); + last = nullptr; + // fall through + case ' ': + case '_': + case ':': + case '|': + case ',': + case '\t': + case '\b': + case '\r': + case '\0': + break; + } + + if (priority >= error) { + if (last != stderr) { + fprintf(stderr, "[ %05u %-10s %.4s ] %s", osal_getpid(), prefix.c_str(), + level2str(priority), suffix.c_str()); + vfprintf(stderr, format, ones); + if (end != '\n') + putc('\n', stderr); + fflush(stderr); + } + va_end(ones); + } + + return true; +} + +bool feed_ap(const char *format, va_list ap) { + if (!last) + return false; + + vfprintf(last, format, ap); + size_t len = strlen(format); + if (len && format[len - 1] == '\n') { + fflush(last); + last = nullptr; + } + return true; +} + +bool feed(const char *format, ...) { + if (!last) + return false; + + va_list ap; + va_start(ap, format); + feed_ap(format, ap); + va_end(ap); + return true; +} + +local_suffix::local_suffix(const char *c_str) + : trim_pos(suffix.size()), indent(0) { + suffix.append(c_str); +} + +local_suffix::local_suffix(const std::string &str) + : trim_pos(suffix.size()), indent(0) { + suffix.append(str); +} + +void local_suffix::push() { + indent += 1; + suffix.push_back('\t'); +} + +void local_suffix::pop() { + assert(indent > 0); + if (indent > 0) { + indent -= 1; + suffix.pop_back(); + } +} + +local_suffix::~local_suffix() { suffix.erase(trim_pos); } + +} // namespace logging + +void log_extra(const char *msg, ...) { + if (logging::extra >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::extra, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_trace(const char *msg, ...) { + if (logging::trace >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::trace, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_verbose(const char *msg, ...) { + if (logging::verbose >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::verbose, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_info(const char *msg, ...) { + if (logging::info >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::info, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_notice(const char *msg, ...) { + if (logging::notice >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::notice, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_warning(const char *msg, ...) { + if (logging::warning >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::warning, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_error(const char *msg, ...) { + if (logging::error >= logging::level) { + va_list ap; + va_start(ap, msg); + logging::output(logging::error, msg, ap); + va_end(ap); + } else + logging::last = nullptr; +} + +void log_trouble(const char *where, const char *what, int errnum) { + log_error("%s: %s %s", where, what, test_strerror(errnum)); +} + +bool log_enabled(const logging::loglevel priority) { + return (priority >= logging::level); +} + +void log_flush(void) { fflushall(); } diff --git a/contrib/db/libmdbx/test/log.h b/contrib/db/libmdbx/test/log.h new file mode 100644 index 00000000..7d6b4012 --- /dev/null +++ b/contrib/db/libmdbx/test/log.h @@ -0,0 +1,83 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" + +void __noreturn usage(void); +void __noreturn __printf_args(1, 2) failure(const char *fmt, ...); +void __noreturn failure_perror(const char *what, int errnum); +const char *test_strerror(int errnum); + +namespace logging { + +enum loglevel { + extra, + trace, + verbose, + info, + notice, + warning, + error, + failure, +}; + +const char *level2str(const loglevel level); +void setup(loglevel level, const std::string &prefix); +void setup(const std::string &prefix); +void setlevel(loglevel level); + +bool output(const loglevel priority, const char *format, va_list ap); +bool __printf_args(2, 3) + output(const loglevel priority, const char *format, ...); +bool feed_ap(const char *format, va_list ap); +bool __printf_args(1, 2) feed(const char *format, ...); + +class local_suffix { +protected: + size_t trim_pos; + int indent; + +public: + local_suffix(const local_suffix &) = delete; + local_suffix(const local_suffix &&) = delete; + const local_suffix &operator=(const local_suffix &) = delete; + + local_suffix(const char *c_str); + local_suffix(const std::string &str); + void push(); + void pop(); + ~local_suffix(); +}; + +} // namespace logging + +void __printf_args(1, 2) log_extra(const char *msg, ...); +void __printf_args(1, 2) log_trace(const char *msg, ...); +void __printf_args(1, 2) log_verbose(const char *msg, ...); +void __printf_args(1, 2) log_info(const char *msg, ...); +void __printf_args(1, 2) log_notice(const char *msg, ...); +void __printf_args(1, 2) log_warning(const char *msg, ...); +void __printf_args(1, 2) log_error(const char *msg, ...); + +void log_trouble(const char *where, const char *what, int errnum); +void log_flush(void); +bool log_enabled(const logging::loglevel priority); + +#ifdef _DEBUG +#define TRACE(...) log_trace(__VA_ARGS__) +#else +#define TRACE(...) __noop(__VA_ARGS__) +#endif diff --git a/contrib/db/libmdbx/test/long_stochastic.sh b/contrib/db/libmdbx/test/long_stochastic.sh new file mode 100644 index 00000000..954d1826 --- /dev/null +++ b/contrib/db/libmdbx/test/long_stochastic.sh @@ -0,0 +1,138 @@ +#!/bin/bash +if ! which make cc c++ tee lz4 >/dev/null; then + echo "Please install the following prerequisites: make cc c++ tee lz4" >&2 + exit 1 +fi + +set -euo pipefail + +UNAME="$(uname -s 2>/dev/null || echo Unknown)" +case ${UNAME} in + Linux) + MAKE=make + if [[ ! -v TESTDB_DIR || -z "$TESTDB_DIR" ]]; then + TESTDB_DIR="/dev/shm/mdbx-test.$$" + fi + mkdir -p $TESTDB_DIR && rm -f $TESTDB_DIR/* + if LC_ALL=C free | grep -q -i available; then + ram_avail_mb=$(($(LC_ALL=C free | grep -i Mem: | tr -s [:blank:] ' ' | cut -d ' ' -f 7) / 1024)) + else + ram_avail_mb=$(($(LC_ALL=C free | grep -i Mem: | tr -s [:blank:] ' ' | cut -d ' ' -f 4) / 1024)) + fi + ;; + FreeBSD) + MAKE=gmake + if [[ ! -v TESTDB_DIR || -z "$TESTDB_DIR" ]]; then + for old_test_dir in $(ls -d /tmp/mdbx-test.[0-9]*); do + umount $old_test_dir && rm -r $old_test_dir + done + TESTDB_DIR="/tmp/mdbx-test.$$" + rm -rf $TESTDB_DIR && mkdir -p $TESTDB_DIR && mount -t tmpfs tmpfs $TESTDB_DIR + else + mkdir -p $TESTDB_DIR && rm -f $TESTDB_DIR/* + fi + ram_avail_mb=$(($(LC_ALL=C vmstat -s | grep -ie '[0-9] pages free$' | cut -d p -f 1) * ($(LC_ALL=C vmstat -s | grep -ie '[0-9] bytes per page$' | cut -d b -f 1) / 1024) / 1024)) + ;; + *) + echo "FIXME: ${UNAME} not supported by this script" + exit 2 + ;; +esac + +echo "=== ${ram_avail_mb}M RAM available" +ram_reserve4logs_mb=1234 +if [ $ram_avail_mb -lt $ram_reserve4logs_mb ]; then + echo "=== At least ${ram_reserve4logs_mb}Mb RAM required" + exit 3 +fi + +# +# В режимах отличных от MDBX_WRITEMAP изменения до записи в файл +# будут накапливаться в памяти, что может потребовать свободной +# памяти размером с БД. Кроме этого, в тест входит сценарий +# создания копия БД на ходу. Поэтому БД не может быть больше 1/3 +# от доступной памяти. Однако, следует учесть что malloc() будет +# не сразу возвращать выделенную память системе, а также +# предусмотреть места для логов. +# +# In non-MDBX_WRITEMAP modes, updates (dirty pages) will +# accumulate in memory before writing to the disk, which may +# require a free memory up to the size of a whole database. In +# addition, the test includes a script create a copy of the +# database on the go. Therefore, the database cannot be more 1/3 +# of available memory. Moreover, should be taken into account +# that malloc() will not return the allocated memory to the +# system immediately, as well some space is required for logs. +# +db_size_mb=$(((ram_avail_mb - ram_reserve4logs_mb) / 4)) +if [ $db_size_mb -gt 3072 ]; then + db_size_mb=3072 +fi +echo "=== use ${db_size_mb}M for DB" + +${MAKE} TESTDB=${TESTDB_DIR}/smoke.db TESTLOG=${TESTDB_DIR}/smoke.log check +rm -f ${TESTDB_DIR}/* + +############################################################################### + +function rep9 { printf "%*s" $1 '' | tr ' ' '9'; } +function join { local IFS="$1"; shift; echo "$*"; } +function bit2option { local -n arr=$1; (( ($2&(1<<$3)) != 0 )) && echo -n '+' || echo -n '-'; echo "${arr[$3]}"; } + +options=(writemap coalesce lifo) + +function bits2list { + local -n arr=$1 + local i + local list=() + for ((i=0; i<${#arr[@]}; ++i)) do + list[$i]=$(bit2option $1 $2 $i) + done + join , "${list[@]}" +} + +function probe { + echo "=============================================== $(date)" + echo "${caption}: $*" + rm -f ${TESTDB_DIR}/* \ + && ./mdbx_test --ignore-dbfull --repeat=42 --pathname=${TESTDB_DIR}/long.db "$@" | lz4 > ${TESTDB_DIR}/long.log.lz4 \ + && ./mdbx_chk -nvvv ${TESTDB_DIR}/long.db | tee ${TESTDB_DIR}/long-chk.log \ + && ([ ! -e ${TESTDB_DIR}/long.db-copy ] || ./mdbx_chk -nvvv ${TESTDB_DIR}/long.db-copy | tee ${TESTDB_DIR}/long-chk-copy.log) \ + || (echo "FAILED"; exit 1) +} + +############################################################################### + +count=0 +for nops in $(seq 2 6); do + for ((wbatch=nops-1; wbatch > 0; --wbatch)); do + loops=$(((111 >> nops) / nops + 3)) + for ((rep=0; rep++ < loops; )); do + for ((bits=2**${#options[@]}; --bits >= 0; )); do + seed=$(($(date +%s) + RANDOM)) + caption="Probe #$((++count)) int-key,w/o-dups, repeat ${rep} of ${loops}" probe \ + --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,-data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=1111 \ + --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ + --keygen.seed=${seed} basic + caption="Probe #$((++count)) int-key,with-dups, repeat ${rep} of ${loops}" probe \ + --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,+data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ + --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ + --keygen.seed=${seed} basic + caption="Probe #$((++count)) int-key,int-data, repeat ${rep} of ${loops}" probe \ + --pagesize=min --size-upper=${db_size_mb}M --table=+key.integer,+data.integer --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ + --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ + --keygen.seed=${seed} basic + caption="Probe #$((++count)) w/o-dups, repeat ${rep} of ${loops}" probe \ + --pagesize=min --size-upper=${db_size_mb}M --table=-data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=1111 \ + --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ + --keygen.seed=${seed} basic + caption="Probe #$((++count)) with-dups, repeat ${rep} of ${loops}" probe \ + --pagesize=min --size-upper=${db_size_mb}M --table=+data.dups --keylen.min=min --keylen.max=max --datalen.min=min --datalen.max=max \ + --nops=$( rep9 $nops ) --batch.write=$( rep9 $wbatch ) --mode=$(bits2list options $bits) \ + --keygen.seed=${seed} basic + done + done + done +done + +echo "=== ALL DONE ====================== $(date)" diff --git a/contrib/db/libmdbx/test/main.cc b/contrib/db/libmdbx/test/main.cc new file mode 100644 index 00000000..959359a5 --- /dev/null +++ b/contrib/db/libmdbx/test/main.cc @@ -0,0 +1,488 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +void __noreturn usage(void) { + printf("usage:\n" + "\tFIXME\n"); + exit(EXIT_FAILURE); +} + +//----------------------------------------------------------------------------- + +void actor_params::set_defaults(const std::string &tmpdir) { + pathname_log = ""; + loglevel = +#ifdef NDEBUG + logging::info; +#elif defined(_WIN32) || defined(_WIN64) + logging::verbose; +#else + logging::trace; +#endif + + pathname_db = tmpdir + "mdbx-test.db"; + mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NORDAHEAD | + MDBX_NOMEMINIT | MDBX_COALESCE | MDBX_LIFORECLAIM; + table_flags = MDBX_DUPSORT; + + size_lower = -1; + size_now = + intptr_t(1024) * 1024 * ((table_flags & MDBX_DUPSORT) ? 256 : 1024); + size_upper = -1; + shrink_threshold = -1; + growth_step = -1; + pagesize = -1; + + keygen.seed = 1; + keygen.keycase = kc_random; + keygen.width = (table_flags & MDBX_DUPSORT) ? 32 : 64; + keygen.mesh = keygen.width; + keygen.split = keygen.width / 2; + keygen.rotate = 3; + keygen.offset = 41; + + test_duration = 0; + test_nops = 1000; + nrepeat = 1; + nthreads = 1; + + keylen_min = mdbx_keylen_min(); + keylen_max = mdbx_keylen_max(); + datalen_min = mdbx_datalen_min(); + datalen_max = std::min(mdbx_datalen_max(), 256u * 1024 + 42); + + batch_read = 42; + batch_write = 42; + + delaystart = 0; + waitfor_nops = 0; + inject_writefaultn = 0; + + drop_table = false; + ignore_dbfull = false; + + max_readers = 42; + max_tables = 42; + + global::config::timeout_duration_seconds = 0 /* infinite */; + global::config::dump_config = true; + global::config::cleanup_before = true; + global::config::cleanup_after = true; + global::config::failfast = true; + global::config::progress_indicator = osal_istty(STDERR_FILENO); +} + +namespace global { + +std::vector actors; +std::unordered_map events; +std::unordered_map pid2actor; +std::set databases; +unsigned nactors; +chrono::time start_motonic; +chrono::time deadline_motonic; +bool singlemode; + +namespace config { +unsigned timeout_duration_seconds; +bool dump_config; +bool cleanup_before; +bool cleanup_after; +bool failfast; +bool progress_indicator; +} /* namespace config */ + +} /* namespace global */ + +//----------------------------------------------------------------------------- + +const char global::thunk_param_prefix[] = "--execute="; + +std::string thunk_param(const actor_config &config) { + return config.serialize(global::thunk_param_prefix); +} + +void cleanup() { + log_trace(">> cleanup"); + /* TODO: remove each database */ + log_trace("<< cleanup"); +} + +int main(int argc, char *const argv[]) { + +#ifdef _DEBUG + log_trace("#argc = %d", argc); + for (int i = 0; i < argc; ++i) + log_trace("#argv[%d] = %s", i, argv[i]); +#endif /* _DEBUG */ + + if (argc < 2) + failure("No parameters given\n"); + + if (argc == 2 && strncmp(argv[1], global::thunk_param_prefix, + strlen(global::thunk_param_prefix)) == 0) + return test_execute( + actor_config(argv[1] + strlen(global::thunk_param_prefix))) + ? EXIT_SUCCESS + : EXIT_FAILURE; + + actor_params params; + params.set_defaults(osal_tempdir()); + global::config::dump_config = true; + logging::setup((logging::loglevel)params.loglevel, "main"); + unsigned last_space_id = 0; + + for (int narg = 1; narg < argc; ++narg) { + const char *value = nullptr; + + if (config::parse_option(argc, argv, narg, "case", &value)) { + testcase_setup(value, params, last_space_id); + continue; + } + if (config::parse_option(argc, argv, narg, "pathname", params.pathname_db)) + continue; + if (config::parse_option(argc, argv, narg, "mode", params.mode_flags, + config::mode_bits)) + continue; + if (config::parse_option(argc, argv, narg, "table", params.table_flags, + config::table_bits)) { + if ((params.table_flags & MDBX_DUPFIXED) == 0) + params.table_flags &= ~MDBX_INTEGERDUP; + if ((params.table_flags & MDBX_DUPSORT) == 0) + params.table_flags &= + ~(MDBX_DUPFIXED | MDBX_REVERSEDUP | MDBX_INTEGERDUP); + continue; + } + + if (config::parse_option(argc, argv, narg, "pagesize", params.pagesize, + mdbx_limits_pgsize_min(), + mdbx_limits_pgsize_max())) { + const unsigned keylen_max = params.mdbx_keylen_max(); + if (params.keylen_min > keylen_max) + params.keylen_min = keylen_max; + if (params.keylen_max > keylen_max) + params.keylen_max = keylen_max; + const unsigned datalen_max = params.mdbx_datalen_max(); + if (params.datalen_min > datalen_max) + params.datalen_min = datalen_max; + if (params.datalen_max > datalen_max) + params.datalen_max = datalen_max; + continue; + } + if (config::parse_option_intptr(argc, argv, narg, "size-lower", + params.size_lower, + mdbx_limits_dbsize_min(params.pagesize), + mdbx_limits_dbsize_max(params.pagesize))) + continue; + if (config::parse_option_intptr(argc, argv, narg, "size-upper", + params.size_upper, + mdbx_limits_dbsize_min(params.pagesize), + mdbx_limits_dbsize_max(params.pagesize))) + continue; + if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now, + mdbx_limits_dbsize_min(params.pagesize), + mdbx_limits_dbsize_max(params.pagesize))) + continue; + if (config::parse_option( + argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0, + (int)std::min((intptr_t)INT_MAX, + mdbx_limits_dbsize_max(params.pagesize) - + mdbx_limits_dbsize_min(params.pagesize)))) + continue; + if (config::parse_option( + argc, argv, narg, "growth-step", params.growth_step, 0, + (int)std::min((intptr_t)INT_MAX, + mdbx_limits_dbsize_max(params.pagesize) - + mdbx_limits_dbsize_min(params.pagesize)))) + continue; + + if (config::parse_option(argc, argv, narg, "keygen.width", + params.keygen.width, 1, 64)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.mesh", + params.keygen.mesh, 1, 64)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.seed", + params.keygen.seed, config::no_scale)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.split", + params.keygen.split, 1, 64)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.rotate", + params.keygen.rotate, 1, 64)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.offset", + params.keygen.offset, config::binary)) + continue; + if (config::parse_option(argc, argv, narg, "keygen.case", &value)) { + keycase_setup(value, params); + continue; + } + + if (config::parse_option(argc, argv, narg, "repeat", params.nrepeat, + config::no_scale)) + continue; + if (config::parse_option(argc, argv, narg, "threads", params.nthreads, + config::no_scale, 1, 64)) + continue; + if (config::parse_option(argc, argv, narg, "timeout", + global::config::timeout_duration_seconds, + config::duration, 1)) + continue; + if (config::parse_option(argc, argv, narg, "keylen.min", params.keylen_min, + config::no_scale, params.mdbx_keylen_min(), + params.mdbx_keylen_max())) { + if ((params.table_flags & MDBX_INTEGERKEY) || + params.keylen_max < params.keylen_min) + params.keylen_max = params.keylen_min; + continue; + } + if (config::parse_option(argc, argv, narg, "keylen.max", params.keylen_max, + config::no_scale, params.mdbx_keylen_min(), + params.mdbx_keylen_max())) { + if ((params.table_flags & MDBX_INTEGERKEY) || + params.keylen_min > params.keylen_max) + params.keylen_min = params.keylen_max; + continue; + } + if (config::parse_option(argc, argv, narg, "datalen.min", + params.datalen_min, config::no_scale, + params.mdbx_datalen_min(), + params.mdbx_datalen_max())) { + if ((params.table_flags & MDBX_DUPFIXED) || + params.datalen_max < params.datalen_min) + params.datalen_max = params.datalen_min; + continue; + } + if (config::parse_option(argc, argv, narg, "datalen.max", + params.datalen_max, config::no_scale, + params.mdbx_datalen_min(), + params.mdbx_datalen_max())) { + if ((params.table_flags & MDBX_DUPFIXED) || + params.datalen_min > params.datalen_max) + params.datalen_min = params.datalen_max; + continue; + } + if (config::parse_option(argc, argv, narg, "batch.read", params.batch_read, + config::no_scale, 1)) + continue; + if (config::parse_option(argc, argv, narg, "batch.write", + params.batch_write, config::no_scale, 1)) + continue; + if (config::parse_option(argc, argv, narg, "delay", params.delaystart, + config::duration)) + continue; + if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops, + config::decimal)) + continue; + if (config::parse_option(argc, argv, narg, "inject-writefault", + params.inject_writefaultn, config::decimal)) + continue; + if (config::parse_option(argc, argv, narg, "drop", params.drop_table)) + continue; + if (config::parse_option(argc, argv, narg, "ignore-dbfull", + params.ignore_dbfull)) + continue; + if (config::parse_option(argc, argv, narg, "dump-config", + global::config::dump_config)) + continue; + if (config::parse_option(argc, argv, narg, "cleanup-before", + global::config::cleanup_before)) + continue; + if (config::parse_option(argc, argv, narg, "cleanup-after", + global::config::cleanup_after)) + continue; + if (config::parse_option(argc, argv, narg, "max-readers", + params.max_readers, config::no_scale, 1, 255)) + continue; + if (config::parse_option(argc, argv, narg, "max-tables", params.max_tables, + config::no_scale, 1, INT16_MAX)) + continue; + + if (config::parse_option(argc, argv, narg, "no-delay", nullptr)) { + params.delaystart = 0; + continue; + } + if (config::parse_option(argc, argv, narg, "no-wait", nullptr)) { + params.waitfor_nops = 0; + continue; + } + if (config::parse_option(argc, argv, narg, "duration", params.test_duration, + config::duration, 1)) { + params.test_nops = 0; + continue; + } + if (config::parse_option(argc, argv, narg, "nops", params.test_nops, + config::decimal, 1)) { + params.test_duration = 0; + continue; + } + if (config::parse_option(argc, argv, narg, "hill", &value, "auto")) { + configure_actor(last_space_id, ac_hill, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "jitter", nullptr)) { + configure_actor(last_space_id, ac_jitter, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "dead.reader", nullptr)) { + configure_actor(last_space_id, ac_deadread, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "dead.writer", nullptr)) { + configure_actor(last_space_id, ac_deadwrite, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "copy", nullptr)) { + configure_actor(last_space_id, ac_copy, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "append", nullptr)) { + configure_actor(last_space_id, ac_append, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "ttl", nullptr)) { + configure_actor(last_space_id, ac_ttl, value, params); + continue; + } + if (config::parse_option(argc, argv, narg, "failfast", + global::config::failfast)) + continue; + if (config::parse_option(argc, argv, narg, "progress", + global::config::progress_indicator)) + continue; + + if (*argv[narg] != '-') + testcase_setup(argv[narg], params, last_space_id); + else + failure("Unknown option '%s'\n", argv[narg]); + } + + if (global::config::dump_config) + config::dump(); + + //-------------------------------------------------------------------------- + + if (global::actors.empty()) { + log_notice("no testcase(s) configured, exiting"); + return EXIT_SUCCESS; + } + + bool failed = false; + global::start_motonic = chrono::now_motonic(); + global::deadline_motonic.fixedpoint = + (global::config::timeout_duration_seconds == 0) + ? chrono::infinite().fixedpoint + : global::start_motonic.fixedpoint + + chrono::from_seconds(global::config::timeout_duration_seconds) + .fixedpoint; + + if (global::config::cleanup_before) + cleanup(); + + log_trace(">> probe entropy_ticks()"); + entropy_ticks(); + log_trace("<< probe entropy_ticks()"); + + if (global::actors.size() == 1) { + logging::setup("main"); + global::singlemode = true; + if (!test_execute(global::actors.front())) + failed = true; + } else { + logging::setup("overlord"); + + log_trace("=== preparing..."); + log_trace(">> osal_setup"); + osal_setup(global::actors); + log_trace("<< osal_setup"); + + for (auto &a : global::actors) { + mdbx_pid_t pid; + log_trace(">> actor_start"); + int rc = osal_actor_start(a, pid); + log_trace("<< actor_start"); + if (rc) { + log_trace(">> killall_actors: (%s)", "start failed"); + osal_killall_actors(); + log_trace("<< killall_actors"); + failure("Failed to start actor #%u (%s)\n", a.actor_id, + test_strerror(rc)); + } + global::pid2actor[pid] = &a; + } + + log_trace("=== ready to start..."); + atexit(osal_killall_actors); + log_trace(">> wait4barrier"); + osal_wait4barrier(); + log_trace("<< wait4barrier"); + + size_t left = global::actors.size(); + log_trace("=== polling..."); + while (left > 0) { + unsigned timeout_seconds_left = INT_MAX; + chrono::time now_motonic = chrono::now_motonic(); + if (now_motonic.fixedpoint >= global::deadline_motonic.fixedpoint) + timeout_seconds_left = 0; + else { + chrono::time left_motonic; + left_motonic.fixedpoint = + global::deadline_motonic.fixedpoint - now_motonic.fixedpoint; + timeout_seconds_left = left_motonic.seconds(); + } + + mdbx_pid_t pid; + int rc = osal_actor_poll(pid, timeout_seconds_left); + if (rc) + failure("Poll error: %s (%d)\n", test_strerror(rc), rc); + + if (pid) { + actor_status status = osal_actor_info(pid); + actor_config *actor = global::pid2actor.at(pid); + if (!actor) + continue; + + log_info("actor #%u, id %d, pid %u: %s\n", actor->actor_id, + actor->space_id, pid, status2str(status)); + if (status > as_running) { + left -= 1; + if (status != as_successful) { + if (global::config::failfast && !failed) { + log_trace(">> killall_actors: (%s)", "failfast"); + osal_killall_actors(); + log_trace("<< killall_actors"); + } + failed = true; + } + } + } else { + if (timeout_seconds_left == 0) + failure("Timeout\n"); + } + } + log_trace("=== done..."); + } + + log_notice("RESULT: %s\n", failed ? "Failed" : "Successful"); + if (global::config::cleanup_before) { + if (failed) + log_info("skip cleanup"); + else + cleanup(); + } + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/db/libmdbx/test/osal-unix.cc b/contrib/db/libmdbx/test/osal-unix.cc new file mode 100644 index 00000000..0157bace --- /dev/null +++ b/contrib/db/libmdbx/test/osal-unix.cc @@ -0,0 +1,313 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +#include "darwin/pthread_barrier.c" +#endif + +struct shared_t { + pthread_barrier_t barrier; + pthread_mutex_t mutex; + size_t conds_size; + pthread_cond_t conds[1]; +}; + +static shared_t *shared; + +void osal_wait4barrier(void) { + assert(shared != nullptr && shared != MAP_FAILED); + int rc = pthread_barrier_wait(&shared->barrier); + if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { + failure_perror("pthread_barrier_wait(shared)", rc); + } +} + +void osal_setup(const std::vector &actors) { + assert(shared == nullptr); + + pthread_mutexattr_t mutexattr; + int rc = pthread_mutexattr_init(&mutexattr); + if (rc) + failure_perror("pthread_mutexattr_init()", rc); + rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); + if (rc) + failure_perror("pthread_mutexattr_setpshared()", rc); + + pthread_barrierattr_t barrierattr; + rc = pthread_barrierattr_init(&barrierattr); + if (rc) + failure_perror("pthread_barrierattr_init()", rc); + rc = pthread_barrierattr_setpshared(&barrierattr, PTHREAD_PROCESS_SHARED); + if (rc) + failure_perror("pthread_barrierattr_setpshared()", rc); + + pthread_condattr_t condattr; + rc = pthread_condattr_init(&condattr); + if (rc) + failure_perror("pthread_condattr_init()", rc); + rc = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED); + if (rc) + failure_perror("pthread_condattr_setpshared()", rc); + + shared = (shared_t *)mmap( + nullptr, sizeof(shared_t) + actors.size() * sizeof(pthread_cond_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == (void *)shared) + failure_perror("mmap(shared_conds)", errno); + + rc = pthread_mutex_init(&shared->mutex, &mutexattr); + if (rc) + failure_perror("pthread_mutex_init(shared)", rc); + + rc = pthread_barrier_init(&shared->barrier, &barrierattr, actors.size() + 1); + if (rc) + failure_perror("pthread_barrier_init(shared)", rc); + + const size_t n = actors.size() + 1; + for (size_t i = 0; i < n; ++i) { + pthread_cond_t *event = &shared->conds[i]; + rc = pthread_cond_init(event, &condattr); + if (rc) + failure_perror("pthread_cond_init(shared)", rc); + log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i, + event); + } + shared->conds_size = actors.size() + 1; + + pthread_barrierattr_destroy(&barrierattr); + pthread_condattr_destroy(&condattr); + pthread_mutexattr_destroy(&mutexattr); +} + +void osal_broadcast(unsigned id) { + assert(shared != nullptr && shared != MAP_FAILED); + log_trace("osal_broadcast: event %u", id); + if (id >= shared->conds_size) + failure("osal_broadcast: id > limit"); + int rc = pthread_cond_broadcast(shared->conds + id); + if (rc) + failure_perror("sem_post(shared)", rc); +} + +int osal_waitfor(unsigned id) { + assert(shared != nullptr && shared != MAP_FAILED); + + log_trace("osal_waitfor: event %u", id); + if (id >= shared->conds_size) + failure("osal_waitfor: id > limit"); + + int rc = pthread_mutex_lock(&shared->mutex); + if (rc != 0) + failure_perror("pthread_mutex_lock(shared)", rc); + + rc = pthread_cond_wait(shared->conds + id, &shared->mutex); + if (rc && rc != EINTR) + failure_perror("pthread_cond_wait(shared)", rc); + + rc = pthread_mutex_unlock(&shared->mutex); + if (rc != 0) + failure_perror("pthread_mutex_unlock(shared)", rc); + + return (rc == 0) ? true : false; +} + +//----------------------------------------------------------------------------- + +const std::string +actor_config::osal_serialize(simple_checksum &checksum) const { + (void)checksum; + /* not used in workload, but just for testing */ + return "unix.fork"; +} + +bool actor_config::osal_deserialize(const char *str, const char *end, + simple_checksum &checksum) { + (void)checksum; + /* not used in workload, but just for testing */ + return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end; +} + +//----------------------------------------------------------------------------- + +static std::unordered_map childs; + +static void handler_SIGCHLD(int unused) { (void)unused; } + +mdbx_pid_t osal_getpid(void) { return getpid(); } + +int osal_delay(unsigned seconds) { return sleep(seconds) ? errno : 0; } + +int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { + if (childs.empty()) + signal(SIGCHLD, handler_SIGCHLD); + + pid = fork(); + + if (pid == 0) { + const bool result = test_execute(config); + exit(result ? EXIT_SUCCESS : EXIT_FAILURE); + } + + if (pid < 0) + return errno; + + log_trace("osal_actor_start: fork pid %i for %u", pid, config.actor_id); + childs[pid] = as_running; + return 0; +} + +actor_status osal_actor_info(const mdbx_pid_t pid) { return childs.at(pid); } + +void osal_killall_actors(void) { + for (auto &pair : childs) { + kill(pair.first, SIGKILL); + pair.second = as_killed; + } +} + +int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { + struct timespec ts; + ts.tv_nsec = 0; + ts.tv_sec = (timeout > INT_MAX) ? INT_MAX : timeout; +retry: + int status, options = WNOHANG; +#ifdef WUNTRACED + options |= WUNTRACED; +#endif +#ifdef WCONTINUED + options |= WCONTINUED; +#endif + pid = waitpid(0, &status, options); + + if (pid > 0) { + if (WIFEXITED(status)) + childs[pid] = + (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed; + else if (WCOREDUMP(status)) + childs[pid] = as_coredump; + else if (WIFSIGNALED(status)) + childs[pid] = as_killed; + else if (WIFSTOPPED(status)) + childs[pid] = as_debuging; + else if (WIFCONTINUED(status)) + childs[pid] = as_running; + else { + assert(false); + } + return 0; + } + + if (pid == 0) { + /* child still running */ + if (ts.tv_sec == 0 && ts.tv_nsec == 0) + ts.tv_nsec = 1; + if (nanosleep(&ts, &ts) == 0) { + /* timeout and no signal from child */ + pid = 0; + return 0; + } + if (errno == EINTR) + goto retry; + } + + switch (errno) { + case EINTR: + pid = 0; + return 0; + + case ECHILD: + default: + pid = 0; + return errno; + } +} + +void osal_yield(void) { + if (sched_yield()) + failure_perror("sched_yield()", errno); +} + +void osal_udelay(unsigned us) { + chrono::time until, now = chrono::now_motonic(); + until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; + struct timespec ts; + + static unsigned threshold_us; + if (threshold_us == 0) { + if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) { + int rc = errno; + failure_perror("clock_getres(CLOCK_PROCESS_CPUTIME_ID)", rc); + } + chrono::time threshold = chrono::from_timespec(ts); + assert(threshold.seconds() == 0); + + threshold_us = chrono::fractional2us(threshold.fractional); + if (threshold_us < 1000) + threshold_us = 1000; + } + + ts.tv_sec = ts.tv_nsec = 0; + if (us > threshold_us) { + ts.tv_sec = us / 1000000u; + ts.tv_nsec = (us % 1000000u) * 1000u; + } + + do { + if (us > threshold_us) { + if (nanosleep(&ts, &ts)) { + int rc = errno; + /* if (rc == EINTR) { ... } ? */ + failure_perror("usleep()", rc); + } + us = ts.tv_sec * 1000000u + ts.tv_nsec / 1000u; + } + cpu_relax(); + + now = chrono::now_motonic(); + } while (until.fixedpoint > now.fixedpoint); +} + +bool osal_istty(int fd) { return isatty(fd) == 1; } + +std::string osal_tempdir(void) { + const char *tempdir = getenv("TMPDIR"); + if (!tempdir) + tempdir = getenv("TMP"); + if (!tempdir) + tempdir = getenv("TEMPDIR"); + if (!tempdir) + tempdir = getenv("TEMP"); + if (tempdir) { + std::string dir(tempdir); + if (!dir.empty() && dir.at(dir.length() - 1) != '/') + dir.append("/"); + return dir; + } + if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0) + return "/dev/shm/"; + return ""; +} + +int osal_removefile(const std::string &pathname) { + return unlink(pathname.c_str()) ? errno : MDBX_SUCCESS; +} diff --git a/contrib/db/libmdbx/test/osal-windows.cc b/contrib/db/libmdbx/test/osal-windows.cc new file mode 100644 index 00000000..975d8268 --- /dev/null +++ b/contrib/db/libmdbx/test/osal-windows.cc @@ -0,0 +1,419 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +static std::unordered_map events; +static HANDLE hBarrierSemaphore, hBarrierEvent; + +static int waitstatus2errcode(DWORD result) { + switch (result) { + case WAIT_OBJECT_0: + return MDBX_SUCCESS; + case WAIT_FAILED: + return GetLastError(); + case WAIT_ABANDONED: + return ERROR_ABANDONED_WAIT_0; + case WAIT_IO_COMPLETION: + return ERROR_USER_APC; + case WAIT_TIMEOUT: + return ERROR_TIMEOUT; + default: + return ERROR_UNHANDLED_ERROR; + } +} + +void osal_wait4barrier(void) { + DWORD rc = WaitForSingleObject(hBarrierSemaphore, 0); + switch (rc) { + default: + failure_perror("WaitForSingleObject(BarrierSemaphore)", + waitstatus2errcode(rc)); + case WAIT_OBJECT_0: + rc = WaitForSingleObject(hBarrierEvent, INFINITE); + if (rc != WAIT_OBJECT_0) + failure_perror("WaitForSingleObject(BarrierEvent)", + waitstatus2errcode(rc)); + break; + case WAIT_TIMEOUT: + if (!SetEvent(hBarrierEvent)) + failure_perror("SetEvent(BarrierEvent)", GetLastError()); + break; + } +} + +static HANDLE make_inheritable(HANDLE hHandle) { + assert(hHandle != NULL && hHandle != INVALID_HANDLE_VALUE); + if (!DuplicateHandle(GetCurrentProcess(), hHandle, GetCurrentProcess(), + &hHandle, 0, TRUE, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) + failure_perror("DuplicateHandle()", GetLastError()); + return hHandle; +} + +void osal_setup(const std::vector &actors) { + assert(events.empty()); + const size_t n = actors.size() + 1; + events.reserve(n); + + for (unsigned i = 0; i < n; ++i) { + HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!hEvent) + failure_perror("CreateEvent()", GetLastError()); + hEvent = make_inheritable(hEvent); + log_trace("osal_setup: event %" PRIuPTR " -> %p", i, hEvent); + events[i] = hEvent; + } + + hBarrierSemaphore = CreateSemaphore(NULL, 0, (LONG)actors.size(), NULL); + if (!hBarrierSemaphore) + failure_perror("CreateSemaphore(BarrierSemaphore)", GetLastError()); + hBarrierSemaphore = make_inheritable(hBarrierSemaphore); + + hBarrierEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!hBarrierEvent) + failure_perror("CreateEvent(BarrierEvent)", GetLastError()); + hBarrierEvent = make_inheritable(hBarrierEvent); +} + +void osal_broadcast(unsigned id) { + log_trace("osal_broadcast: event %u", id); + if (!SetEvent(events.at(id))) + failure_perror("SetEvent()", GetLastError()); +} + +int osal_waitfor(unsigned id) { + log_trace("osal_waitfor: event %u", id); + DWORD rc = WaitForSingleObject(events.at(id), INFINITE); + return waitstatus2errcode(rc); +} + +mdbx_pid_t osal_getpid(void) { return GetCurrentProcessId(); } + +int osal_delay(unsigned seconds) { + Sleep(seconds * 1000u); + return 0; +} + +//----------------------------------------------------------------------------- + +const std::string +actor_config::osal_serialize(simple_checksum &checksum) const { + checksum.push(hBarrierSemaphore); + checksum.push(hBarrierEvent); + + HANDLE hWait = INVALID_HANDLE_VALUE; + if (wait4id) { + hWait = events.at(wait4id); + checksum.push(hWait); + } + + HANDLE hSignal = INVALID_HANDLE_VALUE; + if (wanna_event4signalling()) { + hSignal = events.at(actor_id); + checksum.push(hSignal); + } + + return format("%p.%p.%p.%p", hBarrierSemaphore, hBarrierEvent, hWait, + hSignal); +} + +bool actor_config::osal_deserialize(const char *str, const char *end, + simple_checksum &checksum) { + + std::string copy(str, end - str); + TRACE(">> osal_deserialize(%s)\n", copy.c_str()); + + assert(hBarrierSemaphore == 0); + assert(hBarrierEvent == 0); + assert(events.empty()); + + HANDLE hWait, hSignal; + if (sscanf_s(copy.c_str(), "%p.%p.%p.%p", &hBarrierSemaphore, &hBarrierEvent, + &hWait, &hSignal) != 4) { + TRACE("<< osal_deserialize: failed\n"); + return false; + } + + checksum.push(hBarrierSemaphore); + checksum.push(hBarrierEvent); + + if (wait4id) { + checksum.push(hWait); + events[wait4id] = hWait; + } + + if (wanna_event4signalling()) { + checksum.push(hSignal); + events[actor_id] = hSignal; + } + + TRACE("<< osal_deserialize: OK\n"); + return true; +} + +//----------------------------------------------------------------------------- + +typedef std::pair child; +static std::unordered_map childs; + +static void ArgvQuote(std::string &CommandLine, const std::string &Argument, + bool Force = false) + +/*++ + +https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + +Routine Description: + + This routine appends the given argument to a command line such + that CommandLineToArgvW will return the argument string unchanged. + Arguments in a command line should be separated by spaces; this + function does not add these spaces. + +Arguments: + + Argument - Supplies the argument to encode. + + CommandLine - Supplies the command line to which we append the encoded +argument string. + + Force - Supplies an indication of whether we should quote + the argument even if it does not contain any characters that would + ordinarily require quoting. + +Return Value: + + None. + +Environment: + + Arbitrary. + +--*/ + +{ + // + // Unless we're told otherwise, don't quote unless we actually + // need to do so --- hopefully avoid problems if programs won't + // parse quotes properly + // + + if (Force == false && Argument.empty() == false && + Argument.find_first_of(" \t\n\v\"") == Argument.npos) { + CommandLine.append(Argument); + } else { + CommandLine.push_back('"'); + + for (auto It = Argument.begin();; ++It) { + unsigned NumberBackslashes = 0; + + while (It != Argument.end() && *It == '\\') { + ++It; + ++NumberBackslashes; + } + + if (It == Argument.end()) { + // + // Escape all backslashes, but let the terminating + // double quotation mark we add below be interpreted + // as a metacharacter. + // + CommandLine.append(NumberBackslashes * 2, '\\'); + break; + } else if (*It == L'"') { + // + // Escape all backslashes and the following + // double quotation mark. + // + CommandLine.append(NumberBackslashes * 2 + 1, '\\'); + CommandLine.push_back(*It); + } else { + // + // Backslashes aren't special here. + // + CommandLine.append(NumberBackslashes, '\\'); + CommandLine.push_back(*It); + } + } + + CommandLine.push_back('"'); + } +} + +int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { + if (childs.size() == MAXIMUM_WAIT_OBJECTS) + failure("Could't manage more that %u actors on Windows\n", + MAXIMUM_WAIT_OBJECTS); + + _flushall(); + + STARTUPINFOA StartupInfo; + GetStartupInfoA(&StartupInfo); + + char exename[_MAX_PATH + 1]; + DWORD exename_size = sizeof(exename); + if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, exename, + &exename_size)) + failure_perror("QueryFullProcessImageName()", GetLastError()); + + if (exename[1] != ':') { + exename_size = GetModuleFileName(NULL, exename, sizeof(exename)); + if (exename_size >= sizeof(exename)) + return ERROR_BAD_LENGTH; + } + + std::string cmdline = "$ "; + ArgvQuote(cmdline, thunk_param(config)); + + if (cmdline.size() >= 32767) + return ERROR_BAD_LENGTH; + + PROCESS_INFORMATION ProcessInformation; + if (!CreateProcessA(exename, const_cast(cmdline.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles. + NORMAL_PRIORITY_CLASS | INHERIT_PARENT_AFFINITY, + NULL, // Inherit the parent's environment. + NULL, // Inherit the parent's current directory. + &StartupInfo, &ProcessInformation)) + failure_perror(exename, GetLastError()); + + CloseHandle(ProcessInformation.hThread); + pid = ProcessInformation.dwProcessId; + childs[pid] = std::make_pair(ProcessInformation.hProcess, as_running); + return 0; +} + +actor_status osal_actor_info(const mdbx_pid_t pid) { + actor_status status = childs.at(pid).second; + if (status > as_running) + return status; + + DWORD ExitCode; + if (!GetExitCodeProcess(childs.at(pid).first, &ExitCode)) + failure_perror("GetExitCodeProcess()", GetLastError()); + + switch (ExitCode) { + case STILL_ACTIVE: + return as_running; + case EXIT_SUCCESS: + status = as_successful; + break; + case EXCEPTION_BREAKPOINT: + case EXCEPTION_SINGLE_STEP: + status = as_debuging; + break; + case STATUS_CONTROL_C_EXIT: + status = as_killed; + break; + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + case EXCEPTION_DATATYPE_MISALIGNMENT: + case EXCEPTION_STACK_OVERFLOW: + case EXCEPTION_INVALID_DISPOSITION: + case EXCEPTION_ILLEGAL_INSTRUCTION: + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + status = as_coredump; + break; + default: + status = as_failed; + break; + } + + childs.at(pid).second = status; + return status; +} + +void osal_killall_actors(void) { + for (auto &pair : childs) + TerminateProcess(pair.second.first, STATUS_CONTROL_C_EXIT); +} + +int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { + std::vector handles; + handles.reserve(childs.size()); + for (const auto &pair : childs) + if (pair.second.second <= as_running) + handles.push_back(pair.second.first); + + DWORD rc = + MsgWaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0], + (timeout > 60) ? 60 * 1000 : timeout * 1000, + QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0); + + if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + handles.size()) { + pid = 0; + for (const auto &pair : childs) + if (pair.second.first == handles[rc - WAIT_OBJECT_0]) { + pid = pair.first; + break; + } + return 0; + } + + if (rc == WAIT_TIMEOUT) { + pid = 0; + return 0; + } + + return waitstatus2errcode(rc); +} + +void osal_yield(void) { SwitchToThread(); } + +void osal_udelay(unsigned us) { + chrono::time until, now = chrono::now_motonic(); + until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; + + static unsigned threshold_us; + if (threshold_us == 0) { +#if 1 + unsigned timeslice_ms = 1; + while (timeBeginPeriod(timeslice_ms) == TIMERR_NOCANDO) + ++timeslice_ms; + threshold_us = timeslice_ms * 1500u; +#else + ULONGLONG InterruptTimePrecise_100ns; + QueryInterruptTimePrecise(&InterruptTimePrecise_100ns); + threshold_us = InterruptTimePrecise_100ns / 5; +#endif + assert(threshold_us > 0); + } + + do { + if (us > threshold_us && us > 1000) { + DWORD rc = SleepEx(us / 1000, TRUE); + if (rc) + failure_perror("SleepEx()", waitstatus2errcode(rc)); + us = 0; + } + + YieldProcessor(); + now = chrono::now_motonic(); + } while (now.fixedpoint < until.fixedpoint); +} + +bool osal_istty(int fd) { return _isatty(fd) != 0; } + +std::string osal_tempdir(void) { + char buf[MAX_PATH + 1]; + DWORD len = GetTempPathA(sizeof(buf), buf); + return std::string(buf, len); +} + +int osal_removefile(const std::string &pathname) { + return DeleteFileA(pathname.c_str()) ? MDBX_SUCCESS : GetLastError(); +} diff --git a/contrib/db/libmdbx/test/osal.h b/contrib/db/libmdbx/test/osal.h new file mode 100644 index 00000000..5acf7ad0 --- /dev/null +++ b/contrib/db/libmdbx/test/osal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" + +void osal_setup(const std::vector &actors); +void osal_broadcast(unsigned id); +int osal_waitfor(unsigned id); + +int osal_actor_start(const actor_config &config, mdbx_pid_t &pid); +actor_status osal_actor_info(const mdbx_pid_t pid); +void osal_killall_actors(void); +int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout); +void osal_wait4barrier(void); + +mdbx_pid_t osal_getpid(void); +int osal_delay(unsigned seconds); +void osal_udelay(unsigned us); +void osal_yield(void); +bool osal_istty(int fd); +std::string osal_tempdir(void); +int osal_removefile(const std::string &pathname); + +#ifdef _MSC_VER +#ifndef STDIN_FILENO +#define STDIN_FILENO _fileno(stdin) +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO _fileno(stdout) +#endif +#ifndef STDERR_FILENO +#define STDERR_FILENO _fileno(stderr) +#endif +#endif /* _MSC_VER */ diff --git a/contrib/db/libmdbx/test/pcrf/CMakeLists.txt b/contrib/db/libmdbx/test/pcrf/CMakeLists.txt new file mode 100644 index 00000000..399c33f8 --- /dev/null +++ b/contrib/db/libmdbx/test/pcrf/CMakeLists.txt @@ -0,0 +1,7 @@ +set(TARGET pcrf_test) +project(${TARGET}) + +add_executable(${TARGET} pcrf_test.c) + +target_link_libraries(${TARGET} mdbx) + diff --git a/contrib/db/libmdbx/test/pcrf/README.md b/contrib/db/libmdbx/test/pcrf/README.md new file mode 100644 index 00000000..b2c9b5ce --- /dev/null +++ b/contrib/db/libmdbx/test/pcrf/README.md @@ -0,0 +1,2 @@ +PCRF Session DB emulation test + diff --git a/contrib/db/libmdbx/test/pcrf/pcrf_test.c b/contrib/db/libmdbx/test/pcrf/pcrf_test.c new file mode 100644 index 00000000..213c8b1d --- /dev/null +++ b/contrib/db/libmdbx/test/pcrf/pcrf_test.c @@ -0,0 +1,404 @@ +/* + * Copyright 2016-2017 Leonid Yuriev . + * Copyright 2015 Vladimir Romanov + * , Yota Lab. + * + * This file is part of libmdbx. + * + * ReOpenMDBX is free software; you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * ReOpenMDBX is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "mdbx.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define IP_PRINTF_ARG_HOST(addr) \ + (int)((addr) >> 24), (int)((addr) >> 16 & 0xff), (int)((addr) >> 8 & 0xff), \ + (int)((addr)&0xff) + +char opt_db_path[PATH_MAX] = "/root/lmdbx_bench2"; +static MDBX_env *env; +#define REC_COUNT 10240000 +int64_t ids[REC_COUNT * 10]; +int32_t ids_count = 0; + +int64_t mdbx_add_count = 0; +int64_t mdbx_del_count = 0; +uint64_t mdbx_add_time = 0; +uint64_t mdbx_del_time = 0; +int64_t obj_id = 0; +int64_t mdbx_data_size = 0; +int64_t mdbx_key_size = 0; + +typedef struct { + char session_id1[100]; + char session_id2[100]; + char ip[20]; + uint8_t fill[100]; +} session_data_t; + +typedef struct { + int64_t obj_id; + int8_t event_type; +} __attribute__((__packed__)) event_data_t; + +static void add_id_to_pool(int64_t id) { + ids[ids_count] = id; + ids_count++; +} + +static inline int64_t getClockUs(void) { + struct timespec val; +#ifdef CYGWIN + clock_gettime(CLOCK_REALTIME, &val); +#else + clock_gettime(CLOCK_MONOTONIC, &val); +#endif + return val.tv_sec * ((int64_t)1000000) + val.tv_nsec / 1000; +} + +static int64_t get_id_from_pool() { + if (ids_count == 0) { + return -1; + } + int32_t index = rand() % ids_count; + int64_t id = ids[index]; + ids[index] = ids[ids_count - 1]; + ids_count--; + return id; +} + +#define MDBX_CHECK(x) \ + do { \ + const int rc = (x); \ + if (rc != MDBX_SUCCESS) { \ + printf("Error [%d] %s in %s at %s:%d\n", rc, mdbx_strerror(rc), #x, \ + __FILE__, __LINE__); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) + +static void db_connect() { + MDBX_dbi dbi_session; + MDBX_dbi dbi_session_id; + MDBX_dbi dbi_event; + MDBX_dbi dbi_ip; + + MDBX_CHECK(mdbx_env_create(&env)); + MDBX_CHECK( + mdbx_env_set_mapsize(env, REC_COUNT * sizeof(session_data_t) * 10)); + MDBX_CHECK(mdbx_env_set_maxdbs(env, 30)); + MDBX_CHECK(mdbx_env_open(env, opt_db_path, + MDBX_CREATE | MDBX_WRITEMAP | MDBX_MAPASYNC | + MDBX_NOSYNC | MDBX_LIFORECLAIM, + 0664)); + MDBX_txn *txn; + + // transaction init + MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); + // open database in read-write mode + MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); + MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); + MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); + MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); + // transaction commit + MDBX_CHECK(mdbx_txn_commit(txn)); + printf("Connection open\n"); +} + +static void create_record(int64_t record_id) { + MDBX_dbi dbi_session; + MDBX_dbi dbi_session_id; + MDBX_dbi dbi_event; + MDBX_dbi dbi_ip; + event_data_t event; + MDBX_txn *txn; + session_data_t data; + // transaction init + snprintf(data.session_id1, sizeof(data.session_id1), + "prefix%02ld_%02ld.fill.fill.fill.fill.fill.fill;%ld", + record_id % 3 + 1, record_id % 9 + 1, record_id); + snprintf(data.session_id2, sizeof(data.session_id2), + "dprefix%ld;%ld.fill.fill.;suffix", record_id, + record_id % 1000000000 + 99999); + snprintf(data.ip, sizeof(data.ip), "%d.%d.%d.%d", + IP_PRINTF_ARG_HOST(record_id & 0xFFFFFFFF)); + event.obj_id = record_id; + event.event_type = 1; + + MDBX_val _session_id1_rec = {data.session_id1, strlen(data.session_id1)}; + MDBX_val _session_id2_rec = {data.session_id2, strlen(data.session_id2)}; + MDBX_val _ip_rec = {data.ip, strlen(data.ip)}; + MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)}; + MDBX_val _data_rec = {&data, offsetof(session_data_t, fill) + + (rand() % sizeof(data.fill))}; + MDBX_val _event_rec = {&event, sizeof(event)}; + + uint64_t start = getClockUs(); + MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); + MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); + MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); + MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); + MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); + MDBX_CHECK(mdbx_put(txn, dbi_session, &_obj_id_rec, &_data_rec, + MDBX_NOOVERWRITE | MDBX_NODUPDATA)); + MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id1_rec, &_obj_id_rec, + MDBX_NOOVERWRITE | MDBX_NODUPDATA)); + MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id2_rec, &_obj_id_rec, + MDBX_NOOVERWRITE | MDBX_NODUPDATA)); + MDBX_CHECK(mdbx_put(txn, dbi_ip, &_ip_rec, &_obj_id_rec, 0)); + MDBX_CHECK(mdbx_put(txn, dbi_event, &_event_rec, &_obj_id_rec, 0)); + MDBX_CHECK(mdbx_txn_commit(txn)); + + mdbx_data_size += (_data_rec.iov_len + _obj_id_rec.iov_len * 4); + mdbx_key_size += + (_obj_id_rec.iov_len + _session_id1_rec.iov_len + + _session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len); + + // transaction commit + mdbx_add_count++; + mdbx_add_time += (getClockUs() - start); +} + +static void delete_record(int64_t record_id) { + MDBX_dbi dbi_session; + MDBX_dbi dbi_session_id; + MDBX_dbi dbi_event; + MDBX_dbi dbi_ip; + event_data_t event; + MDBX_txn *txn; + + // transaction init + uint64_t start = getClockUs(); + MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); + // open database in read-write mode + MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); + MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id)); + MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event)); + MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip)); + // put data + MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)}; + MDBX_val _data_rec; + // get data + MDBX_CHECK(mdbx_get(txn, dbi_session, &_obj_id_rec, &_data_rec)); + session_data_t *data = (session_data_t *)_data_rec.iov_base; + + MDBX_val _session_id1_rec = {data->session_id1, strlen(data->session_id1)}; + MDBX_val _session_id2_rec = {data->session_id2, strlen(data->session_id2)}; + MDBX_val _ip_rec = {data->ip, strlen(data->ip)}; + MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id1_rec, NULL)); + MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id2_rec, NULL)); + MDBX_CHECK(mdbx_del(txn, dbi_ip, &_ip_rec, NULL)); + event.obj_id = record_id; + event.event_type = 1; + MDBX_val _event_rec = {&event, sizeof(event)}; + MDBX_CHECK(mdbx_del(txn, dbi_event, &_event_rec, NULL)); + MDBX_CHECK(mdbx_del(txn, dbi_session, &_obj_id_rec, NULL)); + + mdbx_data_size -= (_data_rec.iov_len + _obj_id_rec.iov_len * 4); + mdbx_key_size -= + (_obj_id_rec.iov_len + _session_id1_rec.iov_len + + _session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len); + + // transaction commit + MDBX_CHECK(mdbx_txn_commit(txn)); + mdbx_del_count++; + mdbx_del_time += (getClockUs() - start); +} + +static void db_disconnect() { + mdbx_env_close(env); + printf("Connection closed\n"); +} + +static void get_db_stat(const char *db, int64_t *ms_branch_pages, + int64_t *ms_leaf_pages) { + MDBX_txn *txn; + MDBX_stat stat; + MDBX_dbi dbi; + + MDBX_CHECK(mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn)); + MDBX_CHECK(mdbx_dbi_open(txn, db, MDBX_CREATE, &dbi)); + MDBX_CHECK(mdbx_dbi_stat(txn, dbi, &stat, sizeof(stat))); + mdbx_txn_abort(txn); + printf("%15s | %15ld | %5u | %10ld | %10ld | %11ld |\n", db, + stat.ms_branch_pages, stat.ms_depth, stat.ms_entries, + stat.ms_leaf_pages, stat.ms_overflow_pages); + (*ms_branch_pages) += stat.ms_branch_pages; + (*ms_leaf_pages) += stat.ms_leaf_pages; +} + +static void periodic_stat(void) { + int64_t ms_branch_pages = 0; + int64_t ms_leaf_pages = 0; + MDBX_stat mst; + MDBX_envinfo mei; + MDBX_CHECK(mdbx_env_stat(env, &mst, sizeof(mst))); + MDBX_CHECK(mdbx_env_info(env, &mei, sizeof(mei))); + printf("Environment Info\n"); + printf(" Pagesize: %u\n", mst.ms_psize); + if (mei.mi_geo.lower != mei.mi_geo.upper) { + printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64 + "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64 + "/-%" PRIu64 ")\n", + mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow, + mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize, + mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize, + mei.mi_geo.shrink / mst.ms_psize); + printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", + mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); + } else { + printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", + mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize); + } + printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n", + mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize); + printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1); + printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid); + printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n", + mei.mi_latter_reader_txnid, + mei.mi_latter_reader_txnid - mei.mi_recent_txnid); + printf(" Max readers: %u\n", mei.mi_maxreaders); + printf(" Number of readers used: %u\n", mei.mi_numreaders); + + printf(" Name | ms_branch_pages | depth | entries | leaf_pages " + "| overf_pages |\n"); + get_db_stat("session", &ms_branch_pages, &ms_leaf_pages); + get_db_stat("session_id", &ms_branch_pages, &ms_leaf_pages); + get_db_stat("event", &ms_branch_pages, &ms_leaf_pages); + get_db_stat("ip", &ms_branch_pages, &ms_leaf_pages); + printf("%15s | %15ld | %5s | %10s | %10ld | %11s |\n", "", ms_branch_pages, + "", "", ms_leaf_pages, ""); + + static int64_t prev_add_count; + static int64_t prev_del_count; + static uint64_t prev_add_time; + static uint64_t prev_del_time; + static int64_t t = -1; + if (t > 0) { + int64_t delta = (getClockUs() - t); + printf( + "CPS: add %ld, delete %ld, items processed - %ldK data=%ldK key=%ldK\n", + (mdbx_add_count - prev_add_count) * 1000000 / delta, + (mdbx_del_count - prev_del_count) * 1000000 / delta, obj_id / 1024, + mdbx_data_size / 1024, mdbx_key_size / 1024); + printf("usage data=%ld%%", ((mdbx_data_size + mdbx_key_size) * 100) / + ((ms_leaf_pages + ms_branch_pages) * 4096)); + if (prev_add_time != mdbx_add_time) { + printf(" Add : %ld c/s", (mdbx_add_count - prev_add_count) * 1000000 / + (mdbx_add_time - prev_add_time)); + } + if (prev_del_time != mdbx_del_time) { + printf(" Del : %ld c/s", (mdbx_del_count - prev_del_count) * 1000000 / + (mdbx_del_time - prev_del_time)); + } + if (mdbx_add_time) { + printf(" tAdd : %ld c/s", mdbx_add_count * 1000000 / mdbx_add_time); + } + if (mdbx_del_time) { + printf(" tDel : %ld c/s", mdbx_del_count * 1000000 / mdbx_del_time); + } + puts(""); + } + t = getClockUs(); + prev_add_count = mdbx_add_count; + prev_del_count = mdbx_del_count; + prev_add_time = mdbx_add_time; + prev_del_time = mdbx_del_time; +} + +// static void periodic_add_rec() { +// for (int i = 0; i < 10240; i++) { +// if (ids_count <= REC_COUNT) { +// int64_t id = obj_id++; +// create_record(id); +// add_id_to_pool(id); +// } +// if (ids_count > REC_COUNT) { +// int64_t id = get_id_from_pool(); +// delete_record(id); +// } +// } +// periodic_stat(); +//} + +int main(int argc, char **argv) { + (void)argc; + (void)argv; + + char filename[PATH_MAX]; + int i; + + mkdir(opt_db_path, 0775); + + strcpy(filename, opt_db_path); + strcat(filename, "/mdbx.dat"); + remove(filename); + + strcpy(filename, opt_db_path); + strcat(filename, "/mdbx.lck"); + remove(filename); + + puts("Open DB..."); + db_connect(); + puts("Create data..."); + int64_t t = getClockUs(); + for (i = 0; i < REC_COUNT; i++) { + int64_t id = obj_id++; + create_record(id); + add_id_to_pool(id); + if (i % 1000 == 0) { + int64_t now = getClockUs(); + if ((now - t) > 1000000L) { + periodic_stat(); + t = now; + } + } + } + periodic_stat(); + while (1) { + int i; + for (i = 0; i < 1000; i++) { + int64_t id = obj_id++; + create_record(id); + add_id_to_pool(id); + id = get_id_from_pool(); + delete_record(id); + } + // for (i = 0; i < 50; i++) { + // int64_t id = obj_id++; + // create_record(id); + // add_id_to_pool(id); + // } + // int64_t id = obj_id++; + // create_record(id); + // add_id_to_pool(id); + int64_t now = getClockUs(); + if ((now - t) > 10000000L) { + periodic_stat(); + t = now; + } + } + db_disconnect(); + return 0; +} diff --git a/contrib/db/libmdbx/test/test.cc b/contrib/db/libmdbx/test/test.cc new file mode 100644 index 00000000..e9e925e9 --- /dev/null +++ b/contrib/db/libmdbx/test/test.cc @@ -0,0 +1,601 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" + +const char *testcase2str(const actor_testcase testcase) { + switch (testcase) { + default: + assert(false); + return "?!"; + case ac_none: + return "none"; + case ac_hill: + return "hill"; + case ac_deadread: + return "deadread"; + case ac_deadwrite: + return "deadwrite"; + case ac_jitter: + return "jitter"; + case ac_try: + return "try"; + case ac_copy: + return "copy"; + case ac_append: + return "append"; + case ac_ttl: + return "ttl"; + } +} + +const char *status2str(actor_status status) { + switch (status) { + default: + assert(false); + return "?!"; + case as_debuging: + return "debuging"; + case as_running: + return "running"; + case as_successful: + return "successful"; + case as_killed: + return "killed"; + case as_failed: + return "failed"; + case as_coredump: + return "coredump"; + } +} + +const char *keygencase2str(const keygen_case keycase) { + switch (keycase) { + default: + assert(false); + return "?!"; + case kc_random: + return "random"; + case kc_dashes: + return "dashes"; + case kc_custom: + return "custom"; + } +} + +//----------------------------------------------------------------------------- + +int testcase::oom_callback(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn, + unsigned gap, int retry) { + + testcase *self = (testcase *)mdbx_env_get_userctx(env); + + if (retry == 0) + log_notice("oom_callback: waitfor pid %u, thread %" PRIuPTR + ", txn #%" PRIu64 ", gap %d", + pid, (size_t)tid, txn, gap); + + if (self->should_continue(true)) { + osal_yield(); + if (retry > 0) + osal_udelay(retry * 100); + return 0 /* always retry */; + } + + return -1; +} + +void testcase::db_prepare() { + log_trace(">> db_prepare"); + assert(!db_guard); + + MDBX_env *env = nullptr; + int rc = mdbx_env_create(&env); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_create()", rc); + + assert(env != nullptr); + db_guard.reset(env); + + rc = mdbx_env_set_userctx(env, this); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_set_userctx()", rc); + + rc = mdbx_env_set_maxreaders(env, config.params.max_readers); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_set_maxreaders()", rc); + + rc = mdbx_env_set_maxdbs(env, config.params.max_tables); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_set_maxdbs()", rc); + + rc = mdbx_env_set_oomfunc(env, testcase::oom_callback); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_set_oomfunc()", rc); + + rc = mdbx_env_set_geometry( + env, config.params.size_lower, config.params.size_now, + config.params.size_upper, config.params.growth_step, + config.params.shrink_threshold, config.params.pagesize); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_set_mapsize()", rc); + + log_trace("<< db_prepare"); +} + +void testcase::db_open() { + log_trace(">> db_open"); + + if (!db_guard) + db_prepare(); + + jitter_delay(true); + int rc = mdbx_env_open(db_guard.get(), config.params.pathname_db.c_str(), + (unsigned)config.params.mode_flags, 0640); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_env_open()", rc); + + log_trace("<< db_open"); +} + +void testcase::db_close() { + log_trace(">> db_close"); + cursor_guard.reset(); + txn_guard.reset(); + db_guard.reset(); + log_trace("<< db_close"); +} + +void testcase::txn_begin(bool readonly, unsigned flags) { + assert((flags & MDBX_RDONLY) == 0); + log_trace(">> txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", + flags); + assert(!txn_guard); + + MDBX_txn *txn = nullptr; + int rc = mdbx_txn_begin(db_guard.get(), nullptr, + readonly ? flags | MDBX_RDONLY : flags, &txn); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_txn_begin()", rc); + txn_guard.reset(txn); + + log_trace("<< txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", + flags); +} + +int testcase::breakable_commit() { + int rc = MDBX_SUCCESS; + log_trace(">> txn_commit"); + assert(txn_guard); + + MDBX_txn *txn = txn_guard.release(); + txn_inject_writefault(txn); + int err = mdbx_txn_commit(txn); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + rc = err; + err = mdbx_txn_abort(txn); + if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH)) + failure_perror("mdbx_txn_abort()", err); + } else + failure_perror("mdbx_txn_commit()", err); + } + + log_trace("<< txn_commit: %s", rc ? "failed" : "Ok"); + return rc; +} + +void testcase::txn_end(bool abort) { + log_trace(">> txn_end(%s)", abort ? "abort" : "commit"); + assert(txn_guard); + + MDBX_txn *txn = txn_guard.release(); + if (abort) { + int err = mdbx_txn_abort(txn); + if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH)) + failure_perror("mdbx_txn_abort()", err); + } else { + txn_inject_writefault(txn); + int err = mdbx_txn_commit(txn); + if (unlikely(err != MDBX_SUCCESS)) + failure_perror("mdbx_txn_commit()", err); + } + + log_trace("<< txn_end(%s)", abort ? "abort" : "commit"); +} + +void testcase::cursor_open(unsigned dbi) { + log_trace(">> cursor_open(%u)", dbi); + assert(!cursor_guard); + assert(txn_guard); + + MDBX_cursor *cursor = nullptr; + int rc = mdbx_cursor_open(txn_guard.get(), dbi, &cursor); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_cursor_open()", rc); + cursor_guard.reset(cursor); + + log_trace("<< cursor_open(%u)", dbi); +} + +void testcase::cursor_close() { + log_trace(">> cursor_close()"); + assert(cursor_guard); + MDBX_cursor *cursor = cursor_guard.release(); + mdbx_cursor_close(cursor); + log_trace("<< cursor_close()"); +} + +int testcase::breakable_restart() { + int rc = MDBX_SUCCESS; + if (txn_guard) + rc = breakable_commit(); + if (cursor_guard) + cursor_close(); + txn_begin(false, 0); + return rc; +} + +void testcase::txn_restart(bool abort, bool readonly, unsigned flags) { + if (txn_guard) + txn_end(abort); + if (cursor_guard) + cursor_close(); + txn_begin(readonly, flags); +} + +void testcase::txn_inject_writefault(void) { + if (txn_guard) + txn_inject_writefault(txn_guard.get()); +} + +void testcase::txn_inject_writefault(MDBX_txn *txn) { + if (config.params.inject_writefaultn && txn) { + if (config.params.inject_writefaultn <= nops_completed && + (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) { + log_info("== txn_inject_writefault(): got %u nops or more, inject FAULT", + config.params.inject_writefaultn); + log_flush(); +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + TerminateProcess(GetCurrentProcess(), 42); +#else + raise(SIGKILL); +#endif + } + } +} + +bool testcase::wait4start() { + if (config.wait4id) { + log_trace(">> wait4start(%u)", config.wait4id); + assert(!global::singlemode); + int rc = osal_waitfor(config.wait4id); + if (rc) { + log_trace("<< wait4start(%u), failed %s", config.wait4id, + test_strerror(rc)); + return false; + } + } else { + log_trace("== skip wait4start: not needed"); + } + + if (config.params.delaystart) { + int rc = osal_delay(config.params.delaystart); + if (rc) { + log_trace("<< delay(%u), failed %s", config.params.delaystart, + test_strerror(rc)); + return false; + } + } else { + log_trace("== skip delay: not needed"); + } + + return true; +} + +void testcase::kick_progress(bool active) const { + chrono::time now = chrono::now_motonic(); + if (active) { + static int last_point = -1; + int point = (now.fixedpoint >> 29) & 3; + if (point != last_point) { + last.progress_timestamp = now; + fprintf(stderr, "%c\b", "-\\|/"[last_point = point]); + fflush(stderr); + } + } else if (now.fixedpoint - last.progress_timestamp.fixedpoint > + chrono::from_seconds(2).fixedpoint) { + last.progress_timestamp = now; + fprintf(stderr, "%c\b", "@*"[now.utc & 1]); + fflush(stderr); + } +} + +void testcase::report(size_t nops_done) { + assert(nops_done > 0); + if (!nops_done) + return; + + nops_completed += nops_done; + log_verbose("== complete +%" PRIuPTR " iteration, total %" PRIuPTR " done", + nops_done, nops_completed); + + if (global::config::progress_indicator) + kick_progress(true); + + if (config.signal_nops && !signalled && + config.signal_nops <= nops_completed) { + log_trace(">> signal(n-ops %" PRIuPTR ")", nops_completed); + if (!global::singlemode) + osal_broadcast(config.actor_id); + signalled = true; + log_trace("<< signal(n-ops %" PRIuPTR ")", nops_completed); + } +} + +void testcase::signal() { + if (!signalled) { + log_trace(">> signal(forced)"); + if (!global::singlemode) + osal_broadcast(config.actor_id); + signalled = true; + log_trace("<< signal(forced)"); + } +} + +bool testcase::setup() { + db_prepare(); + if (!wait4start()) + return false; + + start_timestamp = chrono::now_motonic(); + nops_completed = 0; + return true; +} + +bool testcase::teardown() { + log_trace(">> testcase::teardown"); + signal(); + db_close(); + log_trace("<< testcase::teardown"); + return true; +} + +bool testcase::should_continue(bool check_timeout_only) const { + bool result = true; + + if (config.params.test_duration) { + chrono::time since; + since.fixedpoint = + chrono::now_motonic().fixedpoint - start_timestamp.fixedpoint; + if (since.seconds() >= config.params.test_duration) + result = false; + } + + if (!check_timeout_only && config.params.test_nops && + nops_completed >= config.params.test_nops) + result = false; + + if (result && global::config::progress_indicator) + kick_progress(false); + + return result; +} + +void testcase::fetch_canary() { + mdbx_canary canary_now; + log_trace(">> fetch_canary"); + + int rc = mdbx_canary_get(txn_guard.get(), &canary_now); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_canary_get()", rc); + + if (canary_now.v < last.canary.v) + failure("fetch_canary: %" PRIu64 "(canary-now.v) < %" PRIu64 + "(canary-last.v)", + canary_now.v, last.canary.v); + if (canary_now.y < last.canary.y) + failure("fetch_canary: %" PRIu64 "(canary-now.y) < %" PRIu64 + "(canary-last.y)", + canary_now.y, last.canary.y); + + last.canary = canary_now; + log_trace("<< fetch_canary: db-sequence %" PRIu64 + ", db-sequence.txnid %" PRIu64, + last.canary.y, last.canary.v); +} + +void testcase::update_canary(uint64_t increment) { + mdbx_canary canary_now = last.canary; + + log_trace(">> update_canary: sequence %" PRIu64 " += %" PRIu64, canary_now.y, + increment); + canary_now.y += increment; + + int rc = mdbx_canary_put(txn_guard.get(), &canary_now); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_canary_put()", rc); + + log_trace("<< update_canary: sequence = %" PRIu64, canary_now.y); +} + +int testcase::db_open__begin__table_create_open_clean(MDBX_dbi &dbi) { + db_open(); + + int err, retry_left = 42; + for (;;) { + txn_begin(false); + dbi = db_table_open(true); + db_table_clear(dbi); + err = breakable_commit(); + if (likely(err == MDBX_SUCCESS)) { + txn_begin(false); + return MDBX_SUCCESS; + } + if (--retry_left == 0) + break; + jitter_delay(true); + } + log_notice("db_begin_table_create_open_clean: bailout due '%s'", + mdbx_strerror(err)); + return err; +} + +MDBX_dbi testcase::db_table_open(bool create) { + log_trace(">> testcase::db_table_create"); + + char tablename_buf[16]; + const char *tablename = nullptr; + if (config.space_id) { + int rc = snprintf(tablename_buf, sizeof(tablename_buf), "TBL%04u", + config.space_id); + if (rc < 4 || rc >= (int)sizeof(tablename_buf) - 1) + failure("snprintf(tablename): %d", rc); + tablename = tablename_buf; + } + log_verbose("use %s table", tablename ? tablename : "MAINDB"); + + MDBX_dbi handle = 0; + int rc = mdbx_dbi_open(txn_guard.get(), tablename, + (create ? MDBX_CREATE : 0) | config.params.table_flags, + &handle); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_dbi_open()", rc); + + log_trace("<< testcase::db_table_create, handle %u", handle); + return handle; +} + +void testcase::db_table_drop(MDBX_dbi handle) { + log_trace(">> testcase::db_table_drop, handle %u", handle); + + if (config.params.drop_table) { + int rc = mdbx_drop(txn_guard.get(), handle, true); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_drop(delete=true)", rc); + log_trace("<< testcase::db_table_drop"); + } else { + log_trace("<< testcase::db_table_drop: not needed"); + } +} + +void testcase::db_table_clear(MDBX_dbi handle) { + log_trace(">> testcase::db_table_clear, handle %u", handle); + int rc = mdbx_drop(txn_guard.get(), handle, false); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_drop(delete=false)", rc); + log_trace("<< testcase::db_table_clear"); +} + +void testcase::db_table_close(MDBX_dbi handle) { + log_trace(">> testcase::db_table_close, handle %u", handle); + assert(!txn_guard); + int rc = mdbx_dbi_close(db_guard.get(), handle); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_dbi_close()", rc); + log_trace("<< testcase::db_table_close"); +} + +void testcase::checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check, + MDBX_val expected_valued) { + MDBX_val actual_value = expected_valued; + int rc = mdbx_get2(txn_guard.get(), handle, &key2check, &actual_value); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror(step, rc); + if (!is_samedata(&actual_value, &expected_valued)) + failure("%s data mismatch", step); +} + +//----------------------------------------------------------------------------- + +bool test_execute(const actor_config &config_const) { + const mdbx_pid_t pid = osal_getpid(); + actor_config config = config_const; + + if (global::singlemode) { + logging::setup(format("single_%s", testcase2str(config.testcase))); + } else { + logging::setup((logging::loglevel)config.params.loglevel, + format("child_%u.%u", config.actor_id, config.space_id)); + log_trace(">> wait4barrier"); + osal_wait4barrier(); + log_trace("<< wait4barrier"); + } + + try { + std::unique_ptr test; + switch (config.testcase) { + case ac_hill: + test.reset(new testcase_hill(config, pid)); + break; + case ac_deadread: + test.reset(new testcase_deadread(config, pid)); + break; + case ac_deadwrite: + test.reset(new testcase_deadwrite(config, pid)); + break; + case ac_jitter: + test.reset(new testcase_jitter(config, pid)); + break; + case ac_try: + test.reset(new testcase_try(config, pid)); + break; + case ac_copy: + test.reset(new testcase_copy(config, pid)); + break; + case ac_append: + test.reset(new testcase_append(config, pid)); + break; + case ac_ttl: + test.reset(new testcase_ttl(config, pid)); + break; + default: + test.reset(new testcase(config, pid)); + break; + } + + size_t iter = 0; + do { + iter++; + if (!test->setup()) { + log_notice("test setup failed"); + return false; + } + if (!test->run()) { + log_notice("test failed"); + return false; + } + if (!test->teardown()) { + log_notice("test teardown failed"); + return false; + } + + if (config.params.nrepeat == 1) + log_info("test successed"); + else { + if (config.params.nrepeat) + log_info("test successed (iteration %zi of %zi)", iter, + size_t(config.params.nrepeat)); + else + log_info("test successed (iteration %zi)", iter); + config.params.keygen.seed += INT32_C(0xA4F4D37B); + } + + } while (config.params.nrepeat == 0 || iter < config.params.nrepeat); + return true; + } catch (const std::exception &pipets) { + failure("***** Exception: %s *****", pipets.what()); + return false; + } +} diff --git a/contrib/db/libmdbx/test/test.h b/contrib/db/libmdbx/test/test.h new file mode 100644 index 00000000..fb5ad4ee --- /dev/null +++ b/contrib/db/libmdbx/test/test.h @@ -0,0 +1,218 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once + +#include "base.h" +#include "chrono.h" +#include "config.h" +#include "keygen.h" +#include "log.h" +#include "osal.h" +#include "utils.h" + +bool test_execute(const actor_config &config); +std::string thunk_param(const actor_config &config); +void testcase_setup(const char *casename, actor_params ¶ms, + unsigned &last_space_id); +void configure_actor(unsigned &last_space_id, const actor_testcase testcase, + const char *space_id_cstr, const actor_params ¶ms); +void keycase_setup(const char *casename, actor_params ¶ms); + +namespace global { + +extern const char thunk_param_prefix[]; +extern std::vector actors; +extern std::unordered_map events; +extern std::unordered_map pid2actor; +extern std::set databases; +extern unsigned nactors; +extern chrono::time start_motonic; +extern chrono::time deadline_motonic; +extern bool singlemode; + +namespace config { +extern unsigned timeout_duration_seconds; +extern bool dump_config; +extern bool cleanup_before; +extern bool cleanup_after; +extern bool failfast; +extern bool progress_indicator; +} /* namespace config */ + +} /* namespace global */ + +//----------------------------------------------------------------------------- + +struct db_deleter : public std::unary_function { + void operator()(MDBX_env *env) const { mdbx_env_close(env); } +}; + +struct txn_deleter : public std::unary_function { + void operator()(MDBX_txn *txn) const { + int rc = mdbx_txn_abort(txn); + if (rc) + log_trouble(mdbx_func_, "mdbx_txn_abort()", rc); + } +}; + +struct cursor_deleter : public std::unary_function { + void operator()(MDBX_cursor *cursor) const { mdbx_cursor_close(cursor); } +}; + +typedef std::unique_ptr scoped_db_guard; +typedef std::unique_ptr scoped_txn_guard; +typedef std::unique_ptr scoped_cursor_guard; + +//----------------------------------------------------------------------------- + +class testcase { +protected: + const actor_config &config; + const mdbx_pid_t pid; + + scoped_db_guard db_guard; + scoped_txn_guard txn_guard; + scoped_cursor_guard cursor_guard; + bool signalled; + + size_t nops_completed; + chrono::time start_timestamp; + keygen::buffer key; + keygen::buffer data; + keygen::maker keyvalue_maker; + + struct { + mdbx_canary canary; + mutable chrono::time progress_timestamp; + } last; + + static int oom_callback(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn, + unsigned gap, int retry); + + void db_prepare(); + void db_open(); + void db_close(); + void txn_begin(bool readonly, unsigned flags = 0); + int breakable_commit(); + void txn_end(bool abort); + int breakable_restart(); + void txn_restart(bool abort, bool readonly, unsigned flags = 0); + void cursor_open(unsigned dbi); + void cursor_close(); + void txn_inject_writefault(void); + void txn_inject_writefault(MDBX_txn *txn); + void fetch_canary(); + void update_canary(uint64_t increment); + void kick_progress(bool active) const; + void checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check, + MDBX_val expected_valued); + + MDBX_dbi db_table_open(bool create); + void db_table_drop(MDBX_dbi handle); + void db_table_clear(MDBX_dbi handle); + void db_table_close(MDBX_dbi handle); + int db_open__begin__table_create_open_clean(MDBX_dbi &dbi); + + bool wait4start(); + void report(size_t nops_done); + void signal(); + bool should_continue(bool check_timeout_only = false) const; + + void generate_pair(const keygen::serial_t serial, keygen::buffer &out_key, + keygen::buffer &out_value, keygen::serial_t data_age = 0) { + keyvalue_maker.pair(serial, out_key, out_value, data_age); + } + + void generate_pair(const keygen::serial_t serial, + keygen::serial_t data_age = 0) { + generate_pair(serial, key, data, data_age); + } + + bool mode_readonly() const { + return (config.params.mode_flags & MDBX_RDONLY) ? true : false; + } + +public: + testcase(const actor_config &config, const mdbx_pid_t pid) + : config(config), pid(pid), signalled(false), nops_completed(0) { + start_timestamp.reset(); + memset(&last, 0, sizeof(last)); + } + + virtual bool setup(); + virtual bool run() { return true; } + virtual bool teardown(); + virtual ~testcase() {} +}; + +class testcase_ttl : public testcase { +public: + testcase_ttl(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_hill : public testcase { +public: + testcase_hill(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_append : public testcase { +public: + testcase_append(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_deadread : public testcase { +public: + testcase_deadread(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_deadwrite : public testcase { +public: + testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_jitter : public testcase { +public: + testcase_jitter(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_try : public testcase { +public: + testcase_try(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid) {} + bool run(); +}; + +class testcase_copy : public testcase { + const std::string copy_pathname; + void copy_db(const bool with_compaction); + +public: + testcase_copy(const actor_config &config, const mdbx_pid_t pid) + : testcase(config, pid), + copy_pathname(config.params.pathname_db + "-copy") {} + bool run(); +}; diff --git a/contrib/db/libmdbx/test/test.vcxproj b/contrib/db/libmdbx/test/test.vcxproj new file mode 100644 index 00000000..93de00e3 --- /dev/null +++ b/contrib/db/libmdbx/test/test.vcxproj @@ -0,0 +1,209 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {6d19209b-ece7-4b9c-941c-0aa2b484f199} + + + + {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31} + Win32Proj + mdbxtest + 8.1 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + mdbx_test + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + mdbx_test + + + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + mdbx_test + + + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ + mdbx_test + + + + Use + Level4 + Disabled + WIN32;_DEBUG;_CONSOLE;MDBX_DEBUG=1;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + test.h + true + + + Console + true + winmm.lib;%(AdditionalDependencies) + + + + + Use + Level4 + Disabled + _DEBUG;_CONSOLE;MDBX_DEBUG=1;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + test.h + true + + + Console + true + winmm.lib;%(AdditionalDependencies) + + + + + Level4 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + test.h + true + + + Console + true + true + true + winmm.lib;%(AdditionalDependencies) + + + + + Level4 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1 + true + test.h + true + + + Console + true + true + true + winmm.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + diff --git a/contrib/db/libmdbx/test/try.cc b/contrib/db/libmdbx/test/try.cc new file mode 100644 index 00000000..150abd36 --- /dev/null +++ b/contrib/db/libmdbx/test/try.cc @@ -0,0 +1,20 @@ +#include "test.h" + +bool testcase_try::run() { + db_open(); + assert(!txn_guard); + + MDBX_txn *txn = nullptr; + MDBX_txn *txn2 = nullptr; + int rc = mdbx_txn_begin(db_guard.get(), nullptr, 0, &txn); + if (unlikely(rc != MDBX_SUCCESS)) + failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); + else { + rc = mdbx_txn_begin(db_guard.get(), nullptr, MDBX_TRYTXN, &txn2); + if (unlikely(rc != MDBX_BUSY)) + failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); + } + + txn_guard.reset(txn); + return true; +} diff --git a/contrib/db/libmdbx/test/ttl.cc b/contrib/db/libmdbx/test/ttl.cc new file mode 100644 index 00000000..b2650f0c --- /dev/null +++ b/contrib/db/libmdbx/test/ttl.cc @@ -0,0 +1,179 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" +#include +#include + +static unsigned edge2window(uint64_t edge, unsigned window_max) { + const double rnd = u64_to_double1(bleach64(edge)); + const unsigned window = window_max - std::lrint(std::pow(window_max, rnd)); + return window; +} + +static unsigned edge2count(uint64_t edge, unsigned count_max) { + const double rnd = u64_to_double1(prng64_map1_white(edge)); + const unsigned count = std::lrint(std::pow(count_max, rnd)); + return count; +} + +bool testcase_ttl::run() { + MDBX_dbi dbi; + int err = db_open__begin__table_create_open_clean(dbi); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("ttl: bailout-prepare due '%s'", mdbx_strerror(err)); + return true; + } + + /* LY: тест "эмуляцией time-to-live": + * - организуется "скользящее окно", которое двигается вперед вдоль + * числовой оси каждую транзакцию. + * - по переднему краю "скользящего окна" записи добавляются в таблицу, + * а по заднему удаляются. + * - количество добавляемых/удаляемых записей псевдослучайно зависит + * от номера транзакции, но с экспоненциальным распределением. + * - размер "скользящего окна" также псевдослучайно зависит от номера + * транзакции с "отрицательным" экспоненциальным распределением + * MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний + * край и удаляются записи позади него. + * + * Таким образом имитируется поведение таблицы с TTL: записи стохастически + * добавляются и удаляются, но изредка происходят массивные удаления. + */ + + /* LY: для параметризации используем подходящие параметры, которые не имеют + * здесь смысла в первоначальном значении. */ + const unsigned window_max_lower = +#ifdef __APPLE__ + 333; +#else + 999; +#endif + const unsigned count_max_lower = +#ifdef __APPLE__ + 333; +#else + 999; +#endif + + const unsigned window_max = (config.params.batch_read > window_max_lower) + ? config.params.batch_read + : window_max_lower; + const unsigned count_max = (config.params.batch_write > count_max_lower) + ? config.params.batch_write + : count_max_lower; + log_info("ttl: using `batch_read` value %u for window_max", window_max); + log_info("ttl: using `batch_write` value %u for count_max", count_max); + + uint64_t seed = + prng64_map2_white(config.params.keygen.seed) + config.actor_id; + keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */); + key = keygen::alloc(config.params.keylen_max); + data = keygen::alloc(config.params.datalen_max); + const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) + ? MDBX_NODUPDATA + : MDBX_NODUPDATA | MDBX_NOOVERWRITE; + + std::deque> fifo; + uint64_t serial = 0; + while (should_continue()) { + const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */; + + const unsigned window_width = edge2window(salt, window_max); + unsigned head_count = edge2count(salt, count_max); + log_verbose("ttl: step #%zu (serial %" PRIu64 + ", window %u, count %u) salt %" PRIu64, + nops_completed, serial, window_width, head_count, salt); + + if (window_width) { + while (fifo.size() > window_width) { + uint64_t tail_serial = fifo.back().first; + const unsigned tail_count = fifo.back().second; + log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial, + tail_count); + fifo.pop_back(); + for (unsigned n = 0; n < tail_count; ++n) { + log_trace("ttl: remove-tail %" PRIu64, serial); + generate_pair(tail_serial); + err = mdbx_del(txn_guard.get(), dbi, &key->value, &data->value); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("ttl: tail-bailout due '%s'", mdbx_strerror(err)); + goto bailout; + } + failure_perror("mdbx_del(tail)", err); + } + if (unlikely(!keyvalue_maker.increment(tail_serial, 1))) + failure("ttl: unexpected key-space overflow on the tail"); + } + } + } else { + log_trace("ttl: purge state"); + db_table_clear(dbi); + fifo.clear(); + } + + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("ttl: bailout at commit due '%s'", mdbx_strerror(err)); + break; + } + fifo.push_front(std::make_pair(serial, head_count)); + retry: + for (unsigned n = 0; n < head_count; ++n) { + log_trace("ttl: insert-head %" PRIu64, serial); + generate_pair(serial); + err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value, + insert_flags); + if (unlikely(err != MDBX_SUCCESS)) { + if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) { + log_notice("ttl: head-insert skip due '%s'", mdbx_strerror(err)); + txn_restart(true, false); + serial = fifo.front().first; + fifo.front().second = head_count = n; + goto retry; + } + failure_perror("mdbx_put(head)", err); + } + + if (unlikely(!keyvalue_maker.increment(serial, 1))) { + log_notice("ttl: unexpected key-space overflow"); + goto bailout; + } + } + err = breakable_restart(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("ttl: head-commit skip due '%s'", mdbx_strerror(err)); + serial = fifo.front().first; + fifo.pop_front(); + } + report(1); + } + +bailout: + txn_end(true); + if (dbi) { + if (config.params.drop_table && !mode_readonly()) { + txn_begin(false); + db_table_drop(dbi); + err = breakable_commit(); + if (unlikely(err != MDBX_SUCCESS)) { + log_notice("ttl: bailout-clean due '%s'", mdbx_strerror(err)); + return true; + } + } else + db_table_close(dbi); + } + return true; +} diff --git a/contrib/db/libmdbx/test/utils.cc b/contrib/db/libmdbx/test/utils.cc new file mode 100644 index 00000000..d9b3538b --- /dev/null +++ b/contrib/db/libmdbx/test/utils.cc @@ -0,0 +1,367 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "test.h" +#include +#if defined(HAVE_IEEE754_H) || __has_include() +#include +#endif +#if defined(__APPLE__) || defined(__MACH__) +#include +#endif /* defined(__APPLE__) || defined(__MACH__) */ + +std::string format(const char *fmt, ...) { + va_list ap, ones; + va_start(ap, fmt); + va_copy(ones, ap); +#ifdef _MSC_VER + int needed = _vscprintf(fmt, ap); +#else + int needed = vsnprintf(nullptr, 0, fmt, ap); +#endif + assert(needed >= 0); + va_end(ap); + std::string result; + result.reserve((size_t)needed + 1); + result.resize((size_t)needed, '\0'); + int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones); + assert(actual == needed); + (void)actual; + va_end(ones); + return result; +} + +std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) { + std::string result; + if (bytes > 0) { + const uint8_t *data = (const uint8_t *)ptr; + checksum.push(data, bytes); + result.reserve(bytes * 2); + const uint8_t *const end = data + bytes; + do { + char h = *data >> 4; + char l = *data & 15; + result.push_back((l < 10) ? l + '0' : l - 10 + 'a'); + result.push_back((h < 10) ? h + '0' : h - 10 + 'a'); + } while (++data < end); + } + assert(result.size() == bytes * 2); + return result; +} + +bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, + size_t bytes, simple_checksum &checksum) { + if (bytes * 2 != (size_t)(hex_end - hex_begin)) + return false; + + uint8_t *data = (uint8_t *)ptr; + for (const char *hex = hex_begin; hex != hex_end; hex += 2, ++data) { + unsigned l = hex[0], h = hex[1]; + + if (l >= '0' && l <= '9') + l = l - '0'; + else if (l >= 'A' && l <= 'F') + l = l - 'A' + 10; + else if (l >= 'a' && l <= 'f') + l = l - 'a' + 10; + else + return false; + + if (h >= '0' && h <= '9') + h = h - '0'; + else if (h >= 'A' && h <= 'F') + h = h - 'A' + 10; + else if (h >= 'a' && h <= 'f') + h = h - 'a' + 10; + else + return false; + + uint32_t c = l + (h << 4); + checksum.push(c); + *data = (uint8_t)c; + } + return true; +} + +bool is_samedata(const MDBX_val *a, const MDBX_val *b) { + return a->iov_len == b->iov_len && + memcmp(a->iov_base, b->iov_base, a->iov_len) == 0; +} + +//----------------------------------------------------------------------------- + +/* TODO: replace my 'libmera' from t1ha. */ +uint64_t entropy_ticks(void) { +#if defined(EMSCRIPTEN) + return (uint64_t)emscripten_get_now(); +#endif /* EMSCRIPTEN */ + +#if defined(__APPLE__) || defined(__MACH__) + return mach_absolute_time(); +#endif /* defined(__APPLE__) || defined(__MACH__) */ + +#if defined(__sun__) || defined(__sun) + return gethrtime(); +#endif /* __sun__ */ + +#if defined(__GNUC__) || defined(__clang__) + +#if defined(__ia64__) + uint64_t ticks; + __asm __volatile("mov %0=ar.itc" : "=r"(ticks)); + return ticks; +#elif defined(__hppa__) + uint64_t ticks; + __asm __volatile("mfctl 16, %0" : "=r"(ticks)); + return ticks; +#elif defined(__s390__) + uint64_t ticks; + __asm __volatile("stck 0(%0)" : : "a"(&(ticks)) : "memory", "cc"); + return ticks; +#elif defined(__alpha__) + uint64_t ticks; + __asm __volatile("rpcc %0" : "=r"(ticks)); + return ticks; +#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \ + defined(__sparc64) || defined(__sparc_v8plus__) || \ + defined(__sparc_v8plus) || defined(__sparc_v8plusa__) || \ + defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9) + + union { + uint64_t u64; + struct { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + uint32_t h, l; +#else + uint32_t l, h; +#endif + } u32; + } cycles; + +#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || \ + defined(__sparc_v9__) || defined(__sparc_v8plus) || \ + defined(__sparc_v8plusa) || defined(__sparc_v9) + +#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || \ + defined(__sparc64__) || defined(__sparc64) + __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64)); +#else + __asm __volatile("rd %%tick, %1; srlx %1, 32, %0" + : "=r"(cycles.u32.h), "=r"(cycles.u32.l)); +#endif /* __sparc64__ */ + +#else + __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0" + : "=r"(cycles.u64) + : + : "%g1"); +#endif /* __sparc8plus__ || __sparc_v9__ */ + return cycles.u64; + +#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) || \ + defined(__powerpc64)) + uint64_t ticks; + __asm __volatile("mfspr %0, 268" : "=r"(ticks)); + return ticks; +#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) || \ + defined(__ppc)) +#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul + uint64_t ticks; + __asm __volatile("mftb %0" : "=r"(ticks)); + *now = ticks; +#else + uint64_t ticks; + uint32_t low, high_before, high_after; + __asm __volatile("mftbu %0; mftb %1; mftbu %2" + : "=r"(high_before), "=r"(low), "=r"(high_after)); + ticks = (uint64_t)high_after << 32; + ticks |= low & /* zeroes if high part has changed */ + ~(high_before - high_after); +#endif +#elif (defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7)) && \ + !defined(MDBX_SAFE4QEMU) + uint64_t virtual_timer; + __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer)); + return virtual_timer; +#elif (defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8) || \ + defined(_M_ARM) + static uint32_t pmcntenset = 0x00425B00; + if (unlikely(pmcntenset == 0x00425B00)) { + uint32_t pmuseren; +#ifdef _M_ARM + pmuseren = _MoveFromCoprocessor(15, 0, 9, 14, 0); +#else + __asm("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren)); +#endif + if (1 & pmuseren /* Is it allowed for user mode code? */) { +#ifdef _M_ARM + pmcntenset = _MoveFromCoprocessor(15, 0, 9, 12, 1); +#else + __asm("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset)); +#endif + } else + pmcntenset = 0; + } + if (pmcntenset & 0x80000000ul /* Is it counting? */) { +#ifdef _M_ARM + return __rdpmccntr64(); +#else + uint32_t pmccntr; + __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); + return pmccntr; +#endif + } +#elif defined(__mips__) || defined(__mips) || defined(_R4000) + unsigned count; + __asm __volatile("rdhwr %0, $2" : "=r"(count)); + return count; +#endif /* arch selector */ +#endif /* __GNUC__ || __clang__ */ + +#if defined(__e2k__) || defined(__ia32__) + return __rdtsc(); +#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + LARGE_INTEGER PerformanceCount; + if (QueryPerformanceCounter(&PerformanceCount)) + return PerformanceCount.QuadPart; + return GetTickCount64(); +#else + struct timespec ts; +#if defined(CLOCK_MONOTONIC_COARSE) + clockid_t clk_id = CLOCK_MONOTONIC_COARSE; +#elif defined(CLOCK_MONOTONIC_RAW) + clockid_t clk_id = CLOCK_MONOTONIC_RAW; +#else + clockid_t clk_id = CLOCK_MONOTONIC; +#endif + int rc = clock_gettime(clk_id, &ts); + if (unlikely(rc)) + failure_perror("clock_gettime()", rc); + + return (((uint64_t)ts.tv_sec) << 32) + ts.tv_nsec; +#endif +} + +//----------------------------------------------------------------------------- + +uint64_t prng64_white(uint64_t &state) { + state = prng64_map2_careless(state); + return bleach64(state); +} + +uint32_t prng32(uint64_t &state) { + return (uint32_t)(prng64_careless(state) >> 32); +} + +void prng_fill(uint64_t &state, void *ptr, size_t bytes) { + while (bytes >= 4) { + *((uint32_t *)ptr) = prng32(state); + ptr = (uint32_t *)ptr + 1; + bytes -= 4; + } + + switch (bytes & 3) { + case 3: { + uint32_t u32 = prng32(state); + memcpy(ptr, &u32, 3); + } break; + case 2: + *((uint16_t *)ptr) = (uint16_t)prng32(state); + break; + case 1: + *((uint8_t *)ptr) = (uint8_t)prng32(state); + break; + case 0: + break; + } +} + +static __thread uint64_t prng_state; + +void prng_seed(uint64_t seed) { prng_state = bleach64(seed); } + +uint32_t prng32(void) { return prng32(prng_state); } + +uint64_t prng64(void) { return prng64_white(prng_state); } + +void prng_fill(void *ptr, size_t bytes) { prng_fill(prng_state, ptr, bytes); } + +uint64_t entropy_white() { return bleach64(entropy_ticks()); } + +double double_from_lower(uint64_t salt) { +#ifdef IEEE754_DOUBLE_BIAS + ieee754_double r; + r.ieee.negative = 0; + r.ieee.exponent = IEEE754_DOUBLE_BIAS; + r.ieee.mantissa0 = (unsigned)(salt >> 32); + r.ieee.mantissa1 = (unsigned)salt; + return r.d; +#else + const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; + const double scale = 1.0 / (double)top; + return (salt & top) * scale; +#endif +} + +double double_from_upper(uint64_t salt) { +#ifdef IEEE754_DOUBLE_BIAS + ieee754_double r; + r.ieee.negative = 0; + r.ieee.exponent = IEEE754_DOUBLE_BIAS; + salt >>= 64 - DBL_MANT_DIG; + r.ieee.mantissa0 = (unsigned)(salt >> 32); + r.ieee.mantissa1 = (unsigned)salt; + return r.d; +#else + const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; + const double scale = 1.0 / (double)top; + return (salt >> (64 - DBL_MANT_DIG)) * scale; +#endif +} + +bool flipcoin() { return bleach32((uint32_t)entropy_ticks()) & 1; } + +bool jitter(unsigned probability_percent) { + const uint32_t top = UINT32_MAX - UINT32_MAX % 100; + uint32_t dice, edge = (top) / 100 * probability_percent; + do + dice = bleach32((uint32_t)entropy_ticks()); + while (dice >= top); + return dice < edge; +} + +void jitter_delay(bool extra) { + unsigned dice = entropy_white() & 3; + if (dice == 0) { + log_trace("== jitter.no-delay"); + } else { + log_trace(">> jitter.delay: dice %u", dice); + do { + cpu_relax(); + memory_barrier(); + cpu_relax(); + if (dice > 1) { + osal_yield(); + cpu_relax(); + if (dice > 2) { + unsigned us = entropy_white() & + (extra ? 0xffff /* 656 ms */ : 0x3ff /* 1 ms */); + log_trace("== jitter.delay: %0.6f", us / 1000000.0); + osal_udelay(us); + } + } + } while (flipcoin()); + log_trace("<< jitter.delay: dice %u", dice); + } +} diff --git a/contrib/db/libmdbx/test/utils.h b/contrib/db/libmdbx/test/utils.h new file mode 100644 index 00000000..d1b859ac --- /dev/null +++ b/contrib/db/libmdbx/test/utils.h @@ -0,0 +1,359 @@ +/* + * Copyright 2017-2019 Leonid Yuriev + * and other libmdbx authors: please see AUTHORS file. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#pragma once +#include "base.h" + +#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ + !defined(__ORDER_BIG_ENDIAN__) +#error __BYTE_ORDER__ should be defined. +#endif + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \ + __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ +#error Unsupported byte order. +#endif + +#if __GNUC_PREREQ(4, 4) || defined(__clang__) +#ifndef bswap64 +#define bswap64(v) __builtin_bswap64(v) +#endif +#ifndef bswap32 +#define bswap32(v) __builtin_bswap32(v) +#endif +#if (__GNUC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16)) && \ + !defined(bswap16) +#define bswap16(v) __builtin_bswap16(v) +#endif + +#elif defined(_MSC_VER) + +#if _MSC_FULL_VER < 190024215 +#pragma message( \ + "It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.") +#endif + +#define bswap64(v) _byteswap_uint64(v) +#define bswap32(v) _byteswap_ulong(v) +#define bswap16(v) _byteswap_ushort(v) +#define rot64(v, s) _rotr64(v, s) +#define rot32(v, s) _rotr(v, s) + +#if defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64) +#pragma intrinsic(_umul128) +#define mul_64x64_128(a, b, ph) _umul128(a, b, ph) +#pragma intrinsic(__umulh) +#define mul_64x64_high(a, b) __umulh(a, b) +#endif + +#if defined(_M_IX86) +#pragma intrinsic(__emulu) +#define mul_32x32_64(a, b) __emulu(a, b) +#elif defined(_M_ARM) +#define mul_32x32_64(a, b) _arm_umull(a, b) +#endif + +#endif /* compiler */ + +#ifndef bswap64 +#ifdef __bswap_64 +#define bswap64(v) __bswap_64(v) +#else +static __inline uint64_t bswap64(uint64_t v) { + return v << 56 | v >> 56 | ((v << 40) & UINT64_C(0x00ff000000000000)) | + ((v << 24) & UINT64_C(0x0000ff0000000000)) | + ((v << 8) & UINT64_C(0x000000ff00000000)) | + ((v >> 8) & UINT64_C(0x00000000ff0000000)) | + ((v >> 24) & UINT64_C(0x0000000000ff0000)) | + ((v >> 40) & UINT64_C(0x000000000000ff00)); +} +#endif +#endif /* bswap64 */ + +#ifndef bswap32 +#ifdef __bswap_32 +#define bswap32(v) __bswap_32(v) +#else +static __inline uint32_t bswap32(uint32_t v) { + return v << 24 | v >> 24 | ((v << 8) & UINT32_C(0x00ff0000)) | + ((v >> 8) & UINT32_C(0x0000ff00)); +} +#endif +#endif /* bswap32 */ + +#ifndef bswap16 +#ifdef __bswap_16 +#define bswap16(v) __bswap_16(v) +#else +static __inline uint16_t bswap16(uint16_t v) { return v << 8 | v >> 8; } +#endif +#endif /* bswap16 */ + +#define is_byteorder_le() (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define is_byteorder_be() (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + +#ifndef htole16 +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define htobe16(v) bswap16(v) +#define htole16(v) (v) +#define be16toh(v) bswap16(v) +#define le16toh(v) (v) +#else +#define htobe16(v) (v) +#define htole16(v) bswap16(v) +#define be16toh(v) (v) +#define le16toh(v) bswap16(v) +#endif +#endif /* htole16 */ + +#ifndef htole32 +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define htobe32(v) bswap32(v) +#define htole32(v) (v) +#define be32toh(v) bswap32(v) +#define le32toh(v) (v) +#else +#define htobe32(v) (v) +#define htole32(v) bswap32(v) +#define be32toh(v) (v) +#define le32toh(v) bswap32(v) +#endif +#endif /* htole32 */ + +#ifndef htole64 +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define htobe64(v) bswap64(v) +#define htole64(v) (v) +#define be64toh(v) bswap64(v) +#define le64toh(v) (v) +#else +#define htobe64(v) (v) +#define htole64(v) bswap_64(v) +#define be64toh(v) (v) +#define le64toh(v) bswap_64(v) +#endif +#endif /* htole64 */ + +namespace unaligned { + +template static __inline T load(const void *ptr) { +#if defined(_MSC_VER) && \ + (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) + return *(const T __unaligned *)ptr; +#elif UNALIGNED_OK + return *(const T *)ptr; +#else + T local; +#if defined(__GNUC__) || defined(__clang__) + __builtin_memcpy(&local, (const T *)ptr, sizeof(T)); +#else + memcpy(&local, (const T *)ptr, sizeof(T)); +#endif /* __GNUC__ || __clang__ */ + return local; +#endif /* UNALIGNED_OK */ +} + +template static __inline void store(void *ptr, const T &value) { +#if defined(_MSC_VER) && \ + (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) + *((T __unaligned *)ptr) = value; +#elif UNALIGNED_OK + *(volatile T *)ptr = value; +#else +#if defined(__GNUC__) || defined(__clang__) + __builtin_memcpy(ptr, &value, sizeof(T)); +#else + memcpy(ptr, &value, sizeof(T)); +#endif /* __GNUC__ || __clang__ */ +#endif /* UNALIGNED_OK */ +} + +} /* namespace unaligned */ + +//----------------------------------------------------------------------------- + +#ifndef rot64 +static __inline uint64_t rot64(uint64_t v, unsigned s) { + return (v >> s) | (v << (64 - s)); +} +#endif /* rot64 */ + +static __inline bool is_power2(size_t x) { return (x & (x - 1)) == 0; } + +#undef roundup2 +static __inline size_t roundup2(size_t value, size_t granularity) { + assert(is_power2(granularity)); + return (value + granularity - 1) & ~(granularity - 1); +} + +//----------------------------------------------------------------------------- + +static __inline void memory_barrier(void) { +#if __has_extension(c_atomic) || __has_extension(cxx_atomic) + __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); +#elif defined(__ATOMIC_SEQ_CST) + __atomic_thread_fence(__ATOMIC_SEQ_CST); +#elif defined(__clang__) || defined(__GNUC__) + __sync_synchronize(); +#elif defined(_MSC_VER) + MemoryBarrier(); +#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ +#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) + __mf(); +#elif defined(__ia32__) + _mm_mfence(); +#else +#error "Unknown target for Intel Compiler, please report to us." +#endif +#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun) + __machine_rw_barrier(); +#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \ + (defined(HP_IA64) || defined(__ia64)) + _Asm_mf(); +#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \ + defined(__ppc64__) || defined(__powerpc64__) + __lwsync(); +#else +#error "Could not guess the kind of compiler, please report to us." +#endif +} + +static __inline void cpu_relax() { +#if defined(__ia32__) + _mm_pause(); +#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \ + defined(YieldProcessor) + YieldProcessor(); +#else +/* nope */ +#endif +} + +//----------------------------------------------------------------------------- + +struct simple_checksum { + uint64_t value; + + simple_checksum() : value(0) {} + + void push(const uint32_t &data) { + value += data * UINT64_C(9386433910765580089) + 1; + value ^= value >> 41; + value *= UINT64_C(0xBD9CACC22C6E9571); + } + + void push(const uint64_t &data) { + push((uint32_t)data); + push((uint32_t)(data >> 32)); + } + + void push(const bool data) { + push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E)); + } + + void push(const void *ptr, size_t bytes) { + const uint8_t *data = (const uint8_t *)ptr; + for (size_t i = 0; i < bytes; ++i) + push((uint32_t)data[i]); + } + + void push(const double &data) { push(&data, sizeof(double)); } + void push(const char *cstr) { push(cstr, strlen(cstr)); } + void push(const std::string &str) { push(str.data(), str.size()); } + + void push(unsigned salt, const MDBX_val &val) { + push(unsigned(val.iov_len)); + push(salt); + push(val.iov_base, val.iov_len); + } + +#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) + void push(const HANDLE &handle) { push(&handle, sizeof(handle)); } +#endif /* _WINDOWS */ +}; + +std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum); +bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, + size_t bytes, simple_checksum &checksum); +bool is_samedata(const MDBX_val *a, const MDBX_val *b); +std::string format(const char *fmt, ...); + +uint64_t entropy_ticks(void); +uint64_t entropy_white(void); +static inline uint64_t bleach64(uint64_t v) { + // Tommy Ettinger, https://www.blogger.com/profile/04953541827437796598 + // http://mostlymangling.blogspot.com/2019/01/better-stronger-mixer-and-test-procedure.html + v ^= rot64(v, 25) ^ rot64(v, 50); + v *= UINT64_C(0xA24BAED4963EE407); + v ^= rot64(v, 24) ^ rot64(v, 49); + v *= UINT64_C(0x9FB21C651E98DF25); + return v ^ v >> 28; +} + +static inline uint32_t bleach32(uint32_t x) { + // https://github.com/skeeto/hash-prospector + // exact bias: 0.17353355999581582 + x ^= x >> 16; + x *= UINT32_C(0x7feb352d); + x ^= 0x3027C563 ^ (x >> 15); + x *= UINT32_C(0x846ca68b); + x ^= x >> 16; + return x; +} + +static inline uint64_t prng64_map1_careless(uint64_t state) { + return state * UINT64_C(6364136223846793005) + 1; +} + +static inline uint64_t prng64_map2_careless(uint64_t state) { + return (state + UINT64_C(1442695040888963407)) * + UINT64_C(6364136223846793005); +} + +static inline uint64_t prng64_map1_white(uint64_t state) { + return bleach64(prng64_map1_careless(state)); +} + +static inline uint64_t prng64_map2_white(uint64_t state) { + return bleach64(prng64_map2_careless(state)); +} + +static inline uint64_t prng64_careless(uint64_t &state) { + state = prng64_map1_careless(state); + return state; +} + +static inline double u64_to_double1(uint64_t v) { + union { + uint64_t u64; + double d; + } casting; + + casting.u64 = UINT64_C(0x3ff) << 52 | (v >> 12); + assert(casting.d >= 1.0 && casting.d < 2.0); + return casting.d - 1.0; +} + +uint64_t prng64_white(uint64_t &state); +uint32_t prng32(uint64_t &state); +void prng_fill(uint64_t &state, void *ptr, size_t bytes); + +void prng_seed(uint64_t seed); +uint32_t prng32(void); +uint64_t prng64(void); +void prng_fill(void *ptr, size_t bytes); + +bool flipcoin(); +bool jitter(unsigned probability_percent); +void jitter_delay(bool extra = false); diff --git a/contrib/db/libmdbx/tutorial/CMakeLists.txt b/contrib/db/libmdbx/tutorial/CMakeLists.txt new file mode 100644 index 00000000..196f1f48 --- /dev/null +++ b/contrib/db/libmdbx/tutorial/CMakeLists.txt @@ -0,0 +1,7 @@ +set(TARGET mdbx_tutorial) +project(${TARGET}) + +add_executable(${TARGET} sample-mdbx.c) + +target_link_libraries(${TARGET} mdbx) + diff --git a/contrib/db/libmdbx/tutorial/README.md b/contrib/db/libmdbx/tutorial/README.md new file mode 100644 index 00000000..b5218da3 --- /dev/null +++ b/contrib/db/libmdbx/tutorial/README.md @@ -0,0 +1 @@ +This directory is just a placeholder for now. Tutorial and examples will be added later. diff --git a/contrib/db/libmdbx/tutorial/sample-bdb.txt b/contrib/db/libmdbx/tutorial/sample-bdb.txt new file mode 100644 index 00000000..440efddb --- /dev/null +++ b/contrib/db/libmdbx/tutorial/sample-bdb.txt @@ -0,0 +1,77 @@ +/* sample-bdb.txt - BerkeleyDB toy/sample + * + * Do a line-by-line comparison of this and sample-mdb.txt + */ + +/* + * Copyright 2015-2019 Leonid Yuriev . + * Copyright 2012-2015 Howard Chu, Symas Corp. + * Copyright 2015,2016 Peter-Service R&D LLC. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include +#include +#include + +int main(int argc,char * argv[]) +{ + int rc; + DB_ENV *env; + DB *dbi; + DBT key, data; + DB_TXN *txn; + DBC *cursor; + char sval[32], kval[32]; + + /* Note: Most error checking omitted for simplicity */ + +#define FLAGS (DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_INIT_MPOOL|DB_CREATE|DB_THREAD) + rc = db_env_create(&env, 0); + rc = env->open(env, "./testdb", FLAGS, 0664); + rc = db_create(&dbi, env, 0); + rc = env->txn_begin(env, NULL, &txn, 0); + rc = dbi->open(dbi, txn, "test.bdb", NULL, DB_BTREE, DB_CREATE, 0664); + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + key.size = sizeof(int); + key.data = sval; + data.size = sizeof(sval); + data.data = sval; + + sprintf(sval, "%03x %d foo bar", 32, 3141592); + rc = dbi->put(dbi, txn, &key, &data, 0); + rc = txn->commit(txn, 0); + if (rc) { + fprintf(stderr, "txn->commit: (%d) %s\n", rc, db_strerror(rc)); + goto leave; + } + rc = env->txn_begin(env, NULL, &txn, 0); + rc = dbi->cursor(dbi, txn, &cursor, 0); + key.flags = DB_DBT_USERMEM; + key.data = kval; + key.ulen = sizeof(kval); + data.flags = DB_DBT_USERMEM; + data.data = sval; + data.ulen = sizeof(sval); + while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) { + printf("key: %p %.*s, data: %p %.*s\n", + key.data, (int) key.size, (char *) key.data, + data.data, (int) data.size, (char *) data.data); + } + rc = cursor->c_close(cursor); + rc = txn->abort(txn); +leave: + rc = dbi->close(dbi, 0); + rc = env->close(env, 0); + return rc; +} diff --git a/contrib/db/libmdbx/tutorial/sample-mdbx.c b/contrib/db/libmdbx/tutorial/sample-mdbx.c new file mode 100644 index 00000000..991ab698 --- /dev/null +++ b/contrib/db/libmdbx/tutorial/sample-mdbx.c @@ -0,0 +1,112 @@ +/* sample-mdb.txt - MDB toy/sample + * + * Do a line-by-line comparison of this and sample-bdb.txt + */ + +/* + * Copyright 2017 Ilya Shipitsin . + * Copyright 2015-2019 Leonid Yuriev . + * Copyright 2012-2015 Howard Chu, Symas Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +#include "mdbx.h" +#include +#include + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + int rc; + MDBX_env *env = NULL; + MDBX_dbi dbi = 0; + MDBX_val key, data; + MDBX_txn *txn = NULL; + MDBX_cursor *cursor = NULL; + char sval[32]; + + rc = mdbx_env_create(&env); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_env_create: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + rc = mdbx_env_open(env, "./example-db", + MDBX_NOSUBDIR | MDBX_COALESCE | MDBX_LIFORECLAIM, 0664); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_env_open: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + rc = mdbx_txn_begin(env, NULL, 0, &txn); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_txn_begin: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + rc = mdbx_dbi_open(txn, NULL, 0, &dbi); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_dbi_open: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + key.iov_len = sizeof(int); + key.iov_base = sval; + data.iov_len = sizeof(sval); + data.iov_base = sval; + + sprintf(sval, "%03x %d foo bar", 32, 3141592); + rc = mdbx_put(txn, dbi, &key, &data, 0); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_put: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + rc = mdbx_txn_commit(txn); + if (rc) { + fprintf(stderr, "mdbx_txn_commit: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + txn = NULL; + + rc = mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_txn_begin: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + rc = mdbx_cursor_open(txn, dbi, &cursor); + if (rc != MDBX_SUCCESS) { + fprintf(stderr, "mdbx_cursor_open: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } + + int found = 0; + while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == 0) { + printf("key: %p %.*s, data: %p %.*s\n", key.iov_base, (int)key.iov_len, + (char *)key.iov_base, data.iov_base, (int)data.iov_len, + (char *)data.iov_base); + found += 1; + } + if (rc != MDBX_NOTFOUND || found == 0) { + fprintf(stderr, "mdbx_cursor_get: (%d) %s\n", rc, mdbx_strerror(rc)); + goto bailout; + } else { + rc = MDBX_SUCCESS; + } +bailout: + if (cursor) + mdbx_cursor_close(cursor); + if (txn) + mdbx_txn_abort(txn); + if (dbi) + mdbx_dbi_close(env, dbi); + if (env) + mdbx_env_close(env); + return (rc != MDBX_SUCCESS) ? EXIT_FAILURE : EXIT_SUCCESS; +} From e4c28d29e8bab4aecdd93220ecfcbd37bf703f7c Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 29 Aug 2019 22:48:15 +0200 Subject: [PATCH 02/66] few changes to fix compilation --- CMakeLists.txt | 4 +- contrib/CMakeLists.txt | 3 +- contrib/db/CMakeLists.txt | 7 +- contrib/db/libmdbx/dll.vcxproj | 223 --------------------------------- contrib/db/libmdbx/mdbx.sln | 97 -------------- contrib/db/libmdbx/src/osal.c | 2 + contrib/db/libmdbx/src/osal.h | 2 +- src/CMakeLists.txt | 2 +- 8 files changed, 13 insertions(+), 327 deletions(-) delete mode 100644 contrib/db/libmdbx/dll.vcxproj delete mode 100644 contrib/db/libmdbx/mdbx.sln diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e2a4a79..e0b9cb8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,9 @@ endif() set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers for MSVC") -include_directories(src contrib/eos_portable_archive contrib/db/liblmdb contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") +#include_directories(src contrib/eos_portable_archive contrib/db/liblmdb contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") +include_directories(src contrib/eos_portable_archive contrib/db/libmdbx contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") + add_definitions(-DSTATICLIB) set(TESTNET FALSE CACHE BOOL "Compile for testnet") diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index c1ea6bdd..7acb5249 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -9,7 +9,8 @@ add_subdirectory(ethereum) set_property(TARGET upnpc-static PROPERTY FOLDER "contrib/miniupnp") set_property(TARGET zlibstatic PROPERTY FOLDER "contrib") -set_property(TARGET lmdb PROPERTY FOLDER "contrib") +# set_property(TARGET lmdb PROPERTY FOLDER "contrib") +set_property(TARGET mdbx PROPERTY FOLDER "contrib") diff --git a/contrib/db/CMakeLists.txt b/contrib/db/CMakeLists.txt index eb5c8415..3ff49da1 100644 --- a/contrib/db/CMakeLists.txt +++ b/contrib/db/CMakeLists.txt @@ -1,7 +1,8 @@ -add_subdirectory(liblmdb) +# add_subdirectory(liblmdb) +add_subdirectory(libmdbx) if(MSVC) - target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) + # target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) else() # Warnings as used by LMDB itself (LMDB_0.9.23) - target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) + # target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) endif() diff --git a/contrib/db/libmdbx/dll.vcxproj b/contrib/db/libmdbx/dll.vcxproj deleted file mode 100644 index 5464c158..00000000 --- a/contrib/db/libmdbx/dll.vcxproj +++ /dev/null @@ -1,223 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {6D19209B-ECE7-4B9C-941C-0AA2B484F199} - Win32Proj - 8.1 - - - - DynamicLibrary - true - v140 - MultiByte - - - DynamicLibrary - false - v140 - true - MultiByte - - - DynamicLibrary - true - v140 - MultiByte - - - DynamicLibrary - false - v140 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - true - mdbx - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ - PreLinkEvent - - - false - $(SolutionDir)$(Platform)\$(Configuration)\ - mdbx - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ - PreLinkEvent - - - true - mdbx - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ - PreLinkEvent - - - false - mdbx - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\ - PreLinkEvent - - - - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - EnableAllWarnings - ProgramDatabase - Disabled - true - true - - - MachineX86 - true - Windows - ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) - - - Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) - $(IntermediateOutputPath)mdbx_ntdll_extra.lib - $(ProjectDir)src/ntdll.def - lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) - - - - - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) - MultiThreadedDLL - EnableAllWarnings - ProgramDatabase - true - Full - AnySuitable - true - Size - true - true - true - false - All - - - MachineX86 - true - Windows - true - true - UseLinkTimeCodeGeneration - ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) - true - - - Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) - $(IntermediateOutputPath)mdbx_ntdll_extra.lib - $(ProjectDir)src/ntdll.def - lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) - - - - - ProgramDatabase - - - - - EnableAllWarnings - WIN64;_DEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - true - - - ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) - - - Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) - $(IntermediateOutputPath)mdbx_ntdll_extra.lib - $(ProjectDir)src/ntdll.def - lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) - - - - - WIN64;NDEBUG;_WINDOWS;_USRDLL;LIBMDBX_EXPORTS;MDBX_BUILD_DLL;MDBX_AVOID_CRT;%(PreprocessorDefinitions) - MultiThreadedDLL - true - Full - AnySuitable - true - Size - true - true - EnableAllWarnings - true - false - All - - - UseLinkTimeCodeGeneration - ntdll.lib;$(IntermediateOutputPath)mdbx_ntdll_extra.lib;kernel32.lib;advapi32.lib;%(AdditionalDependencies) - true - - - Generate fake-library mdbx_ntdll_extra.lib for $(PlatformTarget) - $(IntermediateOutputPath)mdbx_ntdll_extra.lib - $(ProjectDir)src/ntdll.def - lib.exe /def:%(Inputs) /out:%(Outputs) /machine:$(PlatformTarget) - - - - - - - - - - - - - - - - - - diff --git a/contrib/db/libmdbx/mdbx.sln b/contrib/db/libmdbx/mdbx.sln deleted file mode 100644 index f1462ab8..00000000 --- a/contrib/db/libmdbx/mdbx.sln +++ /dev/null @@ -1,97 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll.vcxproj", "{6D19209B-ECE7-4B9C-941C-0AA2B484F199}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0A147F9F-22D5-44E6-B389-218CFFB0C524}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_load", "src\tools\mdbx_load.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_dump", "src\tools\mdbx_dump.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_copy", "src\tools\mdbx_copy.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_chk", "src\tools\mdbx_chk.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mdbx_stat", "src\tools\mdbx_stat.vcxproj", "{15030120-5F7F-48F9-ABE5-DFC814F2A4BF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x64.ActiveCfg = Debug|x64 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x64.Build.0 = Debug|x64 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x86.ActiveCfg = Debug|Win32 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Debug|x86.Build.0 = Debug|Win32 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x64.ActiveCfg = Release|x64 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x64.Build.0 = Release|x64 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x86.ActiveCfg = Release|Win32 - {30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}.Release|x86.Build.0 = Release|Win32 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x64.ActiveCfg = Debug|x64 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x64.Build.0 = Debug|x64 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x86.ActiveCfg = Debug|Win32 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Debug|x86.Build.0 = Debug|Win32 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.ActiveCfg = Release|x64 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x64.Build.0 = Release|x64 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x86.ActiveCfg = Release|Win32 - {6D19209B-ECE7-4B9C-941C-0AA2B484F199}.Release|x86.Build.0 = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x64.ActiveCfg = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x64.Build.0 = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x86.ActiveCfg = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Debug|x86.Build.0 = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x64.ActiveCfg = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x64.Build.0 = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x86.ActiveCfg = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB}.Release|x86.Build.0 = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x64.ActiveCfg = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x64.Build.0 = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x86.ActiveCfg = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Debug|x86.Build.0 = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x64.ActiveCfg = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x64.Build.0 = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x86.ActiveCfg = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC}.Release|x86.Build.0 = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x64.ActiveCfg = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x64.Build.0 = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x86.ActiveCfg = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Debug|x86.Build.0 = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x64.ActiveCfg = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x64.Build.0 = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x86.ActiveCfg = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD}.Release|x86.Build.0 = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x64.ActiveCfg = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x64.Build.0 = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x86.ActiveCfg = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Debug|x86.Build.0 = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x64.ActiveCfg = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x64.Build.0 = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x86.ActiveCfg = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE}.Release|x86.Build.0 = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x64.ActiveCfg = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x64.Build.0 = Debug|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x86.ActiveCfg = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Debug|x86.Build.0 = Debug|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x64.ActiveCfg = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x64.Build.0 = Release|x64 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x86.ActiveCfg = Release|Win32 - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {15030120-5F7F-48F9-ABE5-DFC814F2A4BB} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} - {15030120-5F7F-48F9-ABE5-DFC814F2A4BC} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} - {15030120-5F7F-48F9-ABE5-DFC814F2A4BD} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} - {15030120-5F7F-48F9-ABE5-DFC814F2A4BE} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} - {15030120-5F7F-48F9-ABE5-DFC814F2A4BF} = {0A147F9F-22D5-44E6-B389-218CFFB0C524} - EndGlobalSection -EndGlobal diff --git a/contrib/db/libmdbx/src/osal.c b/contrib/db/libmdbx/src/osal.c index 993d83b0..48d6d4e2 100644 --- a/contrib/db/libmdbx/src/osal.c +++ b/contrib/db/libmdbx/src/osal.c @@ -18,6 +18,8 @@ #if defined(_WIN32) || defined(_WIN64) +#include + static int waitstatus2errcode(DWORD result) { switch (result) { case WAIT_OBJECT_0: diff --git a/contrib/db/libmdbx/src/osal.h b/contrib/db/libmdbx/src/osal.h index b690a5a5..dba9f798 100644 --- a/contrib/db/libmdbx/src/osal.h +++ b/contrib/db/libmdbx/src/osal.h @@ -753,7 +753,7 @@ typedef NTSTATUS(NTAPI *MDBX_NtFsControlFile)( OUT OPTIONAL PVOID OutputBuffer, IN ULONG OutputBufferLength); extern MDBX_NtFsControlFile mdbx_NtFsControlFile; -#ifndef _WIN32_WINNT_WIN8 +#if (_WIN32_WINNT < _WIN32_WINNT_WIN8) typedef struct _WIN32_MEMORY_RANGE_ENTRY { PVOID VirtualAddress; SIZE_T NumberOfBytes; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6f96312..fa8a230c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,7 +116,7 @@ add_library(wallet ${WALLET}) add_dependencies(wallet version ${PCH_LIB_NAME}) ENABLE_SHARED_PCH(WALLET) -target_link_libraries(currency_core lmdb) +target_link_libraries(currency_core mdbx) add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL}) add_dependencies(daemon version) From c78a1186332080a0aa5afe6e7475769c17f12dcf Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Thu, 29 Aug 2019 22:51:37 +0200 Subject: [PATCH 03/66] added cmakelist --- contrib/db/libmdbx/CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 contrib/db/libmdbx/CMakeLists.txt diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt new file mode 100644 index 00000000..b44b8002 --- /dev/null +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -0,0 +1,20 @@ + +set (mdbx_sources src/mdbx.c src/osal.c) + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}") + +if(NOT MSVC) + # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-missing-braces -Wno-aggregate-return") +endif() + +if(FREEBSD) + # add_definitions(-DMDB_DSYNC=O_SYNC) +endif() + +add_library(mdbx ${mdbx_sources}) + +target_link_libraries(mdbx PRIVATE ${CMAKE_THREAD_LIBS_INIT}) + +if(WIN32) + target_link_libraries(mdbx ntdll) +endif() From 5009a2046128202632d9d5b513bd13e3f5a97d24 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 00:21:53 +0200 Subject: [PATCH 04/66] added mdbx backend, first launch(got some errors) --- contrib/CMakeLists.txt | 2 +- contrib/db/CMakeLists.txt | 8 +- contrib/db/libmdbx/CMakeLists.txt | 2 +- src/CMakeLists.txt | 2 +- src/common/db_backend_mdbx.cpp | 396 +++++++++++++++++++++++ src/common/db_backend_mdbx.h | 62 ++++ src/currency_core/blockchain_storage.cpp | 4 +- src/currency_core/currency_config.h | 6 +- 8 files changed, 471 insertions(+), 11 deletions(-) create mode 100644 src/common/db_backend_mdbx.cpp create mode 100644 src/common/db_backend_mdbx.h diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 7acb5249..bcf3ed09 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -9,7 +9,7 @@ add_subdirectory(ethereum) set_property(TARGET upnpc-static PROPERTY FOLDER "contrib/miniupnp") set_property(TARGET zlibstatic PROPERTY FOLDER "contrib") -# set_property(TARGET lmdb PROPERTY FOLDER "contrib") +set_property(TARGET lmdb PROPERTY FOLDER "contrib") set_property(TARGET mdbx PROPERTY FOLDER "contrib") diff --git a/contrib/db/CMakeLists.txt b/contrib/db/CMakeLists.txt index 3ff49da1..57961a93 100644 --- a/contrib/db/CMakeLists.txt +++ b/contrib/db/CMakeLists.txt @@ -1,8 +1,8 @@ -# add_subdirectory(liblmdb) +add_subdirectory(liblmdb) add_subdirectory(libmdbx) if(MSVC) - # target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) + target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) else() - # Warnings as used by LMDB itself (LMDB_0.9.23) - # target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) + # Warnings as used by LMDB itself (LMDB_0.9.23) + target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) endif() diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index b44b8002..276dd96b 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -1,5 +1,5 @@ -set (mdbx_sources src/mdbx.c src/osal.c) +set (mdbx_sources src/mdbx.c src/osal.c src/lck-windows.c) include_directories("${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fa8a230c..772a4535 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,7 +116,7 @@ add_library(wallet ${WALLET}) add_dependencies(wallet version ${PCH_LIB_NAME}) ENABLE_SHARED_PCH(WALLET) -target_link_libraries(currency_core mdbx) +target_link_libraries(currency_core mdbx lmdb) add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL}) add_dependencies(daemon version) diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp new file mode 100644 index 00000000..66d2ed10 --- /dev/null +++ b/src/common/db_backend_mdbx.cpp @@ -0,0 +1,396 @@ +// Copyright (c) 2014-2019 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "db_backend_mdbx.h" +#include "misc_language.h" +#include "string_coding.h" +#include "profile_tools.h" +#include "util.h" + +#define BUF_SIZE 1024 + +#define CHECK_AND_ASSERT_MESS_MDBX_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(res == MDBX_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); +#define CHECK_AND_ASSERT_THROW_MESS_MDBX_DB(rc, mess) CHECK_AND_ASSERT_THROW_MES(res == MDBX_SUCCESS, "[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); +#define ASSERT_MES_AND_THROW_MDBX(rc, mess) ASSERT_MES_AND_THROW("[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); + +#undef LOG_DEFAULT_CHANNEL +#define LOG_DEFAULT_CHANNEL "mdbx" +// 'mdbx' channel is disabled by default + +namespace tools +{ + namespace db + { + mdbx_db_backend::mdbx_db_backend() : m_penv(AUTO_VAL_INIT(m_penv)) + { + + } + mdbx_db_backend::~mdbx_db_backend() + { + NESTED_TRY_ENTRY(); + + close(); + + NESTED_CATCH_ENTRY(__func__); + } + + bool mdbx_db_backend::open(const std::string& path_, uint64_t cache_sz) + { + int res = 0; + res = mdbx_env_create(&m_penv); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_create"); + + res = mdbx_env_set_maxdbs(m_penv, 15); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_set_maxdbs"); + + intptr_t size_lower = 0; + intptr_t size_now = -1; //don't change current database size + intptr_t size_upper = -1; //don't set db file size limit + intptr_t growth_step = 0x40000000; //increment step 1GB + intptr_t shrink_threshold = -1; + intptr_t pagesize = 0x00001000; //4kb + res = mdbx_env_set_geometry(m_penv, size_lower, size_now, size_upper, growth_step, shrink_threshold, pagesize); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_set_mapsize"); + + m_path = path_; +#ifdef WIN32 + m_path = epee::string_encoding::convert_ansii_to_utf8(m_path); +#endif + + CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path); + + res = mdbx_env_open(m_penv, m_path.c_str(), MDBX_NORDAHEAD , 0644); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_env_open, m_path=" << m_path); + + return true; + } + + bool mdbx_db_backend::open_container(const std::string& name, container_handle& h) + { + + MDBX_dbi dbi = AUTO_VAL_INIT(dbi); + begin_transaction(); + int res = mdbx_dbi_open(get_current_tx(), name.c_str(), MDBX_CREATE, &dbi); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_dbi_open with container name: " << name); + commit_transaction(); + h = static_cast(dbi); + return true; + } + + bool mdbx_db_backend::close() + { + { + std::lock_guard lock(m_cs); + for (auto& tx_thread : m_txs) + { + for (auto txe : tx_thread.second) + { + int res = mdbx_txn_commit(txe.ptx); + if (res != MDBX_SUCCESS) + { + LOG_ERROR("[DB ERROR]: On close tranactions: " << mdbx_strerror(res)); + } + } + } + + m_txs.clear(); + } + if (m_penv) + { + mdbx_env_close(m_penv); + m_penv = nullptr; + } + return true; + } + + bool mdbx_db_backend::begin_transaction(bool read_only) + { + if (!read_only) + { + LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED", LOG_LEVEL_3); + CRITICAL_SECTION_LOCK(m_write_exclusive_lock); + } + PROFILE_FUNC("mdbx_db_backend::begin_transaction"); + { + std::lock_guard lock(m_cs); + CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); + transactions_list& rtxlist = m_txs[std::this_thread::get_id()]; + MDBX_txn* pparent_tx = nullptr; + MDBX_txn* p_new_tx = nullptr; + bool parent_read_only = false; + if (rtxlist.size()) + { + pparent_tx = rtxlist.back().ptx; + parent_read_only = rtxlist.back().read_only; + } + + + if (pparent_tx && read_only) + { + ++rtxlist.back().count; + } + else + { + int res = 0; + unsigned int flags = 0; + if (read_only) + flags += MDBX_RDONLY; + + //don't use parent tx in write transactions if parent tx was read-only (restriction in mdbx) + //see "Nested transactions: Max 1 child, write txns only, no writemap" + if (pparent_tx && parent_read_only) + pparent_tx = nullptr; + + CHECK_AND_ASSERT_THROW_MES(m_penv, "m_penv==null, db closed"); + res = mdbx_txn_begin(m_penv, pparent_tx, flags, &p_new_tx); + if(res != MDBX_SUCCESS) + { + //Important: if mdbx_txn_begin is failed need to unlock previously locked mutex + CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); + //throw exception to avoid regular code execution + ASSERT_MES_AND_THROW_MDBX(res, "Unable to mdbx_txn_begin"); + } + + rtxlist.push_back(tx_entry()); + rtxlist.back().count = read_only ? 1 : 0; + rtxlist.back().ptx = p_new_tx; + rtxlist.back().read_only = read_only; + } + } + + + LOG_PRINT_L4("[DB] Transaction started"); + return true; + } + + MDBX_txn* mdbx_db_backend::get_current_tx() + { + std::lock_guard lock(m_cs); + auto& rtxlist = m_txs[std::this_thread::get_id()]; + CHECK_AND_ASSERT_MES(rtxlist.size(), nullptr, "Unable to find active tx for thread " << std::this_thread::get_id()); + return rtxlist.back().ptx; + } + + bool mdbx_db_backend::pop_tx_entry(tx_entry& txe) + { + std::lock_guard lock(m_cs); + auto it = m_txs.find(std::this_thread::get_id()); + CHECK_AND_ASSERT_MES(it != m_txs.end(), false, "[DB] Unable to find id cor current thread"); + CHECK_AND_ASSERT_MES(it->second.size(), false, "[DB] No active tx for current thread"); + + txe = it->second.back(); + + if (it->second.back().read_only && it->second.back().count == 0) + { + LOG_ERROR("Internal db tx state error: read_only and count readers == 0"); + } + + if ((it->second.back().read_only && it->second.back().count < 2) || (!it->second.back().read_only && it->second.back().count < 1)) + { + it->second.pop_back(); + if (!it->second.size()) + m_txs.erase(it); + } + else + { + --it->second.back().count; + } + return true; + } + + bool mdbx_db_backend::commit_transaction() + { + PROFILE_FUNC("mdbx_db_backend::commit_transaction"); + { + tx_entry txe = AUTO_VAL_INIT(txe); + bool r = pop_tx_entry(txe); + CHECK_AND_ASSERT_MES(r, false, "Unable to pop_tx_entry"); + + if (txe.count == 0 || (txe.read_only && txe.count == 1)) + { + int res = 0; + res = mdbx_txn_commit(txe.ptx); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_txn_commit (error " << res << ")"); + if (!txe.read_only && !txe.count) + { + CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); + LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED", LOG_LEVEL_3); + } + } + } + LOG_PRINT_L4("[DB] Transaction committed"); + return true; + } + + void mdbx_db_backend::abort_transaction() + { + { + tx_entry txe = AUTO_VAL_INIT(txe); + bool r = pop_tx_entry(txe); + CHECK_AND_ASSERT_MES(r, void(), "Unable to pop_tx_entry"); + if (txe.count == 0 || (txe.read_only && txe.count == 1)) + { + mdbx_txn_abort(txe.ptx); + if (!txe.read_only && !txe.count) + { + CRITICAL_SECTION_UNLOCK(m_write_exclusive_lock); + LOG_PRINT_CYAN("[DB " << m_path << "] WRITE UNLOCKED(ABORTED)", LOG_LEVEL_3); + } + } + + + } + LOG_PRINT_L4("[DB] Transaction aborted"); + } + + bool mdbx_db_backend::erase(container_handle h, const char* k, size_t ks) + { + int res = 0; + MDBX_val key = AUTO_VAL_INIT(key); + key.iov_base = (void*)k; + key.iov_len = ks; + + res = mdbx_del(get_current_tx(), static_cast(h), &key, nullptr); + if (res == MDBX_NOTFOUND) + return false; + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_del"); + return true; + } + + bool mdbx_db_backend::have_tx() + { + std::lock_guard lock(m_cs); + auto it = m_txs.find(std::this_thread::get_id()); + if (it == m_txs.end()) + return false; + return it->second.size() ? true : false; + } + + bool mdbx_db_backend::get(container_handle h, const char* k, size_t ks, std::string& res_buff) + { + PROFILE_FUNC("mdbx_db_backend::get"); + int res = 0; + MDBX_val key = AUTO_VAL_INIT(key); + MDBX_val data = AUTO_VAL_INIT(data); + key.iov_base = (void*)k; + key.iov_len = ks; + bool need_to_commit = false; + if (!have_tx()) + { + need_to_commit = true; + begin_transaction(true); + } + + res = mdbx_get(get_current_tx(), static_cast(h), &key, &data); + + if (need_to_commit) + commit_transaction(); + + if (res == MDBX_NOTFOUND) + return false; + + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_get, h: " << h << ", ks: " << ks); + res_buff.assign((const char*)data.iov_base, data.iov_len); + return true; + } + + bool mdbx_db_backend::clear(container_handle h) + { + int res = mdbx_drop(get_current_tx(), static_cast(h), 0); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_drop"); + return true; + } + + uint64_t mdbx_db_backend::size(container_handle h) + { + PROFILE_FUNC("mdbx_db_backend::size"); + MDBX_stat container_stat = AUTO_VAL_INIT(container_stat); + bool need_to_commit = false; + if (!have_tx()) + { + need_to_commit = true; + begin_transaction(true); + } + int res = mdbx_dbi_stat(get_current_tx(), static_cast(h), &container_stat, sizeof(MDBX_stat)); + if (need_to_commit) + commit_transaction(); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_stat"); + return container_stat.ms_entries; + } + + bool mdbx_db_backend::set(container_handle h, const char* k, size_t ks, const char* v, size_t vs) + { + PROFILE_FUNC("mdbx_db_backend::set"); + int res = 0; + MDBX_val key = AUTO_VAL_INIT(key); + MDBX_val data = AUTO_VAL_INIT(data); + key.iov_base = (void*)k; + key.iov_len = ks; + data.iov_base = (void*)v; + data.iov_len = vs; + + res = mdbx_put(get_current_tx(), static_cast(h), &key, &data, 0); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put"); + return true; + } + bool mdbx_db_backend::enumerate(container_handle h, i_db_callback* pcb) + { + CHECK_AND_ASSERT_MES(pcb, false, "null capback ptr passed to enumerate"); + MDBX_val key = AUTO_VAL_INIT(key); + MDBX_val data = AUTO_VAL_INIT(data); + + bool need_to_commit = false; + if (!have_tx()) + { + need_to_commit = true; + begin_transaction(true); + } + MDBX_cursor* cursor_ptr = nullptr; + int res = mdbx_cursor_open(get_current_tx(), static_cast(h), &cursor_ptr); + CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_cursor_open"); + CHECK_AND_ASSERT_MES(cursor_ptr, false, "cursor_ptr is null after mdbx_cursor_open"); + + uint64_t count = 0; + do + { + int res = mdbx_cursor_get(cursor_ptr, &key, &data, MDBX_NEXT); + if (res == MDBX_NOTFOUND) + break; + if (!pcb->on_enum_item(count, key.iov_base, key.iov_len, data.iov_base, data.iov_len)) + break; + count++; + } while (cursor_ptr); + + mdbx_cursor_close(cursor_ptr); + if (need_to_commit) + commit_transaction(); + return true; + } + + bool mdbx_db_backend::get_stat_info(tools::db::stat_info& si) + { + si = AUTO_VAL_INIT_T(tools::db::stat_info); + + MDBX_envinfo ei = AUTO_VAL_INIT(ei); + mdbx_env_info(m_penv, &ei, sizeof(MDBX_envinfo)); + si.map_size = ei.mi_mapsize; + + std::lock_guard lock(m_cs); + for (auto& e : m_txs) + { + for (auto& pr : e.second) + { + ++si.tx_count; + if(!pr.read_only) + ++si.write_tx_count; + } + } + return true; + } + } +} + +#undef LOG_DEFAULT_CHANNEL +#define LOG_DEFAULT_CHANNEL NULL diff --git a/src/common/db_backend_mdbx.h b/src/common/db_backend_mdbx.h new file mode 100644 index 00000000..f60e4028 --- /dev/null +++ b/src/common/db_backend_mdbx.h @@ -0,0 +1,62 @@ +// Copyright (c) 2014-2019 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once +#include + +#include "include_base_utils.h" + +#include "db_backend_base.h" +#include "db/libmdbx/mdbx.h" + + +namespace tools +{ + namespace db + { + class mdbx_db_backend : public i_db_backend + { + + struct tx_entry + { + MDBX_txn* ptx; + bool read_only; // needed for thread-top transaction, for figure out if we need to unlock exclusive access + size_t count; //count of read-only nested emulated transactions + }; + typedef std::list transactions_list; + + + std::string m_path; + MDBX_env *m_penv; + + boost::recursive_mutex m_cs; + boost::recursive_mutex m_write_exclusive_lock; + std::map m_txs; // size_t -> count of nested read_only transactions + bool pop_tx_entry(tx_entry& txe); + public: + mdbx_db_backend(); + ~mdbx_db_backend(); + + //----------------- i_db_backend ----------------------------------------------------- + bool close(); + bool begin_transaction(bool read_only = false); + bool commit_transaction(); + void abort_transaction(); + bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE); + bool open_container(const std::string& name, container_handle& h); + bool erase(container_handle h, const char* k, size_t s); + bool get(container_handle h, const char* k, size_t s, std::string& res_buff); + bool clear(container_handle h); + uint64_t size(container_handle h); + bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs); + bool enumerate(container_handle h, i_db_callback* pcb); + bool get_stat_info(tools::db::stat_info& si); + //------------------------------------------------------------------------------------- + bool have_tx(); + MDBX_txn* get_current_tx(); + + }; + } +} diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 827adc65..a7218a93 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -15,6 +15,7 @@ #include "include_base_utils.h" #include "common/db_backend_lmdb.h" +#include "common/db_backend_mdbx.h" #include "common/command_line.h" #include "blockchain_storage.h" @@ -30,7 +31,6 @@ #include "crypto/hash.h" #include "miner_common.h" #include "storages/portable_storage_template_helper.h" -#include "common/db_backend_lmdb.h" #include "basic_pow_helpers.h" #include "version.h" @@ -81,7 +81,7 @@ namespace } //------------------------------------------------------------------ -blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::shared_ptr(new tools::db::lmdb_db_backend), m_rw_lock), +blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::shared_ptr(new tools::db::mdbx_db_backend), m_rw_lock), m_db_blocks(m_db), m_db_blocks_index(m_db), m_db_transactions(m_db), diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 11d2ec06..10e32087 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -189,8 +189,10 @@ #define CURRENCY_POOLDATA_FOLDERNAME_OLD "poolstate" #define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD "blockchain" -#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_lmdb_v1" -#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_lmdb_v1" +//#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_lmdb_v1" +//#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_lmdb_v1" +#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_mdbx_v1" +#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_mdbx_v1" #define P2P_NET_DATA_FILENAME "p2pstate.bin" #define MINER_CONFIG_FILENAME "miner_conf.json" #define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin" From 704828f4faa31bc38c85bce58fcb02b088e45d80 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 00:44:40 +0200 Subject: [PATCH 05/66] fixed bug in set_geo params --- src/common/db_backend_mdbx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp index 66d2ed10..792d6f67 100644 --- a/src/common/db_backend_mdbx.cpp +++ b/src/common/db_backend_mdbx.cpp @@ -47,7 +47,7 @@ namespace tools intptr_t size_lower = 0; intptr_t size_now = -1; //don't change current database size - intptr_t size_upper = -1; //don't set db file size limit + intptr_t size_upper = 0x10000000000; //don't set db file size limit intptr_t growth_step = 0x40000000; //increment step 1GB intptr_t shrink_threshold = -1; intptr_t pagesize = 0x00001000; //4kb From 64b16b6f2501326ff0fd3d0c059d7c8d4080385e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 15:48:58 +0200 Subject: [PATCH 06/66] fixed warnings --- contrib/db/libmdbx/src/osal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/db/libmdbx/src/osal.h b/contrib/db/libmdbx/src/osal.h index dba9f798..4b15a942 100644 --- a/contrib/db/libmdbx/src/osal.h +++ b/contrib/db/libmdbx/src/osal.h @@ -89,7 +89,7 @@ #endif #if defined(_WIN32) || defined(_WIN64) -#define WIN32_LEAN_AND_MEAN +#d)(efine WIN32_LEAN_AND_MEAN #include #include #include From e2357dfe1367bf91cff91b253111f41d5280eb3d Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 21:30:55 +0200 Subject: [PATCH 07/66] added multiple os lock support files into cmake --- contrib/db/libmdbx/CMakeLists.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 276dd96b..d7d5d018 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -1,5 +1,18 @@ -set (mdbx_sources src/mdbx.c src/osal.c src/lck-windows.c) +set (mdbx_sources src/mdbx.c src/osal.c) + +if(WIN32) + message(STATUS "MDBX locks: lck-windows.c") + set (mdbx_sources "${mdbx_sources} src/lck-windows.c") +elseif(APPLE) + message(STATUS "MDBX locks: lck-posix.c") + set (mdbx_sources "${mdbx_sources} src/lck-posix.c") +else + message(STATUS "MDBX locks: lck-linux.c") + set (mdbx_sources "${mdbx_sources} src/lck-linux.c") +endif() + + include_directories("${CMAKE_CURRENT_SOURCE_DIR}") From a969d28c8eedb7c014dc3a94c296fbf1742e13c4 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 21:36:03 +0200 Subject: [PATCH 08/66] fixed mispring --- contrib/db/libmdbx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index d7d5d018..68ca42eb 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -7,7 +7,7 @@ if(WIN32) elseif(APPLE) message(STATUS "MDBX locks: lck-posix.c") set (mdbx_sources "${mdbx_sources} src/lck-posix.c") -else +else() message(STATUS "MDBX locks: lck-linux.c") set (mdbx_sources "${mdbx_sources} src/lck-linux.c") endif() From 1dee7bc139aa0b86c08b32e87cd1c3faf9108722 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 21:44:24 +0200 Subject: [PATCH 09/66] changed conditions for cmake --- contrib/db/libmdbx/CMakeLists.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 68ca42eb..452942bf 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -1,15 +1,13 @@ -set (mdbx_sources src/mdbx.c src/osal.c) - if(WIN32) message(STATUS "MDBX locks: lck-windows.c") - set (mdbx_sources "${mdbx_sources} src/lck-windows.c") + set (mdbx_sources src/mdbx.c src/lck-windows.c ) elseif(APPLE) message(STATUS "MDBX locks: lck-posix.c") - set (mdbx_sources "${mdbx_sources} src/lck-posix.c") + set (mdbx_sources src/mdbx.c src/lck-posix.c ) else() message(STATUS "MDBX locks: lck-linux.c") - set (mdbx_sources "${mdbx_sources} src/lck-linux.c") + set (mdbx_sources src/mdbx.c src/lck-linux.c ) endif() From e2b9de59a9ba464b3424efa3c12b133bd994093e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 21:51:33 +0200 Subject: [PATCH 10/66] added missing file --- contrib/db/libmdbx/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 452942bf..8a2095d8 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -1,13 +1,13 @@ if(WIN32) message(STATUS "MDBX locks: lck-windows.c") - set (mdbx_sources src/mdbx.c src/lck-windows.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/lck-windows.c ) elseif(APPLE) message(STATUS "MDBX locks: lck-posix.c") - set (mdbx_sources src/mdbx.c src/lck-posix.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/lck-posix.c ) else() message(STATUS "MDBX locks: lck-linux.c") - set (mdbx_sources src/mdbx.c src/lck-linux.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/lck-linux.c ) endif() From 2a0aafd7b3152a5cc8c6ea07a199f54f34b1c922 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 21:57:52 +0200 Subject: [PATCH 11/66] added missing version.c file --- contrib/db/libmdbx/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 8a2095d8..5200edcb 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -1,13 +1,13 @@ if(WIN32) message(STATUS "MDBX locks: lck-windows.c") - set (mdbx_sources src/mdbx.c src/osal.c src/lck-windows.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-windows.c ) elseif(APPLE) message(STATUS "MDBX locks: lck-posix.c") - set (mdbx_sources src/mdbx.c src/osal.c src/lck-posix.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-posix.c ) else() message(STATUS "MDBX locks: lck-linux.c") - set (mdbx_sources src/mdbx.c src/osal.c src/lck-linux.c ) + set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-linux.c ) endif() From 7a1de879720fec1a3703e8b39ad8f7d89c2f79fb Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 22:10:48 +0200 Subject: [PATCH 12/66] fixed mispring --- contrib/db/libmdbx/src/osal.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/db/libmdbx/src/osal.h b/contrib/db/libmdbx/src/osal.h index 4b15a942..c1f645bb 100644 --- a/contrib/db/libmdbx/src/osal.h +++ b/contrib/db/libmdbx/src/osal.h @@ -89,7 +89,9 @@ #endif #if defined(_WIN32) || defined(_WIN64) -#d)(efine WIN32_LEAN_AND_MEAN +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif #include #include #include From 07cc6e4a68c0b16a31d60e29a71952422796da54 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 23:09:04 +0200 Subject: [PATCH 13/66] re-configured platforms supportin cmake for libmdbx --- contrib/db/libmdbx/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 5200edcb..208f12dc 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -2,15 +2,15 @@ if(WIN32) message(STATUS "MDBX locks: lck-windows.c") set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-windows.c ) -elseif(APPLE) - message(STATUS "MDBX locks: lck-posix.c") - set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-posix.c ) -else() +elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") message(STATUS "MDBX locks: lck-linux.c") set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-linux.c ) +else + message(STATUS "MDBX locks: lck-posix.c") + set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-posix.c ) endif() - + include_directories("${CMAKE_CURRENT_SOURCE_DIR}") From b69a9b9bf4268316e2217a20f64de24651f808db Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 30 Aug 2019 23:10:18 +0200 Subject: [PATCH 14/66] added missed () --- contrib/db/libmdbx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 208f12dc..1b19c0f4 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -5,7 +5,7 @@ if(WIN32) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") message(STATUS "MDBX locks: lck-linux.c") set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-linux.c ) -else +else() message(STATUS "MDBX locks: lck-posix.c") set (mdbx_sources src/mdbx.c src/osal.c src/version.c src/lck-posix.c ) endif() From 84dfc6917aa70f0f5b5c6e616ab125b339a1fa82 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 31 Aug 2019 14:41:18 +0200 Subject: [PATCH 15/66] added cmake paramter to have mdbx as an option --- CMakeLists.txt | 8 +++++++- contrib/CMakeLists.txt | 4 +--- contrib/db/CMakeLists.txt | 21 ++++++++++++++------- src/CMakeLists.txt | 2 +- src/common/db_backend_lmdb.cpp | 3 +++ src/common/db_backend_lmdb.h | 3 +++ src/common/db_backend_mdbx.cpp | 5 +++++ src/common/db_backend_mdbx.h | 6 ++++++ src/currency_core/blockchain_storage.cpp | 5 ++--- src/currency_core/currency_config.h | 14 ++++++++++---- src/currency_core/tx_pool.cpp | 4 ++-- 11 files changed, 54 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0b9cb8c..5cd70463 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,7 +215,13 @@ else() endif() set(BUILD_TESTS FALSE CACHE BOOL "Build Zano tests") - +set(DB_ENGINE "lmdb" CACHE STRING "Select database engine") +if (DB_ENGINE STREQUAL "lmdb") + add_definitions(-DDB_ENGINE_LMDB) +elseif(DB_ENGINE STREQUAL "mdbx") + add_definitions(-DDB_ENGINE_MDBX) +endif() + add_subdirectory(contrib) add_subdirectory(src) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index bcf3ed09..6c204adb 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -9,9 +9,7 @@ add_subdirectory(ethereum) set_property(TARGET upnpc-static PROPERTY FOLDER "contrib/miniupnp") set_property(TARGET zlibstatic PROPERTY FOLDER "contrib") -set_property(TARGET lmdb PROPERTY FOLDER "contrib") -set_property(TARGET mdbx PROPERTY FOLDER "contrib") - +set_property(TARGET ${DB_ENGINE} PROPERTY FOLDER "contrib") diff --git a/contrib/db/CMakeLists.txt b/contrib/db/CMakeLists.txt index 57961a93..a0638716 100644 --- a/contrib/db/CMakeLists.txt +++ b/contrib/db/CMakeLists.txt @@ -1,8 +1,15 @@ -add_subdirectory(liblmdb) -add_subdirectory(libmdbx) -if(MSVC) - target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) -else() - # Warnings as used by LMDB itself (LMDB_0.9.23) - target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) + +if (DB_ENGINE STREQUAL "lmdb") + message("DB ENGINE: lmdb") + add_subdirectory(liblmdb) + if(MSVC) + target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172) + else() + # Warnings as used by LMDB itself (LMDB_0.9.23) + target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized) + endif() +elseif(DB_ENGINE STREQUAL "mdbx") + message("DB ENGINE: mdbx") + add_subdirectory(libmdbx) endif() + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 772a4535..1bc8e4d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -116,7 +116,7 @@ add_library(wallet ${WALLET}) add_dependencies(wallet version ${PCH_LIB_NAME}) ENABLE_SHARED_PCH(WALLET) -target_link_libraries(currency_core mdbx lmdb) +target_link_libraries(currency_core ${DB_ENGINE}) add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL}) add_dependencies(daemon version) diff --git a/src/common/db_backend_lmdb.cpp b/src/common/db_backend_lmdb.cpp index fdb289ff..13dea1cd 100644 --- a/src/common/db_backend_lmdb.cpp +++ b/src/common/db_backend_lmdb.cpp @@ -3,6 +3,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifdef DB_ENGINE_LMDB + #include "db_backend_lmdb.h" #include "misc_language.h" #include "string_coding.h" @@ -388,3 +390,4 @@ namespace tools #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL NULL +#endif \ No newline at end of file diff --git a/src/common/db_backend_lmdb.h b/src/common/db_backend_lmdb.h index 95c9d8a9..93effc98 100644 --- a/src/common/db_backend_lmdb.h +++ b/src/common/db_backend_lmdb.h @@ -4,6 +4,8 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once +#ifdef DB_ENGINE_LMDB + #include #include "include_base_utils.h" @@ -60,3 +62,4 @@ namespace tools }; } } +#endif \ No newline at end of file diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp index 792d6f67..ebe80baa 100644 --- a/src/common/db_backend_mdbx.cpp +++ b/src/common/db_backend_mdbx.cpp @@ -3,12 +3,15 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifdef DB_ENGINE_MDBX + #include "db_backend_mdbx.h" #include "misc_language.h" #include "string_coding.h" #include "profile_tools.h" #include "util.h" + #define BUF_SIZE 1024 #define CHECK_AND_ASSERT_MESS_MDBX_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(res == MDBX_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdbx_strerror(rc) << ", [message]: " << mess); @@ -394,3 +397,5 @@ namespace tools #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL NULL + +#endif \ No newline at end of file diff --git a/src/common/db_backend_mdbx.h b/src/common/db_backend_mdbx.h index f60e4028..f2b603ae 100644 --- a/src/common/db_backend_mdbx.h +++ b/src/common/db_backend_mdbx.h @@ -4,6 +4,9 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #pragma once + +#ifdef DB_ENGINE_MDBX + #include #include "include_base_utils.h" @@ -58,5 +61,8 @@ namespace tools MDBX_txn* get_current_tx(); }; + } } + +#endif \ No newline at end of file diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index a7218a93..2d7994c6 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -14,8 +14,7 @@ #include "include_base_utils.h" -#include "common/db_backend_lmdb.h" -#include "common/db_backend_mdbx.h" +#include "common/db_backend_selector.h" #include "common/command_line.h" #include "blockchain_storage.h" @@ -81,7 +80,7 @@ namespace } //------------------------------------------------------------------ -blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::shared_ptr(new tools::db::mdbx_db_backend), m_rw_lock), +blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(std::shared_ptr(new tools::db::default_db_backend), m_rw_lock), m_db_blocks(m_db), m_db_blocks_index(m_db), m_db_transactions(m_db), diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 10e32087..8488f44a 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -189,10 +189,16 @@ #define CURRENCY_POOLDATA_FOLDERNAME_OLD "poolstate" #define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD "blockchain" -//#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_lmdb_v1" -//#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_lmdb_v1" -#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_mdbx_v1" -#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_mdbx_v1" + +#ifdef DB_ENGINE_LMDB + #define CURRENCY_BLOCKCHAINDATA_DB_ENGINE_NAME "lmdb" +#elif DB_ENGINE_MDBX + #define CURRENCY_BLOCKCHAINDATA_DB_ENGINE_NAME "mdbx" +#endif + +#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_" CURRENCY_BLOCKCHAINDATA_DB_ENGINE_NAME "_v1" +#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_" CURRENCY_BLOCKCHAINDATA_DB_ENGINE_NAME "_v1" + #define P2P_NET_DATA_FILENAME "p2pstate.bin" #define MINER_CONFIG_FILENAME "miner_conf.json" #define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin" diff --git a/src/currency_core/tx_pool.cpp b/src/currency_core/tx_pool.cpp index 6803ac16..32fde76b 100644 --- a/src/currency_core/tx_pool.cpp +++ b/src/currency_core/tx_pool.cpp @@ -9,7 +9,7 @@ #include #include -#include "common/db_backend_lmdb.h" +#include "common/db_backend_selector.h" #include "tx_pool.h" #include "currency_boost_serialization.h" #include "currency_core/currency_config.h" @@ -42,7 +42,7 @@ namespace currency tx_memory_pool::tx_memory_pool(blockchain_storage& bchs, i_currency_protocol* pprotocol) : m_blockchain(bchs), m_pprotocol(pprotocol), - m_db(std::shared_ptr(new tools::db::lmdb_db_backend), m_dummy_rw_lock), + m_db(std::shared_ptr(new tools::db::default_db_backend), m_dummy_rw_lock), m_db_transactions(m_db), m_db_black_tx_list(m_db), m_db_solo_options(m_db), From eb4a10e18e7a32d272b5fea30c018b7370b79d32 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 31 Aug 2019 14:48:02 +0200 Subject: [PATCH 16/66] added missing file + code cleanup --- contrib/db/libmdbx/CMakeLists.txt | 8 -------- src/common/db_backend_selector.h | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 src/common/db_backend_selector.h diff --git a/contrib/db/libmdbx/CMakeLists.txt b/contrib/db/libmdbx/CMakeLists.txt index 1b19c0f4..0a1d1044 100644 --- a/contrib/db/libmdbx/CMakeLists.txt +++ b/contrib/db/libmdbx/CMakeLists.txt @@ -14,14 +14,6 @@ endif() include_directories("${CMAKE_CURRENT_SOURCE_DIR}") -if(NOT MSVC) - # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-missing-braces -Wno-aggregate-return") -endif() - -if(FREEBSD) - # add_definitions(-DMDB_DSYNC=O_SYNC) -endif() - add_library(mdbx ${mdbx_sources}) target_link_libraries(mdbx PRIVATE ${CMAKE_THREAD_LIBS_INIT}) diff --git a/src/common/db_backend_selector.h b/src/common/db_backend_selector.h new file mode 100644 index 00000000..e2f37bb0 --- /dev/null +++ b/src/common/db_backend_selector.h @@ -0,0 +1,21 @@ +// Copyright (c) 2014-2019 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once + +#include "db_backend_lmdb.h" +#include "db_backend_mdbx.h" + +namespace tools +{ + namespace db + { +#ifdef DB_ENGINE_LMDB + typedef lmdb_db_backend default_db_backend; +#elif DB_ENGINE_MDBX + typedef mdbx_db_backend default_db_backend; +#endif + } +} \ No newline at end of file From b2036b8c97fad7fd32b00b9eb9822c17b7c9963b Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 27 Sep 2019 22:47:24 +0200 Subject: [PATCH 17/66] fixed warnings --- CMakeLists.txt | 3 +-- contrib/CMakeLists.txt | 3 ++- src/common/ntp.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cd70463..276fc1ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,8 +37,7 @@ endif() set(USE_PCH FALSE CACHE BOOL "Use shared precompiled headers for MSVC") -#include_directories(src contrib/eos_portable_archive contrib/db/liblmdb contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") -include_directories(src contrib/eos_portable_archive contrib/db/libmdbx contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") +include_directories(src contrib/eos_portable_archive contrib contrib/epee/include "${CMAKE_BINARY_DIR}/version" "${CMAKE_BINARY_DIR}/contrib/zlib") add_definitions(-DSTATICLIB) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 09138237..36f7053c 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -12,7 +12,8 @@ set_property(TARGET zlibstatic PROPERTY FOLDER "contrib") set_property(TARGET ${DB_ENGINE} PROPERTY FOLDER "contrib") if(MSVC) - set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267") + set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4244 /wd4267") + set_property(TARGET zlibstatic APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4267 /wd4267") else() set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value -Wno-implicit-fallthrough -Wno-discarded-qualifiers ") set_property(TARGET zlibstatic APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value -Wno-implicit-fallthrough -Wno-discarded-qualifiers ") diff --git a/src/common/ntp.cpp b/src/common/ntp.cpp index 84a23b0a..84b40f8d 100644 --- a/src/common/ntp.cpp +++ b/src/common/ntp.cpp @@ -201,7 +201,7 @@ namespace tools udp_blocking_client ubc(sender_endpoint, socket, io_service); boost::system::error_code ec; - size_t len = ubc.receive(boost::asio::buffer(&packet_received, sizeof packet_received), boost::posix_time::seconds(timeout_sec), ec); + size_t len = ubc.receive(boost::asio::buffer(&packet_received, sizeof packet_received), boost::posix_time::seconds(static_cast(timeout_sec)), ec); if (ec) { LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): boost error: " << ec.message()); From e3cc89846e4fd60221c0032e3aa954d465d4c42a Mon Sep 17 00:00:00 2001 From: sowle Date: Wed, 9 Oct 2019 16:01:33 +0300 Subject: [PATCH 18/66] wallet: make sure there's enough disk space on load, store and wallet generation (simplewallet + GUI) #57 --- src/wallet/wallet2.cpp | 89 +++++++++++++++++++++++++++++++++++++----- src/wallet/wallet2.h | 35 +++++++++-------- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5095a56f..1352b1f1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -28,6 +28,8 @@ using namespace epee; #include "version.h" using namespace currency; +#define MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES (100*1024*1024) // 100 MB + #undef LOG_DEFAULT_CHANNEL #define LOG_DEFAULT_CHANNEL "wallet" ENABLE_CHANNEL_BY_DEFAULT("wallet") @@ -1965,6 +1967,9 @@ void wallet2::generate(const std::wstring& path, const std::string& pass) WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(validate_password(pass), "new wallet generation failed: password contains forbidden characters") clear(); prepare_file_names(path); + + check_for_free_space_and_throw_if_it_lacks(m_wallet_file); + m_password = pass; m_account.generate(); init_log_prefix(); @@ -2000,6 +2005,9 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password) { clear(); prepare_file_names(wallet_); + + check_for_free_space_and_throw_if_it_lacks(m_wallet_file); + m_password = password; std::string keys_buff; @@ -2058,35 +2066,55 @@ void wallet2::store(const std::wstring& path_to_save, const std::string& passwor { LOG_PRINT_L0("(before storing: pending_key_images: " << m_pending_key_images.size() << ", pki file elements: " << m_pending_key_images_file_container.size() << ", tx_keys: " << m_tx_keys.size() << ")"); + check_for_free_space_and_throw_if_it_lacks(path_to_save); + + std::string ascii_path_to_save = epee::string_encoding::convert_to_ansii(path_to_save); + //prepare data std::string keys_buff; bool r = store_keys(keys_buff, password); - CHECK_AND_ASSERT_THROW_MES(r, "failed to store_keys for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file)); - - wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "failed to store_keys for wallet " << ascii_path_to_save); //store data - + wallet_file_binary_header wbh = AUTO_VAL_INIT(wbh); wbh.m_signature = WALLET_FILE_SIGNATURE; wbh.m_cb_keys = keys_buff.size(); //@#@ change it to proper wbh.m_cb_body = 1000; - std::string header_buff((const char*)&wbh, sizeof(wbh)); + uint64_t ts = m_core_runtime_config.get_core_time(); + + // save to tmp file, then rename + boost::filesystem::path tmp_file_path = boost::filesystem::path(path_to_save); + tmp_file_path += L".newtmp_" + std::to_wstring(ts); - //std::ofstream data_file; boost::filesystem::ofstream data_file; - data_file.open(path_to_save, std::ios_base::binary | std::ios_base::out | std::ios::trunc); - CHECK_AND_ASSERT_THROW_MES(!data_file.fail(), "failed to open binary wallet file for saving: " << epee::string_encoding::convert_to_ansii(m_wallet_file)); + data_file.open(tmp_file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(!data_file.fail(), "failed to open binary wallet file for saving: " << tmp_file_path.string()); data_file << header_buff << keys_buff; - WLT_LOG_L0("Storing to file..."); + + WLT_LOG_L0("Storing to " << tmp_file_path.string() << " ..."); r = tools::portble_serialize_obj_to_stream(*this, data_file); - CHECK_AND_ASSERT_THROW_MES(r, "failed to portble_serialize_obj_to_stream for wallet " << epee::string_encoding::convert_to_ansii(m_wallet_file)); + if (!r) + { + boost::filesystem::remove(tmp_file_path); // remove tmp file if smth went wrong + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "portble_serialize_obj_to_stream failed for wallet " << tmp_file_path.string()); + } data_file.flush(); data_file.close(); + + // for the sake of safety perform a double-renaming: wallet file -> old tmp, new tmp -> wallet file, remove old tmp + + boost::filesystem::path tmp_old_file_path = boost::filesystem::path(path_to_save); + tmp_old_file_path += L".oldtmp_" + std::to_wstring(ts); + + if (boost::filesystem::is_regular_file(path_to_save)) + boost::filesystem::rename(path_to_save, tmp_old_file_path); + boost::filesystem::rename(tmp_file_path, path_to_save); + boost::filesystem::remove(tmp_old_file_path); } //---------------------------------------------------------------------------------------------------- void wallet2::store_watch_only(const std::wstring& path_to_save, const std::string& password) const @@ -2134,6 +2162,47 @@ void wallet2::store_watch_only(const std::wstring& path_to_save, const std::stri wo.store(path_to_save, password); } //---------------------------------------------------------------------------------------------------- +void wallet2::check_for_free_space_and_throw_if_it_lacks(const std::wstring& wallet_filename, uint64_t exact_size_needed_if_known /* = UINT64_MAX */) +{ + namespace fs = boost::filesystem; + + try + { + fs::path wallet_file_path(wallet_filename); + fs::path base_path = wallet_file_path.parent_path(); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(fs::is_directory(base_path), "directory does not exist: " << base_path.string()); + + uint64_t min_free_size = exact_size_needed_if_known; + if (min_free_size == UINT64_MAX) + { + // if exact size needed is unknown -- determine it as + // twice the original wallet file size or MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES, which one is bigger + min_free_size = MINIMUM_REQUIRED_WALLET_FREE_SPACE_BYTES; + if (fs::is_regular_file(wallet_file_path)) + min_free_size = std::max(min_free_size, 2 * fs::file_size(wallet_file_path)); + } + else + { + min_free_size += 1024 * 1024 * 10; // add a little for FS overhead and so + } + + fs::space_info si = fs::space(base_path); + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(si.available > min_free_size, "free space at " << base_path.string() << " is too low: " << si.available << ", required minimum is: " << min_free_size); + } + catch (tools::error::wallet_common_error&) + { + throw; + } + catch (std::exception& e) + { + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "failed to determine free space: " << e.what()); + } + catch (...) + { + WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(false, "failed to determine free space: unknown exception"); + } +} +//---------------------------------------------------------------------------------------------------- uint64_t wallet2::unlocked_balance() const { uint64_t stub = 0; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 7d5cf1ba..e1fd1d63 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -47,22 +47,22 @@ ENABLE_CHANNEL_BY_DEFAULT("wallet"); // wallet-specific logging functions -#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L1(msg) LOG_PRINT_L1("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L2(msg) LOG_PRINT_L2("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L3(msg) LOG_PRINT_L3("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_L4(msg) LOG_PRINT_L4("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_ERROR(msg) LOG_ERROR("[W:" << m_log_prefix << "]" << msg) -#define WLT_LOG_BLUE(msg, log_level) LOG_PRINT_BLUE("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_CYAN(msg, log_level) LOG_PRINT_CYAN("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_GREEN(msg, log_level) LOG_PRINT_GREEN("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_MAGENTA(msg, log_level) LOG_PRINT_MAGENTA("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_RED(msg, log_level) LOG_PRINT_RED("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_LOG_YELLOW(msg, log_level) LOG_PRINT_YELLOW("[W:" << m_log_prefix << "]" << msg, log_level) -#define WLT_CHECK_AND_ASSERT_MES(expr, ret, msg) CHECK_AND_ASSERT_MES(expr, ret, "[W:" << m_log_prefix << "]" << msg) -#define WLT_CHECK_AND_ASSERT_MES_NO_RET(expr, msg) CHECK_AND_ASSERT_MES_NO_RET(expr, "[W:" << m_log_prefix << "]" << msg) -#define WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, "[W:" << m_log_prefix << "]" << msg) -#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "]" << msg) +#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L1(msg) LOG_PRINT_L1("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L2(msg) LOG_PRINT_L2("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L3(msg) LOG_PRINT_L3("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_L4(msg) LOG_PRINT_L4("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_ERROR(msg) LOG_ERROR("[W:" << m_log_prefix << "] " << msg) +#define WLT_LOG_BLUE(msg, log_level) LOG_PRINT_BLUE("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_CYAN(msg, log_level) LOG_PRINT_CYAN("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_GREEN(msg, log_level) LOG_PRINT_GREEN("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_MAGENTA(msg, log_level) LOG_PRINT_MAGENTA("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_RED(msg, log_level) LOG_PRINT_RED("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_LOG_YELLOW(msg, log_level) LOG_PRINT_YELLOW("[W:" << m_log_prefix << "] " << msg, log_level) +#define WLT_CHECK_AND_ASSERT_MES(expr, ret, msg) CHECK_AND_ASSERT_MES(expr, ret, "[W:" << m_log_prefix << "] " << msg) +#define WLT_CHECK_AND_ASSERT_MES_NO_RET(expr, msg) CHECK_AND_ASSERT_MES_NO_RET(expr, "[W:" << m_log_prefix << "] " << msg) +#define WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg) +#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg) class test_generator; @@ -729,6 +729,7 @@ namespace tools std::string get_log_prefix() const { return m_log_prefix; } static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const money_transfer2_details& td); + private: void add_transfers_to_expiration_list(const std::vector& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id); void remove_transfer_from_expiration_list(uint64_t transfer_index); @@ -840,7 +841,7 @@ private: void exception_handler(); void exception_handler() const; uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id); - + void check_for_free_space_and_throw_if_it_lacks(const std::wstring& path, uint64_t exact_size_needed_if_known = UINT64_MAX); From 02c04aa30051566a958ee8f1ace67b34c9c270fb Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 11:12:28 +0300 Subject: [PATCH 19/66] p2p: filter out old clients by version + unittest #128 --- .../currency_protocol_handler.inl | 3 +- src/p2p/net_node.inl | 6 +++ src/version.h.in | 40 +++++++++++++++ tests/unit_tests/p2p_client_version.cpp | 51 +++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/p2p_client_version.cpp diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl index e4588490..a5ee5b1f 100644 --- a/src/currency_protocol/currency_protocol_handler.inl +++ b/src/currency_protocol/currency_protocol_handler.inl @@ -174,7 +174,8 @@ namespace currency "That means that current software is outdated, please updated it." << "Current heigh lay under checkpoints on remote host, so it is not possible validate this transactions on local host, disconnecting.", LOG_LEVEL_0); return false; - }else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height) + } + else if (m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() < hshd.last_checkpoint_height) { LOG_PRINT_MAGENTA("Remote node have longer checkpoints zone( " << hshd.last_checkpoint_height << ") " << "that local (" << m_core.get_blockchain_storage().get_checkpoints().get_top_checkpoint_height() << ")" << diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 2ce7099c..72cadef1 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -483,6 +483,12 @@ namespace nodetool return; } + if (!check_remote_client_version(rsp.payload_data.client_version)) + { + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + return; + } + if(!handle_maintainers_entry(rsp.maintrs_entry)) { LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); diff --git a/src/version.h.in b/src/version.h.in index e68df5ce..61d98d65 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,3 +1,4 @@ +#pragma once #include "misc_language.h" #define BUILD_COMMIT_ID "@VERSION@" @@ -10,3 +11,42 @@ #define PROJECT_VERSION_BUILD_NO 67 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" + + + +inline bool check_remote_client_version(const std::string& client_ver) +{ + std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id + v = v.substr(0, v.rfind('.')); // remove build number + + int v_major = 0, v_minor = 0, v_revision = 0; + + size_t dot_pos = v.find('.'); + if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) + return false; + + v = v.substr(dot_pos + 1); + dot_pos = v.find('.'); + if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) + return false; + + if (dot_pos != std::string::npos) + { + // revision + v = v.substr(dot_pos + 1); + if (!epee::string_tools::string_to_num_fast(v, v_revision)) + return false; + } + + // got v_major, v_minor, v_revision + + // allow 1.1.x and greater + + if (v_major < 1) + return false; + + if (v_major == 1 && v_minor < 1) + return false; + + return true; +} diff --git a/tests/unit_tests/p2p_client_version.cpp b/tests/unit_tests/p2p_client_version.cpp new file mode 100644 index 00000000..73b44559 --- /dev/null +++ b/tests/unit_tests/p2p_client_version.cpp @@ -0,0 +1,51 @@ +// Copyright (c) 2019 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "gtest/gtest.h" +#include "version.h" + +TEST(p2p_client_version, test_1) +{ + // good + + ASSERT_TRUE(check_remote_client_version("10.101.999.28391[deadbeef31337-dirty]")); + ASSERT_TRUE(check_remote_client_version("1.1.9.237[aabcd]")); + ASSERT_TRUE(check_remote_client_version("3.0.2.7[aa00bcd]")); + ASSERT_TRUE(check_remote_client_version("1.4.2.7[aabcd]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); + + ASSERT_TRUE(check_remote_client_version("1.1.2.67[88f868c]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8]")); + ASSERT_TRUE(check_remote_client_version("1.1.2.67[26c00a8-dirty]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.65[40ba8cd]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.63[b0f376b]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.58[14bd668]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.58[9920eb7]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.58[e0d4ad8]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.57[b77b915]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae]")); + ASSERT_TRUE(check_remote_client_version("1.1.0.57[7dd61ae-dirty]")); + + ASSERT_TRUE(check_remote_client_version("1.1.0.57")); + + // bad + + ASSERT_FALSE(check_remote_client_version("")); + ASSERT_FALSE(check_remote_client_version(" ")); + + ASSERT_FALSE(check_remote_client_version("1.0.999")); + + ASSERT_FALSE(check_remote_client_version("1.0.40[f77f0d7]")); + ASSERT_FALSE(check_remote_client_version("1.0.40[734b726]")); + ASSERT_FALSE(check_remote_client_version("1.0.41[488e369]")); + + ASSERT_FALSE(check_remote_client_version("1.0.40[469]")); + ASSERT_FALSE(check_remote_client_version("1.0.39[f77f0d7]")); + ASSERT_FALSE(check_remote_client_version("1.0.38[f77f0d7-dirty]")); + ASSERT_FALSE(check_remote_client_version("1.0.37[7dd61ae-dirty]")); + ASSERT_FALSE(check_remote_client_version("0.0.500[000]")); +} From 609969799e0f8b7a5a7dc225b1377d300f101f69 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 16:22:34 +0300 Subject: [PATCH 20/66] p2p: check_remote_client_version() moved to more appropriate place --- src/common/util.cpp | 37 +++++++++++++++++++++++ src/common/util.h | 2 ++ src/p2p/net_node.inl | 2 +- src/version.h.in | 39 ------------------------- tests/unit_tests/p2p_client_version.cpp | 4 ++- 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index 999c5401..6fa15854 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -658,4 +658,41 @@ std::string get_nix_version_display_string() return static_cast(in.tellg()); } + bool check_remote_client_version(const std::string& client_ver) + { + std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id + v = v.substr(0, v.rfind('.')); // remove build number + + int v_major = 0, v_minor = 0, v_revision = 0; + + size_t dot_pos = v.find('.'); + if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) + return false; + + v = v.substr(dot_pos + 1); + dot_pos = v.find('.'); + if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) + return false; + + if (dot_pos != std::string::npos) + { + // revision + v = v.substr(dot_pos + 1); + if (!epee::string_tools::string_to_num_fast(v, v_revision)) + return false; + } + + // got v_major, v_minor, v_revision + + // allow 1.1.x and greater + + if (v_major < 1) + return false; + + if (v_major == 1 && v_minor < 1) + return false; + + return true; + } + } // namespace tools diff --git a/src/common/util.h b/src/common/util.h index 3360c345..87138ef0 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -30,6 +30,8 @@ namespace tools std::string get_default_user_dir(); std::string get_current_username(); std::string get_os_version_string(); + bool check_remote_client_version(const std::string& client_ver); + bool create_directories_if_necessary(const std::string& path); std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 72cadef1..93ee7a61 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -483,7 +483,7 @@ namespace nodetool return; } - if (!check_remote_client_version(rsp.payload_data.client_version)) + if (!tools::check_remote_client_version(rsp.payload_data.client_version)) { LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); return; diff --git a/src/version.h.in b/src/version.h.in index 61d98d65..bbd5c6c5 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -11,42 +11,3 @@ #define PROJECT_VERSION_BUILD_NO 67 #define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO) #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]" - - - -inline bool check_remote_client_version(const std::string& client_ver) -{ - std::string v = client_ver.substr(0, client_ver.find('[')); // remove commit id - v = v.substr(0, v.rfind('.')); // remove build number - - int v_major = 0, v_minor = 0, v_revision = 0; - - size_t dot_pos = v.find('.'); - if (dot_pos == std::string::npos || !epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_major)) - return false; - - v = v.substr(dot_pos + 1); - dot_pos = v.find('.'); - if (!epee::string_tools::string_to_num_fast(v.substr(0, dot_pos), v_minor)) - return false; - - if (dot_pos != std::string::npos) - { - // revision - v = v.substr(dot_pos + 1); - if (!epee::string_tools::string_to_num_fast(v, v_revision)) - return false; - } - - // got v_major, v_minor, v_revision - - // allow 1.1.x and greater - - if (v_major < 1) - return false; - - if (v_major == 1 && v_minor < 1) - return false; - - return true; -} diff --git a/tests/unit_tests/p2p_client_version.cpp b/tests/unit_tests/p2p_client_version.cpp index 73b44559..3761e36a 100644 --- a/tests/unit_tests/p2p_client_version.cpp +++ b/tests/unit_tests/p2p_client_version.cpp @@ -3,10 +3,12 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "gtest/gtest.h" -#include "version.h" +#include "common/util.h" TEST(p2p_client_version, test_1) { + using namespace tools; + // good ASSERT_TRUE(check_remote_client_version("10.101.999.28391[deadbeef31337-dirty]")); From adc08088aac7ddd7a77a118cce3debad72848cfd Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 10 Oct 2019 23:47:15 +0300 Subject: [PATCH 21/66] p2p: fix for filtering old clients mechanism #128 --- src/p2p/net_node.inl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 93ee7a61..4fa28d74 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -485,7 +485,7 @@ namespace nodetool if (!tools::check_remote_client_version(rsp.payload_data.client_version)) { - LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong client version: " << rsp.payload_data.client_version << ", closing connection."); return; } @@ -1310,6 +1310,14 @@ namespace nodetool return 1; } + if (!tools::check_remote_client_version(rsp.payload_data.client_version)) + { + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + drop_connection(context); + add_ip_fail(context.m_remote_ip); + return 1; + } + if(!handle_maintainers_entry(arg.maintrs_entry)) { LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong maintainers entry!, closing connection."); From 47d61b64244235911d754994897289bbab5511aa Mon Sep 17 00:00:00 2001 From: sowle Date: Fri, 11 Oct 2019 00:02:41 +0300 Subject: [PATCH 22/66] p2p: fix for filtering old clients mechanism #128 (2) --- src/p2p/net_node.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 4fa28d74..d81eaeea 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1310,9 +1310,9 @@ namespace nodetool return 1; } - if (!tools::check_remote_client_version(rsp.payload_data.client_version)) + if (!tools::check_remote_client_version(arg.payload_data.client_version)) { - LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << rsp.payload_data.client_version << ", closing connection."); + LOG_PRINT_CCONTEXT_L2("COMMAND_HANDSHAKE: wrong client version: " << arg.payload_data.client_version << ", closing connection."); drop_connection(context); add_ip_fail(context.m_remote_ip); return 1; From 1b6fff2bf39c436d43687b801c402382f9cd5da9 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 11 Oct 2019 19:52:04 +0200 Subject: [PATCH 23/66] fixed resync market issue --- src/daemon/daemon.cpp | 9 ++++-- ...MARKETPLACE_GLOBAL_GET_OFFERS_request.json | 28 +++++++++++++++++++ ...MAND_MARKETPLACE_PUSH_OFFER_request_2.json | 2 +- 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 utils/test_api_files/COMMAND_MARKETPLACE_GLOBAL_GET_OFFERS_request.json diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index eccdec13..31ea716c 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -106,7 +106,7 @@ int main(int argc, char* argv[]) //_CrtSetAllocHook(alloc_hook); #endif - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); + log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0); log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet"); LOG_PRINT_L0("Starting..."); @@ -220,7 +220,7 @@ int main(int argc, char* argv[]) //create objects and link them bc_services::bc_offers_service offers_service(nullptr); - offers_service.set_disabled(true); + offers_service.set_disabled(true); //disable by default currency::core ccore(NULL); currency::t_currency_protocol_handler cprotocol(ccore, NULL ); p2psrv_t p2psrv(cprotocol); @@ -237,8 +237,10 @@ int main(int argc, char* argv[]) if (command_line::get_arg(vm, command_line::arg_enable_offers_service)) { + offers_service.set_disabled(false); ccore.get_blockchain_storage().get_attachment_services_manager().add_service(&offers_service); } + std::shared_ptr stratum_server_ptr; @@ -270,9 +272,10 @@ int main(int argc, char* argv[]) CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize p2p server."); LOG_PRINT_L0("P2p server initialized OK on port: " << p2psrv.get_this_peer_port()); + tools::miniupnp_helper upnp_helper; + if (!command_line::get_arg(vm, command_line::arg_disable_upnp)) { - tools::miniupnp_helper upnp_helper; LOG_PRINT_L0("Starting UPnP"); upnp_helper.start_regular_mapping(p2psrv.get_this_peer_port(), p2psrv.get_this_peer_port(), 20*60*1000); } diff --git a/utils/test_api_files/COMMAND_MARKETPLACE_GLOBAL_GET_OFFERS_request.json b/utils/test_api_files/COMMAND_MARKETPLACE_GLOBAL_GET_OFFERS_request.json new file mode 100644 index 00000000..9bd27c31 --- /dev/null +++ b/utils/test_api_files/COMMAND_MARKETPLACE_GLOBAL_GET_OFFERS_request.json @@ -0,0 +1,28 @@ +{ + "jsonrpc": "2.0", + "id": 0, + "method": "marketplace_global_get_offers_ex", + "params": { + "filter": { + "amount_low_limit": 0, + "amount_up_limit": 0, + "bonus": false, + "category": "", + "fake": false, + "keyword": "", + "limit": 100, + "location_city": "", + "location_country": "", + "offer_type_mask": 0, + "offset": 0, + "order_by": 0, + "primary": "", + "rate_low_limit": "0.000000", + "rate_up_limit": "0.000000", + "reverse": false, + "target": "", + "timestamp_start": 0, + "timestamp_stop": 0 + } + } +} \ No newline at end of file diff --git a/utils/test_api_files/COMMAND_MARKETPLACE_PUSH_OFFER_request_2.json b/utils/test_api_files/COMMAND_MARKETPLACE_PUSH_OFFER_request_2.json index 8a17821d..3c4e7d17 100644 --- a/utils/test_api_files/COMMAND_MARKETPLACE_PUSH_OFFER_request_2.json +++ b/utils/test_api_files/COMMAND_MARKETPLACE_PUSH_OFFER_request_2.json @@ -17,7 +17,7 @@ "ot": 1, "p": "USD", "pt": "Credit cards, BTC, ZANO, ETH", - "t": "Mining farm built by Gigabyted" + "t": "Mining farm built by Gigabyted[2]" } } } \ No newline at end of file From fdddf58ebf05d12170ddbd57614a30ae1a59a89a Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sun, 13 Oct 2019 01:27:03 +0200 Subject: [PATCH 24/66] attempt to fix #127 --- contrib/epee/include/net/abstract_tcp_server2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 07d3cf88..4501a37c 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -133,12 +133,12 @@ class connection volatile uint32_t& m_ref_sockets_count; i_connection_filter*& m_pfilter; volatile bool m_is_multithreaded; + std::list>> m_self_refs; // add_ref/release support + critical_section m_self_refs_lock; //this should be the last one, because it could be wait on destructor, while other activities possible on other threads t_protocol_handler m_protocol_handler; //typename t_protocol_handler::config_type m_dummy_config; - std::list>> m_self_refs; // add_ref/release support - critical_section m_self_refs_lock; }; /************************************************************************/ From 5dabc72bdabffe16c482a6c5d9b1677239442062 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sun, 13 Oct 2019 01:38:55 +0200 Subject: [PATCH 25/66] added huge comment to prevent future shoot in the foot --- contrib/epee/include/net/abstract_tcp_server2.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 4501a37c..7a8fccf5 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -135,10 +135,10 @@ class connection volatile bool m_is_multithreaded; std::list>> m_self_refs; // add_ref/release support critical_section m_self_refs_lock; - - //this should be the last one, because it could be wait on destructor, while other activities possible on other threads - t_protocol_handler m_protocol_handler; - //typename t_protocol_handler::config_type m_dummy_config; + + t_protocol_handler m_protocol_handler; + //this should be the last line with m_protocol_handler, because it could be wait on destructor, while other activities possible on other threads + //DON'T ADD ANYTHING HERE!!! }; /************************************************************************/ From ac8401db73717b7458302282b71acfaf91fdd595 Mon Sep 17 00:00:00 2001 From: sowle Date: Mon, 14 Oct 2019 15:28:35 +0300 Subject: [PATCH 26/66] temporary disable daemon stop on low free space due to issue #133 --- src/daemon/daemon.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 31ea716c..f81d1a5a 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -75,10 +75,16 @@ struct core_critical_error_handler_t : public currency::i_critical_error_handler LOG_ERROR(ENDL << ENDL << "Free space at data directory is critically low (" << available / (1024 * 1024) << " MB, while " << required / (1024 * 1024) << " MB is required), daemon will stop immediately" << ENDL << ENDL); + /* + temporary disable daemon stop due to issue #133 + */ + return false; + /* // stop handling dch.stop_handling(); p2psrv.send_stop_signal(); return true; // the caller must stop processing + */ } daemon_commands_handler& dch; From 8ca969448aa986963b1d56eb1f5aba4c9672165d Mon Sep 17 00:00:00 2001 From: zetov Date: Mon, 14 Oct 2019 23:07:03 +0300 Subject: [PATCH 27/66] price update + password text fix (#134) --- src/gui/qt-daemon/html/assets/i18n/en.json | 4 +- src/gui/qt-daemon/html/main.js | 82 +++++++++---------- src/gui/qt-daemon/html/main.js.map | 2 +- src/gui/qt-daemon/html/polyfills.js | 6 +- src/gui/qt-daemon/html/polyfills.js.map | 2 +- src/gui/qt-daemon/html/styles.js | 4 +- src/gui/qt-daemon/html/styles.js.map | 2 +- .../html_source/src/app/app.component.ts | 12 ++- .../html_source/src/assets/i18n/en.json | 4 +- 9 files changed, 63 insertions(+), 55 deletions(-) diff --git a/src/gui/qt-daemon/html/assets/i18n/en.json b/src/gui/qt-daemon/html/assets/i18n/en.json index a8987454..8376eef7 100644 --- a/src/gui/qt-daemon/html/assets/i18n/en.json +++ b/src/gui/qt-daemon/html/assets/i18n/en.json @@ -166,14 +166,14 @@ }, "MASTER_PASSWORD": { "TITLE": "Update master password", - "OLD": "Old password", + "OLD": "Current password", "NEW": "New password", "CONFIRM": "New password confirmation", "BUTTON": "Save" }, "FORM_ERRORS": { "PASS_REQUIRED": "Password is required", - "PASS_NOT_MATCH": "Old password not match", + "PASS_NOT_MATCH": "Incorrect password", "CONFIRM_NOT_MATCH": "Confirm password not match" }, "LAST_BUILD": "Current build: {{value}}", diff --git a/src/gui/qt-daemon/html/main.js b/src/gui/qt-daemon/html/main.js index 7f823d3e..8e7bab65 100644 --- a/src/gui/qt-daemon/html/main.js +++ b/src/gui/qt-daemon/html/main.js @@ -41,7 +41,7 @@ module.exports = "
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n \r\n
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".form-assign {\n margin: 2.4rem 0; }\n .form-assign .alias-name {\n width: 50%; }\n .form-assign .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-assign .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-assign .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n .assign-alias-tooltip {\n font-size: 1.3rem;\n line-height: 2rem;\n padding: 1rem 1.5rem;\n max-width: 46rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYXNzaWduLWFsaWFzL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGFzc2lnbi1hbGlhc1xcYXNzaWduLWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQTtFQUtsQjtFQUNFLGlCQUFpQjtFQUNqQixpQkFBaUI7RUFDakIsb0JBQW9CO0VBQ3BCLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvYXNzaWduLWFsaWFzL2Fzc2lnbi1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWFzc2lnbiB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuXHJcbiAgLmFsaWFzLW5hbWUge1xyXG4gICAgd2lkdGg6IDUwJTtcclxuICB9XHJcblxyXG4gIC5hbGlhcy1jb3N0IHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbWFyZ2luLXRvcDogMnJlbTtcclxuICB9XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuICAgICAgd2lkdGg6IDE1cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmFzc2lnbi1hbGlhcy10b29sdGlwIHtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuICBsaW5lLWhlaWdodDogMnJlbTtcclxuICBwYWRkaW5nOiAxcmVtIDEuNXJlbTtcclxuICBtYXgtd2lkdGg6IDQ2cmVtO1xyXG59XHJcbiJdfQ== */" +module.exports = ".form-assign {\n margin: 2.4rem 0; }\n .form-assign .alias-name {\n width: 50%; }\n .form-assign .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-assign .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-assign .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n .assign-alias-tooltip {\n font-size: 1.3rem;\n line-height: 2rem;\n padding: 1rem 1.5rem;\n max-width: 46rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYXNzaWduLWFsaWFzL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxhc3NpZ24tYWxpYXNcXGFzc2lnbi1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUE7RUFLbEI7RUFDRSxpQkFBaUI7RUFDakIsaUJBQWlCO0VBQ2pCLG9CQUFvQjtFQUNwQixnQkFBZ0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2Fzc2lnbi1hbGlhcy9hc3NpZ24tYWxpYXMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1hc3NpZ24ge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi5hc3NpZ24tYWxpYXMtdG9vbHRpcCB7XHJcbiAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgcGFkZGluZzogMXJlbSAxLjVyZW07XHJcbiAgbWF4LXdpZHRoOiA0NnJlbTtcclxufVxyXG4iXX0= */" /***/ }), @@ -4312,7 +4312,7 @@ module.exports = "
\r\n
\r\n
\r\n \r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: relative; }\n\n.form-create {\n margin: 2.4rem 0;\n width: 50%; }\n\n.form-create .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem; }\n\n.form-create .wrap-buttons button {\n margin: 0 0.7rem; }\n\n.form-create .wrap-buttons button.transparent-button {\n flex-basis: 50%; }\n\n.form-create .wrap-buttons button.select-button {\n flex-basis: 60%; }\n\n.form-create .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY3JlYXRlLXdhbGxldC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxjcmVhdGUtd2FsbGV0XFxjcmVhdGUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFGWjtJQUtJLGFBQWE7SUFDYixzQkFBc0IsRUFBQTs7QUFOMUI7TUFTTSxnQkFBZ0IsRUFBQTs7QUFUdEI7UUFZUSxlQUFlLEVBQUE7O0FBWnZCO1FBZ0JRLGVBQWUsRUFBQTs7QUFoQnZCO1FBb0JRLGFBQWEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2NyZWF0ZS13YWxsZXQvY3JlYXRlLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5mb3JtLWNyZWF0ZSB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcblxyXG4gICAgICAmLnRyYW5zcGFyZW50LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNTAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnNlbGVjdC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" +module.exports = ":host {\n position: relative; }\n\n.form-create {\n margin: 2.4rem 0;\n width: 50%; }\n\n.form-create .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem; }\n\n.form-create .wrap-buttons button {\n margin: 0 0.7rem; }\n\n.form-create .wrap-buttons button.transparent-button {\n flex-basis: 50%; }\n\n.form-create .wrap-buttons button.select-button {\n flex-basis: 60%; }\n\n.form-create .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY3JlYXRlLXdhbGxldC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcY3JlYXRlLXdhbGxldFxcY3JlYXRlLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7O0FBRlo7SUFLSSxhQUFhO0lBQ2Isc0JBQXNCLEVBQUE7O0FBTjFCO01BU00sZ0JBQWdCLEVBQUE7O0FBVHRCO1FBWVEsZUFBZSxFQUFBOztBQVp2QjtRQWdCUSxlQUFlLEVBQUE7O0FBaEJ2QjtRQW9CUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9jcmVhdGUtd2FsbGV0L2NyZWF0ZS13YWxsZXQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG59XHJcblxyXG4uZm9ybS1jcmVhdGUge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG5cclxuICAgICAgJi50cmFuc3BhcmVudC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDUwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5zZWxlY3QtYnV0dG9uIHtcclxuICAgICAgICBmbGV4LWJhc2lzOiA2MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuY3JlYXRlLWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAxIDUwJTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */" /***/ }), @@ -4758,7 +4758,7 @@ module.exports = "
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".form-edit {\n margin: 2.4rem 0; }\n .form-edit .alias-name {\n width: 50%; }\n .form-edit .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-edit .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-edit .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZWRpdC1hbGlhcy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxlZGl0LWFsaWFzXFxlZGl0LWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQSIsImZpbGUiOiJzcmMvYXBwL2VkaXQtYWxpYXMvZWRpdC1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWVkaXQge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */" +module.exports = ".form-edit {\n margin: 2.4rem 0; }\n .form-edit .alias-name {\n width: 50%; }\n .form-edit .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-edit .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-edit .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZWRpdC1hbGlhcy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcZWRpdC1hbGlhc1xcZWRpdC1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9lZGl0LWFsaWFzL2VkaXQtYWxpYXMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1lZGl0IHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG5cclxuICAuYWxpYXMtbmFtZSB7XHJcbiAgICB3aWR0aDogNTAlO1xyXG4gIH1cclxuXHJcbiAgLmFsaWFzLWNvc3Qge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW4tdG9wOiAycmVtO1xyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG4gICAgICB3aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" /***/ }), @@ -4872,7 +4872,7 @@ module.exports = "
\r\n
\r\n \r\n\r\n \r\n\r\n
\r\ /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%; }\n :host .content {\n display: flex; }\n :host .content .wrap-login {\n margin: auto;\n width: 100%;\n max-width: 40rem; }\n :host .content .wrap-login .logo {\n display: flex;\n justify-content: center; }\n :host .content .wrap-login .logo::ng-deep svg {\n width: 15rem; }\n :host .content .wrap-login .form-login {\n display: flex;\n flex-direction: column; }\n :host .content .wrap-login .form-login .wrap-button {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n :host .content .wrap-login .form-login .wrap-button button {\n margin: 2.5rem 0; }\n :host .content .wrap-login .form-login button {\n margin: 2.5rem auto;\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbG9naW4vRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcbG9naW5cXGxvZ2luLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixPQUFPO0VBQ1AsV0FBVztFQUNYLFlBQVksRUFBQTtFQUxkO0lBUUksYUFBYSxFQUFBO0VBUmpCO01BV00sWUFBWTtNQUNaLFdBQVc7TUFDWCxnQkFBZ0IsRUFBQTtFQWJ0QjtRQWdCUSxhQUFhO1FBQ2IsdUJBQXVCLEVBQUE7RUFqQi9CO1VBb0JVLFlBQVksRUFBQTtFQXBCdEI7UUF5QlEsYUFBYTtRQUNiLHNCQUFzQixFQUFBO0VBMUI5QjtVQTZCVSxhQUFhO1VBQ2IsbUJBQW1CO1VBQ25CLDhCQUE4QixFQUFBO0VBL0J4QztZQWtDWSxnQkFBZ0IsRUFBQTtFQWxDNUI7VUF1Q1UsbUJBQW1CO1VBQ25CLFdBQVc7VUFDWCxnQkFBZ0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2xvZ2luL2xvZ2luLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgbGVmdDogMDtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDEwMCU7XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgLndyYXAtbG9naW4ge1xyXG4gICAgICBtYXJnaW46IGF1dG87XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtYXgtd2lkdGg6IDQwcmVtO1xyXG5cclxuICAgICAgLmxvZ28ge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgICAgICY6Om5nLWRlZXAgc3ZnIHtcclxuICAgICAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5mb3JtLWxvZ2luIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcblxyXG4gICAgICAgIC53cmFwLWJ1dHRvbiB7XHJcbiAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuXHJcbiAgICAgICAgICBidXR0b24ge1xyXG4gICAgICAgICAgICBtYXJnaW46IDIuNXJlbSAwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYnV0dG9uIHtcclxuICAgICAgICAgIG1hcmdpbjogMi41cmVtIGF1dG87XHJcbiAgICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" +module.exports = ":host {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%; }\n :host .content {\n display: flex; }\n :host .content .wrap-login {\n margin: auto;\n width: 100%;\n max-width: 40rem; }\n :host .content .wrap-login .logo {\n display: flex;\n justify-content: center; }\n :host .content .wrap-login .logo::ng-deep svg {\n width: 15rem; }\n :host .content .wrap-login .form-login {\n display: flex;\n flex-direction: column; }\n :host .content .wrap-login .form-login .wrap-button {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n :host .content .wrap-login .form-login .wrap-button button {\n margin: 2.5rem 0; }\n :host .content .wrap-login .form-login button {\n margin: 2.5rem auto;\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbG9naW4vQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGxvZ2luXFxsb2dpbi5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sT0FBTztFQUNQLFdBQVc7RUFDWCxZQUFZLEVBQUE7RUFMZDtJQVFJLGFBQWEsRUFBQTtFQVJqQjtNQVdNLFlBQVk7TUFDWixXQUFXO01BQ1gsZ0JBQWdCLEVBQUE7RUFidEI7UUFnQlEsYUFBYTtRQUNiLHVCQUF1QixFQUFBO0VBakIvQjtVQW9CVSxZQUFZLEVBQUE7RUFwQnRCO1FBeUJRLGFBQWE7UUFDYixzQkFBc0IsRUFBQTtFQTFCOUI7VUE2QlUsYUFBYTtVQUNiLG1CQUFtQjtVQUNuQiw4QkFBOEIsRUFBQTtFQS9CeEM7WUFrQ1ksZ0JBQWdCLEVBQUE7RUFsQzVCO1VBdUNVLG1CQUFtQjtVQUNuQixXQUFXO1VBQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9sb2dpbi9sb2dpbi5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogZml4ZWQ7XHJcbiAgdG9wOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMDAlO1xyXG5cclxuICAuY29udGVudCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAgIC53cmFwLWxvZ2luIHtcclxuICAgICAgbWFyZ2luOiBhdXRvO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgbWF4LXdpZHRoOiA0MHJlbTtcclxuXHJcbiAgICAgIC5sb2dvIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG5cclxuICAgICAgICAmOjpuZy1kZWVwIHN2ZyB7XHJcbiAgICAgICAgICB3aWR0aDogMTVyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuZm9ybS1sb2dpbiB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG5cclxuICAgICAgICAud3JhcC1idXR0b24ge1xyXG4gICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgICAgICAgYnV0dG9uIHtcclxuICAgICAgICAgICAgbWFyZ2luOiAyLjVyZW0gMDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgICBtYXJnaW46IDIuNXJlbSBhdXRvO1xyXG4gICAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */" /***/ }), @@ -5440,7 +5440,7 @@ module.exports = "
\r\n\r\n
\r\n\r\n
\r\n

{{ 'OPEN_WALLET /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.25); }\n\n.modal {\n display: flex;\n flex-direction: column;\n background-position: center;\n background-size: 200%;\n padding: 2rem;\n min-width: 34rem;\n max-width: 64rem; }\n\n.modal .title {\n font-size: 1.8rem;\n text-align: center; }\n\n.modal .open-form .wallet-path {\n font-size: 1.3rem;\n margin: 5rem 0 2rem;\n word-wrap: break-word;\n line-height: 2rem; }\n\n.modal .open-form .wrap-button {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin: 2rem -2rem 0; }\n\n.modal .open-form .wrap-button button {\n flex: 1 0 0;\n margin: 0 2rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcb3Blbi13YWxsZXQtbW9kYWxcXG9wZW4td2FsbGV0LW1vZGFsLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFHdkM7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLDJCQUEyQjtFQUMzQixxQkFBcUI7RUFDckIsYUFBYTtFQUNiLGdCQUFnQjtFQUNoQixnQkFBZ0IsRUFBQTs7QUFQbEI7SUFVSSxpQkFBaUI7SUFDakIsa0JBQWtCLEVBQUE7O0FBWHRCO0lBaUJNLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIscUJBQXFCO0lBQ3JCLGlCQUFpQixFQUFBOztBQXBCdkI7SUF3Qk0sYUFBYTtJQUNiLG1CQUFtQjtJQUNuQiw4QkFBOEI7SUFDOUIsb0JBQW9CLEVBQUE7O0FBM0IxQjtNQThCUSxXQUFXO01BQ1gsY0FBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvb3Blbi13YWxsZXQtbW9kYWwuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGZpeGVkO1xyXG4gIHRvcDogMDtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICByaWdodDogMDtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcclxufVxyXG5cclxuLm1vZGFsIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xyXG4gIGJhY2tncm91bmQtc2l6ZTogMjAwJTtcclxuICBwYWRkaW5nOiAycmVtO1xyXG4gIG1pbi13aWR0aDogMzRyZW07XHJcbiAgbWF4LXdpZHRoOiA2NHJlbTtcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gIH1cclxuXHJcbiAgLm9wZW4tZm9ybSB7XHJcblxyXG4gICAgLndhbGxldC1wYXRoIHtcclxuICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgIG1hcmdpbjogNXJlbSAwIDJyZW07XHJcbiAgICAgIHdvcmQtd3JhcDogYnJlYWstd29yZDtcclxuICAgICAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLndyYXAtYnV0dG9uIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgICBtYXJnaW46IDJyZW0gLTJyZW0gMDtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAwIDA7XHJcbiAgICAgICAgbWFyZ2luOiAwIDJyZW0gO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" +module.exports = ":host {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.25); }\n\n.modal {\n display: flex;\n flex-direction: column;\n background-position: center;\n background-size: 200%;\n padding: 2rem;\n min-width: 34rem;\n max-width: 64rem; }\n\n.modal .title {\n font-size: 1.8rem;\n text-align: center; }\n\n.modal .open-form .wallet-path {\n font-size: 1.3rem;\n margin: 5rem 0 2rem;\n word-wrap: break-word;\n line-height: 2rem; }\n\n.modal .open-form .wrap-button {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin: 2rem -2rem 0; }\n\n.modal .open-form .wrap-button button {\n flex: 1 0 0;\n margin: 0 2rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXG9wZW4td2FsbGV0LW1vZGFsXFxvcGVuLXdhbGxldC1tb2RhbC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBR3ZDO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLGFBQWE7RUFDYixnQkFBZ0I7RUFDaEIsZ0JBQWdCLEVBQUE7O0FBUGxCO0lBVUksaUJBQWlCO0lBQ2pCLGtCQUFrQixFQUFBOztBQVh0QjtJQWlCTSxpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLHFCQUFxQjtJQUNyQixpQkFBaUIsRUFBQTs7QUFwQnZCO0lBd0JNLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCO0lBQzlCLG9CQUFvQixFQUFBOztBQTNCMUI7TUE4QlEsV0FBVztNQUNYLGNBQWUsRUFBQSIsImZpbGUiOiJzcmMvYXBwL29wZW4td2FsbGV0LW1vZGFsL29wZW4td2FsbGV0LW1vZGFsLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuXHJcbi5tb2RhbCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogMnJlbTtcclxuICBtaW4td2lkdGg6IDM0cmVtO1xyXG4gIG1heC13aWR0aDogNjRyZW07XHJcblxyXG4gIC50aXRsZSB7XHJcbiAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuICB9XHJcblxyXG4gIC5vcGVuLWZvcm0ge1xyXG5cclxuICAgIC53YWxsZXQtcGF0aCB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICBtYXJnaW46IDVyZW0gMCAycmVtO1xyXG4gICAgICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC53cmFwLWJ1dHRvbiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgICAgbWFyZ2luOiAycmVtIC0ycmVtIDA7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDEgMCAwO1xyXG4gICAgICAgIG1hcmdpbjogMCAycmVtIDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */" /***/ }), @@ -5783,7 +5783,7 @@ module.exports = "
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".form-open {\n margin: 2.4rem 0;\n width: 50%; }\n .form-open .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem; }\n .form-open .wrap-buttons button {\n margin: 0 0.7rem; }\n .form-open .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcb3Blbi13YWxsZXRcXG9wZW4td2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTtFQUZaO0lBS0ksYUFBYTtJQUNiLHNCQUFzQixFQUFBO0VBTjFCO01BU00sZ0JBQWdCLEVBQUE7RUFUdEI7UUFZUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9vcGVuLXdhbGxldC9vcGVuLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLW9wZW4ge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" +module.exports = ".form-open {\n margin: 2.4rem 0;\n width: 50%; }\n .form-open .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem; }\n .form-open .wrap-buttons button {\n margin: 0 0.7rem; }\n .form-open .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXG9wZW4td2FsbGV0XFxvcGVuLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7RUFGWjtJQUtJLGFBQWE7SUFDYixzQkFBc0IsRUFBQTtFQU4xQjtNQVNNLGdCQUFnQixFQUFBO0VBVHRCO1FBWVEsYUFBYSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvb3Blbi13YWxsZXQvb3Blbi13YWxsZXQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1vcGVuIHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuXHJcbiAgICAgICYuY3JlYXRlLWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAxIDUwJTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */" /***/ }), @@ -5965,7 +5965,7 @@ module.exports = "
\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.head {\n flex: 0 0 auto;\n box-sizing: content-box;\n margin: -3rem -3rem 0; }\n\n.form-purchase {\n flex: 1 1 auto;\n margin: 1.5rem -3rem 0;\n padding: 0 3rem;\n overflow-y: overlay; }\n\n.form-purchase .input-blocks-row {\n display: flex; }\n\n.form-purchase .input-blocks-row .input-block {\n flex-basis: 50%; }\n\n.form-purchase .input-blocks-row .input-block:first-child {\n margin-right: 1.5rem; }\n\n.form-purchase .input-blocks-row .input-block:last-child {\n margin-left: 1.5rem; }\n\n.form-purchase .input-blocks-row .input-block .checkbox-block {\n display: flex; }\n\n.form-purchase .purchase-select {\n display: flex;\n align-items: center;\n background: transparent;\n border: none;\n font-size: 1.3rem;\n line-height: 1.3rem;\n margin: 1.5rem 0 0;\n padding: 0;\n width: 100%;\n max-width: 15rem;\n height: 1.3rem; }\n\n.form-purchase .purchase-select .arrow {\n margin-left: 1rem;\n width: 0.8rem;\n height: 0.8rem; }\n\n.form-purchase .purchase-select .arrow.down {\n -webkit-mask: url('arrow-down.svg') no-repeat center;\n mask: url('arrow-down.svg') no-repeat center; }\n\n.form-purchase .purchase-select .arrow.up {\n -webkit-mask: url('arrow-up.svg') no-repeat center;\n mask: url('arrow-up.svg') no-repeat center; }\n\n.form-purchase .additional-details {\n display: flex;\n margin-top: 1.5rem;\n padding: 0.5rem 0 2rem; }\n\n.form-purchase .additional-details > div {\n flex-basis: 25%; }\n\n.form-purchase .additional-details > div:first-child {\n padding-left: 1.5rem;\n padding-right: 1rem; }\n\n.form-purchase .additional-details > div:last-child {\n padding-left: 1rem;\n padding-right: 1.5rem; }\n\n.form-purchase .purchase-states {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n line-height: 2.9rem; }\n\n.form-purchase .send-button {\n margin: 2.4rem 0;\n width: 100%;\n max-width: 15rem; }\n\n.form-purchase .purchase-buttons {\n display: flex;\n justify-content: flex-start;\n margin: 2.4rem -0.5rem; }\n\n.form-purchase .purchase-buttons button {\n flex: 0 1 33%;\n margin: 0 0.5rem; }\n\n.form-purchase .nullify-block-row {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center; }\n\n.form-purchase .nullify-block-row .nullify-block-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1rem 0;\n width: 100%; }\n\n.form-purchase .nullify-block-row .nullify-block-buttons button {\n flex: 0 1 25%;\n margin: 0 0.5rem; }\n\n.form-purchase .time-cancel-block-row {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-question {\n margin-bottom: 1rem; }\n\n.form-purchase .time-cancel-block-row .input-block {\n width: 25%; }\n\n.form-purchase .time-cancel-block-row label {\n margin-bottom: 1rem; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1rem 0;\n width: 100%; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons button {\n flex: 0 1 25%;\n margin: 0 0.5rem; }\n\n.progress-bar-container {\n position: absolute;\n bottom: 0;\n left: 0;\n padding: 0 3rem;\n width: 100%;\n height: 3rem; }\n\n.progress-bar-container .progress-bar {\n position: absolute;\n top: -0.7rem;\n left: 0;\n margin: 0 3rem;\n width: calc(100% - 6rem);\n height: 0.7rem; }\n\n.progress-bar-container .progress-bar .progress-bar-full {\n height: 0.7rem; }\n\n.progress-bar-container .progress-labels {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n height: 100%; }\n\n.progress-bar-container .progress-time {\n position: absolute;\n top: -3rem;\n left: 50%;\n transform: translateX(-50%);\n font-size: 1.2rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcHVyY2hhc2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxccHVyY2hhc2VcXHB1cmNoYXNlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxjQUFjO0VBQ2QsdUJBQXVCO0VBQ3ZCLHFCQUFxQixFQUFBOztBQUd2QjtFQUNFLGNBQWM7RUFDZCxzQkFBc0I7RUFDdEIsZUFBZTtFQUNmLG1CQUFtQixFQUFBOztBQUpyQjtJQU9JLGFBQWEsRUFBQTs7QUFQakI7TUFVTSxlQUFlLEVBQUE7O0FBVnJCO1FBYVEsb0JBQW9CLEVBQUE7O0FBYjVCO1FBaUJRLG1CQUFtQixFQUFBOztBQWpCM0I7UUFxQlEsYUFBYSxFQUFBOztBQXJCckI7SUEyQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsa0JBQWtCO0lBQ2xCLFVBQVU7SUFDVixXQUFXO0lBQ1gsZ0JBQWdCO0lBQ2hCLGNBQWMsRUFBQTs7QUFyQ2xCO01Bd0NNLGlCQUFpQjtNQUNqQixhQUFhO01BQ2IsY0FBYyxFQUFBOztBQTFDcEI7UUE2Q1Esb0RBQTREO2dCQUE1RCw0Q0FBNEQsRUFBQTs7QUE3Q3BFO1FBaURRLGtEQUEwRDtnQkFBMUQsMENBQTBELEVBQUE7O0FBakRsRTtJQXVESSxhQUFhO0lBQ2Isa0JBQWtCO0lBQ2xCLHNCQUFzQixFQUFBOztBQXpEMUI7TUE0RE0sZUFBZSxFQUFBOztBQTVEckI7UUErRFEsb0JBQW9CO1FBQ3BCLG1CQUFtQixFQUFBOztBQWhFM0I7UUFvRVEsa0JBQWtCO1FBQ2xCLHFCQUFxQixFQUFBOztBQXJFN0I7SUEyRUksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLGlCQUFpQjtJQUNqQixtQkFBbUIsRUFBQTs7QUFoRnZCO0lBb0ZJLGdCQUFnQjtJQUNoQixXQUFXO0lBQ1gsZ0JBQWdCLEVBQUE7O0FBdEZwQjtJQTBGSSxhQUFhO0lBQ2IsMkJBQTJCO0lBQzNCLHNCQUFzQixFQUFBOztBQTVGMUI7TUErRk0sYUFBYTtNQUNiLGdCQUFnQixFQUFBOztBQWhHdEI7SUFxR0ksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7O0FBeEczQjtNQTJHTSxhQUFhO01BQ2IsbUJBQW1CO01BQ25CLHVCQUF1QjtNQUN2QixjQUFjO01BQ2QsV0FBVyxFQUFBOztBQS9HakI7UUFrSFEsYUFBYTtRQUNiLGdCQUFnQixFQUFBOztBQW5IeEI7SUF5SEksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7O0FBNUgzQjtNQStITSxtQkFBbUIsRUFBQTs7QUEvSHpCO01BbUlNLFVBQVUsRUFBQTs7QUFuSWhCO01BdUlNLG1CQUFtQixFQUFBOztBQXZJekI7TUEySU0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLFdBQVcsRUFBQTs7QUEvSWpCO1FBa0pRLGFBQWE7UUFDYixnQkFBZ0IsRUFBQTs7QUFPeEI7RUFDRSxrQkFBa0I7RUFDbEIsU0FBUztFQUNULE9BQU87RUFDUCxlQUFlO0VBQ2YsV0FBVztFQUNYLFlBQVksRUFBQTs7QUFOZDtJQVNJLGtCQUFrQjtJQUNsQixZQUFZO0lBQ1osT0FBTztJQUNQLGNBQWM7SUFDZCx3QkFBd0I7SUFDeEIsY0FBYyxFQUFBOztBQWRsQjtNQWlCTSxjQUFjLEVBQUE7O0FBakJwQjtJQXNCSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixpQkFBaUI7SUFDakIsWUFBWSxFQUFBOztBQTFCaEI7SUE4Qkksa0JBQWtCO0lBQ2xCLFVBQVU7SUFDVixTQUFTO0lBQ1QsMkJBQTJCO0lBQzNCLGlCQUFpQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvcHVyY2hhc2UvcHVyY2hhc2UuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAgZmxleDogMCAwIGF1dG87XHJcbiAgYm94LXNpemluZzogY29udGVudC1ib3g7XHJcbiAgbWFyZ2luOiAtM3JlbSAtM3JlbSAwO1xyXG59XHJcblxyXG4uZm9ybS1wdXJjaGFzZSB7XHJcbiAgZmxleDogMSAxIGF1dG87XHJcbiAgbWFyZ2luOiAxLjVyZW0gLTNyZW0gMDtcclxuICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgb3ZlcmZsb3cteTogb3ZlcmxheTtcclxuXHJcbiAgLmlucHV0LWJsb2Nrcy1yb3cge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgICAuaW5wdXQtYmxvY2sge1xyXG4gICAgICBmbGV4LWJhc2lzOiA1MCU7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICBtYXJnaW4tbGVmdDogMS41cmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuY2hlY2tib3gtYmxvY2sge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1zZWxlY3Qge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlcjogbm9uZTtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuM3JlbTtcclxuICAgIG1hcmdpbjogMS41cmVtIDAgMDtcclxuICAgIHBhZGRpbmc6IDA7XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICBoZWlnaHQ6IDEuM3JlbTtcclxuXHJcbiAgICAuYXJyb3cge1xyXG4gICAgICBtYXJnaW4tbGVmdDogMXJlbTtcclxuICAgICAgd2lkdGg6IDAuOHJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjhyZW07XHJcblxyXG4gICAgICAmLmRvd24ge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy1kb3duLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi51cCB7XHJcbiAgICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2Fycm93LXVwLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLmFkZGl0aW9uYWwtZGV0YWlscyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luLXRvcDogMS41cmVtO1xyXG4gICAgcGFkZGluZzogMC41cmVtIDAgMnJlbTtcclxuXHJcbiAgICA+IGRpdiB7XHJcbiAgICAgIGZsZXgtYmFzaXM6IDI1JTtcclxuXHJcbiAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMS41cmVtO1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDFyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAxcmVtO1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnB1cmNoYXNlLXN0YXRlcyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZvbnQtc2l6ZTogMS4ycmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuOXJlbTtcclxuICB9XHJcblxyXG4gIC5zZW5kLWJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gIH1cclxuXHJcbiAgLnB1cmNoYXNlLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICAgIG1hcmdpbjogMi40cmVtIC0wLjVyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgZmxleDogMCAxIDMzJTtcclxuICAgICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5udWxsaWZ5LWJsb2NrLXJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuXHJcbiAgICAubnVsbGlmeS1ibG9jay1idXR0b25zIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMXJlbSAwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMCAxIDI1JTtcclxuICAgICAgICBtYXJnaW46IDAgMC41cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGltZS1jYW5jZWwtYmxvY2stcm93IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG5cclxuICAgIC50aW1lLWNhbmNlbC1ibG9jay1xdWVzdGlvbiB7XHJcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDI1JTtcclxuICAgIH1cclxuXHJcbiAgICBsYWJlbCB7XHJcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLnRpbWUtY2FuY2VsLWJsb2NrLWJ1dHRvbnMge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAxcmVtIDA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICAgYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAwIDEgMjUlO1xyXG4gICAgICAgIG1hcmdpbjogMCAwLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG59XHJcblxyXG4ucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcbiAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gIGJvdHRvbTogMDtcclxuICBsZWZ0OiAwO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIC5wcm9ncmVzcy1iYXIge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiAtMC43cmVtO1xyXG4gICAgbGVmdDogMDtcclxuICAgIG1hcmdpbjogMCAzcmVtO1xyXG4gICAgd2lkdGg6IGNhbGMoMTAwJSAtIDZyZW0pO1xyXG4gICAgaGVpZ2h0OiAwLjdyZW07XHJcblxyXG4gICAgLnByb2dyZXNzLWJhci1mdWxsIHtcclxuICAgICAgaGVpZ2h0OiAwLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtbGFiZWxzIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICB9XHJcblxyXG4gIC5wcm9ncmVzcy10aW1lIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogLTNyZW07XHJcbiAgICBsZWZ0OiA1MCU7XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICB9XHJcbn1cclxuIl19 */" +module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.head {\n flex: 0 0 auto;\n box-sizing: content-box;\n margin: -3rem -3rem 0; }\n\n.form-purchase {\n flex: 1 1 auto;\n margin: 1.5rem -3rem 0;\n padding: 0 3rem;\n overflow-y: overlay; }\n\n.form-purchase .input-blocks-row {\n display: flex; }\n\n.form-purchase .input-blocks-row .input-block {\n flex-basis: 50%; }\n\n.form-purchase .input-blocks-row .input-block:first-child {\n margin-right: 1.5rem; }\n\n.form-purchase .input-blocks-row .input-block:last-child {\n margin-left: 1.5rem; }\n\n.form-purchase .input-blocks-row .input-block .checkbox-block {\n display: flex; }\n\n.form-purchase .purchase-select {\n display: flex;\n align-items: center;\n background: transparent;\n border: none;\n font-size: 1.3rem;\n line-height: 1.3rem;\n margin: 1.5rem 0 0;\n padding: 0;\n width: 100%;\n max-width: 15rem;\n height: 1.3rem; }\n\n.form-purchase .purchase-select .arrow {\n margin-left: 1rem;\n width: 0.8rem;\n height: 0.8rem; }\n\n.form-purchase .purchase-select .arrow.down {\n -webkit-mask: url('arrow-down.svg') no-repeat center;\n mask: url('arrow-down.svg') no-repeat center; }\n\n.form-purchase .purchase-select .arrow.up {\n -webkit-mask: url('arrow-up.svg') no-repeat center;\n mask: url('arrow-up.svg') no-repeat center; }\n\n.form-purchase .additional-details {\n display: flex;\n margin-top: 1.5rem;\n padding: 0.5rem 0 2rem; }\n\n.form-purchase .additional-details > div {\n flex-basis: 25%; }\n\n.form-purchase .additional-details > div:first-child {\n padding-left: 1.5rem;\n padding-right: 1rem; }\n\n.form-purchase .additional-details > div:last-child {\n padding-left: 1rem;\n padding-right: 1.5rem; }\n\n.form-purchase .purchase-states {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n line-height: 2.9rem; }\n\n.form-purchase .send-button {\n margin: 2.4rem 0;\n width: 100%;\n max-width: 15rem; }\n\n.form-purchase .purchase-buttons {\n display: flex;\n justify-content: flex-start;\n margin: 2.4rem -0.5rem; }\n\n.form-purchase .purchase-buttons button {\n flex: 0 1 33%;\n margin: 0 0.5rem; }\n\n.form-purchase .nullify-block-row {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center; }\n\n.form-purchase .nullify-block-row .nullify-block-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1rem 0;\n width: 100%; }\n\n.form-purchase .nullify-block-row .nullify-block-buttons button {\n flex: 0 1 25%;\n margin: 0 0.5rem; }\n\n.form-purchase .time-cancel-block-row {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-question {\n margin-bottom: 1rem; }\n\n.form-purchase .time-cancel-block-row .input-block {\n width: 25%; }\n\n.form-purchase .time-cancel-block-row label {\n margin-bottom: 1rem; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 1rem 0;\n width: 100%; }\n\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons button {\n flex: 0 1 25%;\n margin: 0 0.5rem; }\n\n.progress-bar-container {\n position: absolute;\n bottom: 0;\n left: 0;\n padding: 0 3rem;\n width: 100%;\n height: 3rem; }\n\n.progress-bar-container .progress-bar {\n position: absolute;\n top: -0.7rem;\n left: 0;\n margin: 0 3rem;\n width: calc(100% - 6rem);\n height: 0.7rem; }\n\n.progress-bar-container .progress-bar .progress-bar-full {\n height: 0.7rem; }\n\n.progress-bar-container .progress-labels {\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2rem;\n height: 100%; }\n\n.progress-bar-container .progress-time {\n position: absolute;\n top: -3rem;\n left: 50%;\n transform: translateX(-50%);\n font-size: 1.2rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcHVyY2hhc2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHB1cmNoYXNlXFxwdXJjaGFzZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsY0FBYztFQUNkLHVCQUF1QjtFQUN2QixxQkFBcUIsRUFBQTs7QUFHdkI7RUFDRSxjQUFjO0VBQ2Qsc0JBQXNCO0VBQ3RCLGVBQWU7RUFDZixtQkFBbUIsRUFBQTs7QUFKckI7SUFPSSxhQUFhLEVBQUE7O0FBUGpCO01BVU0sZUFBZSxFQUFBOztBQVZyQjtRQWFRLG9CQUFvQixFQUFBOztBQWI1QjtRQWlCUSxtQkFBbUIsRUFBQTs7QUFqQjNCO1FBcUJRLGFBQWEsRUFBQTs7QUFyQnJCO0lBMkJJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLFlBQVk7SUFDWixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLGtCQUFrQjtJQUNsQixVQUFVO0lBQ1YsV0FBVztJQUNYLGdCQUFnQjtJQUNoQixjQUFjLEVBQUE7O0FBckNsQjtNQXdDTSxpQkFBaUI7TUFDakIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUExQ3BCO1FBNkNRLG9EQUE0RDtnQkFBNUQsNENBQTRELEVBQUE7O0FBN0NwRTtRQWlEUSxrREFBMEQ7Z0JBQTFELDBDQUEwRCxFQUFBOztBQWpEbEU7SUF1REksYUFBYTtJQUNiLGtCQUFrQjtJQUNsQixzQkFBc0IsRUFBQTs7QUF6RDFCO01BNERNLGVBQWUsRUFBQTs7QUE1RHJCO1FBK0RRLG9CQUFvQjtRQUNwQixtQkFBbUIsRUFBQTs7QUFoRTNCO1FBb0VRLGtCQUFrQjtRQUNsQixxQkFBcUIsRUFBQTs7QUFyRTdCO0lBMkVJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixpQkFBaUI7SUFDakIsbUJBQW1CLEVBQUE7O0FBaEZ2QjtJQW9GSSxnQkFBZ0I7SUFDaEIsV0FBVztJQUNYLGdCQUFnQixFQUFBOztBQXRGcEI7SUEwRkksYUFBYTtJQUNiLDJCQUEyQjtJQUMzQixzQkFBc0IsRUFBQTs7QUE1RjFCO01BK0ZNLGFBQWE7TUFDYixnQkFBZ0IsRUFBQTs7QUFoR3RCO0lBcUdJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QixFQUFBOztBQXhHM0I7TUEyR00sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLFdBQVcsRUFBQTs7QUEvR2pCO1FBa0hRLGFBQWE7UUFDYixnQkFBZ0IsRUFBQTs7QUFuSHhCO0lBeUhJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QixFQUFBOztBQTVIM0I7TUErSE0sbUJBQW1CLEVBQUE7O0FBL0h6QjtNQW1JTSxVQUFVLEVBQUE7O0FBbkloQjtNQXVJTSxtQkFBbUIsRUFBQTs7QUF2SXpCO01BMklNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGNBQWM7TUFDZCxXQUFXLEVBQUE7O0FBL0lqQjtRQWtKUSxhQUFhO1FBQ2IsZ0JBQWdCLEVBQUE7O0FBT3hCO0VBQ0Usa0JBQWtCO0VBQ2xCLFNBQVM7RUFDVCxPQUFPO0VBQ1AsZUFBZTtFQUNmLFdBQVc7RUFDWCxZQUFZLEVBQUE7O0FBTmQ7SUFTSSxrQkFBa0I7SUFDbEIsWUFBWTtJQUNaLE9BQU87SUFDUCxjQUFjO0lBQ2Qsd0JBQXdCO0lBQ3hCLGNBQWMsRUFBQTs7QUFkbEI7TUFpQk0sY0FBYyxFQUFBOztBQWpCcEI7SUFzQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsaUJBQWlCO0lBQ2pCLFlBQVksRUFBQTs7QUExQmhCO0lBOEJJLGtCQUFrQjtJQUNsQixVQUFVO0lBQ1YsU0FBUztJQUNULDJCQUEyQjtJQUMzQixpQkFBaUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3B1cmNoYXNlL3B1cmNoYXNlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmhlYWQge1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xyXG4gIG1hcmdpbjogLTNyZW0gLTNyZW0gMDtcclxufVxyXG5cclxuLmZvcm0tcHVyY2hhc2Uge1xyXG4gIGZsZXg6IDEgMSBhdXRvO1xyXG4gIG1hcmdpbjogMS41cmVtIC0zcmVtIDA7XHJcbiAgcGFkZGluZzogMCAzcmVtO1xyXG4gIG92ZXJmbG93LXk6IG92ZXJsYXk7XHJcblxyXG4gIC5pbnB1dC1ibG9ja3Mtcm93IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgZmxleC1iYXNpczogNTAlO1xyXG5cclxuICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmNoZWNrYm94LWJsb2NrIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHVyY2hhc2Utc2VsZWN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBtYXJnaW46IDEuNXJlbSAwIDA7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgaGVpZ2h0OiAxLjNyZW07XHJcblxyXG4gICAgLmFycm93IHtcclxuICAgICAgbWFyZ2luLWxlZnQ6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAwLjhyZW07XHJcbiAgICAgIGhlaWdodDogMC44cmVtO1xyXG5cclxuICAgICAgJi5kb3duIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctZG93bi5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYudXAge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy11cC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbi10b3A6IDEuNXJlbTtcclxuICAgIHBhZGRpbmc6IDAuNXJlbSAwIDJyZW07XHJcblxyXG4gICAgPiBkaXYge1xyXG4gICAgICBmbGV4LWJhc2lzOiAyNSU7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxcmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1zdGF0ZXMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjlyZW07XHJcbiAgfVxyXG5cclxuICAuc2VuZC1idXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7XHJcbiAgICBtYXJnaW46IDIuNHJlbSAtMC41cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGZsZXg6IDAgMSAzMyU7XHJcbiAgICAgIG1hcmdpbjogMCAwLjVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAubnVsbGlmeS1ibG9jay1yb3cge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgLm51bGxpZnktYmxvY2stYnV0dG9ucyB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBtYXJnaW46IDFyZW0gMDtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDAgMSAyNSU7XHJcbiAgICAgICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRpbWUtY2FuY2VsLWJsb2NrLXJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuXHJcbiAgICAudGltZS1jYW5jZWwtYmxvY2stcXVlc3Rpb24ge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC5pbnB1dC1ibG9jayB7XHJcbiAgICAgIHdpZHRoOiAyNSU7XHJcbiAgICB9XHJcblxyXG4gICAgbGFiZWwge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC50aW1lLWNhbmNlbC1ibG9jay1idXR0b25zIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMXJlbSAwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMCAxIDI1JTtcclxuICAgICAgICBtYXJnaW46IDAgMC41cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuLnByb2dyZXNzLWJhci1jb250YWluZXIge1xyXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAzcmVtO1xyXG5cclxuICAucHJvZ3Jlc3MtYmFyIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogLTAuN3JlbTtcclxuICAgIGxlZnQ6IDA7XHJcbiAgICBtYXJnaW46IDAgM3JlbTtcclxuICAgIHdpZHRoOiBjYWxjKDEwMCUgLSA2cmVtKTtcclxuICAgIGhlaWdodDogMC43cmVtO1xyXG5cclxuICAgIC5wcm9ncmVzcy1iYXItZnVsbCB7XHJcbiAgICAgIGhlaWdodDogMC43cmVtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnByb2dyZXNzLWxhYmVscyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtdGltZSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IC0zcmVtO1xyXG4gICAgbGVmdDogNTAlO1xyXG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */" /***/ }), @@ -6410,7 +6410,7 @@ module.exports = "
\r\n \\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: relative; }\n\n.form-restore {\n margin: 2.4rem 0;\n width: 100%; }\n\n.form-restore .input-block.half-block {\n width: 50%; }\n\n.form-restore .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem;\n width: 50%; }\n\n.form-restore .wrap-buttons button {\n margin: 0 0.7rem; }\n\n.form-restore .wrap-buttons button.transparent-button {\n flex-basis: 50%; }\n\n.form-restore .wrap-buttons button.select-button {\n flex-basis: 60%; }\n\n.form-restore .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVzdG9yZS13YWxsZXQvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxccmVzdG9yZS13YWxsZXRcXHJlc3RvcmUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVcsRUFBQTs7QUFGYjtJQU9NLFVBQVUsRUFBQTs7QUFQaEI7SUFZSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLFVBQVUsRUFBQTs7QUFkZDtNQWlCTSxnQkFBZ0IsRUFBQTs7QUFqQnRCO1FBb0JRLGVBQWUsRUFBQTs7QUFwQnZCO1FBd0JRLGVBQWUsRUFBQTs7QUF4QnZCO1FBNEJRLGFBQWEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3Jlc3RvcmUtd2FsbGV0L3Jlc3RvcmUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxufVxyXG5cclxuLmZvcm0tcmVzdG9yZSB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgLmlucHV0LWJsb2NrIHtcclxuXHJcbiAgICAmLmhhbGYtYmxvY2sge1xyXG4gICAgICB3aWR0aDogNTAlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuICAgIHdpZHRoOiA1MCU7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuXHJcbiAgICAgICYudHJhbnNwYXJlbnQtYnV0dG9uIHtcclxuICAgICAgICBmbGV4LWJhc2lzOiA1MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuc2VsZWN0LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNjAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmNyZWF0ZS1idXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDEgMSA1MCU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */" +module.exports = ":host {\n position: relative; }\n\n.form-restore {\n margin: 2.4rem 0;\n width: 100%; }\n\n.form-restore .input-block.half-block {\n width: 50%; }\n\n.form-restore .wrap-buttons {\n display: flex;\n margin: 2.5rem -0.7rem;\n width: 50%; }\n\n.form-restore .wrap-buttons button {\n margin: 0 0.7rem; }\n\n.form-restore .wrap-buttons button.transparent-button {\n flex-basis: 50%; }\n\n.form-restore .wrap-buttons button.select-button {\n flex-basis: 60%; }\n\n.form-restore .wrap-buttons button.create-button {\n flex: 1 1 50%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVzdG9yZS13YWxsZXQvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHJlc3RvcmUtd2FsbGV0XFxyZXN0b3JlLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLGdCQUFnQjtFQUNoQixXQUFXLEVBQUE7O0FBRmI7SUFPTSxVQUFVLEVBQUE7O0FBUGhCO0lBWUksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixVQUFVLEVBQUE7O0FBZGQ7TUFpQk0sZ0JBQWdCLEVBQUE7O0FBakJ0QjtRQW9CUSxlQUFlLEVBQUE7O0FBcEJ2QjtRQXdCUSxlQUFlLEVBQUE7O0FBeEJ2QjtRQTRCUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9yZXN0b3JlLXdhbGxldC9yZXN0b3JlLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5mb3JtLXJlc3RvcmUge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDEwMCU7XHJcblxyXG4gIC5pbnB1dC1ibG9jayB7XHJcblxyXG4gICAgJi5oYWxmLWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDUwJTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcbiAgICB3aWR0aDogNTAlO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcblxyXG4gICAgICAmLnRyYW5zcGFyZW50LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNTAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnNlbGVjdC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" /***/ }), @@ -6671,7 +6671,7 @@ module.exports = "
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: relative; }\n\n.seed-phrase-title {\n line-height: 2.2rem;\n padding: 2.2rem 0; }\n\n.seed-phrase-content {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n padding: 1.4rem;\n width: 100%;\n height: 12rem; }\n\n.seed-phrase-content .word {\n line-height: 2.2rem;\n max-width: 13rem; }\n\n.wrap-buttons {\n display: flex; }\n\n.wrap-buttons .seed-phrase-button {\n margin: 2.8rem 0;\n width: 25%;\n min-width: 1.5rem; }\n\n.wrap-buttons .copy-button {\n margin: 2.8rem 1rem;\n width: 25%;\n min-width: 1.5rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VlZC1waHJhc2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2VlZC1waHJhc2VcXHNlZWQtcGhyYXNlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsbUJBQW1CO0VBQ25CLGlCQUFpQixFQUFBOztBQUduQjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsZUFBZTtFQUNmLGVBQWU7RUFDZixXQUFXO0VBQ1gsYUFBYSxFQUFBOztBQU5mO0lBU0ksbUJBQW1CO0lBQ25CLGdCQUFnQixFQUFBOztBQUlwQjtFQUNFLGFBQWEsRUFBQTs7QUFEZjtJQUlJLGdCQUFnQjtJQUNoQixVQUFVO0lBQ1YsaUJBQWlCLEVBQUE7O0FBTnJCO0lBVUksbUJBQW1CO0lBQ25CLFVBQVU7SUFDVixpQkFBaUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3NlZWQtcGhyYXNlL3NlZWQtcGhyYXNlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxufVxyXG5cclxuLnNlZWQtcGhyYXNlLXRpdGxlIHtcclxuICBsaW5lLWhlaWdodDogMi4ycmVtO1xyXG4gIHBhZGRpbmc6IDIuMnJlbSAwO1xyXG59XHJcblxyXG4uc2VlZC1waHJhc2UtY29udGVudCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGZsZXgtd3JhcDogd3JhcDtcclxuICBwYWRkaW5nOiAxLjRyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMnJlbTtcclxuXHJcbiAgLndvcmQge1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuMnJlbTtcclxuICAgIG1heC13aWR0aDogMTNyZW07XHJcbiAgfVxyXG59XHJcblxyXG4ud3JhcC1idXR0b25zIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAuc2VlZC1waHJhc2UtYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMi44cmVtIDA7XHJcbiAgICB3aWR0aDogMjUlO1xyXG4gICAgbWluLXdpZHRoOiAxLjVyZW07XHJcbiAgfVxyXG5cclxuICAuY29weS1idXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjhyZW0gMXJlbTtcclxuICAgIHdpZHRoOiAyNSU7XHJcbiAgICBtaW4td2lkdGg6IDEuNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbiJdfQ== */" +module.exports = ":host {\n position: relative; }\n\n.seed-phrase-title {\n line-height: 2.2rem;\n padding: 2.2rem 0; }\n\n.seed-phrase-content {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n padding: 1.4rem;\n width: 100%;\n height: 12rem; }\n\n.seed-phrase-content .word {\n line-height: 2.2rem;\n max-width: 13rem; }\n\n.wrap-buttons {\n display: flex; }\n\n.wrap-buttons .seed-phrase-button {\n margin: 2.8rem 0;\n width: 25%;\n min-width: 1.5rem; }\n\n.wrap-buttons .copy-button {\n margin: 2.8rem 1rem;\n width: 25%;\n min-width: 1.5rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VlZC1waHJhc2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHNlZWQtcGhyYXNlXFxzZWVkLXBocmFzZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLG1CQUFtQjtFQUNuQixpQkFBaUIsRUFBQTs7QUFHbkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLGVBQWU7RUFDZixlQUFlO0VBQ2YsV0FBVztFQUNYLGFBQWEsRUFBQTs7QUFOZjtJQVNJLG1CQUFtQjtJQUNuQixnQkFBZ0IsRUFBQTs7QUFJcEI7RUFDRSxhQUFhLEVBQUE7O0FBRGY7SUFJSSxnQkFBZ0I7SUFDaEIsVUFBVTtJQUNWLGlCQUFpQixFQUFBOztBQU5yQjtJQVVJLG1CQUFtQjtJQUNuQixVQUFVO0lBQ1YsaUJBQWlCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZWVkLXBocmFzZS9zZWVkLXBocmFzZS5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5zZWVkLXBocmFzZS10aXRsZSB7XHJcbiAgbGluZS1oZWlnaHQ6IDIuMnJlbTtcclxuICBwYWRkaW5nOiAyLjJyZW0gMDtcclxufVxyXG5cclxuLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBmbGV4LXdyYXA6IHdyYXA7XHJcbiAgcGFkZGluZzogMS40cmVtO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG4gIGhlaWdodDogMTJyZW07XHJcblxyXG4gIC53b3JkIHtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjJyZW07XHJcbiAgICBtYXgtd2lkdGg6IDEzcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLndyYXAtYnV0dG9ucyB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgLnNlZWQtcGhyYXNlLWJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuOHJlbSAwO1xyXG4gICAgd2lkdGg6IDI1JTtcclxuICAgIG1pbi13aWR0aDogMS41cmVtO1xyXG4gIH1cclxuXHJcbiAgLmNvcHktYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMi44cmVtIDFyZW07XHJcbiAgICB3aWR0aDogMjUlO1xyXG4gICAgbWluLXdpZHRoOiAxLjVyZW07XHJcbiAgfVxyXG59XHJcblxyXG4iXX0= */" /***/ }), @@ -6820,7 +6820,7 @@ module.exports = "
\r\n
\r\n /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.25); }\n\n.modal {\n position: relative;\n display: flex;\n flex-direction: column;\n background-position: center;\n background-size: 200%;\n padding: 0.3rem 3rem 3rem 3rem;\n width: 64rem; }\n\n.modal .title {\n padding: 1.4rem 0;\n font-size: 1.8rem;\n line-height: 3rem; }\n\n.modal .content {\n display: flex;\n font-size: 1.4rem; }\n\n.modal .content .message-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n margin: 1.4rem 3rem 6.2rem 0; }\n\n.modal .content .message-container .message-block {\n display: flex;\n margin-bottom: 1rem; }\n\n.modal .content .message-container .message-block:first-child .message-label {\n line-height: 4rem; }\n\n.modal .content .message-container .message-block:first-child .message-text {\n line-height: 4rem; }\n\n.modal .content .message-container .message-block:last-child {\n margin-bottom: 0; }\n\n.modal .content .message-container .message-block .message-label {\n min-width: 6.7rem;\n line-height: 2rem; }\n\n.modal .content .message-container .message-block .message-text {\n overflow-wrap: break-word;\n margin-left: 4.8rem;\n width: 43.4rem;\n line-height: 2rem; }\n\n.modal .wrapper-buttons {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n\n.modal .wrapper-buttons button {\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC1tb2RhbC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzZW5kLW1vZGFsXFxzZW5kLW1vZGFsLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFFdkM7RUFDRSxrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLDhCQUE4QjtFQUM5QixZQUFZLEVBQUE7O0FBUGQ7SUFVSSxpQkFBaUI7SUFDakIsaUJBQWlCO0lBQ2pCLGlCQUFpQixFQUFBOztBQVpyQjtJQWdCSSxhQUFhO0lBQ2IsaUJBQWlCLEVBQUE7O0FBakJyQjtNQW9CTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLHVCQUF1QjtNQUN2Qix1QkFBdUI7TUFDdkIsNEJBQTRCLEVBQUE7O0FBeEJsQztRQTJCUSxhQUFhO1FBQ2IsbUJBQW1CLEVBQUE7O0FBNUIzQjtVQWlDWSxpQkFBaUIsRUFBQTs7QUFqQzdCO1VBcUNZLGlCQUFpQixFQUFBOztBQXJDN0I7VUEwQ1UsZ0JBQWdCLEVBQUE7O0FBMUMxQjtVQThDVSxpQkFBaUI7VUFDakIsaUJBQWlCLEVBQUE7O0FBL0MzQjtVQW1EVSx5QkFBeUI7VUFDekIsbUJBQW1CO1VBQ25CLGNBQWM7VUFDZCxpQkFBaUIsRUFBQTs7QUF0RDNCO0lBOERJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCLEVBQUE7O0FBaEVsQztNQW1FTSxXQUFXO01BQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZW5kLW1vZGFsL3NlbmQtbW9kYWwuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGZpeGVkO1xyXG4gIHRvcDogMDtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICByaWdodDogMDtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcclxufVxyXG4ubW9kYWwge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xyXG4gIGJhY2tncm91bmQtc2l6ZTogMjAwJTtcclxuICBwYWRkaW5nOiAwLjNyZW0gM3JlbSAzcmVtIDNyZW07XHJcbiAgd2lkdGg6IDY0cmVtO1xyXG5cclxuICAudGl0bGUge1xyXG4gICAgcGFkZGluZzogMS40cmVtIDA7XHJcbiAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAzcmVtO1xyXG4gIH1cclxuXHJcbiAgLmNvbnRlbnQge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xyXG5cclxuICAgIC5tZXNzYWdlLWNvbnRhaW5lciB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAxLjRyZW0gM3JlbSA2LjJyZW0gMDtcclxuICAgICAgXHJcbiAgICAgIC5tZXNzYWdlLWJsb2NrIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcblxyXG4gICAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG5cclxuICAgICAgICAgIC5tZXNzYWdlLWxhYmVsIHtcclxuICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDRyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLm1lc3NhZ2UtdGV4dCB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiA0cmVtO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICAgIG1hcmdpbi1ib3R0b206IDA7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubWVzc2FnZS1sYWJlbCB7XHJcbiAgICAgICAgICBtaW4td2lkdGg6IDYuN3JlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLm1lc3NhZ2UtdGV4dCB7XHJcbiAgICAgICAgICBvdmVyZmxvdy13cmFwOiBicmVhay13b3JkO1xyXG4gICAgICAgICAgbWFyZ2luLWxlZnQ6IDQuOHJlbTtcclxuICAgICAgICAgIHdpZHRoOiA0My40cmVtO1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndyYXBwZXItYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG59XHJcbiJdfQ== */" +module.exports = ":host {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(255, 255, 255, 0.25); }\n\n.modal {\n position: relative;\n display: flex;\n flex-direction: column;\n background-position: center;\n background-size: 200%;\n padding: 0.3rem 3rem 3rem 3rem;\n width: 64rem; }\n\n.modal .title {\n padding: 1.4rem 0;\n font-size: 1.8rem;\n line-height: 3rem; }\n\n.modal .content {\n display: flex;\n font-size: 1.4rem; }\n\n.modal .content .message-container {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n margin: 1.4rem 3rem 6.2rem 0; }\n\n.modal .content .message-container .message-block {\n display: flex;\n margin-bottom: 1rem; }\n\n.modal .content .message-container .message-block:first-child .message-label {\n line-height: 4rem; }\n\n.modal .content .message-container .message-block:first-child .message-text {\n line-height: 4rem; }\n\n.modal .content .message-container .message-block:last-child {\n margin-bottom: 0; }\n\n.modal .content .message-container .message-block .message-label {\n min-width: 6.7rem;\n line-height: 2rem; }\n\n.modal .content .message-container .message-block .message-text {\n overflow-wrap: break-word;\n margin-left: 4.8rem;\n width: 43.4rem;\n line-height: 2rem; }\n\n.modal .wrapper-buttons {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n\n.modal .wrapper-buttons button {\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC1tb2RhbC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2VuZC1tb2RhbFxcc2VuZC1tb2RhbC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBRXZDO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsMkJBQTJCO0VBQzNCLHFCQUFxQjtFQUNyQiw4QkFBOEI7RUFDOUIsWUFBWSxFQUFBOztBQVBkO0lBVUksaUJBQWlCO0lBQ2pCLGlCQUFpQjtJQUNqQixpQkFBaUIsRUFBQTs7QUFackI7SUFnQkksYUFBYTtJQUNiLGlCQUFpQixFQUFBOztBQWpCckI7TUFvQk0sYUFBYTtNQUNiLHNCQUFzQjtNQUN0Qix1QkFBdUI7TUFDdkIsdUJBQXVCO01BQ3ZCLDRCQUE0QixFQUFBOztBQXhCbEM7UUEyQlEsYUFBYTtRQUNiLG1CQUFtQixFQUFBOztBQTVCM0I7VUFpQ1ksaUJBQWlCLEVBQUE7O0FBakM3QjtVQXFDWSxpQkFBaUIsRUFBQTs7QUFyQzdCO1VBMENVLGdCQUFnQixFQUFBOztBQTFDMUI7VUE4Q1UsaUJBQWlCO1VBQ2pCLGlCQUFpQixFQUFBOztBQS9DM0I7VUFtRFUseUJBQXlCO1VBQ3pCLG1CQUFtQjtVQUNuQixjQUFjO1VBQ2QsaUJBQWlCLEVBQUE7O0FBdEQzQjtJQThESSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDhCQUE4QixFQUFBOztBQWhFbEM7TUFtRU0sV0FBVztNQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2VuZC1tb2RhbC9zZW5kLW1vZGFsLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuLm1vZGFsIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogMC4zcmVtIDNyZW0gM3JlbSAzcmVtO1xyXG4gIHdpZHRoOiA2NHJlbTtcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIHBhZGRpbmc6IDEuNHJlbSAwO1xyXG4gICAgZm9udC1zaXplOiAxLjhyZW07XHJcbiAgICBsaW5lLWhlaWdodDogM3JlbTtcclxuICB9XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuXHJcbiAgICAubWVzc2FnZS1jb250YWluZXIge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMS40cmVtIDNyZW0gNi4ycmVtIDA7XHJcbiAgICAgIFxyXG4gICAgICAubWVzc2FnZS1ibG9jayB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG5cclxuICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuXHJcbiAgICAgICAgICAubWVzc2FnZS1sYWJlbCB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiA0cmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5tZXNzYWdlLXRleHQge1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogNHJlbTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLm1lc3NhZ2UtbGFiZWwge1xyXG4gICAgICAgICAgbWluLXdpZHRoOiA2LjdyZW07XHJcbiAgICAgICAgICBsaW5lLWhlaWdodDogMnJlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5tZXNzYWdlLXRleHQge1xyXG4gICAgICAgICAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICAgICAgICAgIG1hcmdpbi1sZWZ0OiA0LjhyZW07XHJcbiAgICAgICAgICB3aWR0aDogNDMuNHJlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC53cmFwcGVyLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG4iXX0= */" /***/ }), @@ -6903,7 +6903,7 @@ module.exports = "
\r\n\r\n
\r\n /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".head {\n justify-content: flex-end; }\n\n.settings-title {\n font-size: 1.7rem; }\n\n.theme-selection {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin: 2.4rem 0;\n width: 50%; }\n\n.theme-selection .radio-block {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n font-size: 1.3rem;\n line-height: 2.7rem; }\n\n.lock-selection {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin: 2.4rem 0;\n width: 50%; }\n\n.lock-selection .lock-selection-title {\n display: flex;\n font-size: 1.5rem;\n line-height: 2.7rem;\n margin-bottom: 1rem; }\n\n.scale-selection {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0 4rem;\n width: 50%;\n height: 0.5rem; }\n\n.scale-selection .button-block {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 0 auto;\n margin: 0 0.2rem;\n padding: 0;\n height: 0.5rem; }\n\n.scale-selection .button-block .label {\n position: absolute;\n bottom: -1rem;\n left: 50%;\n transform: translate(-50%, 100%);\n font-size: 1rem;\n white-space: nowrap; }\n\n.master-password {\n width: 50%; }\n\n.master-password .master-password-title {\n display: flex;\n font-size: 1.5rem;\n line-height: 2.7rem;\n margin-bottom: 1rem; }\n\n.master-password button {\n margin: 2.5rem auto;\n width: 100%;\n max-width: 15rem; }\n\n.last-build {\n font-size: 1rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2V0dGluZ3MvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2V0dGluZ3NcXHNldHRpbmdzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UseUJBQXlCLEVBQUE7O0FBRzNCO0VBQ0UsaUJBQWlCLEVBQUE7O0FBR25CO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0Qix1QkFBdUI7RUFDdkIsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFMWjtJQVFJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsMkJBQTJCO0lBQzNCLGlCQUFpQjtJQUNqQixtQkFBbUIsRUFBQTs7QUFJdkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLHVCQUF1QjtFQUN2QixnQkFBZ0I7RUFDaEIsVUFBVSxFQUFBOztBQUxaO0lBUUksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsbUJBQW1CLEVBQUE7O0FBSXZCO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQiw4QkFBOEI7RUFDOUIsaUJBQWlCO0VBQ2pCLFVBQVU7RUFDVixjQUFjLEVBQUE7O0FBTmhCO0lBU0ksa0JBQWtCO0lBQ2xCLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLGNBQWM7SUFDZCxnQkFBZ0I7SUFDaEIsVUFBVTtJQUNWLGNBQWMsRUFBQTs7QUFoQmxCO01BbUJNLGtCQUFrQjtNQUNsQixhQUFhO01BQ2IsU0FBUztNQUNULGdDQUFnQztNQUNoQyxlQUFlO01BQ2YsbUJBQW1CLEVBQUE7O0FBS3pCO0VBQ0UsVUFBVSxFQUFBOztBQURaO0lBSUksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsbUJBQW1CLEVBQUE7O0FBUHZCO0lBV0ksbUJBQW1CO0lBQ25CLFdBQVc7SUFDWCxnQkFBZ0IsRUFBQTs7QUFJcEI7RUFDRSxlQUFlLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZXR0aW5ncy9zZXR0aW5ncy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5oZWFkIHtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xyXG59XHJcblxyXG4uc2V0dGluZ3MtdGl0bGUge1xyXG4gIGZvbnQtc2l6ZTogMS43cmVtO1xyXG59XHJcblxyXG4udGhlbWUtc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAucmFkaW8tYmxvY2sge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcbiAgfVxyXG59XHJcblxyXG4ubG9jay1zZWxlY3Rpb24ge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC5sb2NrLXNlbGVjdGlvbi10aXRsZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gICAgbWFyZ2luLWJvdHRvbTogMXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5zY2FsZS1zZWxlY3Rpb24ge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgcGFkZGluZzogMCAwIDRyZW07XHJcbiAgd2lkdGg6IDUwJTtcclxuICBoZWlnaHQ6IDAuNXJlbTtcclxuXHJcbiAgLmJ1dHRvbi1ibG9jayB7XHJcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleDogMSAwIGF1dG87XHJcbiAgICBtYXJnaW46IDAgMC4ycmVtO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIGhlaWdodDogMC41cmVtO1xyXG5cclxuICAgIC5sYWJlbCB7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogNTAlO1xyXG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAxMDAlKTtcclxuICAgICAgZm9udC1zaXplOiAxcmVtO1xyXG4gICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLm1hc3Rlci1wYXNzd29yZCB7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLm1hc3Rlci1wYXNzd29yZC10aXRsZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gICAgbWFyZ2luLWJvdHRvbTogMXJlbTtcclxuICB9XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuNXJlbSBhdXRvO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmxhc3QtYnVpbGQge1xyXG4gIGZvbnQtc2l6ZTogMXJlbTtcclxufVxyXG4iXX0= */" +module.exports = ".head {\n justify-content: flex-end; }\n\n.settings-title {\n font-size: 1.7rem; }\n\n.theme-selection {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin: 2.4rem 0;\n width: 50%; }\n\n.theme-selection .radio-block {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n font-size: 1.3rem;\n line-height: 2.7rem; }\n\n.lock-selection {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin: 2.4rem 0;\n width: 50%; }\n\n.lock-selection .lock-selection-title {\n display: flex;\n font-size: 1.5rem;\n line-height: 2.7rem;\n margin-bottom: 1rem; }\n\n.scale-selection {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0 4rem;\n width: 50%;\n height: 0.5rem; }\n\n.scale-selection .button-block {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 0 auto;\n margin: 0 0.2rem;\n padding: 0;\n height: 0.5rem; }\n\n.scale-selection .button-block .label {\n position: absolute;\n bottom: -1rem;\n left: 50%;\n transform: translate(-50%, 100%);\n font-size: 1rem;\n white-space: nowrap; }\n\n.master-password {\n width: 50%; }\n\n.master-password .master-password-title {\n display: flex;\n font-size: 1.5rem;\n line-height: 2.7rem;\n margin-bottom: 1rem; }\n\n.master-password button {\n margin: 2.5rem auto;\n width: 100%;\n max-width: 15rem; }\n\n.last-build {\n font-size: 1rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2V0dGluZ3MvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHNldHRpbmdzXFxzZXR0aW5ncy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLHlCQUF5QixFQUFBOztBQUczQjtFQUNFLGlCQUFpQixFQUFBOztBQUduQjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsdUJBQXVCO0VBQ3ZCLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7O0FBTFo7SUFRSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDJCQUEyQjtJQUMzQixpQkFBaUI7SUFDakIsbUJBQW1CLEVBQUE7O0FBSXZCO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0Qix1QkFBdUI7RUFDdkIsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFMWjtJQVFJLGFBQWE7SUFDYixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLG1CQUFtQixFQUFBOztBQUl2QjtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsOEJBQThCO0VBQzlCLGlCQUFpQjtFQUNqQixVQUFVO0VBQ1YsY0FBYyxFQUFBOztBQU5oQjtJQVNJLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixjQUFjO0lBQ2QsZ0JBQWdCO0lBQ2hCLFVBQVU7SUFDVixjQUFjLEVBQUE7O0FBaEJsQjtNQW1CTSxrQkFBa0I7TUFDbEIsYUFBYTtNQUNiLFNBQVM7TUFDVCxnQ0FBZ0M7TUFDaEMsZUFBZTtNQUNmLG1CQUFtQixFQUFBOztBQUt6QjtFQUNFLFVBQVUsRUFBQTs7QUFEWjtJQUlJLGFBQWE7SUFDYixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLG1CQUFtQixFQUFBOztBQVB2QjtJQVdJLG1CQUFtQjtJQUNuQixXQUFXO0lBQ1gsZ0JBQWdCLEVBQUE7O0FBSXBCO0VBQ0UsZUFBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2V0dGluZ3Mvc2V0dGluZ3MuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuaGVhZCB7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxufVxyXG5cclxuLnNldHRpbmdzLXRpdGxlIHtcclxuICBmb250LXNpemU6IDEuN3JlbTtcclxufVxyXG5cclxuLnRoZW1lLXNlbGVjdGlvbiB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLnJhZGlvLWJsb2NrIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmxvY2stc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAubG9jay1zZWxlY3Rpb24tdGl0bGUge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgfVxyXG59XHJcblxyXG4uc2NhbGUtc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIHBhZGRpbmc6IDAgMCA0cmVtO1xyXG4gIHdpZHRoOiA1MCU7XHJcbiAgaGVpZ2h0OiAwLjVyZW07XHJcblxyXG4gIC5idXR0b24tYmxvY2sge1xyXG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZsZXg6IDEgMCBhdXRvO1xyXG4gICAgbWFyZ2luOiAwIDAuMnJlbTtcclxuICAgIHBhZGRpbmc6IDA7XHJcbiAgICBoZWlnaHQ6IDAuNXJlbTtcclxuXHJcbiAgICAubGFiZWwge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIGJvdHRvbTogLTFyZW07XHJcbiAgICAgIGxlZnQ6IDUwJTtcclxuICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgMTAwJSk7XHJcbiAgICAgIGZvbnQtc2l6ZTogMXJlbTtcclxuICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi5tYXN0ZXItcGFzc3dvcmQge1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC5tYXN0ZXItcGFzc3dvcmQtdGl0bGUge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgfVxyXG5cclxuICBidXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gYXV0bztcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5sYXN0LWJ1aWxkIHtcclxuICBmb250LXNpemU6IDFyZW07XHJcbn1cclxuIl19 */" /***/ }), @@ -7398,7 +7398,7 @@ module.exports = "
\r\n
\r\n
\r\n /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.chart-header {\n display: flex;\n flex: 0 0 auto; }\n\n.chart-header .general {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n flex-grow: 1;\n font-size: 1.3rem;\n margin: -0.5rem 0; }\n\n.chart-header .general > div {\n display: flex;\n align-items: center;\n margin: 0.5rem 0;\n height: 2rem; }\n\n.chart-header .general > div .label {\n display: inline-block;\n width: 9rem; }\n\n.chart-header .selected {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n justify-content: center;\n flex-grow: 1;\n font-size: 1.8rem; }\n\n.chart-header .selected span {\n line-height: 2.9rem; }\n\n.chart {\n position: relative;\n display: flex;\n align-items: center;\n flex: 1 1 auto;\n min-height: 40rem; }\n\n.chart > div {\n position: absolute;\n width: 100%;\n height: 100%; }\n\n.chart-options {\n display: flex;\n align-items: center;\n height: 2.4rem;\n flex: 0 0 auto; }\n\n.chart-options .title {\n font-size: 1.3rem;\n padding: 0 1rem; }\n\n.chart-options .title:first-child {\n padding-left: 0; }\n\n.chart-options .options {\n display: flex;\n justify-content: space-between;\n flex-grow: 1;\n height: 100%; }\n\n.chart-options .options button {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n cursor: pointer;\n font-size: 1.3rem;\n margin: 0 0.1rem;\n padding: 0;\n height: 100%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc3Rha2luZy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzdGFraW5nXFxzdGFraW5nLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxhQUFhO0VBQ2IsY0FBYyxFQUFBOztBQUZoQjtJQUtJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsdUJBQXVCO0lBQ3ZCLHVCQUF1QjtJQUN2QixZQUFZO0lBQ1osaUJBQWlCO0lBQ2pCLGlCQUFpQixFQUFBOztBQVhyQjtNQWNNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsZ0JBQWdCO01BQ2hCLFlBQVksRUFBQTs7QUFqQmxCO1FBb0JRLHFCQUFxQjtRQUNyQixXQUFXLEVBQUE7O0FBckJuQjtJQTJCSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLHFCQUFxQjtJQUNyQix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQixFQUFBOztBQWhDckI7TUFtQ00sbUJBQW1CLEVBQUE7O0FBS3pCO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLGlCQUFpQixFQUFBOztBQUxuQjtJQVFJLGtCQUFrQjtJQUNsQixXQUFXO0lBQ1gsWUFBWSxFQUFBOztBQUloQjtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLGNBQWMsRUFBQTs7QUFKaEI7SUFPSSxpQkFBaUI7SUFDakIsZUFBZSxFQUFBOztBQVJuQjtNQVdNLGVBQWUsRUFBQTs7QUFYckI7SUFnQkksYUFBYTtJQUNiLDhCQUE4QjtJQUM5QixZQUFZO0lBQ1osWUFBWSxFQUFBOztBQW5CaEI7TUFzQk0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLGVBQWU7TUFDZixpQkFBaUI7TUFDakIsZ0JBQWdCO01BQ2hCLFVBQVU7TUFDVixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zdGFraW5nL3N0YWtpbmcuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uY2hhcnQtaGVhZGVyIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG5cclxuICAuZ2VuZXJhbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbjogLTAuNXJlbSAwO1xyXG5cclxuICAgID4gZGl2IHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAwLjVyZW0gMDtcclxuICAgICAgaGVpZ2h0OiAycmVtO1xyXG5cclxuICAgICAgLmxhYmVsIHtcclxuICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XHJcbiAgICAgICAgd2lkdGg6IDlyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zZWxlY3RlZCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBmbGV4LWVuZDtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgZm9udC1zaXplOiAxLjhyZW07XHJcblxyXG4gICAgc3BhbiB7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjlyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4uY2hhcnQge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgZmxleDogMSAxIGF1dG87XHJcbiAgbWluLWhlaWdodDogNDByZW07XHJcblxyXG4gID4gZGl2IHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiAxMDAlO1xyXG4gIH1cclxufVxyXG5cclxuLmNoYXJ0LW9wdGlvbnMge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBoZWlnaHQ6IDIuNHJlbTtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgcGFkZGluZzogMCAxcmVtO1xyXG5cclxuICAgICY6Zmlyc3QtY2hpbGR7XHJcbiAgICAgIHBhZGRpbmctbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5vcHRpb25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIGZsZXg6IDEgMSBhdXRvO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICBtYXJnaW46IDAgMC4xcmVtO1xyXG4gICAgICBwYWRkaW5nOiAwO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" +module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.chart-header {\n display: flex;\n flex: 0 0 auto; }\n\n.chart-header .general {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n flex-grow: 1;\n font-size: 1.3rem;\n margin: -0.5rem 0; }\n\n.chart-header .general > div {\n display: flex;\n align-items: center;\n margin: 0.5rem 0;\n height: 2rem; }\n\n.chart-header .general > div .label {\n display: inline-block;\n width: 9rem; }\n\n.chart-header .selected {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n justify-content: center;\n flex-grow: 1;\n font-size: 1.8rem; }\n\n.chart-header .selected span {\n line-height: 2.9rem; }\n\n.chart {\n position: relative;\n display: flex;\n align-items: center;\n flex: 1 1 auto;\n min-height: 40rem; }\n\n.chart > div {\n position: absolute;\n width: 100%;\n height: 100%; }\n\n.chart-options {\n display: flex;\n align-items: center;\n height: 2.4rem;\n flex: 0 0 auto; }\n\n.chart-options .title {\n font-size: 1.3rem;\n padding: 0 1rem; }\n\n.chart-options .title:first-child {\n padding-left: 0; }\n\n.chart-options .options {\n display: flex;\n justify-content: space-between;\n flex-grow: 1;\n height: 100%; }\n\n.chart-options .options button {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1 1 auto;\n cursor: pointer;\n font-size: 1.3rem;\n margin: 0 0.1rem;\n padding: 0;\n height: 100%; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc3Rha2luZy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc3Rha2luZ1xcc3Rha2luZy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsYUFBYTtFQUNiLGNBQWMsRUFBQTs7QUFGaEI7SUFLSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLHVCQUF1QjtJQUN2Qix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQixpQkFBaUIsRUFBQTs7QUFYckI7TUFjTSxhQUFhO01BQ2IsbUJBQW1CO01BQ25CLGdCQUFnQjtNQUNoQixZQUFZLEVBQUE7O0FBakJsQjtRQW9CUSxxQkFBcUI7UUFDckIsV0FBVyxFQUFBOztBQXJCbkI7SUEyQkksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixxQkFBcUI7SUFDckIsdUJBQXVCO0lBQ3ZCLFlBQVk7SUFDWixpQkFBaUIsRUFBQTs7QUFoQ3JCO01BbUNNLG1CQUFtQixFQUFBOztBQUt6QjtFQUNFLGtCQUFrQjtFQUNsQixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLGNBQWM7RUFDZCxpQkFBaUIsRUFBQTs7QUFMbkI7SUFRSSxrQkFBa0I7SUFDbEIsV0FBVztJQUNYLFlBQVksRUFBQTs7QUFJaEI7RUFDRSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLGNBQWM7RUFDZCxjQUFjLEVBQUE7O0FBSmhCO0lBT0ksaUJBQWlCO0lBQ2pCLGVBQWUsRUFBQTs7QUFSbkI7TUFXTSxlQUFlLEVBQUE7O0FBWHJCO0lBZ0JJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsWUFBWTtJQUNaLFlBQVksRUFBQTs7QUFuQmhCO01Bc0JNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGNBQWM7TUFDZCxlQUFlO01BQ2YsaUJBQWlCO01BQ2pCLGdCQUFnQjtNQUNoQixVQUFVO01BQ1YsWUFBWSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvc3Rha2luZy9zdGFraW5nLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmNoYXJ0LWhlYWRlciB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuXHJcbiAgLmdlbmVyYWwge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW46IC0wLjVyZW0gMDtcclxuXHJcbiAgICA+IGRpdiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMC41cmVtIDA7XHJcbiAgICAgIGhlaWdodDogMnJlbTtcclxuXHJcbiAgICAgIC5sYWJlbCB7XHJcbiAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgIHdpZHRoOiA5cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuc2VsZWN0ZWQge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZsZXgtZ3JvdzogMTtcclxuICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG5cclxuICAgIHNwYW4ge1xyXG4gICAgICBsaW5lLWhlaWdodDogMi45cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmNoYXJ0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGZsZXg6IDEgMSBhdXRvO1xyXG4gIG1pbi1oZWlnaHQ6IDQwcmVtO1xyXG5cclxuICA+IGRpdiB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICB9XHJcbn1cclxuXHJcbi5jaGFydC1vcHRpb25zIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgZmxleDogMCAwIGF1dG87XHJcblxyXG4gIC50aXRsZSB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuXHJcbiAgICAmOmZpcnN0LWNoaWxke1xyXG4gICAgICBwYWRkaW5nLWxlZnQ6IDA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAub3B0aW9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgaGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBmbGV4OiAxIDEgYXV0bztcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgbWFyZ2luOiAwIDAuMXJlbTtcclxuICAgICAgcGFkZGluZzogMDtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */" /***/ }), @@ -7998,7 +7998,7 @@ module.exports = "
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".form-transfer {\n margin: 2.4rem 0; }\n .form-transfer .alias-name {\n width: 50%; }\n .form-transfer .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-transfer .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-transfer .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHJhbnNmZXItYWxpYXMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcdHJhbnNmZXItYWxpYXNcXHRyYW5zZmVyLWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQSIsImZpbGUiOiJzcmMvYXBwL3RyYW5zZmVyLWFsaWFzL3RyYW5zZmVyLWFsaWFzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmZvcm0tdHJhbnNmZXIge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */" +module.exports = ".form-transfer {\n margin: 2.4rem 0; }\n .form-transfer .alias-name {\n width: 50%; }\n .form-transfer .alias-cost {\n font-size: 1.3rem;\n margin-top: 2rem; }\n .form-transfer .wrap-buttons {\n display: flex;\n justify-content: space-between;\n margin: 2.5rem -0.7rem; }\n .form-transfer .wrap-buttons button {\n margin: 0 0.7rem;\n width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHJhbnNmZXItYWxpYXMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHRyYW5zZmVyLWFsaWFzXFx0cmFuc2Zlci1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC90cmFuc2Zlci1hbGlhcy90cmFuc2Zlci1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLXRyYW5zZmVyIHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG5cclxuICAuYWxpYXMtbmFtZSB7XHJcbiAgICB3aWR0aDogNTAlO1xyXG4gIH1cclxuXHJcbiAgLmFsaWFzLWNvc3Qge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW4tdG9wOiAycmVtO1xyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG4gICAgICB3aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */" /***/ }), @@ -8159,7 +8159,7 @@ module.exports = "
\r\n
\r\n /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.head {\n flex: 0 0 auto;\n box-sizing: content-box;\n margin: -3rem -3rem 0; }\n\n.messages-content {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n flex-grow: 1; }\n\n.messages-content .messages-list {\n display: flex;\n flex-direction: column;\n font-size: 1.3rem;\n margin: 1rem -3rem;\n padding: 0 3rem;\n overflow-y: overlay; }\n\n.messages-content .messages-list div {\n margin: 0.7rem 0; }\n\n.messages-content .messages-list div.date {\n text-align: center; }\n\n.messages-content .messages-list div.my, .messages-content .messages-list div.buddy {\n position: relative;\n padding: 1.8rem;\n max-width: 60%; }\n\n.messages-content .messages-list div.buddy {\n align-self: flex-end; }\n\n.messages-content .type-message {\n display: flex;\n flex: 0 0 auto;\n width: 100%;\n height: 4.2rem; }\n\n.messages-content .type-message .input-block {\n width: 100%; }\n\n.messages-content .type-message .input-block > textarea {\n min-height: 4.2rem; }\n\n.messages-content .type-message button {\n flex: 0 0 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcdHlwaW5nLW1lc3NhZ2VcXHR5cGluZy1tZXNzYWdlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxjQUFjO0VBQ2QsdUJBQXVCO0VBQ3ZCLHFCQUFxQixFQUFBOztBQUd2QjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsOEJBQThCO0VBQzlCLFlBQVksRUFBQTs7QUFKZDtJQU9JLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsaUJBQWlCO0lBQ2pCLGtCQUFrQjtJQUNsQixlQUFlO0lBQ2YsbUJBQW1CLEVBQUE7O0FBWnZCO01BZU0sZ0JBQWdCLEVBQUE7O0FBZnRCO1FBa0JRLGtCQUFrQixFQUFBOztBQWxCMUI7UUFzQlEsa0JBQWtCO1FBQ2xCLGVBQWU7UUFDZixjQUFjLEVBQUE7O0FBeEJ0QjtRQTRCUSxvQkFBb0IsRUFBQTs7QUE1QjVCO0lBa0NJLGFBQWE7SUFDYixjQUFjO0lBQ2QsV0FBVztJQUNYLGNBQWMsRUFBQTs7QUFyQ2xCO01Bd0NNLFdBQVcsRUFBQTs7QUF4Q2pCO1FBMkNRLGtCQUFrQixFQUFBOztBQTNDMUI7TUFnRE0sZUFBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvdHlwaW5nLW1lc3NhZ2UuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAgZmxleDogMCAwIGF1dG87XHJcbiAgYm94LXNpemluZzogY29udGVudC1ib3g7XHJcbiAgbWFyZ2luOiAtM3JlbSAtM3JlbSAwO1xyXG59XHJcblxyXG4ubWVzc2FnZXMtY29udGVudCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICBmbGV4LWdyb3c6IDE7XHJcblxyXG4gIC5tZXNzYWdlcy1saXN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW46IDFyZW0gLTNyZW07XHJcbiAgICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgICBvdmVyZmxvdy15OiBvdmVybGF5O1xyXG5cclxuICAgIGRpdiB7XHJcbiAgICAgIG1hcmdpbjogMC43cmVtIDA7XHJcblxyXG4gICAgICAmLmRhdGUge1xyXG4gICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5teSwgJi5idWRkeSB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIHBhZGRpbmc6IDEuOHJlbTtcclxuICAgICAgICBtYXgtd2lkdGg6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5idWRkeSB7XHJcbiAgICAgICAgYWxpZ24tc2VsZjogZmxleC1lbmQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC50eXBlLW1lc3NhZ2Uge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXg6IDAgMCBhdXRvO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDQuMnJlbTtcclxuXHJcbiAgICAuaW5wdXQtYmxvY2sge1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgID4gdGV4dGFyZWEge1xyXG4gICAgICAgIG1pbi1oZWlnaHQ6IDQuMnJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGZsZXg6IDAgMCAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbiJdfQ== */" +module.exports = ":host {\n display: flex;\n flex-direction: column;\n width: 100%; }\n\n.head {\n flex: 0 0 auto;\n box-sizing: content-box;\n margin: -3rem -3rem 0; }\n\n.messages-content {\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n flex-grow: 1; }\n\n.messages-content .messages-list {\n display: flex;\n flex-direction: column;\n font-size: 1.3rem;\n margin: 1rem -3rem;\n padding: 0 3rem;\n overflow-y: overlay; }\n\n.messages-content .messages-list div {\n margin: 0.7rem 0; }\n\n.messages-content .messages-list div.date {\n text-align: center; }\n\n.messages-content .messages-list div.my, .messages-content .messages-list div.buddy {\n position: relative;\n padding: 1.8rem;\n max-width: 60%; }\n\n.messages-content .messages-list div.buddy {\n align-self: flex-end; }\n\n.messages-content .type-message {\n display: flex;\n flex: 0 0 auto;\n width: 100%;\n height: 4.2rem; }\n\n.messages-content .type-message .input-block {\n width: 100%; }\n\n.messages-content .type-message .input-block > textarea {\n min-height: 4.2rem; }\n\n.messages-content .type-message button {\n flex: 0 0 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHR5cGluZy1tZXNzYWdlXFx0eXBpbmctbWVzc2FnZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsY0FBYztFQUNkLHVCQUF1QjtFQUN2QixxQkFBcUIsRUFBQTs7QUFHdkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLDhCQUE4QjtFQUM5QixZQUFZLEVBQUE7O0FBSmQ7SUFPSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLGlCQUFpQjtJQUNqQixrQkFBa0I7SUFDbEIsZUFBZTtJQUNmLG1CQUFtQixFQUFBOztBQVp2QjtNQWVNLGdCQUFnQixFQUFBOztBQWZ0QjtRQWtCUSxrQkFBa0IsRUFBQTs7QUFsQjFCO1FBc0JRLGtCQUFrQjtRQUNsQixlQUFlO1FBQ2YsY0FBYyxFQUFBOztBQXhCdEI7UUE0QlEsb0JBQW9CLEVBQUE7O0FBNUI1QjtJQWtDSSxhQUFhO0lBQ2IsY0FBYztJQUNkLFdBQVc7SUFDWCxjQUFjLEVBQUE7O0FBckNsQjtNQXdDTSxXQUFXLEVBQUE7O0FBeENqQjtRQTJDUSxrQkFBa0IsRUFBQTs7QUEzQzFCO01BZ0RNLGVBQWUsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3R5cGluZy1tZXNzYWdlL3R5cGluZy1tZXNzYWdlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmhlYWQge1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xyXG4gIG1hcmdpbjogLTNyZW0gLTNyZW0gMDtcclxufVxyXG5cclxuLm1lc3NhZ2VzLWNvbnRlbnQge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgZmxleC1ncm93OiAxO1xyXG5cclxuICAubWVzc2FnZXMtbGlzdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbWFyZ2luOiAxcmVtIC0zcmVtO1xyXG4gICAgcGFkZGluZzogMCAzcmVtO1xyXG4gICAgb3ZlcmZsb3cteTogb3ZlcmxheTtcclxuXHJcbiAgICBkaXYge1xyXG4gICAgICBtYXJnaW46IDAuN3JlbSAwO1xyXG5cclxuICAgICAgJi5kYXRlIHtcclxuICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYubXksICYuYnVkZHkge1xyXG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICBwYWRkaW5nOiAxLjhyZW07XHJcbiAgICAgICAgbWF4LXdpZHRoOiA2MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuYnVkZHkge1xyXG4gICAgICAgIGFsaWduLXNlbGY6IGZsZXgtZW5kO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudHlwZS1tZXNzYWdlIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiA0LjJyZW07XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICA+IHRleHRhcmVhIHtcclxuICAgICAgICBtaW4taGVpZ2h0OiA0LjJyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBmbGV4OiAwIDAgMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4iXX0= */" /***/ }), @@ -8226,7 +8226,7 @@ module.exports = "
\r\n\r\n
\r\n < /*! no static exports found */ /***/ (function(module, exports) { -module.exports = ".form-details {\n margin-top: 1.8rem; }\n .form-details .input-block:first-child {\n width: 50%; }\n .form-details .seed-phrase {\n display: flex;\n font-size: 1.4rem;\n line-height: 1.5rem;\n padding: 1.4rem;\n width: 100%;\n height: 8.8rem; }\n .form-details .seed-phrase .seed-phrase-hint {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n width: 100%;\n height: 100%; }\n .form-details .seed-phrase .seed-phrase-content {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n width: 100%;\n height: 100%; }\n .form-details .wallet-buttons {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n .form-details .wallet-buttons button {\n margin: 2.9rem 0;\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0LWRldGFpbHMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcd2FsbGV0LWRldGFpbHNcXHdhbGxldC1kZXRhaWxzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7RUFEcEI7SUFNTSxVQUFVLEVBQUE7RUFOaEI7SUFXSSxhQUFhO0lBQ2IsaUJBQWlCO0lBQ2pCLG1CQUFtQjtJQUNuQixlQUFlO0lBQ2YsV0FBVztJQUNYLGNBQWMsRUFBQTtFQWhCbEI7TUFtQk0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7RUF4QmxCO01BNEJNLGFBQWE7TUFDYixzQkFBc0I7TUFDdEIsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7RUFoQ2xCO0lBcUNJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCLEVBQUE7RUF2Q2xDO01BMENNLGdCQUFnQjtNQUNoQixXQUFXO01BQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC93YWxsZXQtZGV0YWlscy93YWxsZXQtZGV0YWlscy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWRldGFpbHMge1xyXG4gIG1hcmdpbi10b3A6IDEuOHJlbTtcclxuXHJcbiAgLmlucHV0LWJsb2NrIHtcclxuXHJcbiAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgd2lkdGg6IDUwJTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zZWVkLXBocmFzZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS41cmVtO1xyXG4gICAgcGFkZGluZzogMS40cmVtO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDguOHJlbTtcclxuXHJcbiAgICAuc2VlZC1waHJhc2UtaGludCB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcblxyXG4gICAgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBmbGV4LXdyYXA6IHdyYXA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAud2FsbGV0LWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAyLjlyZW0gMDtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG4iXX0= */" +module.exports = ".form-details {\n margin-top: 1.8rem; }\n .form-details .input-block:first-child {\n width: 50%; }\n .form-details .seed-phrase {\n display: flex;\n font-size: 1.4rem;\n line-height: 1.5rem;\n padding: 1.4rem;\n width: 100%;\n height: 8.8rem; }\n .form-details .seed-phrase .seed-phrase-hint {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n width: 100%;\n height: 100%; }\n .form-details .seed-phrase .seed-phrase-content {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n width: 100%;\n height: 100%; }\n .form-details .wallet-buttons {\n display: flex;\n align-items: center;\n justify-content: space-between; }\n .form-details .wallet-buttons button {\n margin: 2.9rem 0;\n width: 100%;\n max-width: 15rem; }\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0LWRldGFpbHMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHdhbGxldC1kZXRhaWxzXFx3YWxsZXQtZGV0YWlscy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBO0VBRHBCO0lBTU0sVUFBVSxFQUFBO0VBTmhCO0lBV0ksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsZUFBZTtJQUNmLFdBQVc7SUFDWCxjQUFjLEVBQUE7RUFoQmxCO01BbUJNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGVBQWU7TUFDZixXQUFXO01BQ1gsWUFBWSxFQUFBO0VBeEJsQjtNQTRCTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLGVBQWU7TUFDZixXQUFXO01BQ1gsWUFBWSxFQUFBO0VBaENsQjtJQXFDSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDhCQUE4QixFQUFBO0VBdkNsQztNQTBDTSxnQkFBZ0I7TUFDaEIsV0FBVztNQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvd2FsbGV0LWRldGFpbHMvd2FsbGV0LWRldGFpbHMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1kZXRhaWxzIHtcclxuICBtYXJnaW4tdG9wOiAxLjhyZW07XHJcblxyXG4gIC5pbnB1dC1ibG9jayB7XHJcblxyXG4gICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgIHdpZHRoOiA1MCU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuc2VlZC1waHJhc2Uge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuNXJlbTtcclxuICAgIHBhZGRpbmc6IDEuNHJlbTtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiA4LjhyZW07XHJcblxyXG4gICAgLnNlZWQtcGhyYXNlLWhpbnQge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG5cclxuICAgIC5zZWVkLXBocmFzZS1jb250ZW50IHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgZmxleC13cmFwOiB3cmFwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndhbGxldC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMi45cmVtIDA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbn1cclxuIl19 */" /***/ }), @@ -8376,7 +8376,7 @@ module.exports = "
\r\n
\r\n

\\r\\n
\\r\\n \\r\\n
\\r\\n {{title}}\\r\\n {{message}}\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n

\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 3rem;\\n min-width: 34rem;\\n max-width: 60rem; }\\n\\n.modal .content {\\n display: flex; }\\n\\n.modal .content .icon {\\n flex: 0 0 auto;\\n width: 4.4rem;\\n height: 4.4rem; }\\n\\n.modal .content .icon.info {\\n -webkit-mask: url('modal-info.svg') no-repeat center;\\n mask: url('modal-info.svg') no-repeat center; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin-left: 2rem; }\\n\\n.modal .content .message-container .title {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 2.2rem; }\\n\\n.modal .content .message-container .message {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n margin-top: 0.4rem; }\\n\\n.modal .wrap-btn {\\n display: flex;\\n justify-content: space-between;\\n width: 100%;\\n margin-top: 3.5rem; }\\n\\n.modal .action-button {\\n width: 10rem;\\n height: 2.4rem; }\\n\\n.modal .close-button {\\n position: absolute;\\n top: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: transparent;\\n margin: 0;\\n padding: 0;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n.modal .close-button .icon {\\n -webkit-mask: url('close.svg') no-repeat center;\\n mask: url('close.svg') no-repeat center;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9jb25maXJtLW1vZGFsL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXF9oZWxwZXJzXFxkaXJlY3RpdmVzXFxjb25maXJtLW1vZGFsXFxjb25maXJtLW1vZGFsLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFFdkM7RUFDRSxrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLGFBQWE7RUFDYixnQkFBZ0I7RUFDaEIsZ0JBQWdCLEVBQUE7O0FBUmxCO0lBV0ksYUFBYSxFQUFBOztBQVhqQjtNQWNNLGNBQWM7TUFDZCxhQUFhO01BQ2IsY0FBYyxFQUFBOztBQWhCcEI7UUFtQlEsb0RBQTREO2dCQUE1RCw0Q0FBNEQsRUFBQTs7QUFuQnBFO01Bd0JNLGFBQWE7TUFDYixzQkFBc0I7TUFDdEIsdUJBQXVCO01BQ3ZCLHVCQUF1QjtNQUN2QixpQkFBaUIsRUFBQTs7QUE1QnZCO1FBK0JRLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsbUJBQW1CLEVBQUE7O0FBakMzQjtRQXFDUSxpQkFBaUI7UUFDakIsbUJBQW1CO1FBQ25CLGtCQUFrQixFQUFBOztBQXZDMUI7SUE2Q0ksYUFBYTtJQUNiLDhCQUE4QjtJQUM5QixXQUFXO0lBQ1gsa0JBQWtCLEVBQUE7O0FBaER0QjtJQW9ESSxZQUFZO0lBQ1osY0FBYyxFQUFBOztBQXJEbEI7SUF5REksa0JBQWtCO0lBQ2xCLE1BQU07SUFDTixRQUFRO0lBQ1IsYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsdUJBQXVCO0lBQ3ZCLFNBQVM7SUFDVCxVQUFVO0lBQ1YsYUFBYTtJQUNiLGNBQWMsRUFBQTs7QUFuRWxCO01Bc0VNLCtDQUF1RDtjQUF2RCx1Q0FBdUQ7TUFDdkQsYUFBYTtNQUNiLGNBQWMsRUFBQSIsImZpbGUiOiJzcmMvYXBwL19oZWxwZXJzL2RpcmVjdGl2ZXMvY29uZmlybS1tb2RhbC9jb25maXJtLW1vZGFsLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuLm1vZGFsIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogM3JlbTtcclxuICBtaW4td2lkdGg6IDM0cmVtO1xyXG4gIG1heC13aWR0aDogNjByZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgICAgd2lkdGg6IDQuNHJlbTtcclxuICAgICAgaGVpZ2h0OiA0LjRyZW07XHJcblxyXG4gICAgICAmLmluZm8ge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9tb2RhbC1pbmZvLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5tZXNzYWdlLWNvbnRhaW5lciB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luLWxlZnQ6IDJyZW07XHJcblxyXG4gICAgICAudGl0bGUge1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IDIuMnJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLm1lc3NhZ2Uge1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgICAgbWFyZ2luLXRvcDogMC40cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAud3JhcC1idG4ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWFyZ2luLXRvcDogMy41cmVtO1xyXG4gIH1cclxuICBcclxuICAuYWN0aW9uLWJ1dHRvbiB7XHJcbiAgICB3aWR0aDogMTByZW07XHJcbiAgICBoZWlnaHQ6IDIuNHJlbTtcclxuICB9XHJcblxyXG4gIC5jbG9zZS1idXR0b24ge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiAwO1xyXG4gICAgcmlnaHQ6IDA7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICBtYXJnaW46IDA7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgd2lkdGg6IDIuNHJlbTtcclxuICAgIGhlaWdodDogMi40cmVtO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2Nsb3NlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDIuNHJlbTtcclxuICAgICAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-confirm-modal',\r\n templateUrl: './confirm-modal.component.html',\r\n styleUrls: ['./confirm-modal.component.scss']\r\n})\r\nexport class ConfirmModalComponent implements OnInit {\r\n\r\n @Input() title: string;\r\n @Input() message: string;\r\n @Output() confirmed: EventEmitter = new EventEmitter();\r\n @ViewChild('btn') button: ElementRef;\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n this.button.nativeElement.focus();\r\n }\r\n\r\n onSubmit() {\r\n this.confirmed.emit(true);\r\n }\r\n\r\n onClose() {\r\n this.confirmed.emit(false);\r\n }\r\n}\r\n","import {Directive, HostListener} from '@angular/core';\r\n\r\n@Directive({\r\n selector: 'input'\r\n})\r\nexport class InputDisableSelectionDirective {\r\n\r\n constructor() {}\r\n\r\n @HostListener('mousedown', ['$event'])\r\n handleInput(event: Event) {\r\n if ((event.target).readOnly) {\r\n event.preventDefault();\r\n }\r\n }\r\n}\r\n","import {Directive, ElementRef, Input, HostListener} from '@angular/core';\r\nimport {VariablesService} from '../../services/variables.service';\r\n\r\n@Directive({\r\n selector: '[appInputValidate]'\r\n})\r\nexport class InputValidateDirective {\r\n\r\n private type: string;\r\n\r\n constructor(private el: ElementRef, private variablesService: VariablesService) {\r\n }\r\n\r\n @Input('appInputValidate')\r\n public set defineInputType(type: string) {\r\n this.type = type;\r\n }\r\n\r\n @HostListener('input', ['$event'])\r\n handleInput(event: Event) {\r\n if ( this.type === 'money' ) {\r\n this.moneyValidation(event);\r\n } else if ( this.type === 'integer' ) {\r\n this.integerValidation(event);\r\n }\r\n }\r\n\r\n private moneyValidation(event: Event) {\r\n let currentValue = (event.target).value;\r\n const originalValue = currentValue;\r\n const OnlyD = /[^\\d\\.]/g;\r\n const _has_error = currentValue.match(OnlyD);\r\n if (_has_error && _has_error.length) {\r\n currentValue = currentValue.replace(',', '.').replace(OnlyD, '');\r\n }\r\n const _double_separator = currentValue.match(/\\./g);\r\n if (_double_separator && _double_separator.length > 1) {\r\n currentValue = currentValue.substr(0, currentValue.lastIndexOf('.'));\r\n }\r\n if (currentValue.indexOf('.') === 0) {\r\n currentValue = '0' + currentValue;\r\n }\r\n const _zero_fill = currentValue.split('.');\r\n if (_zero_fill[0].length > 7) {\r\n _zero_fill[0] = _zero_fill[0].substr(0, 7);\r\n }\r\n\r\n if (1 in _zero_fill && _zero_fill[1].length) {\r\n _zero_fill[1] = _zero_fill[1].substr(0, this.variablesService.digits);\r\n }\r\n currentValue = _zero_fill.join('.');\r\n if (currentValue !== originalValue) {\r\n const cursorPosition = (event.target).selectionEnd;\r\n (event.target).value = currentValue;\r\n (event.target).setSelectionRange(cursorPosition, cursorPosition);\r\n (event.target).dispatchEvent(new Event('input'));\r\n }\r\n }\r\n\r\n private integerValidation(event: Event) {\r\n let currentValue = (event.target).value;\r\n const originalValue = currentValue;\r\n const OnlyD = /[^\\d]/g;\r\n const _has_error = currentValue.match(OnlyD);\r\n if (_has_error && _has_error.length) {\r\n currentValue = currentValue.replace(OnlyD, '');\r\n }\r\n if (currentValue !== originalValue) {\r\n const cursorPosition = (event.target).selectionEnd;\r\n (event.target).value = currentValue;\r\n (event.target).setSelectionRange(cursorPosition, cursorPosition);\r\n }\r\n }\r\n\r\n}\r\n\r\n\r\n\r\n\r\n","module.exports = \"
\\r\\n
\\r\\n \\r\\n
\\r\\n {{title}}\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 2rem;\\n min-width: 34rem;\\n max-width: 60rem; }\\n\\n.modal .content {\\n display: flex;\\n margin: 1.2rem 0; }\\n\\n.modal .content .icon {\\n flex: 0 0 auto;\\n width: 4.4rem;\\n height: 4.4rem; }\\n\\n.modal .content .icon.error {\\n -webkit-mask: url('modal-alert.svg') no-repeat center;\\n mask: url('modal-alert.svg') no-repeat center; }\\n\\n.modal .content .icon.success {\\n -webkit-mask: url('modal-success.svg') no-repeat center;\\n mask: url('modal-success.svg') no-repeat center; }\\n\\n.modal .content .icon.info {\\n -webkit-mask: url('modal-info.svg') no-repeat center;\\n mask: url('modal-info.svg') no-repeat center; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin-left: 2rem; }\\n\\n.modal .content .message-container .title {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 2.2rem; }\\n\\n.modal .content .message-container .message {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n margin-top: 0.4rem; }\\n\\n.modal .action-button {\\n margin: 1.2rem auto 0.6rem;\\n width: 10rem;\\n height: 2.4rem; }\\n\\n.modal .close-button {\\n position: absolute;\\n top: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: transparent;\\n margin: 0;\\n padding: 0;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n.modal .close-button .icon {\\n -webkit-mask: url('close.svg') no-repeat center;\\n mask: url('close.svg') no-repeat center;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9tb2RhbC1jb250YWluZXIvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcX2hlbHBlcnNcXGRpcmVjdGl2ZXNcXG1vZGFsLWNvbnRhaW5lclxcbW9kYWwtY29udGFpbmVyLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFFdkM7RUFDRSxrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLGFBQWE7RUFDYixnQkFBZ0I7RUFDaEIsZ0JBQWdCLEVBQUE7O0FBUmxCO0lBV0ksYUFBYTtJQUNiLGdCQUFnQixFQUFBOztBQVpwQjtNQWVNLGNBQWM7TUFDZCxhQUFhO01BQ2IsY0FBYyxFQUFBOztBQWpCcEI7UUFvQlEscURBQTZEO2dCQUE3RCw2Q0FBNkQsRUFBQTs7QUFwQnJFO1FBd0JRLHVEQUErRDtnQkFBL0QsK0NBQStELEVBQUE7O0FBeEJ2RTtRQTRCUSxvREFBNEQ7Z0JBQTVELDRDQUE0RCxFQUFBOztBQTVCcEU7TUFpQ00sYUFBYTtNQUNiLHNCQUFzQjtNQUN0Qix1QkFBdUI7TUFDdkIsdUJBQXVCO01BQ3ZCLGlCQUFpQixFQUFBOztBQXJDdkI7UUF3Q1EsaUJBQWlCO1FBQ2pCLGdCQUFnQjtRQUNoQixtQkFBbUIsRUFBQTs7QUExQzNCO1FBOENRLGlCQUFpQjtRQUNqQixtQkFBbUI7UUFDbkIsa0JBQWtCLEVBQUE7O0FBaEQxQjtJQXNESSwwQkFBMEI7SUFDMUIsWUFBWTtJQUNaLGNBQWMsRUFBQTs7QUF4RGxCO0lBNERJLGtCQUFrQjtJQUNsQixNQUFNO0lBQ04sUUFBUTtJQUNSLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLHVCQUF1QjtJQUN2QixTQUFTO0lBQ1QsVUFBVTtJQUNWLGFBQWE7SUFDYixjQUFjLEVBQUE7O0FBdEVsQjtNQXlFTSwrQ0FBdUQ7Y0FBdkQsdUNBQXVEO01BQ3ZELGFBQWE7TUFDYixjQUFjLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9faGVscGVycy9kaXJlY3RpdmVzL21vZGFsLWNvbnRhaW5lci9tb2RhbC1jb250YWluZXIuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGZpeGVkO1xyXG4gIHRvcDogMDtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICByaWdodDogMDtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcclxufVxyXG4ubW9kYWwge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xyXG4gIGJhY2tncm91bmQtc2l6ZTogMjAwJTtcclxuICBwYWRkaW5nOiAycmVtO1xyXG4gIG1pbi13aWR0aDogMzRyZW07XHJcbiAgbWF4LXdpZHRoOiA2MHJlbTtcclxuXHJcbiAgLmNvbnRlbnQge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbjogMS4ycmVtIDA7XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgICAgd2lkdGg6IDQuNHJlbTtcclxuICAgICAgaGVpZ2h0OiA0LjRyZW07XHJcblxyXG4gICAgICAmLmVycm9yIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvbW9kYWwtYWxlcnQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnN1Y2Nlc3Mge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9tb2RhbC1zdWNjZXNzLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5pbmZvIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvbW9kYWwtaW5mby5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAubWVzc2FnZS1jb250YWluZXIge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbi1sZWZ0OiAycmVtO1xyXG5cclxuICAgICAgLnRpdGxlIHtcclxuICAgICAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICAgIGxpbmUtaGVpZ2h0OiAyLjJyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5tZXNzYWdlIHtcclxuICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDAuNHJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLmFjdGlvbi1idXR0b24ge1xyXG4gICAgbWFyZ2luOiAxLjJyZW0gYXV0byAwLjZyZW07XHJcbiAgICB3aWR0aDogMTByZW07XHJcbiAgICBoZWlnaHQ6IDIuNHJlbTtcclxuICB9XHJcblxyXG4gIC5jbG9zZS1idXR0b24ge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiAwO1xyXG4gICAgcmlnaHQ6IDA7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICBtYXJnaW46IDA7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgd2lkdGg6IDIuNHJlbTtcclxuICAgIGhlaWdodDogMi40cmVtO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2Nsb3NlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDIuNHJlbTtcclxuICAgICAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-modal-container',\r\n templateUrl: './modal-container.component.html',\r\n styleUrls: ['./modal-container.component.scss']\r\n})\r\nexport class ModalContainerComponent implements OnInit {\r\n\r\n public title: string;\r\n @Input() type: string;\r\n @Input() message: string;\r\n @Output() close = new EventEmitter();\r\n @ViewChild('btn') button: ElementRef;\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n ngOnInit() {\r\n this.button.nativeElement.focus();\r\n switch (this.type) {\r\n case 'error': this.title = this.translate.instant('MODALS.ERROR'); break;\r\n case 'success': this.title = this.translate.instant('MODALS.SUCCESS'); break;\r\n case 'info': this.title = this.translate.instant('MODALS.INFO'); break;\r\n }\r\n }\r\n\r\n onClose() {\r\n this.close.emit();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n {{ label | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \".progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n padding: 0 3rem;\\n width: 100%;\\n height: 3rem; }\\n .progress-bar-container .progress-bar {\\n position: absolute;\\n top: -0.7rem;\\n left: 0;\\n margin: 0 3rem;\\n width: calc(100% - 6rem);\\n height: 0.7rem; }\\n .progress-bar-container .progress-bar .progress-bar-full {\\n height: 0.7rem; }\\n .progress-bar-container .progress-labels {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n font-size: 1.2rem;\\n height: 100%; }\\n .progress-bar-container .progress-labels span {\\n flex: 1 0 0;\\n text-align: center; }\\n .progress-bar-container .progress-labels span:first-child {\\n text-align: left; }\\n .progress-bar-container .progress-labels span:last-child {\\n text-align: right; }\\n .progress-bar-container .progress-time {\\n position: absolute;\\n top: -3rem;\\n left: 50%;\\n transform: translateX(-50%);\\n font-size: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9wcm9ncmVzcy1jb250YWluZXIvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcX2hlbHBlcnNcXGRpcmVjdGl2ZXNcXHByb2dyZXNzLWNvbnRhaW5lclxccHJvZ3Jlc3MtY29udGFpbmVyLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCO0VBQ2xCLFNBQVM7RUFDVCxPQUFPO0VBQ1AsZUFBZTtFQUNmLFdBQVc7RUFDWCxZQUFZLEVBQUE7RUFOZDtJQVNJLGtCQUFrQjtJQUNsQixZQUFZO0lBQ1osT0FBTztJQUNQLGNBQWM7SUFDZCx3QkFBd0I7SUFDeEIsY0FBYyxFQUFBO0VBZGxCO01BaUJNLGNBQWMsRUFBQTtFQWpCcEI7SUFzQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQiw4QkFBOEI7SUFDOUIsaUJBQWlCO0lBQ2pCLFlBQVksRUFBQTtFQTFCaEI7TUE2Qk0sV0FBVztNQUNYLGtCQUFrQixFQUFBO0VBOUJ4QjtRQWlDUSxnQkFBZ0IsRUFBQTtFQWpDeEI7UUFxQ1EsaUJBQWlCLEVBQUE7RUFyQ3pCO0lBMkNJLGtCQUFrQjtJQUNsQixVQUFVO0lBQ1YsU0FBUztJQUNULDJCQUEyQjtJQUMzQixpQkFBaUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL19oZWxwZXJzL2RpcmVjdGl2ZXMvcHJvZ3Jlc3MtY29udGFpbmVyL3Byb2dyZXNzLWNvbnRhaW5lci5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcGFkZGluZzogMCAzcmVtO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG4gIGhlaWdodDogM3JlbTtcclxuXHJcbiAgLnByb2dyZXNzLWJhciB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IC0wLjdyZW07XHJcbiAgICBsZWZ0OiAwO1xyXG4gICAgbWFyZ2luOiAwIDNyZW07XHJcbiAgICB3aWR0aDogY2FsYygxMDAlIC0gNnJlbSk7XHJcbiAgICBoZWlnaHQ6IDAuN3JlbTtcclxuXHJcbiAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG4gICAgICBoZWlnaHQ6IDAuN3JlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wcm9ncmVzcy1sYWJlbHMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICAgIGhlaWdodDogMTAwJTtcclxuXHJcbiAgICBzcGFuIHtcclxuICAgICAgZmxleDogMSAwIDA7XHJcbiAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuXHJcbiAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgIHRleHQtYWxpZ246IGxlZnQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgdGV4dC1hbGlnbjogcmlnaHQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wcm9ncmVzcy10aW1lIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogLTNyZW07XHJcbiAgICBsZWZ0OiA1MCU7XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICB9XHJcbn1cclxuIl19 */\"","import { Component, Input, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-progress-container',\r\n templateUrl: './progress-container.component.html',\r\n styleUrls: ['./progress-container.component.scss']\r\n})\r\nexport class ProgressContainerComponent implements OnInit {\r\n\r\n @Input() width: string;\r\n @Input() labels: [];\r\n\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n}\r\n","module.exports = \"
\\r\\n {{ 'STAKING.SWITCH.ON' | translate }}\\r\\n \\r\\n {{ 'STAKING.SWITCH.OFF' | translate }}\\r\\n
\\r\\n\"","module.exports = \".switch {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n border-radius: 1rem;\\n cursor: pointer;\\n font-size: 1rem;\\n padding: 0.5rem;\\n width: 5rem;\\n height: 2rem; }\\n .switch .circle {\\n border-radius: 1rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n .switch .option {\\n margin: 0 0.2rem;\\n line-height: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9zdGFraW5nLXN3aXRjaC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxfaGVscGVyc1xcZGlyZWN0aXZlc1xcc3Rha2luZy1zd2l0Y2hcXHN0YWtpbmctc3dpdGNoLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQiw4QkFBOEI7RUFDOUIsbUJBQW1CO0VBQ25CLGVBQWU7RUFDZixlQUFlO0VBQ2YsZUFBZTtFQUNmLFdBQVc7RUFDWCxZQUFZLEVBQUE7RUFUZDtJQVlJLG1CQUFtQjtJQUNuQixhQUFhO0lBQ2IsY0FBYyxFQUFBO0VBZGxCO0lBa0JJLGdCQUFnQjtJQUNoQixtQkFBbUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL19oZWxwZXJzL2RpcmVjdGl2ZXMvc3Rha2luZy1zd2l0Y2gvc3Rha2luZy1zd2l0Y2guY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuc3dpdGNoIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGJvcmRlci1yYWRpdXM6IDFyZW07XHJcbiAgY3Vyc29yOiBwb2ludGVyO1xyXG4gIGZvbnQtc2l6ZTogMXJlbTtcclxuICBwYWRkaW5nOiAwLjVyZW07XHJcbiAgd2lkdGg6IDVyZW07XHJcbiAgaGVpZ2h0OiAycmVtO1xyXG5cclxuICAuY2lyY2xlIHtcclxuICAgIGJvcmRlci1yYWRpdXM6IDFyZW07XHJcbiAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgaGVpZ2h0OiAxLjJyZW07XHJcbiAgfVxyXG5cclxuICAub3B0aW9uIHtcclxuICAgIG1hcmdpbjogMCAwLjJyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS4ycmVtO1xyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, Input, Output, EventEmitter} from '@angular/core';\r\nimport {BackendService} from '../../services/backend.service';\r\nimport {VariablesService} from '../../services/variables.service';\r\n\r\n@Component({\r\n selector: 'app-staking-switch',\r\n templateUrl: './staking-switch.component.html',\r\n styleUrls: ['./staking-switch.component.scss']\r\n})\r\nexport class StakingSwitchComponent implements OnInit {\r\n\r\n @Input() wallet_id: boolean;\r\n @Input() staking: boolean;\r\n @Output() stakingChange = new EventEmitter();\r\n\r\n constructor(private backend: BackendService, private variablesService: VariablesService) {}\r\n\r\n ngOnInit() {}\r\n\r\n toggleStaking() {\r\n const wallet = this.variablesService.getWallet(this.wallet_id);\r\n if (wallet && wallet.loaded) {\r\n this.stakingChange.emit(!this.staking);\r\n if (!this.staking) {\r\n this.backend.startPosMining(this.wallet_id);\r\n } else {\r\n this.backend.stopPosMining(this.wallet_id);\r\n }\r\n }\r\n }\r\n}\r\n","import {Directive, Input, Output, ElementRef, HostListener, Renderer2, HostBinding, OnDestroy, EventEmitter} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\n\r\n@Directive({\r\n selector: '[tooltip]'\r\n})\r\n\r\nexport class TooltipDirective implements OnDestroy {\r\n\r\n @HostBinding('style.cursor') cursor;\r\n\r\n @Input('tooltip') tooltipInner: any;\r\n @Input() placement: string;\r\n @Input() tooltipClass: string;\r\n @Input() timeout = 0;\r\n @Input() timeDelay = 0;\r\n @Input() delay = 0;\r\n @Input() showWhenNoOverflow = true;\r\n @Output() onHide = new EventEmitter();\r\n tooltip: HTMLElement;\r\n private enter: (event: MouseEvent) => void;\r\n private leave: (event: MouseEvent) => void;\r\n\r\n removeTooltipTimeout;\r\n removeTooltipTimeoutInner;\r\n\r\n removeTooltipTimeDelay;\r\n\r\n constructor(private el: ElementRef, private renderer: Renderer2, private route: ActivatedRoute) {\r\n }\r\n\r\n @HostListener('mouseenter') onMouseEnter() {\r\n if (this.showWhenNoOverflow || (!this.showWhenNoOverflow && this.el.nativeElement.offsetWidth < this.el.nativeElement.scrollWidth)) {\r\n this.cursor = 'pointer';\r\n if (!this.tooltip) {\r\n if (this.timeDelay !== 0) {\r\n this.removeTooltipTimeDelay = setTimeout(() => {\r\n this.show();\r\n }, this.timeDelay);\r\n } else {\r\n this.show();\r\n }\r\n } else {\r\n this.cancelHide();\r\n }\r\n }\r\n }\r\n\r\n @HostListener('mouseleave') onMouseLeave() {\r\n clearTimeout(this.removeTooltipTimeDelay);\r\n if (this.tooltip) {\r\n this.hide();\r\n }\r\n }\r\n\r\n // @HostListener('click') onClick() {\r\n // clearTimeout(this.removeTooltipTimeDelay);\r\n // if (this.tooltip) {\r\n // this.hide();\r\n // }\r\n // }\r\n\r\n show() {\r\n this.create();\r\n this.placement = this.placement === null ? 'top' : this.placement;\r\n this.setPosition(this.placement);\r\n }\r\n\r\n hide() {\r\n this.removeTooltipTimeout = setTimeout(() => {\r\n this.renderer.setStyle(this.tooltip, 'opacity', '0');\r\n this.removeTooltipTimeoutInner = setTimeout(() => {\r\n this.renderer.removeChild(document.body, this.tooltip);\r\n this.tooltip.removeEventListener('mouseenter', this.enter);\r\n this.tooltip.removeEventListener('mouseleave', this.leave);\r\n this.tooltip = null;\r\n this.onHide.emit(true);\r\n }, this.delay);\r\n }, this.timeout);\r\n }\r\n\r\n cancelHide() {\r\n clearTimeout(this.removeTooltipTimeout);\r\n clearTimeout(this.removeTooltipTimeoutInner);\r\n this.renderer.setStyle(this.tooltip, 'opacity', '1');\r\n }\r\n\r\n create() {\r\n this.tooltip = this.renderer.createElement('div');\r\n let innerBlock = this.renderer.createElement('div');\r\n if (typeof this.tooltipInner === 'string') {\r\n innerBlock.innerHTML = this.tooltipInner;\r\n } else {\r\n innerBlock = this.tooltipInner;\r\n }\r\n this.renderer.addClass(innerBlock, 'tooltip-inner');\r\n this.renderer.addClass(innerBlock, 'scrolled-content');\r\n this.renderer.appendChild(this.tooltip, innerBlock);\r\n this.renderer.appendChild(document.body, this.tooltip);\r\n\r\n this.enter = () => {\r\n this.cancelHide();\r\n };\r\n this.tooltip.addEventListener('mouseenter', this.enter);\r\n this.leave = () => {\r\n if (this.tooltip) {\r\n this.hide();\r\n }\r\n };\r\n this.tooltip.addEventListener('mouseleave', this.leave);\r\n\r\n this.renderer.setStyle(document.body, 'position', 'relative');\r\n this.renderer.setStyle(this.tooltip, 'position', 'absolute');\r\n if (this.tooltipClass !== null) {\r\n const classes = this.tooltipClass.split(' ');\r\n for (let i = 0; i < classes.length; i++) {\r\n this.renderer.addClass(this.tooltip, classes[i]);\r\n }\r\n }\r\n this.renderer.setStyle(this.tooltip, 'opacity', '0');\r\n this.renderer.setStyle(this.tooltip, '-webkit-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, '-moz-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, '-o-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, 'transition', `opacity ${this.delay}ms`);\r\n window.setTimeout(() => {\r\n this.renderer.setStyle(this.tooltip, 'opacity', '1');\r\n }, 0);\r\n }\r\n\r\n setPosition(placement) {\r\n const hostPos = this.el.nativeElement.getBoundingClientRect();\r\n this.renderer.addClass(this.tooltip, 'ng-tooltip-' + placement);\r\n const topExit = hostPos.top - this.tooltip.getBoundingClientRect().height - parseInt(getComputedStyle(this.tooltip).marginTop, 10) < 0;\r\n const bottomExit = window.innerHeight < hostPos.bottom + this.tooltip.getBoundingClientRect().height + parseInt(getComputedStyle(this.tooltip).marginTop, 10);\r\n\r\n switch (placement) {\r\n case 'top':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + (hostPos.right - hostPos.left) / 2 - this.tooltip.getBoundingClientRect().width / 2 + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'top-left':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom-left');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'top-right':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom-right');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right - this.tooltip.offsetWidth + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + (hostPos.right - hostPos.left) / 2 - this.tooltip.getBoundingClientRect().width / 2 + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom-left':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top-left');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom-right':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top-right');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right - this.tooltip.offsetWidth + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'left':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + (hostPos.bottom - hostPos.top) / 2 - this.tooltip.getBoundingClientRect().height / 2 + 'px');\r\n break;\r\n case 'left-top':\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n break;\r\n case 'left-bottom':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom - this.tooltip.getBoundingClientRect().height + 'px');\r\n break;\r\n case 'right':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + (hostPos.bottom - hostPos.top) / 2 - this.tooltip.getBoundingClientRect().height / 2 + 'px');\r\n break;\r\n case 'right-top':\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n break;\r\n case 'right-bottom':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom - this.tooltip.getBoundingClientRect().height + 'px');\r\n break;\r\n }\r\n }\r\n\r\n checkSides() {\r\n if (this.tooltip.getBoundingClientRect().left < 0) {\r\n this.renderer.setStyle(this.tooltip, 'left', 0);\r\n }\r\n if (this.tooltip.getBoundingClientRect().right > window.innerWidth) {\r\n this.renderer.setStyle(this.tooltip, 'left', window.innerWidth - this.tooltip.getBoundingClientRect().width + 'px');\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n clearTimeout(this.removeTooltipTimeout);\r\n clearTimeout(this.removeTooltipTimeoutInner);\r\n clearTimeout(this.removeTooltipTimeDelay);\r\n if (this.tooltip) {\r\n this.renderer.removeChild(document.body, this.tooltip);\r\n this.tooltip = null;\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.ID' | translate }}\\r\\n {{transaction.tx_hash}}\\r\\n {{ 'HISTORY.DETAILS.SIZE' | translate }}\\r\\n {{ 'HISTORY.DETAILS.SIZE_VALUE' | translate : {value: transaction.tx_blob_size} }}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.HEIGHT' | translate }}\\r\\n {{transaction.height}}\\r\\n {{ 'HISTORY.DETAILS.CONFIRMATION' | translate }}\\r\\n {{transaction.height === 0 ? 0 : variablesService.height_app - transaction.height}}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.INPUTS' | translate }}\\r\\n {{inputs.join(', ')}}\\r\\n {{ 'HISTORY.DETAILS.OUTPUTS' | translate }}\\r\\n {{outputs.join(', ')}}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.PAYMENT_ID' | translate }}\\r\\n \\r\\n {{transaction.payment_id}}\\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.COMMENT' | translate }}\\r\\n \\r\\n {{transaction.comment}}\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%; }\\n\\n.table {\\n border-top: 0.2rem solid #ebebeb;\\n margin: 0 3rem;\\n padding: 0.5rem 0; }\\n\\n.table .row {\\n display: flex;\\n justify-content: flex-start;\\n align-items: center;\\n border-top: none;\\n line-height: 3rem;\\n margin: 0 -3rem;\\n width: 100%;\\n height: 3rem; }\\n\\n.table .row .cell {\\n flex-shrink: 0;\\n flex-grow: 0;\\n padding: 0 1rem;\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n\\n.table .row .cell:first-child {\\n padding-left: 3rem; }\\n\\n.table .row .cell:last-child {\\n padding-right: 3rem; }\\n\\n.table .row .cell.key-value {\\n cursor: pointer; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy90cmFuc2FjdGlvbi1kZXRhaWxzL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXF9oZWxwZXJzXFxkaXJlY3RpdmVzXFx0cmFuc2FjdGlvbi1kZXRhaWxzXFx0cmFuc2FjdGlvbi1kZXRhaWxzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCO0VBQ2xCLE1BQU07RUFDTixPQUFPO0VBQ1AsV0FBVyxFQUFBOztBQUdiO0VBQ0UsZ0NBQWdDO0VBQ2hDLGNBQWM7RUFDZCxpQkFBaUIsRUFBQTs7QUFIbkI7SUFNSSxhQUFhO0lBQ2IsMkJBQTJCO0lBQzNCLG1CQUFtQjtJQUNuQixnQkFBZ0I7SUFDaEIsaUJBQWlCO0lBQ2pCLGVBQWU7SUFDZixXQUFXO0lBQ1gsWUFBWSxFQUFBOztBQWJoQjtNQWdCTSxjQUFjO01BQ2QsWUFBWTtNQUNaLGVBQWU7TUFDZixnQkFBZ0I7TUFDaEIsdUJBQXVCLEVBQUE7O0FBcEI3QjtRQXVCUSxrQkFBa0IsRUFBQTs7QUF2QjFCO1FBMkJRLG1CQUFtQixFQUFBOztBQTNCM0I7UUErQlEsZUFBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy90cmFuc2FjdGlvbi1kZXRhaWxzL3RyYW5zYWN0aW9uLWRldGFpbHMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gIHRvcDogMDtcclxuICBsZWZ0OiAwO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4udGFibGUge1xyXG4gIGJvcmRlci10b3A6IDAuMnJlbSBzb2xpZCAjZWJlYmViO1xyXG4gIG1hcmdpbjogMCAzcmVtO1xyXG4gIHBhZGRpbmc6IDAuNXJlbSAwO1xyXG5cclxuICAucm93IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgYm9yZGVyLXRvcDogbm9uZTtcclxuICAgIGxpbmUtaGVpZ2h0OiAzcmVtO1xyXG4gICAgbWFyZ2luOiAwIC0zcmVtO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gICAgLmNlbGwge1xyXG4gICAgICBmbGV4LXNocmluazogMDtcclxuICAgICAgZmxleC1ncm93OiAwO1xyXG4gICAgICBwYWRkaW5nOiAwIDFyZW07XHJcbiAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG5cclxuICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYua2V5LXZhbHVlIHtcclxuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, OnDestroy, Input} from '@angular/core';\r\nimport {Transaction} from '../../models/transaction.model';\r\nimport {VariablesService} from '../../services/variables.service';\r\nimport {BackendService} from '../../services/backend.service';\r\nimport {IntToMoneyPipe} from '../../pipes/int-to-money.pipe';\r\n\r\n@Component({\r\n selector: 'app-transaction-details',\r\n templateUrl: './transaction-details.component.html',\r\n styleUrls: ['./transaction-details.component.scss']\r\n})\r\nexport class TransactionDetailsComponent implements OnInit, OnDestroy {\r\n\r\n @Input() transaction: Transaction;\r\n @Input() sizes: Array;\r\n inputs: Array = [];\r\n outputs: Array = [];\r\n\r\n constructor(public variablesService: VariablesService, private backendService: BackendService, private intToMoneyPipe: IntToMoneyPipe) {}\r\n\r\n ngOnInit() {\r\n for (const input in this.transaction.td['spn']) {\r\n if (this.transaction.td['spn'].hasOwnProperty(input)) {\r\n this.inputs.push(this.intToMoneyPipe.transform(this.transaction.td['spn'][input]));\r\n }\r\n }\r\n for (const output in this.transaction.td['rcv']) {\r\n if (this.transaction.td['rcv'].hasOwnProperty(output)) {\r\n this.outputs.push(this.intToMoneyPipe.transform(this.transaction.td['rcv'][output]));\r\n }\r\n }\r\n }\r\n\r\n openInBrowser(tr) {\r\n this.backendService.openUrlInBrowser('explorer.zano.org/transaction/' + tr);\r\n }\r\n\r\n ngOnDestroy() {}\r\n}\r\n","import {BigNumber} from 'bignumber.js';\r\n\r\nexport class Transaction {\r\n amount: BigNumber;\r\n comment: string;\r\n contract: any[];\r\n fee: BigNumber;\r\n height: number;\r\n is_income: boolean;\r\n is_mining: boolean;\r\n is_mixing: boolean;\r\n is_service: boolean;\r\n payment_id: string;\r\n show_sender: boolean;\r\n td: object;\r\n timestamp: number;\r\n tx_blob_size: number;\r\n tx_hash: string;\r\n tx_type: number;\r\n unlock_time: number;\r\n\r\n sortAmount?: BigNumber;\r\n sortFee?: BigNumber;\r\n}\r\n","import {Contract} from './contract.model';\r\nimport {Transaction} from './transaction.model';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\nexport class Wallet {\r\n wallet_id: number;\r\n name: string;\r\n pass: string;\r\n path: string;\r\n address: string;\r\n balance: BigNumber;\r\n unlocked_balance: BigNumber;\r\n mined_total: number;\r\n tracking_hey: string;\r\n alias_available: boolean;\r\n\r\n alias?: object;\r\n wakeAlias?: boolean;\r\n staking?: boolean;\r\n new_messages?: number;\r\n new_contracts?: number;\r\n\r\n history: Array = [];\r\n excluded_history: Array = [];\r\n\r\n contracts: Array = [];\r\n\r\n progress?: number;\r\n loaded?: boolean;\r\n\r\n send_data?: any = {\r\n address: null,\r\n amount: null,\r\n comment: null,\r\n mixin: null,\r\n fee: null,\r\n hide: null\r\n };\r\n\r\n constructor(id, name, pass, path, address, balance, unlocked_balance, mined = 0, tracking = '') {\r\n this.wallet_id = id;\r\n this.name = name;\r\n this.pass = pass;\r\n this.path = path;\r\n this.address = address;\r\n this.balance = balance;\r\n this.unlocked_balance = unlocked_balance;\r\n this.mined_total = mined;\r\n this.tracking_hey = tracking;\r\n\r\n this.alias = {};\r\n this.staking = false;\r\n this.new_messages = 0;\r\n this.new_contracts = 0;\r\n\r\n this.history = [];\r\n this.excluded_history = [];\r\n\r\n this.progress = 0;\r\n this.loaded = false;\r\n }\r\n\r\n getMoneyEquivalent(equivalent) {\r\n return this.balance.multipliedBy(equivalent).toFixed(0);\r\n }\r\n\r\n havePass(): boolean {\r\n return (this.pass !== '' && this.pass !== null);\r\n }\r\n\r\n isActive(id): boolean {\r\n return this.wallet_id === id;\r\n }\r\n\r\n prepareHistoryItem(item: Transaction): any {\r\n if (item.tx_type === 4) {\r\n item.sortFee = item.amount.plus(item.fee).negated();\r\n item.sortAmount = new BigNumber(0);\r\n } else if (item.tx_type === 3) {\r\n item.sortFee = new BigNumber(0);\r\n } else if ((item.hasOwnProperty('contract') && (item.contract[0].state === 3 || item.contract[0].state === 6 || item.contract[0].state === 601) && !item.contract[0].is_a)) {\r\n item.sortFee = item.fee.negated();\r\n item.sortAmount = item.amount;\r\n } else {\r\n if (!item.is_income) {\r\n item.sortFee = item.fee.negated();\r\n item.sortAmount = item.amount.negated();\r\n } else {\r\n item.sortAmount = item.amount;\r\n }\r\n }\r\n return item;\r\n }\r\n\r\n prepareHistory(items: Transaction[]): void {\r\n for (let i = 0; i < items.length; i++) {\r\n if ((items[i].tx_type === 7 && items[i].is_income) || (items[i].tx_type === 11 && items[i].is_income) || (items[i].amount.eq(0) && items[i].fee.eq(0))) {\r\n let exists = false;\r\n for (let j = 0; j < this.excluded_history.length; j++) {\r\n if (this.excluded_history[j].tx_hash === items[i].tx_hash) {\r\n exists = true;\r\n if (this.excluded_history[j].height !== items[i].height) {\r\n this.excluded_history[j] = items[i];\r\n }\r\n break;\r\n }\r\n }\r\n if (!exists) {\r\n this.excluded_history.push(items[i]);\r\n }\r\n } else {\r\n let exists = false;\r\n for (let j = 0; j < this.history.length; j++) {\r\n if (this.history[j].tx_hash === items[i].tx_hash) {\r\n exists = true;\r\n if (this.history[j].height !== items[i].height) {\r\n this.history[j] = this.prepareHistoryItem(items[i]);\r\n }\r\n break;\r\n }\r\n }\r\n if (!exists) {\r\n if (this.history.length && items[i].timestamp >= this.history[0].timestamp) {\r\n this.history.unshift(this.prepareHistoryItem(items[i]));\r\n } else {\r\n this.history.push(this.prepareHistoryItem(items[i]));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n removeFromHistory(hash: string): void {\r\n for (let i = 0; i < this.history.length; i++) {\r\n if (this.history[i].tx_hash === hash) {\r\n this.history.splice(i, 1);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n prepareContractsAfterOpen(items: any[], exp_med_ts, height_app, viewedContracts, notViewedContracts): void {\r\n const wallet = this;\r\n for (let i = 0; i < items.length; i++) {\r\n const contract = items[i];\r\n let contractTransactionExist = false;\r\n if (wallet && wallet.history) {\r\n contractTransactionExist = wallet.history.some(elem => elem.contract && elem.contract.length && elem.contract[0].contract_id === contract.contract_id);\r\n }\r\n if (!contractTransactionExist && wallet && wallet.excluded_history) {\r\n contractTransactionExist = wallet.excluded_history.some(elem => elem.contract && elem.contract.length && elem.contract[0].contract_id === contract.contract_id);\r\n }\r\n\r\n if (!contractTransactionExist) {\r\n contract.state = 140;\r\n } else if (contract.state === 1 && contract.expiration_time < exp_med_ts) {\r\n contract.state = 110;\r\n } else if (contract.state === 2 && contract.cancel_expiration_time !== 0 && contract.cancel_expiration_time < exp_med_ts && contract.height === 0) {\r\n const searchResult1 = viewedContracts.some(elem => elem.state === 2 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (!searchResult1) {\r\n contract.state = 130;\r\n contract.is_new = true;\r\n }\r\n } else if (contract.state === 1) {\r\n const searchResult2 = notViewedContracts.find(elem => elem.state === 110 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult2) {\r\n if (searchResult2.time === contract.expiration_time) {\r\n contract.state = 110;\r\n } else {\r\n for (let j = 0; j < notViewedContracts.length; j++) {\r\n if (notViewedContracts[j].contract_id === contract.contract_id && notViewedContracts[j].is_a === contract.is_a) {\r\n notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < viewedContracts.length; j++) {\r\n if (viewedContracts[j].contract_id === contract.contract_id && viewedContracts[j].is_a === contract.is_a) {\r\n viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 2 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 201;\r\n } else if (contract.state === 2) {\r\n const searchResult3 = viewedContracts.some(elem => elem.state === 120 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult3) {\r\n contract.state = 120;\r\n }\r\n } else if (contract.state === 5) {\r\n const searchResult4 = notViewedContracts.find(elem => elem.state === 130 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult4) {\r\n if (searchResult4.time === contract.cancel_expiration_time) {\r\n contract.state = 130;\r\n } else {\r\n for (let j = 0; j < notViewedContracts.length; j++) {\r\n if (notViewedContracts[j].contract_id === contract.contract_id && notViewedContracts[j].is_a === contract.is_a) {\r\n notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < viewedContracts.length; j++) {\r\n if (viewedContracts[j].contract_id === contract.contract_id && viewedContracts[j].is_a === contract.is_a) {\r\n viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 6 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 601;\r\n }\r\n const searchResult = viewedContracts.some(elem => elem.state === contract.state && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n contract.is_new = !searchResult;\r\n\r\n wallet.contracts.push(contract);\r\n }\r\n this.recountNewContracts();\r\n }\r\n\r\n recountNewContracts() {\r\n this.new_contracts = (this.contracts.filter(item => item.is_new === true )).length;\r\n }\r\n\r\n getContract(id): Contract {\r\n for (let i = 0; i < this.contracts.length; i++) {\r\n if (this.contracts[i].contract_id === id) {\r\n return this.contracts[i];\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'contractStatusMessages'\r\n})\r\nexport class ContractStatusMessagesPipe implements PipeTransform {\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n getStateSeller(stateNum: number): string {\r\n const state = {part1: '', part2: ''};\r\n switch (stateNum) {\r\n case 1:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NEW_CONTRACT');\r\n break;\r\n case 110:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.IGNORED');\r\n break;\r\n case 201:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.ACCEPTED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.WAIT');\r\n break;\r\n case 2:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.WAITING_BUYER');\r\n break;\r\n case 3:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.COMPLETED');\r\n break;\r\n case 4:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NOT_RECEIVED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NULLIFIED');\r\n break;\r\n case 5:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.PROPOSAL_CANCEL');\r\n break;\r\n case 601:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.BEING_CANCELLED');\r\n break;\r\n case 6:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.CANCELLED');\r\n break;\r\n case 130:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.IGNORED_CANCEL');\r\n break;\r\n case 140:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.EXPIRED');\r\n break;\r\n }\r\n return state.part1 + (state.part2.length ? '. ' + state.part2 : '');\r\n }\r\n\r\n getStateBuyer(stateNum: number): string {\r\n const state = {part1: '', part2: ''};\r\n switch (stateNum) {\r\n case 1:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING');\r\n break;\r\n case 110:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.IGNORED');\r\n break;\r\n case 201:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.ACCEPTED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAIT');\r\n break;\r\n case 2:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.ACCEPTED');\r\n break;\r\n case 120:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING_SELLER');\r\n break;\r\n case 3:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.COMPLETED');\r\n break;\r\n case 4:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.NOT_RECEIVED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.NULLIFIED');\r\n break;\r\n case 5:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING_CANCEL');\r\n break;\r\n case 601:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.BEING_CANCELLED');\r\n break;\r\n case 6:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.CANCELLED');\r\n break;\r\n case 130:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.IGNORED_CANCEL');\r\n break;\r\n case 140:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.EXPIRED');\r\n break;\r\n }\r\n return state.part1 + (state.part2.length ? '. ' + state.part2 : '');\r\n }\r\n\r\n transform(state: number, is_a?: boolean): any {\r\n if (is_a) {\r\n return this.getStateBuyer(state);\r\n } else {\r\n return this.getStateSeller(state);\r\n }\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'contractTimeLeft'\r\n})\r\nexport class ContractTimeLeftPipe implements PipeTransform {\r\n\r\n constructor(private service: VariablesService, private translate: TranslateService) {}\r\n\r\n transform(value: any, arg?: any): any {\r\n const time = parseInt(((parseInt(value, 10) - this.service.exp_med_ts) / 3600).toFixed(0), 10);\r\n const type = arg || 0;\r\n if (time === 0) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_LESS_ONE');\r\n }\r\n if (this.service.settings.language === 'en') {\r\n if (type === 0) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY', {time: time});\r\n }\r\n } else if (type === 1) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_RESPONSE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_RESPONSE', {time: time});\r\n }\r\n } else if (type === 2) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_WAITING', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_WAITING', {time: time});\r\n }\r\n }\r\n } else {\r\n const rest = time % 10;\r\n if (type === 0) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT', {time: time});\r\n }\r\n } else if (type === 1) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_RESPONSE', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_RESPONSE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT_RESPONSE', {time: time});\r\n }\r\n } else if (type === 2) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_WAITING', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_WAITING', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT_WAITING', {time: time});\r\n }\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'historyTypeMessages'\r\n})\r\nexport class HistoryTypeMessagesPipe implements PipeTransform {\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n transform(item: any, args?: any): any {\r\n\r\n if (item.tx_type === 0) {\r\n if (item.remote_addresses && item.remote_addresses[0]) {\r\n return item.remote_addresses[0];\r\n } else {\r\n if (item.is_income) {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.HIDDEN');\r\n } else {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UNDEFINED');\r\n }\r\n }\r\n } else if (item.tx_type === 6 && item.height === 0) {\r\n return 'unknown';\r\n } else if (item.tx_type === 9) {\r\n if (item.hasOwnProperty('contract') && item.contract[0].is_a) {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.COMPLETE_BUYER');\r\n } else {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.COMPLETE_SELLER');\r\n }\r\n } else {\r\n switch (item.tx_type) {\r\n // case 0:\r\n // return '';\r\n // case 1:\r\n // return '';\r\n // case 2:\r\n // return '';\r\n // case 3:\r\n // return '';\r\n case 4:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CREATE_ALIAS');\r\n case 5:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UPDATE_ALIAS');\r\n case 6:\r\n return (item.td['spn'] && item.td['spn'].length) ? this.translate.instant('HISTORY.TYPE_MESSAGES.POS_REWARD') : this.translate.instant('HISTORY.TYPE_MESSAGES.POW_REWARD');\r\n case 7:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CREATE_CONTRACT');\r\n case 8:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.PLEDGE_CONTRACT');\r\n // case 9:\r\n // return '';\r\n case 10:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.NULLIFY_CONTRACT');\r\n case 11:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.PROPOSAL_CANCEL_CONTRACT');\r\n case 12:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CANCEL_CONTRACT');\r\n }\r\n }\r\n\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UNDEFINED');\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Pipe({\r\n name: 'intToMoney'\r\n})\r\nexport class IntToMoneyPipe implements PipeTransform {\r\n\r\n constructor(private variablesService: VariablesService) {}\r\n\r\n transform(value: any, args?: any): any {\r\n if (value === 0 || value === undefined) {\r\n return '0';\r\n }\r\n let maxFraction = this.variablesService.digits;\r\n if (args) {\r\n maxFraction = parseInt(args, 10);\r\n }\r\n const power = Math.pow(10, this.variablesService.digits);\r\n let str = (new BigNumber(value)).div(power).toFixed(maxFraction);\r\n\r\n for (let i = str.length - 1; i >= 0; i--) {\r\n if (str[i] !== '0') {\r\n str = str.substr(0, i + 1);\r\n break;\r\n }\r\n }\r\n if (str[str.length - 1] === '.') {\r\n str = str.substr(0, str.length - 1);\r\n }\r\n return str;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Pipe({\r\n name: 'moneyToInt'\r\n})\r\nexport class MoneyToIntPipe implements PipeTransform {\r\n\r\n constructor(private variablesService: VariablesService) {}\r\n\r\n transform(value: any, args?: any): any {\r\n const CURRENCY_DISPLAY_DECIMAL_POINT = this.variablesService.digits;\r\n let result;\r\n if (value) {\r\n let am_str = value.toString().trim();\r\n const point_index = am_str.indexOf('.');\r\n let fraction_size = 0;\r\n if (-1 !== point_index) {\r\n fraction_size = am_str.length - point_index - 1;\r\n while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' === am_str[am_str.length - 1]) {\r\n am_str = am_str.slice(0, am_str.length - 1);\r\n --fraction_size;\r\n }\r\n if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size) {\r\n return undefined;\r\n }\r\n am_str = am_str.slice(0, point_index) + am_str.slice(point_index + 1, am_str.length);\r\n } else {\r\n fraction_size = 0;\r\n }\r\n if (!am_str.length) {\r\n return undefined;\r\n }\r\n if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT) {\r\n for (let i = 0; i !== CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size; i++) {\r\n am_str = am_str + '0';\r\n }\r\n }\r\n result = (new BigNumber(am_str)).integerValue();\r\n }\r\n return result;\r\n }\r\n\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\n\r\n@Pipe({\r\n name: 'safeHTML'\r\n})\r\nexport class SafeHTMLPipe implements PipeTransform {\r\n\r\n constructor(private sanitizer: DomSanitizer) { }\r\n\r\n transform(html: string) {\r\n return this.sanitizer.bypassSecurityTrustHtml(html);\r\n }\r\n\r\n}\r\n","import {Injectable} from '@angular/core';\r\nimport {Observable} from 'rxjs';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {VariablesService} from './variables.service';\r\nimport {ModalService} from './modal.service';\r\nimport {MoneyToIntPipe} from '../pipes/money-to-int.pipe';\r\nimport JSONBigNumber from 'json-bignumber';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Injectable()\r\nexport class BackendService {\r\n\r\n backendObject: any;\r\n backendLoaded = false;\r\n\r\n constructor(\r\n private translate: TranslateService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private moneyToIntPipe: MoneyToIntPipe\r\n ) {\r\n }\r\n\r\n static bigNumberParser(key, val) {\r\n if (val.constructor.name === 'BigNumber' && ['balance', 'unlocked_balance', 'amount', 'fee', 'b_fee', 'to_pay', 'a_pledge', 'b_pledge', 'coast', 'a'].indexOf(key) === -1) {\r\n return val.toNumber();\r\n }\r\n if (key === 'rcv' || key === 'spn') {\r\n for (let i = 0; i < val.length; i++) {\r\n val[i] = new BigNumber(val[i]);\r\n }\r\n }\r\n return val;\r\n }\r\n\r\n static Debug(type, message) {\r\n switch (type) {\r\n case 0:\r\n console.error(message);\r\n break;\r\n case 1:\r\n console.warn(message);\r\n break;\r\n case 2:\r\n console.log(message);\r\n break;\r\n default:\r\n console.log(message);\r\n break;\r\n }\r\n }\r\n\r\n private informerRun(error, params, command) {\r\n let error_translate = '';\r\n\r\n switch (error) {\r\n case 'NOT_ENOUGH_MONEY':\r\n error_translate = 'ERRORS.NOT_ENOUGH_MONEY';\r\n break;\r\n case 'CORE_BUSY':\r\n if (command !== 'get_all_aliases') {\r\n error_translate = 'ERRORS.CORE_BUSY';\r\n }\r\n break;\r\n case 'OVERFLOW':\r\n if (command !== 'get_all_aliases') {\r\n error_translate = '';\r\n }\r\n break;\r\n case 'INTERNAL_ERROR:daemon is busy':\r\n error_translate = 'ERRORS.DAEMON_BUSY';\r\n break;\r\n case 'INTERNAL_ERROR:not enough money':\r\n case 'INTERNAL_ERROR:NOT_ENOUGH_MONEY':\r\n if (command === 'cancel_offer') {\r\n error_translate = this.translate.instant('ERRORS.NO_MONEY_REMOVE_OFFER', {\r\n 'fee': this.variablesService.default_fee,\r\n 'currency': this.variablesService.defaultCurrency\r\n });\r\n } else {\r\n error_translate = 'ERRORS.NO_MONEY';\r\n }\r\n break;\r\n case 'INTERNAL_ERROR:not enough outputs to mix':\r\n error_translate = 'ERRORS.NOT_ENOUGH_OUTPUTS_TO_MIX';\r\n break;\r\n case 'INTERNAL_ERROR:transaction is too big':\r\n error_translate = 'ERRORS.TRANSACTION_IS_TO_BIG';\r\n break;\r\n case 'INTERNAL_ERROR:Transfer attempt while daemon offline':\r\n error_translate = 'ERRORS.TRANSFER_ATTEMPT';\r\n break;\r\n case 'ACCESS_DENIED':\r\n error_translate = 'ERRORS.ACCESS_DENIED';\r\n break;\r\n case 'INTERNAL_ERROR:transaction was rejected by daemon':\r\n // if (command === 'request_alias_registration') {\r\n // error_translate = 'INFORMER.ALIAS_IN_REGISTER';\r\n // } else {\r\n error_translate = 'ERRORS.TRANSACTION_ERROR';\r\n // }\r\n break;\r\n case 'INTERNAL_ERROR':\r\n error_translate = 'ERRORS.TRANSACTION_ERROR';\r\n break;\r\n case 'BAD_ARG':\r\n error_translate = 'ERRORS.BAD_ARG';\r\n break;\r\n case 'WALLET_WRONG_ID':\r\n error_translate = 'ERRORS.WALLET_WRONG_ID';\r\n break;\r\n case 'WRONG_PASSWORD':\r\n case 'WRONG_PASSWORD:invalid password':\r\n params = JSON.parse(params);\r\n if (!params.testEmpty) {\r\n error_translate = 'ERRORS.WRONG_PASSWORD';\r\n }\r\n break;\r\n case 'FILE_RESTORED':\r\n if (command === 'open_wallet') {\r\n error_translate = 'ERRORS.FILE_RESTORED';\r\n }\r\n break;\r\n case 'FILE_NOT_FOUND':\r\n if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {\r\n error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');\r\n params = JSON.parse(params);\r\n if (params.path) {\r\n error_translate += ': ' + params.path;\r\n }\r\n }\r\n break;\r\n case 'NOT_FOUND':\r\n if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {\r\n error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');\r\n params = JSON.parse(params);\r\n if (params.path) {\r\n error_translate += ': ' + params.path;\r\n }\r\n }\r\n break;\r\n case 'CANCELED':\r\n case '':\r\n break;\r\n case 'FAIL':\r\n if (command === 'create_proposal' || command === 'accept_proposal' || command === 'release_contract' || command === 'request_cancel_contract' || command === 'accept_cancel_contract') {\r\n error_translate = ' ';\r\n }\r\n break;\r\n case 'ALREADY_EXISTS':\r\n error_translate = 'ERRORS.FILE_EXIST';\r\n break;\r\n default:\r\n error_translate = error;\r\n }\r\n if (error.indexOf('FAIL:failed to save file') > -1) {\r\n error_translate = 'ERRORS.FILE_NOT_SAVED';\r\n }\r\n if (error.indexOf('FAILED:failed to open binary wallet file for saving') > -1 && command === 'generate_wallet') {\r\n error_translate = '';\r\n }\r\n if (error_translate !== '') {\r\n this.modalService.prepareModal('error', error_translate);\r\n }\r\n }\r\n\r\n\r\n private commandDebug(command, params, result) {\r\n BackendService.Debug(2, '----------------- ' + command + ' -----------------');\r\n const debug = {\r\n _send_params: params,\r\n _result: result\r\n };\r\n BackendService.Debug(2, debug);\r\n try {\r\n BackendService.Debug(2, JSONBigNumber.parse(result, BackendService.bigNumberParser));\r\n } catch (e) {\r\n BackendService.Debug(2, {response_data: result, error_code: 'OK'});\r\n }\r\n }\r\n\r\n private backendCallback(resultStr, params, callback, command) {\r\n let Result = resultStr;\r\n if (command !== 'get_clipboard') {\r\n if (!resultStr || resultStr === '') {\r\n Result = {};\r\n } else {\r\n try {\r\n Result = JSONBigNumber.parse(resultStr, BackendService.bigNumberParser);\r\n } catch (e) {\r\n Result = {response_data: resultStr, error_code: 'OK'};\r\n }\r\n }\r\n } else {\r\n Result = {\r\n error_code: 'OK',\r\n response_data: Result\r\n };\r\n }\r\n\r\n const Status = (Result.error_code === 'OK' || Result.error_code === 'TRUE');\r\n\r\n if (!Status && Status !== undefined && Result.error_code !== undefined) {\r\n BackendService.Debug(1, 'API error for command: \"' + command + '\". Error code: ' + Result.error_code);\r\n }\r\n const data = ((typeof Result === 'object') && 'response_data' in Result) ? Result.response_data : Result;\r\n\r\n let res_error_code = false;\r\n if (typeof Result === 'object' && 'error_code' in Result && Result.error_code !== 'OK' && Result.error_code !== 'TRUE' && Result.error_code !== 'FALSE') {\r\n this.informerRun(Result.error_code, params, command);\r\n res_error_code = Result.error_code;\r\n }\r\n\r\n // if ( command === 'get_offers_ex' ){\r\n // Service.printLog( \"get_offers_ex offers count \"+((data.offers)?data.offers.length:0) );\r\n // }\r\n\r\n if (typeof callback === 'function') {\r\n callback(Status, data, res_error_code);\r\n } else {\r\n return data;\r\n }\r\n }\r\n\r\n\r\n private runCommand(command, params?, callback?) {\r\n if (this.backendObject) {\r\n const Action = this.backendObject[command];\r\n if (!Action) {\r\n BackendService.Debug(0, 'Run Command Error! Command \"' + command + '\" don\\'t found in backendObject');\r\n } else {\r\n const that = this;\r\n params = (typeof params === 'string') ? params : JSONBigNumber.stringify(params);\r\n if (params === undefined || params === '{}') {\r\n Action(function (resultStr) {\r\n that.commandDebug(command, params, resultStr);\r\n return that.backendCallback(resultStr, params, callback, command);\r\n });\r\n } else {\r\n Action(params, function (resultStr) {\r\n that.commandDebug(command, params, resultStr);\r\n return that.backendCallback(resultStr, params, callback, command);\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n\r\n eventSubscribe(command, callback) {\r\n if (command === 'on_core_event') {\r\n this.backendObject[command].connect(callback);\r\n } else {\r\n this.backendObject[command].connect((str) => {\r\n callback(JSONBigNumber.parse(str, BackendService.bigNumberParser));\r\n });\r\n }\r\n }\r\n\r\n\r\n initService() {\r\n return new Observable(\r\n observer => {\r\n if (!this.backendLoaded) {\r\n this.backendLoaded = true;\r\n const that = this;\r\n (window).QWebChannel((window).qt.webChannelTransport, function (channel) {\r\n that.backendObject = channel.objects.mediator_object;\r\n observer.next('ok');\r\n });\r\n } else {\r\n if (!this.backendObject) {\r\n observer.error('error');\r\n observer.error('error');\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n\r\n webkitLaunchedScript() {\r\n return this.runCommand('webkit_launched_script');\r\n }\r\n\r\n quitRequest() {\r\n return this.runCommand('on_request_quit');\r\n }\r\n\r\n getAppData(callback) {\r\n this.runCommand('get_app_data', {}, callback);\r\n }\r\n\r\n storeAppData(callback?) {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.settings.wallets = [];\r\n this.variablesService.wallets.forEach((wallet) => {\r\n this.variablesService.settings.wallets.push({name: wallet.name, path: wallet.path});\r\n });\r\n }\r\n this.runCommand('store_app_data', this.variablesService.settings, callback);\r\n }\r\n\r\n getSecureAppData(pass, callback) {\r\n this.runCommand('get_secure_app_data', pass, callback);\r\n }\r\n\r\n setMasterPassword(pass, callback) {\r\n this.runCommand('set_master_password', pass, callback);\r\n }\r\n\r\n checkMasterPassword(pass, callback) {\r\n this.runCommand('check_master_password', pass, callback);\r\n }\r\n storeSecureAppData(callback?) {\r\n let data;\r\n const wallets = [];\r\n const contacts = [];\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallets.push({name: wallet.name, pass: wallet.pass, path: wallet.path, staking: wallet.staking});\r\n });\r\n this.variablesService.contacts.forEach((contact) => {\r\n contacts.push({name: contact.name, address: contact.address, notes: contact.notes});\r\n });\r\n data = {wallets: wallets, contacts: contacts};\r\n this.backendObject['store_secure_app_data'](JSON.stringify(data), this.variablesService.appPass, (dataStore) => {\r\n this.backendCallback(dataStore, {}, callback, 'store_secure_app_data');\r\n });\r\n }\r\n\r\n dropSecureAppData(callback?) {\r\n this.backendObject['drop_secure_app_data']((dataStore) => {\r\n this.backendCallback(dataStore, {}, callback, 'drop_secure_app_data');\r\n });\r\n }\r\n\r\n haveSecureAppData(callback) {\r\n this.runCommand('have_secure_app_data', {}, callback);\r\n }\r\n\r\n saveFileDialog(caption, fileMask, default_path, callback) {\r\n const dir = default_path ? default_path : '/';\r\n const params = {\r\n caption: caption,\r\n filemask: fileMask,\r\n default_dir: dir\r\n };\r\n this.runCommand('show_savefile_dialog', params, callback);\r\n }\r\n\r\n openFileDialog(caption, fileMask, default_path, callback) {\r\n const dir = default_path ? default_path : '/';\r\n const params = {\r\n caption: caption,\r\n filemask: fileMask,\r\n default_dir: dir\r\n };\r\n this.runCommand('show_openfile_dialog', params, callback);\r\n }\r\n\r\n storeFile(path, buff) {\r\n this.backendObject['store_to_file'](path, buff);\r\n }\r\n\r\n loadFile(path, callback) {\r\n this.runCommand('load_from_file', path, callback);\r\n }\r\n\r\n generateWallet(path, pass, callback) {\r\n const params = {\r\n path: path,\r\n pass: pass\r\n };\r\n this.runCommand('generate_wallet', params, callback);\r\n }\r\n\r\n openWallet(path, pass, testEmpty, callback) {\r\n const params = {\r\n path: path,\r\n pass: pass\r\n };\r\n params['testEmpty'] = !!(testEmpty);\r\n this.runCommand('open_wallet', params, callback);\r\n }\r\n\r\n closeWallet(wallet_id, callback?) {\r\n this.runCommand('close_wallet', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n getSmartWalletInfo(wallet_id, callback) {\r\n this.runCommand('get_smart_wallet_info', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n runWallet(wallet_id, callback?) {\r\n this.runCommand('run_wallet', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n isValidRestoreWalletText(text, callback) {\r\n this.runCommand('is_valid_restore_wallet_text', text, callback);\r\n }\r\n\r\n restoreWallet(path, pass, restore_key, callback) {\r\n const params = {\r\n restore_key: restore_key,\r\n path: path,\r\n pass: pass\r\n };\r\n this.runCommand('restore_wallet', params, callback);\r\n }\r\n\r\n sendMoney(from_wallet_id, to_address, amount, fee, mixin, comment, hide, callback) {\r\n const params = {\r\n wallet_id: parseInt(from_wallet_id, 10),\r\n destinations: [\r\n {\r\n address: to_address,\r\n amount: amount\r\n }\r\n ],\r\n mixin_count: (mixin) ? parseInt(mixin, 10) : 0,\r\n lock_time: 0,\r\n fee: this.moneyToIntPipe.transform(fee),\r\n comment: comment,\r\n push_payer: !hide\r\n };\r\n this.runCommand('transfer', params, callback);\r\n }\r\n\r\n validateAddress(address, callback) {\r\n this.runCommand('validate_address', address, callback);\r\n }\r\n\r\n setClipboard(str, callback?) {\r\n return this.runCommand('set_clipboard', str, callback);\r\n }\r\n\r\n getClipboard(callback) {\r\n return this.runCommand('get_clipboard', {}, callback);\r\n }\r\n\r\n createProposal(wallet_id, title, comment, a_addr, b_addr, to_pay, a_pledge, b_pledge, time, payment_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n details: {\r\n t: title,\r\n c: comment,\r\n a_addr: a_addr,\r\n b_addr: b_addr,\r\n to_pay: this.moneyToIntPipe.transform(to_pay),\r\n a_pledge: this.moneyToIntPipe.transform(a_pledge),\r\n b_pledge: this.moneyToIntPipe.transform(b_pledge)\r\n },\r\n payment_id: payment_id,\r\n expiration_period: parseInt(time, 10) * 60 * 60,\r\n fee: this.variablesService.default_fee_big,\r\n b_fee: this.variablesService.default_fee_big\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('create_proposal', params, callback);\r\n }\r\n\r\n getContracts(wallet_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10)\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('get_contracts', params, callback);\r\n }\r\n\r\n acceptProposal(wallet_id, contract_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('accept_proposal', params, callback);\r\n }\r\n\r\n releaseProposal(wallet_id, contract_id, release_type, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id,\r\n release_type: release_type // \"normal\" or \"burn\"\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('release_contract', params, callback);\r\n }\r\n\r\n requestCancelContract(wallet_id, contract_id, time, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id,\r\n fee: this.variablesService.default_fee_big,\r\n expiration_period: parseInt(time, 10) * 60 * 60\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('request_cancel_contract', params, callback);\r\n }\r\n\r\n acceptCancelContract(wallet_id, contract_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('accept_cancel_contract', params, callback);\r\n }\r\n\r\n getMiningHistory(wallet_id, callback) {\r\n this.runCommand('get_mining_history', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n startPosMining(wallet_id, callback?) {\r\n this.runCommand('start_pos_mining', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n stopPosMining(wallet_id, callback?) {\r\n this.runCommand('stop_pos_mining', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n openUrlInBrowser(url, callback?) {\r\n this.runCommand('open_url_in_browser', url, callback);\r\n }\r\n\r\n start_backend(node, host, port, callback) {\r\n const params = {\r\n configure_for_remote_node: node,\r\n remote_node_host: host,\r\n remote_node_port: parseInt(port, 10)\r\n };\r\n this.runCommand('start_backend', params, callback);\r\n }\r\n\r\n getDefaultFee(callback) {\r\n this.runCommand('get_default_fee', {}, callback);\r\n }\r\n\r\n setBackendLocalization(stringsArray, title, callback?) {\r\n const params = {\r\n strings: stringsArray,\r\n language_title: title\r\n };\r\n this.runCommand('set_localization_strings', params, callback);\r\n }\r\n\r\n registerAlias(wallet_id, alias, address, fee, comment, reward, callback) {\r\n const params = {\r\n wallet_id: wallet_id,\r\n alias: {\r\n alias: alias,\r\n address: address,\r\n tracking_key: '',\r\n comment: comment\r\n },\r\n fee: this.moneyToIntPipe.transform(fee),\r\n reward: this.moneyToIntPipe.transform(reward)\r\n };\r\n this.runCommand('request_alias_registration', params, callback);\r\n }\r\n\r\n updateAlias(wallet_id, alias, fee, callback) {\r\n const params = {\r\n wallet_id: wallet_id,\r\n alias: {\r\n alias: alias.name.replace('@', ''),\r\n address: alias.address,\r\n tracking_key: '',\r\n comment: alias.comment\r\n },\r\n fee: this.moneyToIntPipe.transform(fee)\r\n };\r\n this.runCommand('request_alias_update', params, callback);\r\n }\r\n\r\n getAllAliases(callback) {\r\n this.runCommand('get_all_aliases', {}, callback);\r\n }\r\n\r\n getAliasByName(value, callback) {\r\n return this.runCommand('get_alias_info_by_name', value, callback);\r\n }\r\n\r\n getAliasByAddress(value, callback) {\r\n return this.runCommand('get_alias_info_by_address', value, callback);\r\n }\r\n\r\n getAliasCoast(alias, callback) {\r\n this.runCommand('get_alias_coast', {v: alias}, callback);\r\n }\r\n\r\n getWalletAlias(address) {\r\n if (address !== null && this.variablesService.daemon_state === 2) {\r\n if (this.variablesService.aliasesChecked[address] == null) {\r\n this.variablesService.aliasesChecked[address] = {};\r\n if (this.variablesService.aliases.length) {\r\n for (let i = 0, length = this.variablesService.aliases.length; i < length; i++) {\r\n if (i in this.variablesService.aliases && this.variablesService.aliases[i]['address'] === address) {\r\n this.variablesService.aliasesChecked[address]['name'] = this.variablesService.aliases[i].name;\r\n this.variablesService.aliasesChecked[address]['address'] = this.variablesService.aliases[i].address;\r\n this.variablesService.aliasesChecked[address]['comment'] = this.variablesService.aliases[i].comment;\r\n return this.variablesService.aliasesChecked[address];\r\n }\r\n }\r\n }\r\n this.getAliasByAddress(address, (status, data) => {\r\n if (status) {\r\n this.variablesService.aliasesChecked[data.address]['name'] = '@' + data.alias;\r\n this.variablesService.aliasesChecked[data.address]['address'] = data.address;\r\n this.variablesService.aliasesChecked[data.address]['comment'] = data.comment;\r\n }\r\n });\r\n }\r\n return this.variablesService.aliasesChecked[address];\r\n }\r\n return {};\r\n }\r\n\r\n getContactAlias() {\r\n if (this.variablesService.contacts.length && this.variablesService.daemon_state === 2) {\r\n this.variablesService.contacts.map(contact => {\r\n this.getAliasByAddress(contact.address, (status, data) => {\r\n if (status) {\r\n if (data.alias) {\r\n contact.alias = '@' + data.alias;\r\n }\r\n } else {\r\n contact.alias = null;\r\n }\r\n });\r\n });\r\n }\r\n }\r\n\r\n getPoolInfo(callback) {\r\n this.runCommand('get_tx_pool_info', {}, callback);\r\n }\r\n\r\n getVersion(callback) {\r\n this.runCommand('get_version', {}, (status, version) => {\r\n callback(version);\r\n });\r\n }\r\n\r\n setLogLevel(level) {\r\n return this.runCommand('set_log_level', {v: level});\r\n }\r\n\r\n}\r\n\r\n\r\n/*\r\n\r\n toggleAutoStart: function (value) {\r\n return this.runCommand('toggle_autostart', asVal(value));\r\n },\r\n\r\n getOptions: function (callback) {\r\n return this.runCommand('get_options', {}, callback);\r\n },\r\n\r\n isFileExist: function (path, callback) {\r\n return this.runCommand('is_file_exist', path, callback);\r\n },\r\n\r\n isAutoStartEnabled: function (callback) {\r\n this.runCommand('is_autostart_enabled', {}, function (status, data) {\r\n if (angular.isFunction(callback)) {\r\n callback('error_code' in data && data.error_code !== 'FALSE')\r\n }\r\n });\r\n },\r\n\r\n resetWalletPass: function (wallet_id, pass, callback) {\r\n this.runCommand('reset_wallet_password', {wallet_id: wallet_id, pass: pass}, callback);\r\n },\r\n\r\n\r\n\r\n getOsVersion: function (callback) {\r\n this.runCommand('get_os_version', {}, function (status, version) {\r\n callback(version)\r\n })\r\n },\r\n\r\n getLogFile: function (callback) {\r\n this.runCommand('get_log_file', {}, function (status, version) {\r\n callback(version)\r\n })\r\n },\r\n\r\n resync_wallet: function (wallet_id, callback) {\r\n this.runCommand('resync_wallet', {wallet_id: wallet_id}, callback);\r\n },\r\n\r\n storeFile: function (path, buff, callback) {\r\n this.backendObject['store_to_file'](path, (typeof buff === 'string' ? buff : JSON.stringify(buff)), function (data) {\r\n backendCallback(data, {}, callback, 'store_to_file');\r\n });\r\n },\r\n\r\n getMiningEstimate: function (amount_coins, time, callback) {\r\n var params = {\r\n \"amount_coins\": $filter('money_to_int')(amount_coins),\r\n \"time\": parseInt(time)\r\n };\r\n this.runCommand('get_mining_estimate', params, callback);\r\n },\r\n\r\n backupWalletKeys: function (wallet_id, path, callback) {\r\n var params = {\r\n \"wallet_id\": wallet_id,\r\n \"path\": path\r\n };\r\n this.runCommand('backup_wallet_keys', params, callback);\r\n },\r\n\r\n setBlockedIcon: function (enabled, callback) {\r\n var mode = (enabled) ? \"blocked\" : \"normal\";\r\n Service.runCommand('bool_toggle_icon', mode, callback);\r\n },\r\n\r\n getWalletInfo: function (wallet_id, callback) {\r\n this.runCommand('get_wallet_info', {wallet_id: wallet_id}, callback);\r\n },\r\n\r\n printText: function (content) {\r\n return this.runCommand('print_text', {html_text: content});\r\n },\r\n\r\n printLog: function (msg, log_level) {\r\n return this.runCommand('print_log', {msg: msg, log_level: log_level});\r\n },\r\n\r\n*/\r\n\r\n","import {Injectable, Injector, ComponentFactoryResolver, EmbeddedViewRef, ApplicationRef, NgZone} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {ModalContainerComponent} from '../directives/modal-container/modal-container.component';\r\n\r\n@Injectable()\r\nexport class ModalService {\r\n\r\n private components: any[] = [];\r\n\r\n constructor(\r\n private componentFactoryResolver: ComponentFactoryResolver,\r\n private appRef: ApplicationRef,\r\n private injector: Injector,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {}\r\n\r\n prepareModal(type, message) {\r\n const length = this.components.push(\r\n this.componentFactoryResolver.resolveComponentFactory(ModalContainerComponent).create(this.injector)\r\n );\r\n\r\n this.components[length - 1].instance['type'] = type;\r\n this.components[length - 1].instance['message'] = message.length ? this.translate.instant(message) : '';\r\n this.components[length - 1].instance['close'].subscribe(() => {\r\n this.removeModal(length - 1);\r\n });\r\n\r\n this.ngZone.run(() => {\r\n this.appendModal(length - 1);\r\n });\r\n }\r\n\r\n appendModal(index) {\r\n this.appRef.attachView(this.components[index].hostView);\r\n const domElem = (this.components[index].hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n }\r\n\r\n removeModal(index) {\r\n if (this.components[index]) {\r\n this.appRef.detachView(this.components[index].hostView);\r\n this.components[index].destroy();\r\n this.components.splice(index, 1);\r\n } else {\r\n const last = this.components.length - 1;\r\n this.appRef.detachView(this.components[last].hostView);\r\n this.components[last].destroy();\r\n this.components.splice(last, 1);\r\n }\r\n }\r\n}\r\n","import {Injectable, NgZone} from '@angular/core';\r\nimport {Wallet} from '../models/wallet.model';\r\nimport {Contact} from '../models/contact.model';\r\nimport {BehaviorSubject} from 'rxjs';\r\nimport {Idle} from 'idlejs/dist';\r\nimport {Router} from '@angular/router';\r\nimport {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class VariablesService {\r\n\r\n public digits = 12;\r\n public appPass = '';\r\n public appLogin = false;\r\n public moneyEquivalent = 0;\r\n public defaultTheme = 'dark';\r\n public defaultCurrency = 'ZANO';\r\n public opening_wallet: Wallet;\r\n public exp_med_ts = 0;\r\n public net_time_delta_median = 0;\r\n public height_app = 0;\r\n public height_max = 0;\r\n public last_build_available = '';\r\n public last_build_displaymode = 0;\r\n public daemon_state = 3;\r\n public sync = {\r\n progress_value: 0,\r\n progress_value_text: '0'\r\n };\r\n public default_fee = '0.010000000000';\r\n public default_fee_big = new BigNumber('10000000000');\r\n\r\n public settings = {\r\n appLockTime: 15,\r\n appLog: 0,\r\n theme: '',\r\n scale: 10,\r\n language: 'en',\r\n default_path: '/',\r\n viewedContracts: [],\r\n notViewedContracts: [],\r\n wallets: []\r\n };\r\n\r\n public wallets: Array = [];\r\n public currentWallet: Wallet;\r\n public selectWallet: number;\r\n public aliases: any = [];\r\n public aliasesChecked: any = {};\r\n public enableAliasSearch = false;\r\n public maxWalletNameLength = 25;\r\n public maxCommentLength = 255;\r\n public dataIsLoaded = false;\r\n\r\n public contacts: Array = [];\r\n public newContact: Contact = {name: null, address: null, notes: null};\r\n\r\n public pattern = '^[a-zA-Z0-9_.\\\\\\]\\*\\|\\~\\!\\?\\@\\#\\$\\%\\^\\&\\+\\{\\}\\(\\)\\<\\>\\:\\;\\\"\\'\\-\\=\\/\\,\\[\\\\\\\\]*$';\r\n\r\n getExpMedTsEvent = new BehaviorSubject(null);\r\n getHeightAppEvent = new BehaviorSubject(null);\r\n getHeightMaxEvent = new BehaviorSubject(null);\r\n getRefreshStackingEvent = new BehaviorSubject(null);\r\n getAliasChangedEvent = new BehaviorSubject(null);\r\n\r\n public idle = new Idle()\r\n .whenNotInteractive()\r\n .do(() => {\r\n if (this.appPass == '') {\r\n this.restartCountdown();\r\n } else {\r\n this.ngZone.run(() => {\r\n this.idle.stop();\r\n this.appPass = '';\r\n this.appLogin = false;\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n }\r\n });\r\n\r\n public allContextMenu: ContextMenuComponent;\r\n public onlyCopyContextMenu: ContextMenuComponent;\r\n public pasteSelectContextMenu: ContextMenuComponent;\r\n\r\n constructor(private router: Router, private ngZone: NgZone, private contextMenuService: ContextMenuService) {\r\n }\r\n\r\n setExpMedTs(timestamp: number) {\r\n if (timestamp !== this.exp_med_ts) {\r\n this.exp_med_ts = timestamp;\r\n this.getExpMedTsEvent.next(timestamp);\r\n }\r\n }\r\n\r\n setHeightApp(height: number) {\r\n if (height !== this.height_app) {\r\n this.height_app = height;\r\n this.getHeightAppEvent.next(height);\r\n }\r\n }\r\n\r\n setHeightMax(height: number) {\r\n if (height !== this.height_max) {\r\n this.height_max = height;\r\n this.getHeightMaxEvent.next(height);\r\n }\r\n }\r\n\r\n setRefreshStacking(wallet_id: number) {\r\n this.getHeightAppEvent.next(wallet_id);\r\n }\r\n\r\n changeAliases() {\r\n this.getAliasChangedEvent.next(true);\r\n }\r\n\r\n setCurrentWallet(id): void {\r\n this.wallets.forEach((wallet) => {\r\n if (wallet.wallet_id === id) {\r\n this.currentWallet = wallet;\r\n }\r\n });\r\n }\r\n\r\n getWallet(id): Wallet {\r\n for (let i = 0; i < this.wallets.length; i++) {\r\n if (this.wallets[i].wallet_id === id) {\r\n return this.wallets[i];\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n startCountdown() {\r\n this.idle.within(this.settings.appLockTime).start();\r\n }\r\n\r\n stopCountdown() {\r\n this.idle.stop();\r\n }\r\n\r\n restartCountdown() {\r\n this.idle.within(this.settings.appLockTime).restart();\r\n }\r\n\r\n public onContextMenu($event: MouseEvent): void {\r\n $event.target['contextSelectionStart'] = $event.target['selectionStart'];\r\n $event.target['contextSelectionEnd'] = $event.target['selectionEnd'];\r\n if ($event.target && ($event.target['nodeName'].toUpperCase() === 'TEXTAREA' || $event.target['nodeName'].toUpperCase() === 'INPUT') && !$event.target['readOnly']) {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.allContextMenu,\r\n event: $event,\r\n item: $event.target,\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n }\r\n\r\n public onContextMenuOnlyCopy($event: MouseEvent, copyText?: string): void {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.onlyCopyContextMenu,\r\n event: $event,\r\n item: copyText\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n\r\n public onContextMenuPasteSelect($event: MouseEvent): void {\r\n $event.target['contextSelectionStart'] = $event.target['selectionStart'];\r\n $event.target['contextSelectionEnd'] = $event.target['selectionEnd'];\r\n\r\n console.warn($event.target);\r\n console.warn($event.target['disabled']);\r\n\r\n\r\n if ($event.target && ($event.target['nodeName'].toUpperCase() === 'TEXTAREA' || $event.target['nodeName'].toUpperCase() === 'INPUT') && !$event.target['readOnly']) {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.pasteSelectContextMenu,\r\n event: $event,\r\n item: $event.target,\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.TITLE' | translate }}\\r\\n {{ 'CONTACTS.ADD' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_DUBLICATED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_DUBLICATED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\"","module.exports = \".form-add {\\n margin-top: 3rem; }\\n .form-add .input-block-name {\\n width: 50%; }\\n .form-add button {\\n margin-top: 3rem;\\n width: 100%;\\n max-width: 18rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYWRkLWNvbnRhY3RzL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGFkZC1jb250YWN0c1xcYWRkLWNvbnRhY3RzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGdCQUFnQjtJQUNoQixXQUFXO0lBQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9hZGQtY29udGFjdHMvYWRkLWNvbnRhY3RzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmZvcm0tYWRkIHtcclxuICBtYXJnaW4tdG9wOiAzcmVtO1xyXG5cclxuICAuaW5wdXQtYmxvY2stbmFtZSB7XHJcbiAgICB3aWR0aDogNTAlO1xyXG4gIH1cclxuXHJcbiAgYnV0dG9uIHtcclxuICAgIG1hcmdpbi10b3A6IDNyZW07XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIG1heC13aWR0aDogMThyZW07XHJcbiAgfVxyXG59Il19 */\"","import { Component, OnInit, NgZone, OnDestroy } from '@angular/core';\r\nimport { FormGroup, FormControl, Validators } from '@angular/forms';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\nimport { Location } from '@angular/common';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-add-contacts',\r\n templateUrl: './add-contacts.component.html',\r\n styleUrls: ['./add-contacts.component.scss']\r\n})\r\nexport class AddContactsComponent implements OnInit, OnDestroy {\r\n id: number;\r\n queryRouting;\r\n addContactForm = new FormGroup({\r\n address: new FormControl('', [\r\n Validators.required,\r\n (g: FormControl) => {\r\n if (g.value) {\r\n this.backend.validateAddress(g.value, valid_status => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(\r\n Object.assign({ address_not_valid: true }, g.errors)\r\n );\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return g.hasError('address_not_valid')\r\n ? { address_not_valid: true }\r\n : null;\r\n }\r\n return null;\r\n },\r\n (g: FormControl) => {\r\n const isDublicated = this.variablesService.contacts.findIndex(\r\n contact => contact.address === g.value\r\n );\r\n if (isDublicated !== -1 && !(this.id === isDublicated)) {\r\n return { dublicated: true };\r\n }\r\n return null;\r\n }\r\n ]),\r\n notes: new FormControl('', [\r\n (g: FormControl) => {\r\n if (g.value) {\r\n if (g.value.length > this.variablesService.maxCommentLength) {\r\n return { maxLength: true };\r\n } else {\r\n return null;\r\n }\r\n } else {\r\n return null;\r\n }\r\n }\r\n ]),\r\n name: new FormControl('', [\r\n Validators.required,\r\n Validators.minLength(4),\r\n Validators.maxLength(25),\r\n (g: FormControl) => {\r\n if (g.value) {\r\n const isDublicated = this.variablesService.contacts.findIndex(\r\n contact => contact.name === g.value.trim()\r\n );\r\n if (isDublicated !== -1 && !(this.id === isDublicated)) {\r\n return { dublicated: true };\r\n }\r\n return null;\r\n }\r\n }\r\n ])\r\n });\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private location: Location\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.id) {\r\n this.id = parseInt(params.id, 10);\r\n this.addContactForm.reset({\r\n name: this.variablesService.contacts[params.id]['name'],\r\n address: this.variablesService.contacts[params.id]['address'],\r\n notes: this.variablesService.contacts[params.id]['notes']\r\n });\r\n } else {\r\n this.addContactForm.reset({\r\n name: this.variablesService.newContact['name'],\r\n address: this.variablesService.newContact['address'],\r\n notes: this.variablesService.newContact['notes']\r\n });\r\n }\r\n });\r\n }\r\n\r\n add() {\r\n if (!this.variablesService.appPass) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.FORM_ERRORS.SET_MASTER_PASSWORD'\r\n );\r\n } else {\r\n if (this.addContactForm.valid) {\r\n this.backend.validateAddress(\r\n this.addContactForm.get('address').value,\r\n valid_status => {\r\n if (valid_status === false) {\r\n this.ngZone.run(() => {\r\n this.addContactForm\r\n .get('address')\r\n .setErrors({ address_not_valid: true });\r\n });\r\n } else {\r\n if (this.id || this.id === 0) {\r\n this.variablesService.contacts.forEach((contact, index) => {\r\n if (index === this.id) {\r\n contact.name = this.addContactForm.get('name').value.trim();\r\n contact.address = this.addContactForm.get('address').value;\r\n contact.notes =\r\n this.addContactForm.get('notes').value || '';\r\n }\r\n });\r\n this.backend.storeSecureAppData();\r\n this.backend.getContactAlias();\r\n this.modalService.prepareModal(\r\n 'success',\r\n 'CONTACTS.SUCCESS_SAVE'\r\n );\r\n } else {\r\n this.variablesService.contacts.push({\r\n name: this.addContactForm.get('name').value.trim(),\r\n address: this.addContactForm.get('address').value,\r\n notes: this.addContactForm.get('notes').value || ''\r\n });\r\n this.backend.storeSecureAppData();\r\n this.backend.getContactAlias();\r\n this.modalService.prepareModal(\r\n 'success',\r\n 'CONTACTS.SUCCESS_SENT'\r\n );\r\n this.variablesService.newContact = {\r\n name: null,\r\n address: null,\r\n notes: null\r\n };\r\n this.addContactForm.reset({\r\n name: null,\r\n address: null,\r\n notes: null\r\n });\r\n }\r\n }\r\n }\r\n );\r\n }\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n if (!(this.id || this.id === 0)) {\r\n this.variablesService.newContact = {\r\n name: this.addContactForm.get('name').value,\r\n address: this.addContactForm.get('address').value,\r\n notes: this.addContactForm.get('notes').value\r\n };\r\n }\r\n this.queryRouting.unsubscribe();\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { Routes, RouterModule } from '@angular/router';\r\n\r\n// Components\r\nimport { MainComponent } from './main/main.component';\r\nimport { LoginComponent } from './login/login.component';\r\nimport { WalletComponent } from './wallet/wallet.component';\r\nimport { SendComponent } from './send/send.component';\r\nimport { ReceiveComponent } from './receive/receive.component';\r\nimport { HistoryComponent } from './history/history.component';\r\nimport { ContractsComponent } from './contracts/contracts.component';\r\nimport { PurchaseComponent } from './purchase/purchase.component';\r\nimport { MessagesComponent } from './messages/messages.component';\r\nimport { TypingMessageComponent } from './typing-message/typing-message.component';\r\nimport { StakingComponent } from './staking/staking.component';\r\nimport { SettingsComponent } from './settings/settings.component';\r\nimport { CreateWalletComponent } from './create-wallet/create-wallet.component';\r\nimport { OpenWalletComponent } from './open-wallet/open-wallet.component';\r\nimport { RestoreWalletComponent } from './restore-wallet/restore-wallet.component';\r\nimport { SeedPhraseComponent } from './seed-phrase/seed-phrase.component';\r\nimport { WalletDetailsComponent } from './wallet-details/wallet-details.component';\r\nimport { AssignAliasComponent } from './assign-alias/assign-alias.component';\r\nimport { EditAliasComponent } from './edit-alias/edit-alias.component';\r\nimport { TransferAliasComponent } from './transfer-alias/transfer-alias.component';\r\nimport { ContactsComponent } from './contacts/contacts.component';\r\nimport { AddContactsComponent } from './add-contacts/add-contacts.component';\r\nimport { ContactSendComponent } from './contact-send/contact-send.component';\r\nimport { ExportImportComponent } from './export-import/export-import.component';\r\n\r\nconst routes: Routes = [\r\n {\r\n path: '',\r\n component: MainComponent\r\n },\r\n {\r\n path: 'main',\r\n component: MainComponent\r\n },\r\n {\r\n path: 'login',\r\n component: LoginComponent\r\n },\r\n {\r\n path: 'wallet/:id',\r\n component: WalletComponent,\r\n children: [\r\n {\r\n path: 'send',\r\n component: SendComponent\r\n },\r\n {\r\n path: 'receive',\r\n component: ReceiveComponent\r\n },\r\n {\r\n path: 'history',\r\n component: HistoryComponent\r\n },\r\n {\r\n path: 'contracts',\r\n component: ContractsComponent,\r\n },\r\n {\r\n path: 'purchase',\r\n component: PurchaseComponent\r\n },\r\n {\r\n path: 'purchase/:id',\r\n component: PurchaseComponent\r\n },\r\n {\r\n path: 'messages',\r\n component: MessagesComponent,\r\n },\r\n {\r\n path: 'messages/:id',\r\n component: TypingMessageComponent,\r\n },\r\n {\r\n path: 'staking',\r\n component: StakingComponent\r\n },\r\n {\r\n path: '',\r\n redirectTo: 'history',\r\n pathMatch: 'full'\r\n }\r\n ]\r\n },\r\n {\r\n path: 'create',\r\n component: CreateWalletComponent\r\n },\r\n {\r\n path: 'open',\r\n component: OpenWalletComponent\r\n },\r\n {\r\n path: 'restore',\r\n component: RestoreWalletComponent\r\n },\r\n {\r\n path: 'seed-phrase',\r\n component: SeedPhraseComponent\r\n },\r\n {\r\n path: 'details',\r\n component: WalletDetailsComponent\r\n },\r\n {\r\n path: 'assign-alias',\r\n component: AssignAliasComponent\r\n },\r\n {\r\n path: 'edit-alias',\r\n component: EditAliasComponent\r\n },\r\n {\r\n path: 'transfer-alias',\r\n component: TransferAliasComponent\r\n },\r\n {\r\n path: 'settings',\r\n component: SettingsComponent\r\n },\r\n {\r\n path: 'contacts',\r\n component: ContactsComponent\r\n },\r\n {\r\n path: 'add-contacts',\r\n component: AddContactsComponent\r\n },\r\n {\r\n path: 'edit-contacts/:id',\r\n component: AddContactsComponent\r\n },\r\n {\r\n path: 'contact-send/:id',\r\n component: ContactSendComponent\r\n },\r\n {\r\n path: 'import',\r\n component: ExportImportComponent\r\n },\r\n {\r\n path: '',\r\n redirectTo: '/',\r\n pathMatch: 'full'\r\n }\r\n];\r\n\r\n@NgModule({\r\n imports: [RouterModule.forRoot(routes)],\r\n exports: [RouterModule]\r\n})\r\n\r\n\r\nexport class AppRoutingModule { }\r\n","module.exports = \"\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n {{ 'CONTEXT_MENU.COPY' | translate }}\\r\\n {{ 'CONTEXT_MENU.PASTE' | translate }}\\r\\n {{ 'CONTEXT_MENU.SELECT' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n {{ 'CONTEXT_MENU.COPY' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n {{ 'CONTEXT_MENU.PASTE' | translate }}\\r\\n {{ 'CONTEXT_MENU.SELECT' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\"","module.exports = \"/*\\r\\n* Implementation of themes\\r\\n*/\\n.app-content {\\n display: flex;\\n overflow-x: overlay;\\n overflow-y: hidden;\\n width: 100%; }\\n.app-content .preloader {\\n align-self: center;\\n color: #fff;\\n font-size: 2rem;\\n margin: 0 auto;\\n text-align: center;\\n width: 50%; }\\n.app-content .preloader .loading-bar {\\n display: block;\\n -webkit-animation: move 5s linear infinite;\\n animation: move 5s linear infinite;\\n background-image: -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.125, rgba(0, 0, 0, 0.15)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.1)), color-stop(0.375, rgba(0, 0, 0, 0.1)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.15)), color-stop(0.625, rgba(0, 0, 0, 0.15)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.1)), color-stop(0.875, rgba(0, 0, 0, 0.1)), color-stop(0.875, transparent), to(transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.125, rgba(0, 0, 0, 0.3)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.25)), color-stop(0.375, rgba(0, 0, 0, 0.25)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.3)), color-stop(0.625, rgba(0, 0, 0, 0.3)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.25)), color-stop(0.875, rgba(0, 0, 0, 0.25)), color-stop(0.875, transparent), to(transparent));\\n background-size: 10rem 10rem;\\n margin-top: 2rem;\\n width: 100%;\\n height: 1rem; }\\n@-webkit-keyframes move {\\n 0% {\\n background-position: 100% -10rem; }\\n 100% {\\n background-position: 100% 10rem; } }\\n@keyframes move {\\n 0% {\\n background-position: 100% -10rem; }\\n 100% {\\n background-position: 100% 10rem; } }\\n\\r\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX21peGlucy5zY3NzIiwic3JjL2FwcC9hcHAuY29tcG9uZW50LnNjc3MiLCJzcmMvYXBwL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGFwcC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUE4RUE7O0NDNUVDO0FDQUQ7RUFDRSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLGtCQUFrQjtFQUNsQixXQUFXLEVBQUE7QUFKYjtJQU9JLGtCQUFrQjtJQUNsQixXQUFXO0lBQ1gsZUFBZTtJQUNmLGNBQWM7SUFDZCxrQkFBa0I7SUFDbEIsVUFBVSxFQUFBO0FBWmQ7TUFlTSxjQUFjO01BQ2QsMENBQWtDO2NBQWxDLGtDQUFrQztNQUNsQywrbENBc0JHO01BQ0gsNEJBQTRCO01BQzVCLGdCQUFnQjtNQUNoQixXQUFXO01BQ1gsWUFBWSxFQUFBO0FBSWhCO0VBQ0U7SUFDRSxnQ0FBZ0MsRUFBQTtFQUVsQztJQUNFLCtCQUErQixFQUFBLEVBQUE7QUFMbkM7RUFDRTtJQUNFLGdDQUFnQyxFQUFBO0VBRWxDO0lBQ0UsK0JBQStCLEVBQUEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2FwcC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIkBtaXhpbiB0ZXh0LXRydW5jYXRlIHtcclxuICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbn1cclxuQG1peGluIHRleHRXcmFwIHtcclxuICB3aGl0ZS1zcGFjZTogbm9ybWFsO1xyXG4gIG92ZXJmbG93LXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgd29yZC13cmFwOiBicmVhay13b3JkO1xyXG4gIHdvcmQtYnJlYWs6IGJyZWFrLWFsbDtcclxuICBsaW5lLWJyZWFrOiBzdHJpY3Q7XHJcbiAgLXdlYmtpdC1oeXBoZW5zOiBhdXRvO1xyXG4gIC1tcy1oeXBoZW5zOiBhdXRvO1xyXG4gIGh5cGhlbnM6IGF1dG87XHJcbn1cclxuQG1peGluIGNvdmVyQm94IHtcclxuXHRwb3NpdGlvbjogYWJzb2x1dGU7XHJcblx0dG9wOiAwO1xyXG5cdGxlZnQ6IDA7XHJcblx0d2lkdGg6IDEwMCU7XHJcblx0aGVpZ2h0OiAxMDAlO1xyXG59XHJcbkBtaXhpbiBhYnMgKCR0b3A6IGF1dG8sICRyaWdodDogYXV0bywgJGJvdHRvbTogYXV0bywgJGxlZnQ6IGF1dG8pIHtcclxuICB0b3A6ICR0b3A7XHJcbiAgcmlnaHQ6ICRyaWdodDtcclxuICBib3R0b206ICRib3R0b207XHJcbiAgbGVmdDogJGxlZnQ7XHJcbiAgcG9zaXRpb246IGFic29sdXRlO1xyXG59XHJcbkBtaXhpbiBjb3ZlckltZyB7XHJcblx0YmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcclxuXHQtd2Via2l0LWJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcblx0LW8tYmFja2dyb3VuZC1zaXplOiBjb3ZlcjtcclxuXHRiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG5cdGJhY2tncm91bmQtcG9zaXRpb246IDUwJSA1MCU7XHJcbn1cclxuQG1peGluIHZhbGluZ0JveCB7XHJcblx0cG9zaXRpb246IGFic29sdXRlO1xyXG5cdHRvcDogIDUwJTtcclxuXHRsZWZ0OiA1MCU7XHJcblx0dHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XHJcbn1cclxuQG1peGluIHVuU2VsZWN0IHtcclxuXHQtd2Via2l0LXRvdWNoLWNvbGxvdXQ6IG5vbmU7XHJcbiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcclxuICAta2h0bWwtdXNlci1zZWxlY3Q6IG5vbmU7XHJcbiAgLW1vei11c2VyLXNlbGVjdDogbm9uZTtcclxuICAtbXMtdXNlci1zZWxlY3Q6IG5vbmU7XHJcbiAgdXNlci1zZWxlY3Q6IG5vbmU7XHJcbn1cclxuQG1peGluIG1heDExOTkgeyAvLyBtYWtldCAxMTcxXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExOTlweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXgxMTcwIHsgLy8gbWFrZXRzIDk5MlxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiAxMTcwcHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbWF4OTkxIHsgLy8gbWFrZXRzIDc2MlxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA5OTFweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXg3NjEgeyAvLyBtYWtldHMgNTc2XHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDc2MXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDU3NSB7IC8vIG1ha2V0cyA0MDBcclxuICBAbWVkaWEgKG1heC13aWR0aDogNTc1cHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbW9iaWxlIHtcclxuICBAbWVkaWEgKG1heC13aWR0aDogMzk5cHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gaWNvQ2VudGVyIHtcclxuICAgIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7XHJcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXIgY2VudGVyO1xyXG59XHJcbkBtaXhpbiBwc2V1ZG8gKCRkaXNwbGF5OiBibG9jaywgJHBvczogYWJzb2x1dGUsICRjb250ZW50OiAnJyl7XHJcbiAgY29udGVudDogJGNvbnRlbnQ7XHJcbiAgZGlzcGxheTogJGRpc3BsYXk7XHJcbiAgcG9zaXRpb246ICRwb3M7XHJcbn1cclxuXHJcbi8qXHJcbiogSW1wbGVtZW50YXRpb24gb2YgdGhlbWVzXHJcbiovXHJcbkBtaXhpbiB0aGVtaWZ5KCR0aGVtZXM6ICR0aGVtZXMpIHtcclxuICBAZWFjaCAkdGhlbWUsICRtYXAgaW4gJHRoZW1lcyB7XHJcbiAgICAudGhlbWUtI3skdGhlbWV9ICYge1xyXG4gICAgICAkdGhlbWUtbWFwOiAoKSAhZ2xvYmFsO1xyXG4gICAgICBAZWFjaCAka2V5LCAkc3VibWFwIGluICRtYXAge1xyXG4gICAgICAgICR2YWx1ZTogbWFwLWdldChtYXAtZ2V0KCR0aGVtZXMsICR0aGVtZSksICcjeyRrZXl9Jyk7XHJcbiAgICAgICAgJHRoZW1lLW1hcDogbWFwLW1lcmdlKCR0aGVtZS1tYXAsICgka2V5OiAkdmFsdWUpKSAhZ2xvYmFsO1xyXG4gICAgICB9XHJcbiAgICAgIEBjb250ZW50O1xyXG4gICAgICAkdGhlbWUtbWFwOiBudWxsICFnbG9iYWw7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5AZnVuY3Rpb24gdGhlbWVkKCRrZXkpIHtcclxuICBAcmV0dXJuIG1hcC1nZXQoJHRoZW1lLW1hcCwgJGtleSk7XHJcbn1cclxuIiwiLypcclxuKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGVtZXNcclxuKi9cbi5hcHAtY29udGVudCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIG92ZXJmbG93LXg6IG92ZXJsYXk7XG4gIG92ZXJmbG93LXk6IGhpZGRlbjtcbiAgd2lkdGg6IDEwMCU7IH1cbiAgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIge1xuICAgIGFsaWduLXNlbGY6IGNlbnRlcjtcbiAgICBjb2xvcjogI2ZmZjtcbiAgICBmb250LXNpemU6IDJyZW07XG4gICAgbWFyZ2luOiAwIGF1dG87XG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xuICAgIHdpZHRoOiA1MCU7IH1cbiAgICAuYXBwLWNvbnRlbnQgLnByZWxvYWRlciAubG9hZGluZy1iYXIge1xuICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICBhbmltYXRpb246IG1vdmUgNXMgbGluZWFyIGluZmluaXRlO1xuICAgICAgYmFja2dyb3VuZC1pbWFnZTogLXdlYmtpdC1ncmFkaWVudChsaW5lYXIsIDAgMCwgMTAwJSAxMDAlLCBjb2xvci1zdG9wKDAuMTI1LCByZ2JhKDAsIDAsIDAsIDAuMTUpKSwgY29sb3Itc3RvcCgwLjEyNSwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKDAuMjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjI1LCByZ2JhKDAsIDAsIDAsIDAuMSkpLCBjb2xvci1zdG9wKDAuMzc1LCByZ2JhKDAsIDAsIDAsIDAuMSkpLCBjb2xvci1zdG9wKDAuMzc1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC41LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC41LCByZ2JhKDAsIDAsIDAsIDAuMTUpKSwgY29sb3Itc3RvcCgwLjYyNSwgcmdiYSgwLCAwLCAwLCAwLjE1KSksIGNvbG9yLXN0b3AoMC42MjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjc1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC43NSwgcmdiYSgwLCAwLCAwLCAwLjEpKSwgY29sb3Itc3RvcCgwLjg3NSwgcmdiYSgwLCAwLCAwLCAwLjEpKSwgY29sb3Itc3RvcCgwLjg3NSwgdHJhbnNwYXJlbnQpLCB0byh0cmFuc3BhcmVudCkpLCAtd2Via2l0LWdyYWRpZW50KGxpbmVhciwgMCAxMDAlLCAxMDAlIDAsIGNvbG9yLXN0b3AoMC4xMjUsIHJnYmEoMCwgMCwgMCwgMC4zKSksIGNvbG9yLXN0b3AoMC4xMjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjI1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC4yNSwgcmdiYSgwLCAwLCAwLCAwLjI1KSksIGNvbG9yLXN0b3AoMC4zNzUsIHJnYmEoMCwgMCwgMCwgMC4yNSkpLCBjb2xvci1zdG9wKDAuMzc1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC41LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC41LCByZ2JhKDAsIDAsIDAsIDAuMykpLCBjb2xvci1zdG9wKDAuNjI1LCByZ2JhKDAsIDAsIDAsIDAuMykpLCBjb2xvci1zdG9wKDAuNjI1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC43NSwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKDAuNzUsIHJnYmEoMCwgMCwgMCwgMC4yNSkpLCBjb2xvci1zdG9wKDAuODc1LCByZ2JhKDAsIDAsIDAsIDAuMjUpKSwgY29sb3Itc3RvcCgwLjg3NSwgdHJhbnNwYXJlbnQpLCB0byh0cmFuc3BhcmVudCkpO1xuICAgICAgYmFja2dyb3VuZC1zaXplOiAxMHJlbSAxMHJlbTtcbiAgICAgIG1hcmdpbi10b3A6IDJyZW07XG4gICAgICB3aWR0aDogMTAwJTtcbiAgICAgIGhlaWdodDogMXJlbTsgfVxuXG5Aa2V5ZnJhbWVzIG1vdmUge1xuICAwJSB7XG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMTAwJSAtMTByZW07IH1cbiAgMTAwJSB7XG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMTAwJSAxMHJlbTsgfSB9XG4iLCJAaW1wb3J0ICd+c3JjL2Fzc2V0cy9zY3NzL2Jhc2UvbWl4aW5zJztcclxuXHJcbi5hcHAtY29udGVudCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBvdmVyZmxvdy14OiBvdmVybGF5O1xyXG4gIG92ZXJmbG93LXk6IGhpZGRlbjtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgLnByZWxvYWRlciB7XHJcbiAgICBhbGlnbi1zZWxmOiBjZW50ZXI7XHJcbiAgICBjb2xvcjogI2ZmZjtcclxuICAgIGZvbnQtc2l6ZTogMnJlbTtcclxuICAgIG1hcmdpbjogMCBhdXRvO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgd2lkdGg6IDUwJTtcclxuXHJcbiAgICAubG9hZGluZy1iYXIge1xyXG4gICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgYW5pbWF0aW9uOiBtb3ZlIDVzIGxpbmVhciBpbmZpbml0ZTtcclxuICAgICAgYmFja2dyb3VuZC1pbWFnZTpcclxuICAgICAgICAtd2Via2l0LWdyYWRpZW50KFxyXG4gICAgICAgICAgICBsaW5lYXIsIDAgMCwgMTAwJSAxMDAlLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC4xMjUsIHJnYmEoMCwgMCwgMCwgLjE1KSksIGNvbG9yLXN0b3AoLjEyNSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC4yNTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguMjUwLCByZ2JhKDAsIDAsIDAsIC4xMCkpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC4zNzUsIHJnYmEoMCwgMCwgMCwgLjEwKSksIGNvbG9yLXN0b3AoLjM3NSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC41MDAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguNTAwLCByZ2JhKDAsIDAsIDAsIC4xNSkpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC42MjUsIHJnYmEoMCwgMCwgMCwgLjE1KSksIGNvbG9yLXN0b3AoLjYyNSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC43NTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguNzUwLCByZ2JhKDAsIDAsIDAsIC4xMCkpLFxyXG4gICAgICAgICAgICBjb2xvci1zdG9wKC44NzUsIHJnYmEoMCwgMCwgMCwgLjEwKSksIGNvbG9yLXN0b3AoLjg3NSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICB0byh0cmFuc3BhcmVudClcclxuICAgICAgICApLFxyXG4gICAgICAgIC13ZWJraXQtZ3JhZGllbnQoXHJcbiAgICAgICAgICAgIGxpbmVhciwgMCAxMDAlLCAxMDAlIDAsXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjEyNSwgcmdiYSgwLCAwLCAwLCAuMzApKSwgY29sb3Itc3RvcCguMTI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjI1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC4yNTAsIHJnYmEoMCwgMCwgMCwgLjI1KSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjM3NSwgcmdiYSgwLCAwLCAwLCAuMjUpKSwgY29sb3Itc3RvcCguMzc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjUwMCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC41MDAsIHJnYmEoMCwgMCwgMCwgLjMwKSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjYyNSwgcmdiYSgwLCAwLCAwLCAuMzApKSwgY29sb3Itc3RvcCguNjI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjc1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC43NTAsIHJnYmEoMCwgMCwgMCwgLjI1KSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjg3NSwgcmdiYSgwLCAwLCAwLCAuMjUpKSwgY29sb3Itc3RvcCguODc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIHRvKHRyYW5zcGFyZW50KVxyXG4gICAgICAgICk7XHJcbiAgICAgIGJhY2tncm91bmQtc2l6ZTogMTByZW0gMTByZW07XHJcbiAgICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDFyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBAa2V5ZnJhbWVzIG1vdmUge1xyXG4gICAgMCUge1xyXG4gICAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAxMDAlIC0xMHJlbTtcclxuICAgIH1cclxuICAgIDEwMCUge1xyXG4gICAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAxMDAlIDEwcmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, NgZone, Renderer2, OnDestroy, ViewChild} from '@angular/core';\r\nimport {HttpClient} from '@angular/common/http';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {BackendService} from './_helpers/services/backend.service';\r\nimport {Router} from '@angular/router';\r\nimport {VariablesService} from './_helpers/services/variables.service';\r\nimport {ContextMenuComponent} from 'ngx-contextmenu';\r\nimport {IntToMoneyPipe} from './_helpers/pipes/int-to-money.pipe';\r\nimport {BigNumber} from 'bignumber.js';\r\nimport {ModalService} from './_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.scss']\r\n})\r\nexport class AppComponent implements OnInit, OnDestroy {\r\n\r\n intervalUpdateContractsState;\r\n expMedTsEvent;\r\n onQuitRequest = false;\r\n firstOnlineState = false;\r\n translateUsed = false;\r\n\r\n needOpenWallets = [];\r\n\r\n @ViewChild('allContextMenu') public allContextMenu: ContextMenuComponent;\r\n @ViewChild('onlyCopyContextMenu') public onlyCopyContextMenu: ContextMenuComponent;\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private renderer: Renderer2,\r\n public translate: TranslateService,\r\n private backend: BackendService,\r\n private router: Router,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private intToMoneyPipe: IntToMoneyPipe,\r\n private modalService: ModalService\r\n ) {\r\n translate.addLangs(['en', 'fr', 'de', 'it', 'pt']);\r\n translate.setDefaultLang('en');\r\n // const browserLang = translate.getBrowserLang();\r\n // translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');\r\n translate.use('en').subscribe(() => {\r\n this.translateUsed = true;\r\n });\r\n }\r\n\r\n setBackendLocalization() {\r\n if (this.translateUsed) {\r\n const stringsArray = [\r\n this.translate.instant('BACKEND_LOCALIZATION.QUIT'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_RECEIVED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_CONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.INCOME_TRANSFER_UNCONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.INCOME_TRANSFER_CONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.MINED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.LOCKED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_MINIMIZE'),\r\n this.translate.instant('BACKEND_LOCALIZATION.RESTORE'),\r\n this.translate.instant('BACKEND_LOCALIZATION.TRAY_MENU_SHOW'),\r\n this.translate.instant('BACKEND_LOCALIZATION.TRAY_MENU_MINIMIZE')\r\n ];\r\n this.backend.setBackendLocalization(stringsArray, this.variablesService.settings.language);\r\n } else {\r\n console.warn('wait translate use');\r\n setTimeout(() => {\r\n this.setBackendLocalization();\r\n }, 10000);\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.variablesService.allContextMenu = this.allContextMenu;\r\n this.variablesService.onlyCopyContextMenu = this.onlyCopyContextMenu;\r\n\r\n this.backend.initService().subscribe(initMessage => {\r\n console.log('Init message: ', initMessage);\r\n\r\n this.backend.webkitLaunchedScript();\r\n\r\n this.backend.start_backend(false, '127.0.0.1', 11512, (st2, dd2) => {\r\n console.log(st2, dd2);\r\n });\r\n\r\n this.backend.eventSubscribe('quit_requested', () => {\r\n if (!this.onQuitRequest) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n this.needOpenWallets = [];\r\n this.variablesService.daemon_state = 5;\r\n const saveFunction = () => {\r\n this.backend.storeAppData(() => {\r\n const recursionCloseWallets = () => {\r\n if (this.variablesService.wallets.length) {\r\n const lastIndex = this.variablesService.wallets.length - 1;\r\n this.backend.closeWallet(this.variablesService.wallets[lastIndex].wallet_id, () => {\r\n this.variablesService.wallets.splice(lastIndex, 1);\r\n recursionCloseWallets();\r\n });\r\n } else {\r\n this.backend.quitRequest();\r\n }\r\n };\r\n recursionCloseWallets();\r\n });\r\n };\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData(() => {\r\n saveFunction();\r\n });\r\n } else {\r\n saveFunction();\r\n }\r\n }\r\n this.onQuitRequest = true;\r\n });\r\n\r\n this.backend.eventSubscribe('update_wallet_status', (data) => {\r\n console.log('----------------- update_wallet_status -----------------');\r\n console.log(data);\r\n\r\n const wallet_state = data.wallet_state;\r\n const is_mining = data.is_mining;\r\n const wallet = this.variablesService.getWallet(data.wallet_id);\r\n\r\n // 1-synch, 2-ready, 3 - error\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n wallet.loaded = false;\r\n wallet.staking = is_mining;\r\n if (wallet_state === 2) { // ready\r\n wallet.loaded = true;\r\n }\r\n if (wallet_state === 3) { // error\r\n // wallet.error = true;\r\n }\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n wallet.mined_total = data.minied_total;\r\n wallet.alias_available = data.is_alias_operations_available;\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('wallet_sync_progress', (data) => {\r\n console.log('----------------- wallet_sync_progress -----------------');\r\n console.log(data);\r\n\r\n const wallet = this.variablesService.getWallet(data.wallet_id);\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n wallet.progress = (data.progress < 0) ? 0 : ((data.progress > 100) ? 100 : data.progress);\r\n if (wallet.progress === 0) {\r\n wallet.loaded = false;\r\n } else if (wallet.progress === 100) {\r\n wallet.loaded = true;\r\n }\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('update_daemon_state', (data) => {\r\n console.log('----------------- update_daemon_state -----------------');\r\n console.log('DAEMON:' + data.daemon_network_state);\r\n console.log(data);\r\n // this.variablesService.exp_med_ts = data['expiration_median_timestamp'] + 600 + 1;\r\n this.variablesService.setExpMedTs(data['expiration_median_timestamp'] + 600 + 1);\r\n this.variablesService.net_time_delta_median = data.net_time_delta_median;\r\n this.variablesService.last_build_available = data.last_build_available;\r\n this.variablesService.last_build_displaymode = data.last_build_displaymode;\r\n this.variablesService.setHeightApp(data.height);\r\n this.variablesService.setHeightMax(data.max_net_seen_height);\r\n this.backend.getContactAlias();\r\n this.ngZone.run(() => {\r\n this.variablesService.daemon_state = data['daemon_network_state'];\r\n if (data['daemon_network_state'] === 1) {\r\n const max = data['max_net_seen_height'] - data['synchronization_start_height'];\r\n const current = data.height - data['synchronization_start_height'];\r\n const return_val = Math.floor((current * 100 / max) * 100) / 100;\r\n if (max === 0 || return_val < 0) {\r\n this.variablesService.sync.progress_value = 0;\r\n this.variablesService.sync.progress_value_text = '0.00';\r\n } else if (return_val >= 100) {\r\n this.variablesService.sync.progress_value = 100;\r\n this.variablesService.sync.progress_value_text = '99.99';\r\n } else {\r\n this.variablesService.sync.progress_value = return_val;\r\n this.variablesService.sync.progress_value_text = return_val.toFixed(2);\r\n }\r\n }\r\n });\r\n if (!this.firstOnlineState && data['daemon_network_state'] === 2) {\r\n this.getAliases();\r\n this.backend.getContactAlias();\r\n this.backend.getDefaultFee((status_fee, data_fee) => {\r\n this.variablesService.default_fee_big = new BigNumber(data_fee);\r\n this.variablesService.default_fee = this.intToMoneyPipe.transform(data_fee);\r\n });\r\n this.firstOnlineState = true;\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('money_transfer', (data) => {\r\n console.log('----------------- money_transfer -----------------');\r\n console.log(data);\r\n\r\n if (!data.ti) {\r\n return;\r\n }\r\n\r\n const wallet_id = data.wallet_id;\r\n const tr_info = data.ti;\r\n\r\n const wallet = this.variablesService.getWallet(wallet_id);\r\n\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n\r\n if (!wallet.loaded) {\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n } else {\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n }\r\n\r\n if (tr_info.tx_type === 6) {\r\n this.variablesService.setRefreshStacking(wallet_id);\r\n }\r\n\r\n let tr_exists = wallet.excluded_history.some(elem => elem.tx_hash === tr_info.tx_hash);\r\n tr_exists = (!tr_exists) ? wallet.history.some(elem => elem.tx_hash === tr_info.tx_hash) : tr_exists;\r\n\r\n wallet.prepareHistory([tr_info]);\r\n\r\n if (tr_info.hasOwnProperty('contract')) {\r\n const exp_med_ts = this.variablesService.exp_med_ts;\r\n const height_app = this.variablesService.height_app;\r\n\r\n const contract = tr_info.contract[0];\r\n\r\n if (tr_exists) {\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === contract.contract_id && wallet.contracts[i].is_a === contract.is_a) {\r\n wallet.contracts[i].cancel_expiration_time = contract.cancel_expiration_time;\r\n wallet.contracts[i].expiration_time = contract.expiration_time;\r\n wallet.contracts[i].height = contract.height;\r\n wallet.contracts[i].timestamp = contract.timestamp;\r\n break;\r\n }\r\n }\r\n // $rootScope.getContractsRecount();\r\n return;\r\n }\r\n\r\n if (contract.state === 1 && contract.expiration_time < exp_med_ts) {\r\n contract.state = 110;\r\n } else if (contract.state === 5 && contract.cancel_expiration_time < exp_med_ts) {\r\n contract.state = 130;\r\n } else if (contract.state === 1) {\r\n const searchResult2 = this.variablesService.settings.notViewedContracts.find(elem => elem.state === 110 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult2) {\r\n if (searchResult2.time === contract.expiration_time) {\r\n contract.state = 110;\r\n } else {\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 2 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 201;\r\n } else if (contract.state === 2) {\r\n const searchResult3 = this.variablesService.settings.viewedContracts.some(elem => elem.state === 120 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult3) {\r\n contract.state = 120;\r\n }\r\n } else if (contract.state === 5) {\r\n const searchResult4 = this.variablesService.settings.notViewedContracts.find(elem => elem.state === 130 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult4) {\r\n if (searchResult4.time === contract.cancel_expiration_time) {\r\n contract.state = 130;\r\n } else {\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 6 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 601;\r\n }\r\n\r\n const searchResult = this.variablesService.settings.viewedContracts.some(elem => elem.state === contract.state && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n contract.is_new = !searchResult;\r\n\r\n let findContract = false;\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === contract.contract_id && wallet.contracts[i].is_a === contract.is_a) {\r\n for (const prop in contract) {\r\n if (contract.hasOwnProperty(prop)) {\r\n wallet.contracts[i][prop] = contract[prop];\r\n }\r\n }\r\n findContract = true;\r\n break;\r\n }\r\n }\r\n if (findContract === false) {\r\n wallet.contracts.push(contract);\r\n }\r\n wallet.recountNewContracts();\r\n }\r\n\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('money_transfer_cancel', (data) => {\r\n console.log('----------------- money_transfer_cancel -----------------');\r\n console.log(data);\r\n\r\n if (!data.ti) {\r\n return;\r\n }\r\n\r\n const wallet_id = data.wallet_id;\r\n const tr_info = data.ti;\r\n const wallet = this.variablesService.getWallet(wallet_id);\r\n\r\n if (wallet) {\r\n if (tr_info.hasOwnProperty('contract')) {\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === tr_info.contract[0].contract_id && wallet.contracts[i].is_a === tr_info.contract[0].is_a) {\r\n if (wallet.contracts[i].state === 1 || wallet.contracts[i].state === 110) {\r\n wallet.contracts[i].is_new = true;\r\n wallet.contracts[i].state = 140;\r\n wallet.recountNewContracts();\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n\r\n wallet.removeFromHistory(tr_info.tx_hash);\r\n\r\n let error_tr = '';\r\n switch (tr_info.tx_type) {\r\n case 0:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_NORMAL') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NORMAL_TO') + ' ' + this.intToMoneyPipe.transform(tr_info.amount) + ' ' +\r\n this.translate.instant('ERRORS.TX_TYPE_NORMAL_END');\r\n break;\r\n case 1:\r\n // this.translate.instant('ERRORS.TX_TYPE_PUSH_OFFER');\r\n break;\r\n case 2:\r\n // this.translate.instant('ERRORS.TX_TYPE_UPDATE_OFFER');\r\n break;\r\n case 3:\r\n // this.translate.instant('ERRORS.TX_TYPE_CANCEL_OFFER');\r\n break;\r\n case 4:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS_END');\r\n break;\r\n case 5:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_UPDATE_ALIAS') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS_END');\r\n break;\r\n case 6:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_COIN_BASE');\r\n break;\r\n }\r\n if (error_tr) {\r\n this.modalService.prepareModal('error', error_tr);\r\n }\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('on_core_event', (data) => {\r\n console.log('----------------- on_core_event -----------------');\r\n console.log(data);\r\n\r\n data = JSON.parse(data);\r\n\r\n if (data.events != null) {\r\n for (let i = 0, length = data.events.length; i < length; i++) {\r\n\r\n switch (data.events[i].method) {\r\n case 'CORE_EVENT_BLOCK_ADDED':\r\n break;\r\n case 'CORE_EVENT_ADD_ALIAS':\r\n if (this.variablesService.aliasesChecked[data.events[i].details.address] != null) {\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['name'] = '@' + data.events[i].details.alias;\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['address'] = data.events[i].details.address;\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['comment'] = data.events[i].details.comment;\r\n }\r\n if (this.variablesService.enableAliasSearch) {\r\n const newAlias = {\r\n name: '@' + data.events[i].details.alias,\r\n address: data.events[i].details.address,\r\n comment: data.events[i].details.comment\r\n };\r\n this.variablesService.aliases = this.variablesService.aliases.concat(newAlias);\r\n this.variablesService.changeAliases();\r\n }\r\n break;\r\n case 'CORE_EVENT_UPDATE_ALIAS':\r\n for (const address in this.variablesService.aliasesChecked) {\r\n if (this.variablesService.aliasesChecked.hasOwnProperty(address)) {\r\n if (this.variablesService.aliasesChecked[address].name === '@' + data.events[i].details.alias) {\r\n if (this.variablesService.aliasesChecked[address].address !== data.events[i].details.details.address) {\r\n delete this.variablesService.aliasesChecked[address]['name'];\r\n delete this.variablesService.aliasesChecked[address]['address'];\r\n delete this.variablesService.aliasesChecked[address]['comment'];\r\n } else {\r\n this.variablesService.aliasesChecked[address].comment = data.events[i].details.details.comment;\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n if (this.variablesService.aliasesChecked[data.events[i].details.details.address] != null) {\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['name'] = '@' + data.events[i].details.alias;\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['address'] = data.events[i].details.details.address;\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['comment'] = data.events[i].details.details.comment;\r\n }\r\n if (this.variablesService.enableAliasSearch) {\r\n const CurrentAlias = this.variablesService.aliases.find((element) => element.name === '@' + data.events[i].details.alias);\r\n if (CurrentAlias) {\r\n CurrentAlias.address = data.events[i].details.details.address;\r\n CurrentAlias.comment = data.events[i].details.details.comment;\r\n }\r\n }\r\n this.variablesService.changeAliases();\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.intervalUpdateContractsState = setInterval(() => {\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallet.contracts.forEach((contract) => {\r\n if (contract.state === 201 && contract.height !== 0 && (this.variablesService.height_app - contract.height) >= 10) {\r\n contract.state = 2;\r\n contract.is_new = true;\r\n console.warn('need check state in contracts');\r\n } else if (contract.state === 601 && contract.height !== 0 && (this.variablesService.height_app - contract.height) >= 10) {\r\n contract.state = 6;\r\n contract.is_new = true;\r\n }\r\n });\r\n });\r\n }, 30000);\r\n\r\n this.expMedTsEvent = this.variablesService.getExpMedTsEvent.subscribe((newTimestamp: number) => {\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallet.contracts.forEach((contract) => {\r\n if (contract.state === 1 && contract.expiration_time <= newTimestamp) {\r\n contract.state = 110;\r\n contract.is_new = true;\r\n wallet.recountNewContracts();\r\n } else if (contract.state === 5 && contract.cancel_expiration_time <= newTimestamp) {\r\n contract.state = 130;\r\n contract.is_new = true;\r\n wallet.recountNewContracts();\r\n }\r\n });\r\n });\r\n });\r\n\r\n\r\n this.backend.getAppData((status, data) => {\r\n if (data && Object.keys(data).length > 0) {\r\n for (const key in data) {\r\n if (data.hasOwnProperty(key) && this.variablesService.settings.hasOwnProperty(key)) {\r\n this.variablesService.settings[key] = data[key];\r\n }\r\n }\r\n if (this.variablesService.settings.hasOwnProperty('theme') && ['dark', 'white', 'gray'].indexOf(this.variablesService.settings.theme) !== -1) {\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.settings.theme);\r\n } else {\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.defaultTheme);\r\n }\r\n if (this.variablesService.settings.hasOwnProperty('scale') && [7.5, 10, 12.5, 15].indexOf(this.variablesService.settings.scale) !== -1) {\r\n this.renderer.setStyle(document.documentElement, 'font-size', this.variablesService.settings.scale + 'px');\r\n }\r\n } else {\r\n this.variablesService.settings.theme = this.variablesService.defaultTheme;\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.settings.theme);\r\n }\r\n this.translate.use(this.variablesService.settings.language);\r\n this.setBackendLocalization();\r\n\r\n this.backend.setLogLevel(this.variablesService.settings.appLog);\r\n\r\n if (this.router.url !== '/login') {\r\n this.backend.haveSecureAppData((statusPass) => {\r\n if (statusPass) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n } else {\r\n if (Object.keys(data).length !== 0) {\r\n this.needOpenWallets = JSON.parse(JSON.stringify(this.variablesService.settings.wallets));\r\n this.ngZone.run(() => {\r\n this.variablesService.appLogin = true;\r\n this.router.navigate(['/']);\r\n });\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'reg'}});\r\n });\r\n }\r\n }\r\n });\r\n }\r\n });\r\n }, error => {\r\n console.log(error);\r\n });\r\n this.getMoneyEquivalent();\r\n }\r\n\r\n getMoneyEquivalent() {\r\n this.http.get('https://api.coingecko.com/api/v3/ping').subscribe(\r\n () => {\r\n this.http.get('https://api.coingecko.com/api/v3/simple/price?ids=zano&vs_currencies=usd').subscribe(\r\n data => {\r\n this.variablesService.moneyEquivalent = data['zano']['usd'];\r\n },\r\n error => {\r\n console.warn('api.coingecko.com price error: ', error);\r\n }\r\n );\r\n },\r\n error => {\r\n console.warn('api.coingecko.com error: ', error);\r\n setTimeout(() => {\r\n this.getMoneyEquivalent();\r\n }, 60000);\r\n }\r\n )\r\n }\r\n\r\n getAliases() {\r\n this.backend.getAllAliases((status, data, error) => {\r\n\r\n console.warn(error);\r\n\r\n if (error === 'CORE_BUSY') {\r\n window.setTimeout(() => {\r\n this.getAliases();\r\n }, 10000);\r\n } else if (error === 'OVERFLOW') {\r\n this.variablesService.aliases = [];\r\n this.variablesService.enableAliasSearch = false;\r\n this.variablesService.wallets.forEach(wallet => {\r\n wallet.alias = this.backend.getWalletAlias(wallet.address);\r\n });\r\n } else {\r\n this.variablesService.enableAliasSearch = true;\r\n if (data.aliases && data.aliases.length) {\r\n this.variablesService.aliases = [];\r\n data.aliases.forEach(alias => {\r\n const newAlias = {\r\n name: '@' + alias.alias,\r\n address: alias.address,\r\n comment: alias.comment\r\n };\r\n this.variablesService.aliases.push(newAlias);\r\n });\r\n this.variablesService.wallets.forEach(wallet => {\r\n wallet.alias = this.backend.getWalletAlias(wallet.address);\r\n });\r\n this.variablesService.aliases = this.variablesService.aliases.sort((a, b) => {\r\n if (a.name.length > b.name.length) {\r\n return 1;\r\n }\r\n if (a.name.length < b.name.length) {\r\n return -1;\r\n }\r\n if (a.name > b.name) {\r\n return 1;\r\n }\r\n if (a.name < b.name) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n this.variablesService.changeAliases();\r\n }\r\n }\r\n });\r\n }\r\n\r\n contextMenuCopy(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n const start = (target['contextSelectionStart']) ? 'contextSelectionStart' : 'selectionStart';\r\n const end = (target['contextSelectionEnd']) ? 'contextSelectionEnd' : 'selectionEnd';\r\n const canUseSelection = ((target[start]) || (target[start] === '0'));\r\n const SelectedText = (canUseSelection) ? target['value'].substring(target[start], target[end]) : target['value'];\r\n this.backend.setClipboard(String(SelectedText));\r\n }\r\n }\r\n\r\n contextMenuOnlyCopy(text) {\r\n if (text) {\r\n this.backend.setClipboard(String(text));\r\n }\r\n }\r\n\r\n contextMenuPaste(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n this.backend.getClipboard((status, clipboard) => {\r\n clipboard = String(clipboard);\r\n if (typeof clipboard !== 'string' || clipboard.length) {\r\n const start = (target['contextSelectionStart']) ? 'contextSelectionStart' : 'selectionStart';\r\n const end = (target['contextSelectionEnd']) ? 'contextSelectionEnd' : 'selectionEnd';\r\n const _pre = target['value'].substring(0, target[start]);\r\n const _aft = target['value'].substring(target[end], target['value'].length);\r\n let text = _pre + clipboard + _aft;\r\n const cursorPosition = (_pre + clipboard).length;\r\n if (target['maxLength'] && parseInt(target['maxLength'], 10) > 0) {\r\n text = text.substr(0, parseInt(target['maxLength'], 10));\r\n }\r\n target['value'] = text;\r\n target.setSelectionRange(cursorPosition, cursorPosition);\r\n target.dispatchEvent(new Event('input'));\r\n target['focus']();\r\n }\r\n });\r\n }\r\n }\r\n\r\n contextMenuSelect(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n target['focus']();\r\n setTimeout(() => {\r\n target['select']();\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.intervalUpdateContractsState) {\r\n clearInterval(this.intervalUpdateContractsState);\r\n }\r\n this.expMedTsEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { NgModule } from '@angular/core';\r\n\r\nimport { AppRoutingModule } from './app-routing.module';\r\n\r\nimport { AppComponent } from './app.component';\r\nimport { LoginComponent } from './login/login.component';\r\nimport { SettingsComponent } from './settings/settings.component';\r\nimport { SidebarComponent } from './sidebar/sidebar.component';\r\nimport { MainComponent } from './main/main.component';\r\nimport { CreateWalletComponent } from './create-wallet/create-wallet.component';\r\nimport { OpenWalletComponent } from './open-wallet/open-wallet.component';\r\nimport { OpenWalletModalComponent } from './open-wallet-modal/open-wallet-modal.component';\r\nimport { RestoreWalletComponent } from './restore-wallet/restore-wallet.component';\r\nimport { SeedPhraseComponent } from './seed-phrase/seed-phrase.component';\r\nimport { WalletDetailsComponent } from './wallet-details/wallet-details.component';\r\nimport { AssignAliasComponent } from './assign-alias/assign-alias.component';\r\nimport { EditAliasComponent } from './edit-alias/edit-alias.component';\r\nimport { TransferAliasComponent } from './transfer-alias/transfer-alias.component';\r\nimport { WalletComponent } from './wallet/wallet.component';\r\nimport { SendComponent } from './send/send.component';\r\nimport { ReceiveComponent } from './receive/receive.component';\r\nimport { HistoryComponent } from './history/history.component';\r\nimport { ContractsComponent } from './contracts/contracts.component';\r\nimport { PurchaseComponent } from './purchase/purchase.component';\r\nimport { MessagesComponent } from './messages/messages.component';\r\nimport { TypingMessageComponent } from './typing-message/typing-message.component';\r\nimport { StakingComponent } from './staking/staking.component';\r\n\r\nimport { HttpClient, HttpClientModule } from '@angular/common/http';\r\nimport { TranslateLoader, TranslateModule } from '@ngx-translate/core';\r\nimport { TranslateHttpLoader } from '@ngx-translate/http-loader';\r\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { NgSelectModule } from '@ng-select/ng-select';\r\n\r\nimport { BackendService } from './_helpers/services/backend.service';\r\nimport { ModalService } from './_helpers/services/modal.service';\r\nimport { MoneyToIntPipe } from './_helpers/pipes/money-to-int.pipe';\r\nimport { IntToMoneyPipe } from './_helpers/pipes/int-to-money.pipe';\r\nimport { HistoryTypeMessagesPipe } from './_helpers/pipes/history-type-messages.pipe';\r\nimport { ContractStatusMessagesPipe } from './_helpers/pipes/contract-status-messages.pipe';\r\nimport { ContractTimeLeftPipe } from './_helpers/pipes/contract-time-left.pipe';\r\nimport { SafeHTMLPipe } from './_helpers/pipes/safe-html.pipe';\r\nimport { TooltipDirective } from './_helpers/directives/tooltip.directive';\r\nimport { InputValidateDirective } from './_helpers/directives/input-validate/input-validate.directive';\r\nimport { StakingSwitchComponent } from './_helpers/directives/staking-switch/staking-switch.component';\r\nimport { ModalContainerComponent } from './_helpers/directives/modal-container/modal-container.component';\r\nimport { TransactionDetailsComponent } from './_helpers/directives/transaction-details/transaction-details.component';\r\nimport { ContextMenuModule } from 'ngx-contextmenu';\r\nimport { ChartModule, HIGHCHARTS_MODULES } from 'angular-highcharts';\r\nimport * as highcharts from 'highcharts';\r\nimport exporting from 'highcharts/modules/exporting.src';\r\nimport { ProgressContainerComponent } from './_helpers/directives/progress-container/progress-container.component';\r\nimport { InputDisableSelectionDirective } from './_helpers/directives/input-disable-selection/input-disable-selection.directive';\r\nimport { SendModalComponent } from './send-modal/send-modal.component';\r\nimport { ContactsComponent } from './contacts/contacts.component';\r\nimport { AddContactsComponent } from './add-contacts/add-contacts.component';\r\nimport { ContactSendComponent } from './contact-send/contact-send.component';\r\nimport { ExportImportComponent } from './export-import/export-import.component';\r\nimport { ConfirmModalComponent } from './_helpers/directives/confirm-modal/confirm-modal.component';\r\n\r\nexport function HttpLoaderFactory(httpClient: HttpClient) {\r\n return new TranslateHttpLoader(httpClient, './assets/i18n/', '.json');\r\n}\r\n\r\nimport { PapaParseModule } from 'ngx-papaparse';\r\n\r\n// import * as more from 'highcharts/highcharts-more.src';\r\n// import * as exporting from 'highcharts/modules/exporting.src';\r\n// import * as highstock from 'highcharts/modules/stock.src';\r\n\r\nexport function highchartsFactory() {\r\n // Default options.\r\n highcharts.setOptions({\r\n time: {\r\n useUTC: false\r\n }\r\n });\r\n\r\n return [exporting];\r\n}\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n LoginComponent,\r\n SettingsComponent,\r\n SidebarComponent,\r\n MainComponent,\r\n CreateWalletComponent,\r\n OpenWalletComponent,\r\n OpenWalletModalComponent,\r\n RestoreWalletComponent,\r\n SeedPhraseComponent,\r\n WalletDetailsComponent,\r\n AssignAliasComponent,\r\n EditAliasComponent,\r\n TransferAliasComponent,\r\n WalletComponent,\r\n SendComponent,\r\n ReceiveComponent,\r\n HistoryComponent,\r\n ContractsComponent,\r\n PurchaseComponent,\r\n MessagesComponent,\r\n StakingComponent,\r\n TypingMessageComponent,\r\n MoneyToIntPipe,\r\n IntToMoneyPipe,\r\n StakingSwitchComponent,\r\n HistoryTypeMessagesPipe,\r\n ContractStatusMessagesPipe,\r\n ContractTimeLeftPipe,\r\n TooltipDirective,\r\n InputValidateDirective,\r\n ModalContainerComponent,\r\n TransactionDetailsComponent,\r\n ProgressContainerComponent,\r\n InputDisableSelectionDirective,\r\n SendModalComponent,\r\n ContactsComponent,\r\n AddContactsComponent,\r\n ContactSendComponent,\r\n ExportImportComponent,\r\n SafeHTMLPipe,\r\n ConfirmModalComponent\r\n ],\r\n imports: [\r\n BrowserModule,\r\n AppRoutingModule,\r\n HttpClientModule,\r\n TranslateModule.forRoot({\r\n loader: {\r\n provide: TranslateLoader,\r\n useFactory: HttpLoaderFactory,\r\n deps: [HttpClient]\r\n }\r\n }),\r\n FormsModule,\r\n ReactiveFormsModule,\r\n NgSelectModule,\r\n ChartModule,\r\n PapaParseModule,\r\n ContextMenuModule.forRoot()\r\n ],\r\n providers: [\r\n BackendService,\r\n ModalService,\r\n MoneyToIntPipe,\r\n IntToMoneyPipe,\r\n { provide: HIGHCHARTS_MODULES, useFactory: highchartsFactory }\r\n // {provide: HIGHCHARTS_MODULES, useFactory: () => [ highstock, more, exporting ] }\r\n ],\r\n entryComponents: [\r\n ModalContainerComponent,\r\n SendModalComponent,\r\n ConfirmModalComponent\r\n ],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.ASSIGN_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
6 && assignForm.get('name').value.length <= 25\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_WRONG' | translate }}\\r\\n
\\r\\n
25\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_EXISTS' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"ASSIGN_ALIAS.COST\\\" | translate : {value: alias.price | intToMoney, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n\\r\\n\"","module.exports = \".form-assign {\\n margin: 2.4rem 0; }\\n .form-assign .alias-name {\\n width: 50%; }\\n .form-assign .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-assign .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-assign .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n .assign-alias-tooltip {\\n font-size: 1.3rem;\\n line-height: 2rem;\\n padding: 1rem 1.5rem;\\n max-width: 46rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYXNzaWduLWFsaWFzL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGFzc2lnbi1hbGlhc1xcYXNzaWduLWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQTtFQUtsQjtFQUNFLGlCQUFpQjtFQUNqQixpQkFBaUI7RUFDakIsb0JBQW9CO0VBQ3BCLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvYXNzaWduLWFsaWFzL2Fzc2lnbi1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWFzc2lnbiB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuXHJcbiAgLmFsaWFzLW5hbWUge1xyXG4gICAgd2lkdGg6IDUwJTtcclxuICB9XHJcblxyXG4gIC5hbGlhcy1jb3N0IHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbWFyZ2luLXRvcDogMnJlbTtcclxuICB9XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuICAgICAgd2lkdGg6IDE1cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmFzc2lnbi1hbGlhcy10b29sdGlwIHtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuICBsaW5lLWhlaWdodDogMnJlbTtcclxuICBwYWRkaW5nOiAxcmVtIDEuNXJlbTtcclxuICBtYXgtd2lkdGg6IDQ2cmVtO1xyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {MoneyToIntPipe} from '../_helpers/pipes/money-to-int.pipe';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport BigNumber from 'bignumber.js';\r\nimport {Subscription} from 'rxjs';\r\n\r\n@Component({\r\n selector: 'app-assign-alias',\r\n templateUrl: './assign-alias.component.html',\r\n styleUrls: ['./assign-alias.component.scss']\r\n})\r\nexport class AssignAliasComponent implements OnInit, OnDestroy {\r\n\r\n wallet: Wallet;\r\n assignForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, Validators.pattern(/^@?[a-z0-9\\.\\-]{6,25}$/)]),\r\n comment: new FormControl('', [(g: FormControl) => {\r\n if (g.value > this.variablesService.maxCommentLength) {\r\n return {'maxLength': true};\r\n } else {\r\n return null;\r\n }\r\n }])\r\n });\r\n assignFormSubscription: Subscription;\r\n alias = {\r\n name: '',\r\n fee: this.variablesService.default_fee,\r\n price: new BigNumber(0),\r\n reward: '0',\r\n rewardOriginal: '0',\r\n comment: '',\r\n exists: false\r\n };\r\n canRegister = false;\r\n notEnoughMoney = false;\r\n\r\n constructor(\r\n private ngZone: NgZone,\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private moneyToInt: MoneyToIntPipe,\r\n private intToMoney: IntToMoneyPipe\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n this.assignFormSubscription = this.assignForm.get('name').valueChanges.subscribe(value => {\r\n this.canRegister = false;\r\n this.alias.exists = false;\r\n const newName = value.toLowerCase().replace('@', '');\r\n if (!(this.assignForm.controls['name'].errors && this.assignForm.controls['name'].errors.hasOwnProperty('pattern')) && newName.length >= 6 && newName.length <= 25) {\r\n this.backend.getAliasByName(newName, status => {\r\n this.ngZone.run(() => {\r\n this.alias.exists = status;\r\n });\r\n if (!status) {\r\n this.alias.price = new BigNumber(0);\r\n this.backend.getAliasCoast(newName, (statusPrice, dataPrice) => {\r\n this.ngZone.run(() => {\r\n if (statusPrice) {\r\n this.alias.price = BigNumber.sum(dataPrice['coast'], this.variablesService.default_fee_big);\r\n }\r\n this.notEnoughMoney = this.alias.price.isGreaterThan(this.wallet.unlocked_balance);\r\n this.alias.reward = this.intToMoney.transform(this.alias.price, false);\r\n this.alias.rewardOriginal = this.intToMoney.transform(dataPrice['coast'], false);\r\n this.canRegister = !this.notEnoughMoney;\r\n });\r\n });\r\n } else {\r\n this.notEnoughMoney = false;\r\n this.alias.reward = '0';\r\n this.alias.rewardOriginal = '0';\r\n }\r\n });\r\n } else {\r\n this.notEnoughMoney = false;\r\n this.alias.reward = '0';\r\n this.alias.rewardOriginal = '0';\r\n }\r\n this.alias.name = newName;\r\n });\r\n }\r\n\r\n assignAlias() {\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n if (alias.hasOwnProperty('name')) {\r\n this.modalService.prepareModal('info', 'ASSIGN_ALIAS.ONE_ALIAS');\r\n } else {\r\n this.alias.comment = this.assignForm.get('comment').value;\r\n this.backend.registerAlias(this.wallet.wallet_id, this.alias.name, this.wallet.address, this.alias.fee, this.alias.comment, this.alias.rewardOriginal, (status, data) => {\r\n if (status) {\r\n this.wallet.wakeAlias = true;\r\n this.modalService.prepareModal('info', 'ASSIGN_ALIAS.REQUEST_ADD_REG');\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.assignFormSubscription.unsubscribe();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{\\r\\n 'CONTACTS.TITLE' | translate\\r\\n }}\\r\\n {{ 'CONTACTS.SEND' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\"","module.exports = \".wallets-selection {\\n display: flex;\\n align-items: center;\\n margin-top: 2rem; }\\n .wallets-selection .input-block {\\n width: 18rem; }\\n .wallets-selection button {\\n padding: 2rem;\\n background: transparent;\\n border: none;\\n outline: none; }\\n .input-block {\\n width: 44rem; }\\n .input-block input {\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n .blue-button {\\n margin-top: 2.5rem;\\n width: 100%;\\n max-width: 18rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udGFjdC1zZW5kL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGNvbnRhY3Qtc2VuZFxcY29udGFjdC1zZW5kLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQixnQkFBZ0IsRUFBQTtFQUhsQjtJQU1JLFlBQVksRUFBQTtFQU5oQjtJQVVJLGFBQWE7SUFDYix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGFBQWEsRUFBQTtFQUlqQjtFQUNFLFlBQVksRUFBQTtFQURkO0lBSUksZ0JBQWdCO0lBQ2hCLHVCQUF1QixFQUFBO0VBSTNCO0VBQ0Usa0JBQWtCO0VBQ2xCLFdBQVc7RUFDWCxnQkFBZ0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2NvbnRhY3Qtc2VuZC9jb250YWN0LXNlbmQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIud2FsbGV0cy1zZWxlY3Rpb24ge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBtYXJnaW4tdG9wOiAycmVtO1xyXG4gIFxyXG4gIC5pbnB1dC1ibG9jayB7XHJcbiAgICB3aWR0aDogMThyZW07XHJcbiAgfVxyXG5cclxuICBidXR0b24ge1xyXG4gICAgcGFkZGluZzogMnJlbTtcclxuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgb3V0bGluZTogbm9uZTtcclxuICB9XHJcbn1cclxuXHJcbi5pbnB1dC1ibG9jayB7XHJcbiAgd2lkdGg6IDQ0cmVtO1xyXG5cclxuICBpbnB1dCB7XHJcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgfVxyXG59XHJcblxyXG4uYmx1ZS1idXR0b24ge1xyXG4gIG1hcmdpbi10b3A6IDIuNXJlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBtYXgtd2lkdGg6IDE4cmVtO1xyXG59XHJcblxyXG5cclxuIl19 */\"","import { Component, OnInit, OnDestroy } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n\r\n@Component({\r\n selector: 'app-contact-send',\r\n templateUrl: './contact-send.component.html',\r\n styleUrls: ['./contact-send.component.scss']\r\n})\r\nexport class ContactSendComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n address;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private route: ActivatedRoute\r\n ) { }\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.address) {\r\n this.address = params.address;\r\n }\r\n });\r\n }\r\n\r\n goToWallet(id) {\r\n this.variablesService.setCurrentWallet(id);\r\n this.variablesService.currentWallet.send_data['address'] = this.address;\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'CONTACTS.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n

\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'CONTACTS.TABLE.NAME' | translate }}{{ 'CONTACTS.TABLE.ALIAS' | translate }}{{ 'CONTACTS.TABLE.ADDRESS' | translate }}{{ 'CONTACTS.TABLE.NOTES' | translate }}
\\r\\n {{ contact.name }}\\r\\n \\r\\n \\r\\n {{ contact.alias }}\\r\\n \\r\\n \\r\\n {{ contact.address }}\\r\\n \\r\\n {{ contact.notes }}\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n {{ 'CONTACTS.BUTTON.SEND' | translate }}\\r\\n \\r\\n \\r\\n \\r\\n {{ 'CONTACTS.BUTTON.EDIT' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n\\r\\n \\r\\n
\\r\\n {{ 'CONTACTS.TABLE.EMPTY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n min-width: 95rem;\\n width: 100%;\\n height: 100%; }\\n\\n.head {\\n justify-content: flex-end; }\\n\\n.contacts-title {\\n font-size: 1.7rem; }\\n\\n.wrap-table {\\n margin: 1rem -3rem; }\\n\\n.wrap-table table tbody tr td {\\n padding: 0 3rem 0 1rem;\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n\\n.wrap-table table tbody tr td:first-child {\\n max-width: 10rem;\\n padding: 0 3rem 0 3rem; }\\n\\n.wrap-table table tbody tr td:nth-child(2) {\\n max-width: 10rem; }\\n\\n.wrap-table table tbody tr td .alias {\\n cursor: pointer; }\\n\\n.wrap-table table tbody tr td .button-wrapper {\\n display: flex; }\\n\\n.wrap-table table tbody tr td .button-wrapper button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n font-weight: 400;\\n line-height: 3rem;\\n outline: none;\\n padding: 0;\\n height: auto;\\n margin-right: 1.8rem; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon {\\n cursor: pointer;\\n margin-right: 0.8rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.edit {\\n -webkit-mask: url('edit.svg') no-repeat center;\\n mask: url('edit.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.transfer {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.delete {\\n -webkit-mask: url('delete.svg') no-repeat center;\\n mask: url('delete.svg') no-repeat center; }\\n\\n.wrap-table .empty-list {\\n margin: 2.5rem 3rem; }\\n\\n.blue-button {\\n width: 100%;\\n max-width: 18rem;\\n margin-top: 3rem; }\\n\\n.footer {\\n position: absolute;\\n bottom: 3rem;\\n font-size: 1.3rem; }\\n\\n.footer .import-btn {\\n display: flex;\\n align-items: center;\\n background-color: transparent;\\n font-size: inherit;\\n font-weight: 400;\\n line-height: 1.3rem;\\n padding: 0;\\n height: auto; }\\n\\n.footer .import-btn .icon {\\n margin-right: 0.7rem;\\n -webkit-mask: url('import-export.svg') no-repeat center;\\n mask: url('import-export.svg') no-repeat center;\\n width: 0.9rem;\\n height: 0.9rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udGFjdHMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcY29udGFjdHNcXGNvbnRhY3RzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVc7RUFDWCxZQUFZLEVBQUE7O0FBR2Q7RUFDRSx5QkFBeUIsRUFBQTs7QUFHM0I7RUFDRSxpQkFBaUIsRUFBQTs7QUFHbkI7RUFDRSxrQkFBa0IsRUFBQTs7QUFEcEI7SUFVVSxzQkFBc0I7SUFDdEIsZ0JBQWdCO0lBQ2hCLHVCQUF1QixFQUFBOztBQVpqQztNQWVZLGdCQUFnQjtNQUNoQixzQkFBc0IsRUFBQTs7QUFoQmxDO01Bb0JZLGdCQUFnQixFQUFBOztBQXBCNUI7TUF3QlksZUFBZSxFQUFBOztBQXhCM0I7TUE0QlksYUFBYSxFQUFBOztBQTVCekI7UUErQmMsYUFBYTtRQUNiLG1CQUFtQjtRQUNuQix1QkFBdUI7UUFDdkIsWUFBWTtRQUNaLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsaUJBQWlCO1FBQ2pCLGFBQWE7UUFDYixVQUFVO1FBQ1YsWUFBWTtRQUNaLG9CQUFvQixFQUFBOztBQXpDbEM7VUE0Q2dCLGVBQWU7VUFDZixvQkFBb0I7VUFDcEIsYUFBYTtVQUNiLGNBQWMsRUFBQTs7QUEvQzlCO1lBa0RrQiw4Q0FBdUQ7b0JBQXZELHNDQUF1RCxFQUFBOztBQWxEekU7WUFzRGtCLDhDQUF1RDtvQkFBdkQsc0NBQXVELEVBQUE7O0FBdER6RTtZQTBEa0IsZ0RBQXlEO29CQUF6RCx3Q0FBeUQsRUFBQTs7QUExRDNFO0lBcUVJLG1CQUFtQixFQUFBOztBQUl2QjtFQUNFLFdBQVc7RUFDWCxnQkFBZ0I7RUFDaEIsZ0JBQWdCLEVBQUE7O0FBSWxCO0VBQ0Usa0JBQWtCO0VBQ2xCLFlBQVk7RUFDWixpQkFBaUIsRUFBQTs7QUFIbkI7SUFNSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDZCQUE2QjtJQUM3QixrQkFBa0I7SUFDbEIsZ0JBQWdCO0lBQ2hCLG1CQUFtQjtJQUNuQixVQUFVO0lBQ1YsWUFBWSxFQUFBOztBQWJoQjtNQWdCTSxvQkFBb0I7TUFDcEIsdURBQWdFO2NBQWhFLCtDQUFnRTtNQUNoRSxhQUFhO01BQ2IsY0FBYyxFQUFBIiwiZmlsZSI6InNyYy9hcHAvY29udGFjdHMvY29udGFjdHMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgbWluLXdpZHRoOiA5NXJlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDEwMCU7XHJcbn1cclxuXHJcbi5oZWFkIHtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xyXG59XHJcblxyXG4uY29udGFjdHMtdGl0bGUge1xyXG4gIGZvbnQtc2l6ZTogMS43cmVtO1xyXG59XHJcblxyXG4ud3JhcC10YWJsZSB7XHJcbiAgbWFyZ2luOiAxcmVtIC0zcmVtO1xyXG5cclxuICB0YWJsZSB7XHJcblxyXG4gICAgdGJvZHl7XHJcblxyXG4gICAgICB0ciB7XHJcblxyXG4gICAgICAgIHRkIHtcclxuICAgICAgICAgIHBhZGRpbmc6IDAgM3JlbSAwIDFyZW07XHJcbiAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcblxyXG4gICAgICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgICAgIG1heC13aWR0aDogMTByZW07XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDAgM3JlbSAwIDNyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJjpudGgtY2hpbGQoMikge1xyXG4gICAgICAgICAgICBtYXgtd2lkdGg6IDEwcmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5hbGlhcyB7XHJcbiAgICAgICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuYnV0dG9uLXdyYXBwZXIge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgYnV0dG9uIHtcclxuICAgICAgICAgICAgICBkaXNwbGF5OiBmbGV4OyAgXHJcbiAgICAgICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgICAgICAgICAgICBib3JkZXI6IG5vbmU7XHJcbiAgICAgICAgICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgICAgICAgICAgICBsaW5lLWhlaWdodDogM3JlbTtcclxuICAgICAgICAgICAgICBvdXRsaW5lOiBub25lO1xyXG4gICAgICAgICAgICAgIHBhZGRpbmc6IDA7XHJcbiAgICAgICAgICAgICAgaGVpZ2h0OiBhdXRvO1xyXG4gICAgICAgICAgICAgIG1hcmdpbi1yaWdodDogMS44cmVtO1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAgICAgLmljb24ge1xyXG4gICAgICAgICAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICAgICAgICAgICAgbWFyZ2luLXJpZ2h0OiAwLjhyZW07XHJcbiAgICAgICAgICAgICAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAxLjdyZW07XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgJi5lZGl0IHtcclxuICAgICAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9lZGl0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAmLnRyYW5zZmVyIHtcclxuICAgICAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZW5kLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgICYuZGVsZXRlIHtcclxuICAgICAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9kZWxldGUuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICBcclxuICAuZW1wdHktbGlzdCB7XHJcbiAgICBtYXJnaW46IDIuNXJlbSAzcmVtO1xyXG4gIH0gIFxyXG59XHJcblxyXG4uYmx1ZS1idXR0b24ge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG4gIG1heC13aWR0aDogMThyZW07XHJcbiAgbWFyZ2luLXRvcDogM3JlbTtcclxufVxyXG5cclxuXHJcbi5mb290ZXIge1xyXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICBib3R0b206IDNyZW07XHJcbiAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgXHJcbiAgLmltcG9ydC1idG4ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGZvbnQtc2l6ZTogaW5oZXJpdDtcclxuICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICBsaW5lLWhlaWdodDogMS4zcmVtO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIGhlaWdodDogYXV0bztcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIG1hcmdpbi1yaWdodDogMC43cmVtO1xyXG4gICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2ltcG9ydC1leHBvcnQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB3aWR0aDogMC45cmVtO1xyXG4gICAgICBoZWlnaHQ6IDAuOXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\n\r\n@Component({\r\n selector: 'app-contacts',\r\n templateUrl: './contacts.component.html',\r\n styleUrls: ['./contacts.component.scss']\r\n})\r\nexport class ContactsComponent implements OnInit {\r\n calculatedWidth = [];\r\n @ViewChild('head') head: ElementRef;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private backend: BackendService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.backend.getContactAlias();\r\n }\r\n\r\n delete(index: number) {\r\n if (this.variablesService.appPass) {\r\n this.variablesService.contacts.splice(index, 1);\r\n this.backend.storeSecureAppData();\r\n }\r\n }\r\n\r\n calculateWidth() {\r\n this.calculatedWidth = [];\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[0].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[1].clientWidth +\r\n this.head.nativeElement.childNodes[2].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[3].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[4].clientWidth\r\n );\r\n }\r\n\r\n // openInBrowser(alias: string) {\r\n // if (alias !== null) {\r\n // this.backend.openUrlInBrowser(\r\n // `explorer.zano.org/aliases/${alias.slice(1)}#modalOpen`\r\n // );\r\n // }\r\n // }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n {{ 'CONTRACTS.EMPTY' | translate }}\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'CONTRACTS.CONTRACTS' | translate }}{{ 'CONTRACTS.DATE' | translate }}{{ 'CONTRACTS.AMOUNT' | translate }}{{ 'CONTRACTS.STATUS' | translate }}{{ 'CONTRACTS.COMMENTS' | translate }}
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.private_detailes.t}}\\r\\n
\\r\\n
\\r\\n
{{item.timestamp * 1000 | date : 'dd-MM-yyyy HH:mm'}}
\\r\\n
\\r\\n
{{item.private_detailes.to_pay | intToMoney}} {{variablesService.defaultCurrency}}
\\r\\n
\\r\\n
\\r\\n {{item.state | contractStatusMessages : item.is_a}}\\r\\n
\\r\\n
\\r\\n
\\r\\n {{item.private_detailes.c}}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.empty-contracts {\\n font-size: 1.5rem; }\\n\\n.wrap-table {\\n margin: -3rem -3rem 0 -3rem;\\n overflow-x: auto; }\\n\\n.wrap-table table tbody tr {\\n cursor: pointer;\\n outline: none !important; }\\n\\n.wrap-table table tbody tr .contract {\\n position: relative;\\n display: flex;\\n align-items: center; }\\n\\n.wrap-table table tbody tr .contract .icon {\\n flex-shrink: 0; }\\n\\n.wrap-table table tbody tr .contract .icon.new, .wrap-table table tbody tr .contract .icon.alert {\\n position: absolute;\\n top: 0; }\\n\\n.wrap-table table tbody tr .contract .icon.new {\\n left: -2.3rem;\\n -webkit-mask: url('new.svg') no-repeat center;\\n mask: url('new.svg') no-repeat center;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr .contract .icon.alert {\\n top: 0.2rem;\\n left: -2.1rem;\\n -webkit-mask: url('alert.svg') no-repeat center;\\n mask: url('alert.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.wrap-table table tbody tr .contract .icon.purchase, .wrap-table table tbody tr .contract .icon.sell {\\n margin-right: 1rem;\\n width: 1.5rem;\\n height: 1.5rem; }\\n\\n.wrap-table table tbody tr .contract .icon.purchase {\\n -webkit-mask: url('purchase.svg') no-repeat center;\\n mask: url('purchase.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .contract .icon.sell {\\n -webkit-mask: url('sell.svg') no-repeat center;\\n mask: url('sell.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .contract span {\\n text-overflow: ellipsis;\\n overflow: hidden; }\\n\\n.wrap-table table tbody tr .status, .wrap-table table tbody tr .comment {\\n display: inline-block;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n max-width: 100%; }\\n\\n.contracts-buttons {\\n display: flex;\\n margin: 3rem 0;\\n width: 50%; }\\n\\n.contracts-buttons button {\\n flex: 0 1 50%;\\n margin-right: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udHJhY3RzL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGNvbnRyYWN0c1xcY29udHJhY3RzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBQ0UsaUJBQWlCLEVBQUE7O0FBR25CO0VBQ0UsMkJBQTJCO0VBQzNCLGdCQUFnQixFQUFBOztBQUZsQjtJQVNRLGVBQWU7SUFDZix3QkFBd0IsRUFBQTs7QUFWaEM7TUFhVSxrQkFBa0I7TUFDbEIsYUFBYTtNQUNiLG1CQUFtQixFQUFBOztBQWY3QjtRQWtCWSxjQUFjLEVBQUE7O0FBbEIxQjtVQXFCYyxrQkFBa0I7VUFDbEIsTUFBTSxFQUFBOztBQXRCcEI7VUEwQmMsYUFBYTtVQUNiLDZDQUFzRDtrQkFBdEQscUNBQXNEO1VBQ3RELGFBQWE7VUFDYixjQUFjLEVBQUE7O0FBN0I1QjtVQWlDYyxXQUFXO1VBQ1gsYUFBYTtVQUNiLCtDQUF3RDtrQkFBeEQsdUNBQXdEO1VBQ3hELGFBQWE7VUFDYixjQUFjLEVBQUE7O0FBckM1QjtVQXlDYyxrQkFBa0I7VUFDbEIsYUFBYTtVQUNiLGNBQWMsRUFBQTs7QUEzQzVCO1VBK0NjLGtEQUEyRDtrQkFBM0QsMENBQTJELEVBQUE7O0FBL0N6RTtVQW1EYyw4Q0FBdUQ7a0JBQXZELHNDQUF1RCxFQUFBOztBQW5EckU7UUF3RFksdUJBQXVCO1FBQ3ZCLGdCQUFnQixFQUFBOztBQXpENUI7TUE4RFUscUJBQXFCO01BQ3JCLHVCQUF1QjtNQUN2QixnQkFBZ0I7TUFDaEIsZUFBZSxFQUFBOztBQU96QjtFQUNFLGFBQWE7RUFDYixjQUFjO0VBQ2QsVUFBVSxFQUFBOztBQUhaO0lBTUksYUFBYTtJQUNiLG9CQUFvQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvY29udHJhY3RzL2NvbnRyYWN0cy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmVtcHR5LWNvbnRyYWN0cyB7XHJcbiAgZm9udC1zaXplOiAxLjVyZW07XHJcbn1cclxuXHJcbi53cmFwLXRhYmxlIHtcclxuICBtYXJnaW46IC0zcmVtIC0zcmVtIDAgLTNyZW07XHJcbiAgb3ZlcmZsb3cteDogYXV0bztcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgICAgb3V0bGluZTogbm9uZSAhaW1wb3J0YW50O1xyXG5cclxuICAgICAgICAuY29udHJhY3Qge1xyXG4gICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcblxyXG4gICAgICAgICAgLmljb24ge1xyXG4gICAgICAgICAgICBmbGV4LXNocmluazogMDtcclxuXHJcbiAgICAgICAgICAgICYubmV3LCAmLmFsZXJ0IHtcclxuICAgICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAmLm5ldyB7XHJcbiAgICAgICAgICAgICAgbGVmdDogLTIuM3JlbTtcclxuICAgICAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL25ldy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgd2lkdGg6IDEuN3JlbTtcclxuICAgICAgICAgICAgICBoZWlnaHQ6IDEuN3JlbTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5hbGVydCB7XHJcbiAgICAgICAgICAgICAgdG9wOiAwLjJyZW07XHJcbiAgICAgICAgICAgICAgbGVmdDogLTIuMXJlbTtcclxuICAgICAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2FsZXJ0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgICAgICAgICAgIGhlaWdodDogMS4ycmVtO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAmLnB1cmNoYXNlLCAmLnNlbGwge1xyXG4gICAgICAgICAgICAgIG1hcmdpbi1yaWdodDogMXJlbTtcclxuICAgICAgICAgICAgICB3aWR0aDogMS41cmVtO1xyXG4gICAgICAgICAgICAgIGhlaWdodDogMS41cmVtO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAmLnB1cmNoYXNlIHtcclxuICAgICAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3B1cmNoYXNlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5zZWxsIHtcclxuICAgICAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3NlbGwuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgc3BhbiB7XHJcbiAgICAgICAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cywgLmNvbW1lbnQge1xyXG4gICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgICAgbWF4LXdpZHRoOiAxMDAlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmNvbnRyYWN0cy1idXR0b25zIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIG1hcmdpbjogM3JlbSAwO1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBmbGV4OiAwIDEgNTAlO1xyXG4gICAgbWFyZ2luLXJpZ2h0OiAxLjVyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, OnDestroy} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\n\r\n@Component({\r\n selector: 'app-contracts',\r\n templateUrl: './contracts.component.html',\r\n styleUrls: ['./contracts.component.scss']\r\n})\r\nexport class ContractsComponent implements OnInit, OnDestroy {\r\n\r\n parentRouting;\r\n walletId;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n public variablesService: VariablesService\r\n ) {\r\n }\r\n\r\n public get sortedArrayContracts(): any[] {\r\n return this.variablesService.currentWallet.contracts.sort((a, b) => {\r\n if (a.is_new < b.is_new) {\r\n return 1;\r\n }\r\n if (a.is_new > b.is_new) {\r\n return -1;\r\n }\r\n if (a.timestamp < b.timestamp) {\r\n return 1;\r\n }\r\n if (a.timestamp > b.timestamp) {\r\n return -1;\r\n }\r\n if (a.contract_id < b.contract_id) {\r\n return 1;\r\n }\r\n if (a.contract_id > b.contract_id) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n if (params.hasOwnProperty('id')) {\r\n this.walletId = params['id'];\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.CREATE_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.form-create {\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.form-create .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem; }\\n\\n.form-create .wrap-buttons button {\\n margin: 0 0.7rem; }\\n\\n.form-create .wrap-buttons button.transparent-button {\\n flex-basis: 50%; }\\n\\n.form-create .wrap-buttons button.select-button {\\n flex-basis: 60%; }\\n\\n.form-create .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY3JlYXRlLXdhbGxldC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxjcmVhdGUtd2FsbGV0XFxjcmVhdGUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFGWjtJQUtJLGFBQWE7SUFDYixzQkFBc0IsRUFBQTs7QUFOMUI7TUFTTSxnQkFBZ0IsRUFBQTs7QUFUdEI7UUFZUSxlQUFlLEVBQUE7O0FBWnZCO1FBZ0JRLGVBQWUsRUFBQTs7QUFoQnZCO1FBb0JRLGFBQWEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2NyZWF0ZS13YWxsZXQvY3JlYXRlLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5mb3JtLWNyZWF0ZSB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcblxyXG4gICAgICAmLnRyYW5zcGFyZW50LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNTAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnNlbGVjdC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Router} from '@angular/router';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-create-wallet',\r\n templateUrl: './create-wallet.component.html',\r\n styleUrls: ['./create-wallet.component.scss']\r\n})\r\nexport class CreateWalletComponent implements OnInit {\r\n\r\n createForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n confirm: new FormControl('')\r\n }, function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirm').value ? null : {'confirm_mismatch': true};\r\n });\r\n\r\n wallet = {\r\n id: ''\r\n };\r\n\r\n walletSaved = false;\r\n walletSavedName = '';\r\n progressWidth = '9rem';\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n createWallet() {\r\n this.ngZone.run(() => {\r\n this.progressWidth = '100%';\r\n this.router.navigate(['/seed-phrase'], {queryParams: {wallet_id: this.wallet.id}});\r\n });\r\n }\r\n\r\n saveWallet() {\r\n if (this.createForm.valid && this.createForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.saveFileDialog(this.translate.instant('CREATE_WALLET.TITLE_SAVE'), '*', this.variablesService.settings.default_path, (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(0, file_data.path.lastIndexOf('/'));\r\n this.walletSavedName = file_data.path.substr(file_data.path.lastIndexOf('/') + 1, file_data.path.length - 1);\r\n this.backend.generateWallet(file_data.path, this.createForm.get('password').value, (generate_status, generate_data, errorCode) => {\r\n if (generate_status) {\r\n this.wallet.id = generate_data.wallet_id;\r\n this.variablesService.opening_wallet = new Wallet(\r\n generate_data.wallet_id,\r\n this.createForm.get('name').value,\r\n this.createForm.get('password').value,\r\n generate_data['wi'].path,\r\n generate_data['wi'].address,\r\n generate_data['wi'].balance,\r\n generate_data['wi'].unlocked_balance,\r\n generate_data['wi'].mined_total,\r\n generate_data['wi'].tracking_hey\r\n );\r\n this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(generate_data['wi'].address);\r\n this.ngZone.run(() => {\r\n this.walletSaved = true;\r\n this.progressWidth = '50%';\r\n });\r\n } else {\r\n if (errorCode && errorCode === 'ALREADY_EXISTS') {\r\n this.modalService.prepareModal('error', 'CREATE_WALLET.ERROR_CANNOT_SAVE_TOP');\r\n } else {\r\n this.modalService.prepareModal('error', 'CREATE_WALLET.ERROR_CANNOT_SAVE_SYSTEM');\r\n }\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.EDIT_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
0 && notEnoughMoney\\\">\\r\\n {{ 'EDIT_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'EDIT_ALIAS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"EDIT_ALIAS.COST\\\" | translate : {value: variablesService.default_fee, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \".form-edit {\\n margin: 2.4rem 0; }\\n .form-edit .alias-name {\\n width: 50%; }\\n .form-edit .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-edit .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-edit .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZWRpdC1hbGlhcy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxlZGl0LWFsaWFzXFxlZGl0LWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQSIsImZpbGUiOiJzcmMvYXBwL2VkaXQtYWxpYXMvZWRpdC1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWVkaXQge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\n@Component({\r\n selector: 'app-edit-alias',\r\n templateUrl: './edit-alias.component.html',\r\n styleUrls: ['./edit-alias.component.scss']\r\n})\r\nexport class EditAliasComponent implements OnInit {\r\n\r\n wallet: Wallet;\r\n alias: any;\r\n oldAliasComment: string;\r\n notEnoughMoney: boolean;\r\n requestProcessing = false;\r\n\r\n constructor(\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n this.alias = {\r\n name: alias.name,\r\n address: alias.address,\r\n comment: alias.comment\r\n };\r\n this.oldAliasComment = alias.comment;\r\n this.notEnoughMoney = this.wallet.unlocked_balance.isLessThan(this.variablesService.default_fee_big);\r\n }\r\n\r\n updateAlias() {\r\n if (this.requestProcessing || this.notEnoughMoney || this.oldAliasComment === this.alias.comment || this.alias.comment.length > this.variablesService.maxCommentLength) {\r\n return;\r\n }\r\n this.requestProcessing = true;\r\n this.backend.updateAlias(this.wallet.wallet_id, this.alias, this.variablesService.default_fee, (status) => {\r\n if (status) {\r\n this.modalService.prepareModal('success', '');\r\n this.wallet.alias['comment'] = this.alias.comment;\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n this.requestProcessing = false;\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'CONTACTS.IMPORT_EXPORT' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.head {\\n justify-content: flex-end; }\\n\\n.contacts-title {\\n font-size: 1.7rem;\\n margin-bottom: 1rem; }\\n\\n.btn-wrapper {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 0 -0.5rem;\\n padding: 1.5rem 0; }\\n\\n.btn-wrapper button {\\n flex: 1 0 auto;\\n margin: 0 0.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZXhwb3J0LWltcG9ydC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxleHBvcnQtaW1wb3J0XFxleHBvcnQtaW1wb3J0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBQ0UseUJBQXlCLEVBQUE7O0FBRzNCO0VBQ0UsaUJBQWlCO0VBQ2pCLG1CQUFtQixFQUFBOztBQUdyQjtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsOEJBQThCO0VBQzlCLGlCQUFpQjtFQUNqQixpQkFBaUIsRUFBQTs7QUFMbkI7SUFRSSxjQUFjO0lBQ2QsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9leHBvcnQtaW1wb3J0L2V4cG9ydC1pbXBvcnQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi5oZWFkIHtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xyXG59XHJcblxyXG4uY29udGFjdHMtdGl0bGUge1xyXG4gIGZvbnQtc2l6ZTogMS43cmVtO1xyXG4gIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbn1cclxuXHJcbi5idG4td3JhcHBlciB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICBtYXJnaW46IDAgLTAuNXJlbTtcclxuICBwYWRkaW5nOiAxLjVyZW0gMDtcclxuXHJcbiAgYnV0dG9uIHtcclxuICAgIGZsZXg6IDEgMCBhdXRvO1xyXG4gICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICB9XHJcbn0iXX0= */\"","import { Component, OnInit, NgZone } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { Contact } from '../_helpers/models/contact.model';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\nimport { Papa } from 'ngx-papaparse';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { Router } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-export-import',\r\n templateUrl: './export-import.component.html',\r\n styleUrls: ['./export-import.component.scss']\r\n})\r\nexport class ExportImportComponent implements OnInit {\r\n csvContent;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private backend: BackendService,\r\n private modalService: ModalService,\r\n private papa: Papa,\r\n private translate: TranslateService,\r\n private router: Router,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {}\r\n\r\n import() {\r\n this.backend.openFileDialog(\r\n '',\r\n '*',\r\n this.variablesService.settings.default_path,\r\n (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(\r\n 0,\r\n file_data.path.lastIndexOf('/')\r\n );\r\n if (this.isValid(file_data.path)) {\r\n this.backend.loadFile(file_data.path, (status, data) => {\r\n if (!status) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.ERROR_IMPORT_EMPTY'\r\n );\r\n } else {\r\n const options = {\r\n header: true\r\n };\r\n const elements = this.papa.parse(data, options);\r\n const isArray = Array.isArray(elements.data);\r\n if (isArray && elements.data.length !== 0 && !elements.errors.length) {\r\n if (!this.variablesService.contacts.length) {\r\n elements.data.forEach(element => {\r\n this.variablesService.contacts.push(element);\r\n });\r\n } else {\r\n elements.data.forEach(element => {\r\n const indexName = this.variablesService.contacts.findIndex(\r\n contact => contact.name === element.name\r\n );\r\n const indexAddress = this.variablesService.contacts.findIndex(\r\n contact => contact.address === element.address\r\n );\r\n if (indexAddress === -1 && indexName === -1) {\r\n this.variablesService.contacts.push(element);\r\n }\r\n if (indexName !== -1 && indexAddress === -1) {\r\n this.variablesService.contacts.push({\r\n name: `${element.name} ${this.translate.instant(\r\n 'CONTACTS.COPY'\r\n )}`,\r\n address: element.address,\r\n notes: element.notes\r\n });\r\n }\r\n });\r\n }\r\n this.backend.getContactAlias();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/contacts']);\r\n });\r\n }\r\n if (elements.errors.length) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.ERROR_IMPORT'\r\n );\r\n console.log(elements.errors);\r\n }\r\n }\r\n });\r\n } else {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_TYPE_FILE');\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n export() {\r\n const contacts: Array = [];\r\n this.variablesService.contacts.forEach(contact => {\r\n delete contact.alias;\r\n contacts.push(contact);\r\n });\r\n\r\n this.backend.saveFileDialog(\r\n '',\r\n '*',\r\n this.variablesService.settings.default_path,\r\n (file_status, file_data) => {\r\n if (!this.variablesService.contacts.length && !(file_data.error_code === 'CANCELED')) {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_EMPTY_LIST');\r\n }\r\n const path = this.isValid(file_data.path) ? file_data.path : `${file_data.path}.csv`;\r\n if (file_status && this.isValid(path) && this.variablesService.contacts.length) {\r\n this.backend.storeFile(path, this.papa.unparse(contacts));\r\n }\r\n if (!(file_data.error_code === 'CANCELED') && !this.isValid(path)) {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_EXPORT');\r\n }\r\n }\r\n );\r\n }\r\n\r\n isValid(file) {\r\n return file.endsWith('.csv');\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'HISTORY.STATUS' | translate }}{{ 'HISTORY.DATE' | translate }}{{ 'HISTORY.AMOUNT' | translate }}{{ 'HISTORY.FEE' | translate }}{{ 'HISTORY.ADDRESS' | translate }}
\\r\\n
\\r\\n 0\\\">\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n 500000000\\\">\\r\\n 0\\\">\\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n {{ (item.is_income ? 'HISTORY.RECEIVED' : 'HISTORY.SEND') | translate }}\\r\\n
\\r\\n
{{item.timestamp * 1000 | date : 'dd-MM-yyyy HH:mm'}}\\r\\n {{item.sortAmount | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n \\r\\n {{item.sortFee | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n \\r\\n {{item | historyTypeMessages}}\\r\\n {{item.remote_addresses[0]}}\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-table {\\n margin: -3rem; }\\n\\n.wrap-table table tbody tr td {\\n min-width: 10rem; }\\n\\n.wrap-table table tbody tr .status {\\n position: relative;\\n display: flex;\\n align-items: center; }\\n\\n.wrap-table table tbody tr .status .confirmation {\\n position: absolute;\\n top: 50%;\\n left: -2rem;\\n transform: translateY(-50%);\\n display: flex;\\n align-items: flex-end;\\n width: 0.7rem;\\n height: 1.5rem; }\\n\\n.wrap-table table tbody tr .status .confirmation .fill {\\n width: 100%; }\\n\\n.wrap-table table tbody tr .status .lock-transaction {\\n position: absolute;\\n left: -2rem;\\n -webkit-mask: url('lock-transaction.svg') no-repeat center;\\n mask: url('lock-transaction.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem;\\n margin-right: 1.1rem; }\\n\\n.wrap-table table tbody tr .status .unlock-transaction {\\n position: absolute;\\n left: -2rem;\\n -webkit-mask: url('unlock-transaction.svg') no-repeat center;\\n mask: url('unlock-transaction.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem;\\n margin-right: 1.1rem; }\\n\\n.wrap-table table tbody tr .status .position {\\n position: static; }\\n\\n.wrap-table table tbody tr .status .status-transaction {\\n margin-right: 1rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr .status.send .status-transaction {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .status.received .status-transaction {\\n -webkit-mask: url('receive.svg') no-repeat center;\\n mask: url('receive.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .remote-address {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n max-width: 25vw; }\\n\\n.wrap-table table tbody tr:not(.transaction-details) {\\n cursor: pointer; }\\n\\n.wrap-table table tbody tr.transaction-details {\\n transition: 0.5s height linear, 0s font-size;\\n transition-delay: 0s, 0.5s;\\n height: 0; }\\n\\n.wrap-table table tbody tr.transaction-details.open {\\n height: 16.2rem; }\\n\\n.wrap-table table tbody tr.transaction-details td {\\n position: relative;\\n overflow: hidden;\\n line-height: inherit;\\n padding-top: 0;\\n padding-bottom: 0; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvaGlzdG9yeS9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxoaXN0b3J5XFxoaXN0b3J5LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBQ0UsYUFBYSxFQUFBOztBQURmO0lBVVUsZ0JBQWdCLEVBQUE7O0FBVjFCO0lBY1Usa0JBQWtCO0lBQ2xCLGFBQWE7SUFDYixtQkFBbUIsRUFBQTs7QUFoQjdCO01BbUJZLGtCQUFrQjtNQUNsQixRQUFRO01BQ1IsV0FBVztNQUNYLDJCQUEyQjtNQUMzQixhQUFhO01BQ2IscUJBQXFCO01BQ3JCLGFBQWE7TUFDYixjQUFjLEVBQUE7O0FBMUIxQjtRQTZCYyxXQUFXLEVBQUE7O0FBN0J6QjtNQWtDWSxrQkFBa0I7TUFDbEIsV0FBVztNQUNYLDBEQUFtRTtjQUFuRSxrREFBbUU7TUFDbkUsYUFBYTtNQUNiLGNBQWM7TUFDZCxvQkFBb0IsRUFBQTs7QUF2Q2hDO01BMkNZLGtCQUFrQjtNQUNsQixXQUFXO01BQ1gsNERBQXFFO2NBQXJFLG9EQUFxRTtNQUNyRSxhQUFhO01BQ2IsY0FBYztNQUNkLG9CQUFvQixFQUFBOztBQWhEaEM7TUFvRFksZ0JBQWdCLEVBQUE7O0FBcEQ1QjtNQXdEWSxrQkFBa0I7TUFDbEIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUExRDFCO01BZ0VjLDhDQUF1RDtjQUF2RCxzQ0FBdUQsRUFBQTs7QUFoRXJFO01BdUVjLGlEQUEwRDtjQUExRCx5Q0FBMEQsRUFBQTs7QUF2RXhFO0lBNkVVLGdCQUFnQjtJQUNoQix1QkFBdUI7SUFDdkIsZUFBZSxFQUFBOztBQS9FekI7SUFtRlUsZUFBZSxFQUFBOztBQW5GekI7SUF3RlUsNENBQTRDO0lBQzVDLDBCQUEwQjtJQUMxQixTQUFTLEVBQUE7O0FBMUZuQjtNQTZGWSxlQUFlLEVBQUE7O0FBN0YzQjtNQWlHWSxrQkFBa0I7TUFDbEIsZ0JBQWdCO01BQ2hCLG9CQUFvQjtNQUNwQixjQUFjO01BQ2QsaUJBQWlCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9oaXN0b3J5L2hpc3RvcnkuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi53cmFwLXRhYmxlIHtcclxuICBtYXJnaW46IC0zcmVtO1xyXG5cclxuICB0YWJsZSB7XHJcblxyXG4gICAgdGJvZHkge1xyXG5cclxuICAgICAgdHIge1xyXG5cclxuICAgICAgICB0ZCB7XHJcbiAgICAgICAgICBtaW4td2lkdGg6IDEwcmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cyB7XHJcbiAgICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuXHJcbiAgICAgICAgICAuY29uZmlybWF0aW9uIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICB0b3A6IDUwJTtcclxuICAgICAgICAgICAgbGVmdDogLTJyZW07XHJcbiAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNTAlKTtcclxuICAgICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgICAgYWxpZ24taXRlbXM6IGZsZXgtZW5kO1xyXG4gICAgICAgICAgICB3aWR0aDogMC43cmVtO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEuNXJlbTtcclxuXHJcbiAgICAgICAgICAgIC5maWxsIHtcclxuICAgICAgICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5sb2NrLXRyYW5zYWN0aW9uIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICBsZWZ0OiAtMnJlbTtcclxuICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9sb2NrLXRyYW5zYWN0aW9uLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgd2lkdGg6IDEuMnJlbTtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxLjJyZW07XHJcbiAgICAgICAgICAgIG1hcmdpbi1yaWdodDogMS4xcmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC51bmxvY2stdHJhbnNhY3Rpb24ge1xyXG4gICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgIGxlZnQ6IC0ycmVtO1xyXG4gICAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3VubG9jay10cmFuc2FjdGlvbi5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIHdpZHRoOiAxLjJyZW07XHJcbiAgICAgICAgICAgIGhlaWdodDogMS4ycmVtO1xyXG4gICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuMXJlbTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAucG9zaXRpb24ge1xyXG4gICAgICAgICAgICBwb3NpdGlvbjogc3RhdGljO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xyXG4gICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDFyZW07XHJcbiAgICAgICAgICAgIHdpZHRoOiAxLjdyZW07XHJcbiAgICAgICAgICAgIGhlaWdodDogMS43cmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICYuc2VuZCAge1xyXG5cclxuICAgICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZW5kLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICYucmVjZWl2ZWQge1xyXG5cclxuICAgICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9yZWNlaXZlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnJlbW90ZS1hZGRyZXNzIHtcclxuICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcclxuICAgICAgICAgIG1heC13aWR0aDogMjV2dztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bm90KC50cmFuc2FjdGlvbi1kZXRhaWxzKSB7XHJcbiAgICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnRyYW5zYWN0aW9uLWRldGFpbHMge1xyXG4gICAgICAgICAgLXdlYmtpdC10cmFuc2l0aW9uOiAwLjVzIGhlaWdodCBsaW5lYXIsIDBzIGZvbnQtc2l6ZTtcclxuICAgICAgICAgIHRyYW5zaXRpb246IDAuNXMgaGVpZ2h0IGxpbmVhciwgMHMgZm9udC1zaXplO1xyXG4gICAgICAgICAgdHJhbnNpdGlvbi1kZWxheTogMHMsIDAuNXM7XHJcbiAgICAgICAgICBoZWlnaHQ6IDA7XHJcblxyXG4gICAgICAgICAgJi5vcGVuIHtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxNi4ycmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHRkIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogaW5oZXJpdDtcclxuICAgICAgICAgICAgcGFkZGluZy10b3A6IDA7XHJcbiAgICAgICAgICAgIHBhZGRpbmctYm90dG9tOiAwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, OnDestroy, AfterViewChecked, ViewChild, ElementRef} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport { Transaction } from '../_helpers/models/transaction.model';\r\n\r\n@Component({\r\n selector: 'app-history',\r\n templateUrl: './history.component.html',\r\n styleUrls: ['./history.component.scss']\r\n})\r\nexport class HistoryComponent implements OnInit, OnDestroy, AfterViewChecked {\r\n parentRouting;\r\n openedDetails = false;\r\n calculatedWidth = [];\r\n @ViewChild('head') head: ElementRef;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n public variablesService: VariablesService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n this.openedDetails = false;\r\n });\r\n }\r\n\r\n ngAfterViewChecked() {\r\n this.calculateWidth();\r\n }\r\n\r\n getHeight(item) {\r\n if ((this.variablesService.height_app - item.height >= 10 && item.height !== 0) || (item.is_mining === true && item.height === 0)) {\r\n return 100;\r\n } else {\r\n if (item.height === 0 || this.variablesService.height_app - item.height < 0) {\r\n return 0;\r\n } else {\r\n return (this.variablesService.height_app - item.height) * 10;\r\n }\r\n }\r\n }\r\n\r\n openDetails(tx_hash) {\r\n if (tx_hash === this.openedDetails) {\r\n this.openedDetails = false;\r\n } else {\r\n this.openedDetails = tx_hash;\r\n }\r\n }\r\n\r\n calculateWidth() {\r\n this.calculatedWidth = [];\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[0].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[1].clientWidth + this.head.nativeElement.childNodes[2].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[3].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[4].clientWidth);\r\n }\r\n\r\n time(item: Transaction) {\r\n const now = new Date().getTime();\r\n const unlockTime = now + ((item.unlock_time - this.variablesService.height_max) * 60 * 1000);\r\n return unlockTime;\r\n }\r\n\r\n isLocked(item: Transaction) {\r\n if ((item.unlock_time > 500000000) && (item.unlock_time > new Date().getTime() / 1000)) {\r\n return true;\r\n }\r\n if ((item.unlock_time < 500000000) && (item.unlock_time > this.variablesService.height_max)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'LOGIN.FORM_ERRORS.MISMATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 100%; }\\n :host .content {\\n display: flex; }\\n :host .content .wrap-login {\\n margin: auto;\\n width: 100%;\\n max-width: 40rem; }\\n :host .content .wrap-login .logo {\\n display: flex;\\n justify-content: center; }\\n :host .content .wrap-login .logo::ng-deep svg {\\n width: 15rem; }\\n :host .content .wrap-login .form-login {\\n display: flex;\\n flex-direction: column; }\\n :host .content .wrap-login .form-login .wrap-button {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n :host .content .wrap-login .form-login .wrap-button button {\\n margin: 2.5rem 0; }\\n :host .content .wrap-login .form-login button {\\n margin: 2.5rem auto;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbG9naW4vRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcbG9naW5cXGxvZ2luLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixPQUFPO0VBQ1AsV0FBVztFQUNYLFlBQVksRUFBQTtFQUxkO0lBUUksYUFBYSxFQUFBO0VBUmpCO01BV00sWUFBWTtNQUNaLFdBQVc7TUFDWCxnQkFBZ0IsRUFBQTtFQWJ0QjtRQWdCUSxhQUFhO1FBQ2IsdUJBQXVCLEVBQUE7RUFqQi9CO1VBb0JVLFlBQVksRUFBQTtFQXBCdEI7UUF5QlEsYUFBYTtRQUNiLHNCQUFzQixFQUFBO0VBMUI5QjtVQTZCVSxhQUFhO1VBQ2IsbUJBQW1CO1VBQ25CLDhCQUE4QixFQUFBO0VBL0J4QztZQWtDWSxnQkFBZ0IsRUFBQTtFQWxDNUI7VUF1Q1UsbUJBQW1CO1VBQ25CLFdBQVc7VUFDWCxnQkFBZ0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2xvZ2luL2xvZ2luLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgbGVmdDogMDtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDEwMCU7XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgLndyYXAtbG9naW4ge1xyXG4gICAgICBtYXJnaW46IGF1dG87XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtYXgtd2lkdGg6IDQwcmVtO1xyXG5cclxuICAgICAgLmxvZ28ge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgICAgICY6Om5nLWRlZXAgc3ZnIHtcclxuICAgICAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5mb3JtLWxvZ2luIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcblxyXG4gICAgICAgIC53cmFwLWJ1dHRvbiB7XHJcbiAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuXHJcbiAgICAgICAgICBidXR0b24ge1xyXG4gICAgICAgICAgICBtYXJnaW46IDIuNXJlbSAwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYnV0dG9uIHtcclxuICAgICAgICAgIG1hcmdpbjogMi41cmVtIGF1dG87XHJcbiAgICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-login',\r\n templateUrl: './login.component.html',\r\n styleUrls: ['./login.component.scss']\r\n})\r\nexport class LoginComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n\r\n regForm = new FormGroup({\r\n password: new FormControl('',\r\n Validators.pattern(this.variablesService.pattern)),\r\n confirmation: new FormControl('')\r\n }, [function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirmation').value ? null : {'mismatch': true};\r\n }\r\n]);\r\n\r\n authForm = new FormGroup({\r\n password: new FormControl('')\r\n });\r\n\r\n type = 'reg';\r\n\r\n logo = icons.logo;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.type) {\r\n this.type = params.type;\r\n }\r\n });\r\n }\r\n\r\n onSubmitCreatePass(): void {\r\n if (this.regForm.valid) {\r\n this.variablesService.appPass = this.regForm.get('password').value; // the pass what was written in input of login form by user\r\n\r\n this.backend.setMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.backend.storeSecureAppData({pass: this.variablesService.appPass});\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n } else {\r\n console.log(data['error_code']);\r\n }\r\n });\r\n }\r\n }\r\n\r\n onSkipCreatePass(): void {\r\n this.variablesService.appPass = '';\r\n this.ngZone.run(() => {\r\n this.variablesService.appLogin = true;\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n\r\n dropSecureAppData(): void {\r\n this.backend.dropSecureAppData(() => {\r\n this.onSkipCreatePass();\r\n });\r\n this.variablesService.wallets = [];\r\n this.variablesService.contacts = [];\r\n }\r\n\r\n onSubmitAuthPass(): void {\r\n if (this.authForm.valid) {\r\n this.variablesService.appPass = this.authForm.get('password').value;\r\n\r\n if (this.variablesService.dataIsLoaded) {\r\n this.backend.checkMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.variablesService.appLogin = true;\r\n this.variablesService.startCountdown();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n });\r\n } else {\r\n this.getData(this.variablesService.appPass);\r\n }\r\n }\r\n }\r\n\r\n getData(appPass) {\r\n this.backend.getSecureAppData({pass: appPass}, (status, data) => {\r\n if (!data.error_code) {\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n this.variablesService.appPass = appPass;\r\n const isEmptyObject = Object.keys(data).length === 0 && data.constructor === Object;\r\n\r\n if (this.variablesService.wallets.length) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.variablesService.wallets[0].wallet_id]);\r\n });\r\n return;\r\n }\r\n if (data.hasOwnProperty('contacts')) {\r\n if (Object.keys(data['contacts']).length !== 0) {\r\n data['contacts'].map(contact => {\r\n this.variablesService.contacts.push(contact);\r\n });\r\n }\r\n }\r\n if (data.hasOwnProperty('wallets')) {\r\n if (Object.keys(data['wallets']).length !== 0) {\r\n this.getWalletData(data['wallets']);\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n if (!data.hasOwnProperty('wallets') && !data.hasOwnProperty('contacts')) {\r\n if (data.length !== 0 && !isEmptyObject) {\r\n this.getWalletData(data);\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n getWalletData(walletData) {\r\n let openWallets = 0;\r\n let runWallets = 0;\r\n walletData.forEach((wallet, wallet_index) => {\r\n this.backend.openWallet(wallet.path, wallet.pass, true, (open_status, open_data, open_error) => {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n openWallets++;\r\n this.ngZone.run(() => {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n wallet.name,\r\n wallet.pass,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (wallet.staking) {\r\n new_wallet.staking = true;\r\n this.backend.startPosMining(new_wallet.wallet_id);\r\n } else {\r\n new_wallet.staking = false;\r\n }\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n if (this.variablesService.wallets.length === 1) {\r\n this.router.navigate(['/wallet/' + this.variablesService.wallets[0].wallet_id]);\r\n }\r\n });\r\n this.backend.runWallet(open_data.wallet_id, (run_status) => {\r\n if (run_status) {\r\n runWallets++;\r\n } else {\r\n if (wallet_index === walletData.length - 1 && runWallets === 0) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n });\r\n } else {\r\n if (wallet_index === walletData.length - 1 && openWallets === 0) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
0\\\">\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n

{{ 'MAIN.TITLE' | translate }}

\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'MAIN.HELP' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n flex: 1 0 auto;\\n padding: 3rem; }\\n\\n.content {\\n padding: 3rem;\\n min-height: 100%; }\\n\\n.content .head {\\n justify-content: flex-end; }\\n\\n.add-wallet .add-wallet-title {\\n margin-bottom: 1rem; }\\n\\n.add-wallet .add-wallet-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 0 -0.5rem;\\n padding: 1.5rem 0; }\\n\\n.add-wallet .add-wallet-buttons button {\\n flex: 1 0 auto;\\n margin: 0 0.5rem; }\\n\\n.add-wallet .add-wallet-help {\\n display: flex;\\n cursor: pointer;\\n font-size: 1.3rem;\\n line-height: 1.5rem; }\\n\\n.add-wallet .add-wallet-help .icon {\\n -webkit-mask: url('howto.svg') no-repeat center;\\n mask: url('howto.svg') no-repeat center;\\n margin-right: 0.8rem;\\n width: 1.5rem;\\n height: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbWFpbi9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxtYWluXFxtYWluLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsY0FBYztFQUNkLGFBQWEsRUFBQTs7QUFHZjtFQUNFLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTs7QUFGbEI7SUFLSSx5QkFBeUIsRUFBQTs7QUFJN0I7RUFHSSxtQkFBbUIsRUFBQTs7QUFIdkI7RUFPSSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLDhCQUE4QjtFQUM5QixpQkFBaUI7RUFDakIsaUJBQWlCLEVBQUE7O0FBWHJCO0lBY00sY0FBYztJQUNkLGdCQUFnQixFQUFBOztBQWZ0QjtFQW9CSSxhQUFhO0VBQ2IsZUFBZTtFQUNmLGlCQUFpQjtFQUNqQixtQkFBbUIsRUFBQTs7QUF2QnZCO0lBMEJNLCtDQUF3RDtZQUF4RCx1Q0FBd0Q7SUFDeEQsb0JBQW9CO0lBQ3BCLGFBQWE7SUFDYixjQUFjLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9tYWluL21haW4uY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZmxleDogMSAwIGF1dG87XHJcbiAgcGFkZGluZzogM3JlbTtcclxufVxyXG5cclxuLmNvbnRlbnQge1xyXG4gIHBhZGRpbmc6IDNyZW07XHJcbiAgbWluLWhlaWdodDogMTAwJTtcclxuXHJcbiAgLmhlYWQge1xyXG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxuICB9XHJcbn1cclxuXHJcbi5hZGQtd2FsbGV0IHtcclxuXHJcbiAgLmFkZC13YWxsZXQtdGl0bGUge1xyXG4gICAgbWFyZ2luLWJvdHRvbTogMXJlbTtcclxuICB9XHJcblxyXG4gIC5hZGQtd2FsbGV0LWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDAgLTAuNXJlbTtcclxuICAgIHBhZGRpbmc6IDEuNXJlbSAwO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGZsZXg6IDEgMCBhdXRvO1xyXG4gICAgICBtYXJnaW46IDAgMC41cmVtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLmFkZC13YWxsZXQtaGVscCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS41cmVtO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9ob3d0by5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbi1yaWdodDogMC44cmVtO1xyXG4gICAgICB3aWR0aDogMS41cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Router} from '@angular/router';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-main',\r\n templateUrl: './main.component.html',\r\n styleUrls: ['./main.component.scss']\r\n})\r\nexport class MainComponent implements OnInit {\r\n\r\n constructor(\r\n private router: Router,\r\n private location: Location,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n openWallet() {\r\n this.backend.openFileDialog(this.translate.instant('MAIN.CHOOSE_PATH'), '*', this.variablesService.settings.default_path, (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(0, file_data.path.lastIndexOf('/'));\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/open'], {queryParams: {path: file_data.path}});\r\n });\r\n } else {\r\n console.log(file_data['error_code']);\r\n }\r\n });\r\n }\r\n\r\n openInBrowser() {\r\n this.backend.openUrlInBrowser('docs.zano.org/docs/getting-started-1#section-create-new-wallet');\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'MESSAGES.ADDRESS' | translate }}{{ 'MESSAGES.MESSAGE' | translate }}
\\r\\n {{message.address}}\\r\\n \\r\\n \\r\\n {{message.message}}\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-table {\\n margin: -3rem; }\\n\\n.wrap-table table tbody tr td:first-child {\\n position: relative;\\n padding-right: 5rem;\\n width: 18rem; }\\n\\n.wrap-table table tbody tr td:first-child span {\\n display: block;\\n line-height: 3.5rem;\\n max-width: 10rem; }\\n\\n.wrap-table table tbody tr td:first-child .icon {\\n position: absolute;\\n top: 50%;\\n right: 1rem;\\n transform: translateY(-50%);\\n display: block;\\n -webkit-mask: url('alert.svg') no-repeat 0;\\n mask: url('alert.svg') no-repeat 0;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbWVzc2FnZXMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcbWVzc2FnZXNcXG1lc3NhZ2VzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBQ0UsYUFBYSxFQUFBOztBQURmO0lBWVksa0JBQWtCO0lBQ2xCLG1CQUFtQjtJQUNuQixZQUFZLEVBQUE7O0FBZHhCO01BaUJjLGNBQWM7TUFDZCxtQkFBbUI7TUFDbkIsZ0JBQWdCLEVBQUE7O0FBbkI5QjtNQXVCYyxrQkFBa0I7TUFDbEIsUUFBUTtNQUNSLFdBQVc7TUFDWCwyQkFBMkI7TUFDM0IsY0FBYztNQUNkLDBDQUFtRDtjQUFuRCxrQ0FBbUQ7TUFDbkQsYUFBYTtNQUNiLGNBQWMsRUFBQSIsImZpbGUiOiJzcmMvYXBwL21lc3NhZ2VzL21lc3NhZ2VzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4ud3JhcC10YWJsZSB7XHJcbiAgbWFyZ2luOiAtM3JlbTtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgdGQge1xyXG5cclxuICAgICAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDVyZW07XHJcbiAgICAgICAgICAgIHdpZHRoOiAxOHJlbTtcclxuXHJcbiAgICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAzLjVyZW07XHJcbiAgICAgICAgICAgICAgbWF4LXdpZHRoOiAxMHJlbTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLmljb24ge1xyXG4gICAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgICB0b3A6IDUwJTtcclxuICAgICAgICAgICAgICByaWdodDogMXJlbTtcclxuICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICAgICAgICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9hbGVydC5zdmcpIG5vLXJlcGVhdCAwO1xyXG4gICAgICAgICAgICAgIHdpZHRoOiAxLjJyZW07XHJcbiAgICAgICAgICAgICAgaGVpZ2h0OiAxLjJyZW07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import { Component, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-messages',\r\n templateUrl: './messages.component.html',\r\n styleUrls: ['./messages.component.scss']\r\n})\r\nexport class MessagesComponent implements OnInit {\r\n\r\n messages = [\r\n {\r\n is_new: true,\r\n address: '@bitmap',\r\n message: 'No more miners for you!'\r\n },\r\n {\r\n is_new: false,\r\n address: 'Hjkwey36gHasdhkajshd4bxnb5mcvowyefb2633FdsFGGWbb',\r\n message: 'Hey! What’s with our BBR deal?'\r\n },\r\n {\r\n is_new: false,\r\n address: '@john',\r\n message: 'I’m coming!'\r\n }\r\n ];\r\n\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n\r\n}\r\n","module.exports = \"
\\r\\n

{{ 'OPEN_WALLET.MODAL.TITLE' | translate }}

\\r\\n
\\r\\n
{{ wallet.name }}
\\r\\n
{{ wallet.path }}
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.MODAL.NOT_FOUND' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 2rem;\\n min-width: 34rem;\\n max-width: 64rem; }\\n\\n.modal .title {\\n font-size: 1.8rem;\\n text-align: center; }\\n\\n.modal .open-form .wallet-path {\\n font-size: 1.3rem;\\n margin: 5rem 0 2rem;\\n word-wrap: break-word;\\n line-height: 2rem; }\\n\\n.modal .open-form .wrap-button {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 2rem -2rem 0; }\\n\\n.modal .open-form .wrap-button button {\\n flex: 1 0 0;\\n margin: 0 2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcb3Blbi13YWxsZXQtbW9kYWxcXG9wZW4td2FsbGV0LW1vZGFsLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFHdkM7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLDJCQUEyQjtFQUMzQixxQkFBcUI7RUFDckIsYUFBYTtFQUNiLGdCQUFnQjtFQUNoQixnQkFBZ0IsRUFBQTs7QUFQbEI7SUFVSSxpQkFBaUI7SUFDakIsa0JBQWtCLEVBQUE7O0FBWHRCO0lBaUJNLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIscUJBQXFCO0lBQ3JCLGlCQUFpQixFQUFBOztBQXBCdkI7SUF3Qk0sYUFBYTtJQUNiLG1CQUFtQjtJQUNuQiw4QkFBOEI7SUFDOUIsb0JBQW9CLEVBQUE7O0FBM0IxQjtNQThCUSxXQUFXO01BQ1gsY0FBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvb3Blbi13YWxsZXQtbW9kYWwuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGZpeGVkO1xyXG4gIHRvcDogMDtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICByaWdodDogMDtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcclxufVxyXG5cclxuLm1vZGFsIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xyXG4gIGJhY2tncm91bmQtc2l6ZTogMjAwJTtcclxuICBwYWRkaW5nOiAycmVtO1xyXG4gIG1pbi13aWR0aDogMzRyZW07XHJcbiAgbWF4LXdpZHRoOiA2NHJlbTtcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gIH1cclxuXHJcbiAgLm9wZW4tZm9ybSB7XHJcblxyXG4gICAgLndhbGxldC1wYXRoIHtcclxuICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgIG1hcmdpbjogNXJlbSAwIDJyZW07XHJcbiAgICAgIHdvcmQtd3JhcDogYnJlYWstd29yZDtcclxuICAgICAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLndyYXAtYnV0dG9uIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgICBtYXJnaW46IDJyZW0gLTJyZW0gMDtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAwIDA7XHJcbiAgICAgICAgbWFyZ2luOiAwIDJyZW0gO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, Input, NgZone} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-open-wallet-modal',\r\n templateUrl: './open-wallet-modal.component.html',\r\n styleUrls: ['./open-wallet-modal.component.scss']\r\n})\r\nexport class OpenWalletModalComponent implements OnInit {\r\n\r\n @Input() wallets;\r\n\r\n wallet = {\r\n name: '',\r\n path: '',\r\n pass: '',\r\n notFound: false,\r\n emptyPass: false\r\n };\r\n\r\n constructor(\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private translate: TranslateService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n if (this.wallets.length) {\r\n this.wallet = this.wallets[0];\r\n this.wallet.pass = '';\r\n\r\n this.backend.openWallet(this.wallet.path, '', true, (status, data, error) => {\r\n if (error === 'FILE_NOT_FOUND') {\r\n this.wallet.notFound = true;\r\n }\r\n if (status) {\r\n this.wallet.pass = '';\r\n this.wallet.emptyPass = true;\r\n this.backend.closeWallet(data.wallet_id);\r\n this.openWallet();\r\n }\r\n });\r\n }\r\n }\r\n\r\n openWallet() {\r\n if (this.wallets.length === 0) {\r\n return;\r\n }\r\n this.backend.openWallet(this.wallet.path, this.wallet.pass, false, (open_status, open_data, open_error) => {\r\n if (open_error && open_error === 'FILE_NOT_FOUND') {\r\n let error_translate = this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND1');\r\n error_translate += ':
' + this.wallet.path;\r\n error_translate += this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND2');\r\n this.modalService.prepareModal('error', error_translate);\r\n } else {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === open_data['wi'].address) {\r\n exists = true;\r\n }\r\n });\r\n\r\n if (exists) {\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(open_data.wallet_id);\r\n } else {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n this.wallet.name,\r\n this.wallet.pass,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(\r\n contracts_data.contracts,\r\n this.variablesService.exp_med_ts,\r\n this.variablesService.height_app,\r\n this.variablesService.settings.viewedContracts,\r\n this.variablesService.settings.notViewedContracts\r\n );\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n this.backend.runWallet(open_data.wallet_id);\r\n this.skipWallet();\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n skipWallet() {\r\n if (this.wallets.length) {\r\n this.wallets.splice(0, 1);\r\n this.ngOnInit();\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.OPEN_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\"","module.exports = \".form-open {\\n margin: 2.4rem 0;\\n width: 50%; }\\n .form-open .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem; }\\n .form-open .wrap-buttons button {\\n margin: 0 0.7rem; }\\n .form-open .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcb3Blbi13YWxsZXRcXG9wZW4td2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTtFQUZaO0lBS0ksYUFBYTtJQUNiLHNCQUFzQixFQUFBO0VBTjFCO01BU00sZ0JBQWdCLEVBQUE7RUFUdEI7UUFZUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9vcGVuLXdhbGxldC9vcGVuLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLW9wZW4ge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-open-wallet',\r\n templateUrl: './open-wallet.component.html',\r\n styleUrls: ['./open-wallet.component.scss']\r\n})\r\nexport class OpenWalletComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n filePath: string;\r\n\r\n openForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n password: new FormControl('')\r\n });\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.path) {\r\n this.filePath = params.path;\r\n let filename = '';\r\n if (params.path.lastIndexOf('.') === -1) {\r\n filename = params.path.substr(params.path.lastIndexOf('/') + 1);\r\n } else {\r\n filename = params.path.substr(params.path.lastIndexOf('/') + 1, params.path.lastIndexOf('.') - 1 - params.path.lastIndexOf('/'));\r\n }\r\n if (filename.length > 25) {\r\n filename = filename.slice(0, 25);\r\n }\r\n this.openForm.get('name').setValue(filename);\r\n this.openForm.get('name').markAsTouched();\r\n }\r\n });\r\n }\r\n\r\n openWallet() {\r\n if (this.openForm.valid && this.openForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.openWallet(this.filePath, this.openForm.get('password').value, false, (open_status, open_data, open_error) => {\r\n if (open_error && open_error === 'FILE_NOT_FOUND') {\r\n let error_translate = this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND1');\r\n error_translate += ':
' + this.filePath;\r\n error_translate += this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND2');\r\n this.modalService.prepareModal('error', error_translate);\r\n } else {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === open_data['wi'].address) {\r\n exists = true;\r\n }\r\n });\r\n\r\n if (exists) {\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(open_data.wallet_id, () => {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n });\r\n } else {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n this.openForm.get('name').value,\r\n this.openForm.get('password').value,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n this.backend.runWallet(open_data.wallet_id, (run_status, run_data) => {\r\n if (run_status) {\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + open_data.wallet_id]);\r\n });\r\n } else {\r\n console.log(run_data['error_code']);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'BREADCRUMBS.CONTRACTS' | translate }}\\r\\n {{ 'BREADCRUMBS.NEW_PURCHASE' | translate }}\\r\\n {{ 'BREADCRUMBS.OLD_PURCHASE' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.DESC_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
= 100\\\">\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.COMMENT_MAXIMUM' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
{{item.name}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_SAME' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.ALIAS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.AMOUNT_ZERO' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.YOUR_DEPOSIT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_DEPOSIT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= 100\\\">\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.COMMENT_MAXIMUM' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n 1 {{ 'PURCHASE.HOUR' | translate }}\\r\\n \\r\\n {{title}} {{ 'PURCHASE.HOURS' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n {{ 'PURCHASE.NEED_MONEY' | translate }}\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n
{{'PURCHASE.NULLIFY_QUESTION' | translate}}
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
{{ 'PURCHASE.WAITING_TIME_QUESTION' | translate }}
\\r\\n \\r\\n
\\r\\n \\r\\n 1 {{ 'PURCHASE.HOUR' | translate }}\\r\\n \\r\\n {{title}} {{ 'PURCHASE.HOURS' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NEW_PURCHASE' | translate }}\\r\\n \\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_DELIVERY' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_CANCEL_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.EXPIRED' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_SELLER' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_CONFIRMATION' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.COMPLETED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NOT_RECEIVED' | translate }}. {{ 'PURCHASE.STATUS_MESSAGES.NULLIFIED' | translate }}\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.PROPOSAL_CANCEL_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.CANCELLED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.BEING_CANCELLED' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_CANCEL_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.EXPIRED' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_DELIVERY' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_CONFIRMATION' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.COMPLETED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NOT_RECEIVED' | translate }}. {{ 'PURCHASE.STATUS_MESSAGES.NULLIFIED' | translate }}\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.PROPOSAL_CANCEL_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.CANCELLED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.BEING_CANCELLED' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n {{currentContract.expiration_time | contractTimeLeft: 0}}\\r\\n {{currentContract.cancel_expiration_time | contractTimeLeft: 2}}\\r\\n {{currentContract.expiration_time | contractTimeLeft: 1}}\\r\\n {{currentContract.cancel_expiration_time | contractTimeLeft: 1}}\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.head {\\n flex: 0 0 auto;\\n box-sizing: content-box;\\n margin: -3rem -3rem 0; }\\n\\n.form-purchase {\\n flex: 1 1 auto;\\n margin: 1.5rem -3rem 0;\\n padding: 0 3rem;\\n overflow-y: overlay; }\\n\\n.form-purchase .input-blocks-row {\\n display: flex; }\\n\\n.form-purchase .input-blocks-row .input-block {\\n flex-basis: 50%; }\\n\\n.form-purchase .input-blocks-row .input-block:first-child {\\n margin-right: 1.5rem; }\\n\\n.form-purchase .input-blocks-row .input-block:last-child {\\n margin-left: 1.5rem; }\\n\\n.form-purchase .input-blocks-row .input-block .checkbox-block {\\n display: flex; }\\n\\n.form-purchase .purchase-select {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n line-height: 1.3rem;\\n margin: 1.5rem 0 0;\\n padding: 0;\\n width: 100%;\\n max-width: 15rem;\\n height: 1.3rem; }\\n\\n.form-purchase .purchase-select .arrow {\\n margin-left: 1rem;\\n width: 0.8rem;\\n height: 0.8rem; }\\n\\n.form-purchase .purchase-select .arrow.down {\\n -webkit-mask: url('arrow-down.svg') no-repeat center;\\n mask: url('arrow-down.svg') no-repeat center; }\\n\\n.form-purchase .purchase-select .arrow.up {\\n -webkit-mask: url('arrow-up.svg') no-repeat center;\\n mask: url('arrow-up.svg') no-repeat center; }\\n\\n.form-purchase .additional-details {\\n display: flex;\\n margin-top: 1.5rem;\\n padding: 0.5rem 0 2rem; }\\n\\n.form-purchase .additional-details > div {\\n flex-basis: 25%; }\\n\\n.form-purchase .additional-details > div:first-child {\\n padding-left: 1.5rem;\\n padding-right: 1rem; }\\n\\n.form-purchase .additional-details > div:last-child {\\n padding-left: 1rem;\\n padding-right: 1.5rem; }\\n\\n.form-purchase .purchase-states {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n font-size: 1.2rem;\\n line-height: 2.9rem; }\\n\\n.form-purchase .send-button {\\n margin: 2.4rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n.form-purchase .purchase-buttons {\\n display: flex;\\n justify-content: flex-start;\\n margin: 2.4rem -0.5rem; }\\n\\n.form-purchase .purchase-buttons button {\\n flex: 0 1 33%;\\n margin: 0 0.5rem; }\\n\\n.form-purchase .nullify-block-row {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center; }\\n\\n.form-purchase .nullify-block-row .nullify-block-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n margin: 1rem 0;\\n width: 100%; }\\n\\n.form-purchase .nullify-block-row .nullify-block-buttons button {\\n flex: 0 1 25%;\\n margin: 0 0.5rem; }\\n\\n.form-purchase .time-cancel-block-row {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-question {\\n margin-bottom: 1rem; }\\n\\n.form-purchase .time-cancel-block-row .input-block {\\n width: 25%; }\\n\\n.form-purchase .time-cancel-block-row label {\\n margin-bottom: 1rem; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n margin: 1rem 0;\\n width: 100%; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons button {\\n flex: 0 1 25%;\\n margin: 0 0.5rem; }\\n\\n.progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n padding: 0 3rem;\\n width: 100%;\\n height: 3rem; }\\n\\n.progress-bar-container .progress-bar {\\n position: absolute;\\n top: -0.7rem;\\n left: 0;\\n margin: 0 3rem;\\n width: calc(100% - 6rem);\\n height: 0.7rem; }\\n\\n.progress-bar-container .progress-bar .progress-bar-full {\\n height: 0.7rem; }\\n\\n.progress-bar-container .progress-labels {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-size: 1.2rem;\\n height: 100%; }\\n\\n.progress-bar-container .progress-time {\\n position: absolute;\\n top: -3rem;\\n left: 50%;\\n transform: translateX(-50%);\\n font-size: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcHVyY2hhc2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxccHVyY2hhc2VcXHB1cmNoYXNlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxjQUFjO0VBQ2QsdUJBQXVCO0VBQ3ZCLHFCQUFxQixFQUFBOztBQUd2QjtFQUNFLGNBQWM7RUFDZCxzQkFBc0I7RUFDdEIsZUFBZTtFQUNmLG1CQUFtQixFQUFBOztBQUpyQjtJQU9JLGFBQWEsRUFBQTs7QUFQakI7TUFVTSxlQUFlLEVBQUE7O0FBVnJCO1FBYVEsb0JBQW9CLEVBQUE7O0FBYjVCO1FBaUJRLG1CQUFtQixFQUFBOztBQWpCM0I7UUFxQlEsYUFBYSxFQUFBOztBQXJCckI7SUEyQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsa0JBQWtCO0lBQ2xCLFVBQVU7SUFDVixXQUFXO0lBQ1gsZ0JBQWdCO0lBQ2hCLGNBQWMsRUFBQTs7QUFyQ2xCO01Bd0NNLGlCQUFpQjtNQUNqQixhQUFhO01BQ2IsY0FBYyxFQUFBOztBQTFDcEI7UUE2Q1Esb0RBQTREO2dCQUE1RCw0Q0FBNEQsRUFBQTs7QUE3Q3BFO1FBaURRLGtEQUEwRDtnQkFBMUQsMENBQTBELEVBQUE7O0FBakRsRTtJQXVESSxhQUFhO0lBQ2Isa0JBQWtCO0lBQ2xCLHNCQUFzQixFQUFBOztBQXpEMUI7TUE0RE0sZUFBZSxFQUFBOztBQTVEckI7UUErRFEsb0JBQW9CO1FBQ3BCLG1CQUFtQixFQUFBOztBQWhFM0I7UUFvRVEsa0JBQWtCO1FBQ2xCLHFCQUFxQixFQUFBOztBQXJFN0I7SUEyRUksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLGlCQUFpQjtJQUNqQixtQkFBbUIsRUFBQTs7QUFoRnZCO0lBb0ZJLGdCQUFnQjtJQUNoQixXQUFXO0lBQ1gsZ0JBQWdCLEVBQUE7O0FBdEZwQjtJQTBGSSxhQUFhO0lBQ2IsMkJBQTJCO0lBQzNCLHNCQUFzQixFQUFBOztBQTVGMUI7TUErRk0sYUFBYTtNQUNiLGdCQUFnQixFQUFBOztBQWhHdEI7SUFxR0ksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7O0FBeEczQjtNQTJHTSxhQUFhO01BQ2IsbUJBQW1CO01BQ25CLHVCQUF1QjtNQUN2QixjQUFjO01BQ2QsV0FBVyxFQUFBOztBQS9HakI7UUFrSFEsYUFBYTtRQUNiLGdCQUFnQixFQUFBOztBQW5IeEI7SUF5SEksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7O0FBNUgzQjtNQStITSxtQkFBbUIsRUFBQTs7QUEvSHpCO01BbUlNLFVBQVUsRUFBQTs7QUFuSWhCO01BdUlNLG1CQUFtQixFQUFBOztBQXZJekI7TUEySU0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLFdBQVcsRUFBQTs7QUEvSWpCO1FBa0pRLGFBQWE7UUFDYixnQkFBZ0IsRUFBQTs7QUFPeEI7RUFDRSxrQkFBa0I7RUFDbEIsU0FBUztFQUNULE9BQU87RUFDUCxlQUFlO0VBQ2YsV0FBVztFQUNYLFlBQVksRUFBQTs7QUFOZDtJQVNJLGtCQUFrQjtJQUNsQixZQUFZO0lBQ1osT0FBTztJQUNQLGNBQWM7SUFDZCx3QkFBd0I7SUFDeEIsY0FBYyxFQUFBOztBQWRsQjtNQWlCTSxjQUFjLEVBQUE7O0FBakJwQjtJQXNCSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixpQkFBaUI7SUFDakIsWUFBWSxFQUFBOztBQTFCaEI7SUE4Qkksa0JBQWtCO0lBQ2xCLFVBQVU7SUFDVixTQUFTO0lBQ1QsMkJBQTJCO0lBQzNCLGlCQUFpQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvcHVyY2hhc2UvcHVyY2hhc2UuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAgZmxleDogMCAwIGF1dG87XHJcbiAgYm94LXNpemluZzogY29udGVudC1ib3g7XHJcbiAgbWFyZ2luOiAtM3JlbSAtM3JlbSAwO1xyXG59XHJcblxyXG4uZm9ybS1wdXJjaGFzZSB7XHJcbiAgZmxleDogMSAxIGF1dG87XHJcbiAgbWFyZ2luOiAxLjVyZW0gLTNyZW0gMDtcclxuICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgb3ZlcmZsb3cteTogb3ZlcmxheTtcclxuXHJcbiAgLmlucHV0LWJsb2Nrcy1yb3cge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgICAuaW5wdXQtYmxvY2sge1xyXG4gICAgICBmbGV4LWJhc2lzOiA1MCU7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICBtYXJnaW4tbGVmdDogMS41cmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuY2hlY2tib3gtYmxvY2sge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1zZWxlY3Qge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlcjogbm9uZTtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuM3JlbTtcclxuICAgIG1hcmdpbjogMS41cmVtIDAgMDtcclxuICAgIHBhZGRpbmc6IDA7XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICBoZWlnaHQ6IDEuM3JlbTtcclxuXHJcbiAgICAuYXJyb3cge1xyXG4gICAgICBtYXJnaW4tbGVmdDogMXJlbTtcclxuICAgICAgd2lkdGg6IDAuOHJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjhyZW07XHJcblxyXG4gICAgICAmLmRvd24ge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy1kb3duLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi51cCB7XHJcbiAgICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2Fycm93LXVwLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLmFkZGl0aW9uYWwtZGV0YWlscyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luLXRvcDogMS41cmVtO1xyXG4gICAgcGFkZGluZzogMC41cmVtIDAgMnJlbTtcclxuXHJcbiAgICA+IGRpdiB7XHJcbiAgICAgIGZsZXgtYmFzaXM6IDI1JTtcclxuXHJcbiAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMS41cmVtO1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDFyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAxcmVtO1xyXG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnB1cmNoYXNlLXN0YXRlcyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZvbnQtc2l6ZTogMS4ycmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuOXJlbTtcclxuICB9XHJcblxyXG4gIC5zZW5kLWJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gIH1cclxuXHJcbiAgLnB1cmNoYXNlLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICAgIG1hcmdpbjogMi40cmVtIC0wLjVyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgZmxleDogMCAxIDMzJTtcclxuICAgICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5udWxsaWZ5LWJsb2NrLXJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuXHJcbiAgICAubnVsbGlmeS1ibG9jay1idXR0b25zIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMXJlbSAwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMCAxIDI1JTtcclxuICAgICAgICBtYXJnaW46IDAgMC41cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGltZS1jYW5jZWwtYmxvY2stcm93IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG5cclxuICAgIC50aW1lLWNhbmNlbC1ibG9jay1xdWVzdGlvbiB7XHJcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDI1JTtcclxuICAgIH1cclxuXHJcbiAgICBsYWJlbCB7XHJcbiAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLnRpbWUtY2FuY2VsLWJsb2NrLWJ1dHRvbnMge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAxcmVtIDA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICAgYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAwIDEgMjUlO1xyXG4gICAgICAgIG1hcmdpbjogMCAwLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG59XHJcblxyXG4ucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcbiAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gIGJvdHRvbTogMDtcclxuICBsZWZ0OiAwO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIC5wcm9ncmVzcy1iYXIge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiAtMC43cmVtO1xyXG4gICAgbGVmdDogMDtcclxuICAgIG1hcmdpbjogMCAzcmVtO1xyXG4gICAgd2lkdGg6IGNhbGMoMTAwJSAtIDZyZW0pO1xyXG4gICAgaGVpZ2h0OiAwLjdyZW07XHJcblxyXG4gICAgLnByb2dyZXNzLWJhci1mdWxsIHtcclxuICAgICAgaGVpZ2h0OiAwLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtbGFiZWxzIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICB9XHJcblxyXG4gIC5wcm9ncmVzcy10aW1lIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogLTNyZW07XHJcbiAgICBsZWZ0OiA1MCU7XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, OnDestroy, NgZone, HostListener} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {FormControl, FormGroup, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Location} from '@angular/common';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-purchase',\r\n templateUrl: './purchase.component.html',\r\n styleUrls: ['./purchase.component.scss']\r\n})\r\nexport class PurchaseComponent implements OnInit, OnDestroy {\r\n\r\n isOpen = false;\r\n localAliases = [];\r\n\r\n currentWalletId;\r\n newPurchase = false;\r\n parentRouting;\r\n subRouting;\r\n historyBlock;\r\n\r\n purchaseForm = new FormGroup({\r\n description: new FormControl('', Validators.required),\r\n seller: new FormControl('', [Validators.required, (g: FormControl) => {\r\n if (g.value === this.variablesService.currentWallet.address) {\r\n return {'address_same': true};\r\n }\r\n return null;\r\n }, (g: FormControl) => {\r\n this.localAliases = [];\r\n if (g.value) {\r\n if (g.value.indexOf('@') !== 0) {\r\n this.isOpen = false;\r\n this.backend.validateAddress(g.value, (valid_status) => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(Object.assign({'address_not_valid': true}, g.errors));\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return (g.hasError('address_not_valid')) ? {'address_not_valid': true} : null;\r\n } else {\r\n this.isOpen = true;\r\n this.localAliases = this.variablesService.aliases.filter((item) => {\r\n return item.name.indexOf(g.value) > -1;\r\n });\r\n if (!(/^@?[a-z0-9\\.\\-]{6,25}$/.test(g.value))) {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n } else {\r\n this.backend.getAliasByName(g.value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status) {\r\n if (alias_data.address === this.variablesService.currentWallet.address) {\r\n g.setErrors(Object.assign({'address_same': true}, g.errors));\r\n }\r\n if (g.hasError('alias_not_valid')) {\r\n delete g.errors['alias_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n } else {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n }\r\n });\r\n });\r\n }\r\n return (g.hasError('alias_not_valid')) ? {'alias_not_valid': true} : null;\r\n }\r\n }\r\n return null;\r\n }]),\r\n amount: new FormControl(null, [Validators.required, (g: FormControl) => {\r\n if (parseFloat(g.value) === 0) {\r\n return {'amount_zero': true};\r\n }\r\n return null;\r\n }]),\r\n yourDeposit: new FormControl(null, Validators.required),\r\n sellerDeposit: new FormControl(null, Validators.required),\r\n sameAmount: new FormControl({value: false, disabled: false}),\r\n comment: new FormControl(''),\r\n fee: new FormControl(this.variablesService.default_fee),\r\n time: new FormControl({value: 12, disabled: false}),\r\n timeCancel: new FormControl({value: 12, disabled: false}),\r\n payment: new FormControl('')\r\n });\r\n\r\n additionalOptions = false;\r\n currentContract = null;\r\n heightAppEvent;\r\n showTimeSelect = false;\r\n showNullify = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private location: Location,\r\n private intToMoneyPipe: IntToMoneyPipe\r\n ) {\r\n }\r\n\r\n checkAndChangeHistory() {\r\n if (this.currentContract.state === 201) {\r\n this.historyBlock = this.variablesService.currentWallet.history.find(item => item.tx_type === 8 && item.contract[0].contract_id === this.currentContract.contract_id && item.contract[0].is_a === this.currentContract.is_a);\r\n } else if (this.currentContract.state === 601) {\r\n this.historyBlock = this.variablesService.currentWallet.history.find(item => item.tx_type === 12 && item.contract[0].contract_id === this.currentContract.contract_id && item.contract[0].is_a === this.currentContract.is_a);\r\n }\r\n }\r\n\r\n addressMouseDown(e) {\r\n if (e['button'] === 0 && this.purchaseForm.get('seller').value && this.purchaseForm.get('seller').value.indexOf('@') === 0) {\r\n this.isOpen = true;\r\n }\r\n }\r\n\r\n setAlias(alias) {\r\n this.purchaseForm.get('seller').setValue(alias);\r\n }\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement) {\r\n if (targetElement.id !== 'purchase-seller' && this.isOpen) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n this.currentWalletId = params['id'];\r\n });\r\n this.subRouting = this.route.params.subscribe(params => {\r\n if (params.hasOwnProperty('id')) {\r\n this.currentContract = this.variablesService.currentWallet.getContract(params['id']);\r\n this.purchaseForm.controls['seller'].setValidators([]);\r\n this.purchaseForm.updateValueAndValidity();\r\n this.purchaseForm.setValue({\r\n description: this.currentContract.private_detailes.t,\r\n seller: this.currentContract.private_detailes.b_addr,\r\n amount: this.intToMoneyPipe.transform(this.currentContract.private_detailes.to_pay),\r\n yourDeposit: this.intToMoneyPipe.transform(this.currentContract.private_detailes.a_pledge),\r\n sellerDeposit: this.intToMoneyPipe.transform(this.currentContract.private_detailes.b_pledge),\r\n sameAmount: this.currentContract.private_detailes.to_pay.isEqualTo(this.currentContract.private_detailes.b_pledge),\r\n comment: this.currentContract.private_detailes.c,\r\n fee: this.variablesService.default_fee,\r\n time: 12,\r\n timeCancel: 12,\r\n payment: this.currentContract.payment_id\r\n });\r\n this.purchaseForm.get('sameAmount').disable();\r\n this.newPurchase = false;\r\n\r\n if (this.currentContract.is_new) {\r\n if (this.currentContract.is_a && this.currentContract.state === 2) {\r\n this.currentContract.state = 120;\r\n }\r\n if (this.currentContract.state === 130 && this.currentContract.cancel_expiration_time !== 0 && this.currentContract.cancel_expiration_time < this.variablesService.exp_med_ts) {\r\n this.currentContract.state = 2;\r\n }\r\n this.variablesService.settings.viewedContracts = (this.variablesService.settings.viewedContracts) ? this.variablesService.settings.viewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.viewedContracts[j].state = this.currentContract.state;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.viewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: this.currentContract.state\r\n });\r\n }\r\n this.currentContract.is_new = false;\r\n setTimeout(() => {\r\n this.variablesService.currentWallet.recountNewContracts();\r\n }, 0);\r\n }\r\n this.checkAndChangeHistory();\r\n } else {\r\n this.newPurchase = true;\r\n }\r\n });\r\n this.heightAppEvent = this.variablesService.getHeightAppEvent.subscribe((newHeight: number) => {\r\n if (this.currentContract && this.currentContract.state === 201 && this.currentContract.height !== 0 && (newHeight - this.currentContract.height) >= 10) {\r\n this.currentContract.state = 2;\r\n this.currentContract.is_new = true;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n } else if (this.currentContract && this.currentContract.state === 601 && this.currentContract.height !== 0 && (newHeight - this.currentContract.height) >= 10) {\r\n this.currentContract.state = 6;\r\n this.currentContract.is_new = true;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n }\r\n });\r\n }\r\n\r\n toggleOptions() {\r\n this.additionalOptions = !this.additionalOptions;\r\n }\r\n\r\n getProgressBarWidth() {\r\n let progress = '0';\r\n if (!this.newPurchase) {\r\n if (this.currentContract) {\r\n if (this.currentContract.state === 1) {\r\n progress = '10%';\r\n }\r\n if (this.currentContract.state === 201) {\r\n progress = '25%';\r\n }\r\n if ([120, 2].indexOf(this.currentContract.state) !== -1) {\r\n progress = '50%';\r\n }\r\n if ([5, 601].indexOf(this.currentContract.state) !== -1) {\r\n progress = '75%';\r\n }\r\n if ([110, 130, 140, 3, 4, 6].indexOf(this.currentContract.state) !== -1) {\r\n progress = '100%';\r\n }\r\n }\r\n }\r\n return progress;\r\n }\r\n\r\n sameAmountChange() {\r\n if (this.purchaseForm.get('sameAmount').value) {\r\n this.purchaseForm.get('sellerDeposit').clearValidators();\r\n this.purchaseForm.get('sellerDeposit').updateValueAndValidity();\r\n } else {\r\n this.purchaseForm.get('sellerDeposit').setValidators([Validators.required]);\r\n this.purchaseForm.get('sellerDeposit').updateValueAndValidity();\r\n }\r\n }\r\n\r\n createPurchase() {\r\n if (this.purchaseForm.valid) {\r\n const sellerDeposit = this.purchaseForm.get('sameAmount').value ? this.purchaseForm.get('amount').value : this.purchaseForm.get('sellerDeposit').value;\r\n if (this.purchaseForm.get('seller').value.indexOf('@') !== 0) {\r\n this.backend.createProposal(\r\n this.variablesService.currentWallet.wallet_id,\r\n this.purchaseForm.get('description').value,\r\n this.purchaseForm.get('comment').value,\r\n this.variablesService.currentWallet.address,\r\n this.purchaseForm.get('seller').value,\r\n this.purchaseForm.get('amount').value,\r\n this.purchaseForm.get('yourDeposit').value,\r\n sellerDeposit,\r\n this.purchaseForm.get('time').value,\r\n this.purchaseForm.get('payment').value,\r\n (create_status) => {\r\n if (create_status) {\r\n this.back();\r\n }\r\n });\r\n } else {\r\n this.backend.getAliasByName(this.purchaseForm.get('seller').value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status === false) {\r\n this.ngZone.run(() => {\r\n this.purchaseForm.get('seller').setErrors({'alias_not_valid': true});\r\n });\r\n } else {\r\n this.backend.createProposal(\r\n this.variablesService.currentWallet.wallet_id,\r\n this.purchaseForm.get('description').value,\r\n this.purchaseForm.get('comment').value,\r\n this.variablesService.currentWallet.address,\r\n alias_data.address,\r\n this.purchaseForm.get('amount').value,\r\n this.purchaseForm.get('yourDeposit').value,\r\n sellerDeposit,\r\n this.purchaseForm.get('time').value,\r\n this.purchaseForm.get('payment').value,\r\n (create_status) => {\r\n if (create_status) {\r\n this.back();\r\n }\r\n });\r\n }\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n acceptState() {\r\n this.backend.acceptProposal(this.currentWalletId, this.currentContract.contract_id, (accept_status) => {\r\n if (accept_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.ACCEPT_STATE_WAIT_BIG');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n ignoredContract() {\r\n this.variablesService.settings.notViewedContracts = (this.variablesService.settings.notViewedContracts) ? this.variablesService.settings.notViewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.notViewedContracts[j].state = 110;\r\n this.variablesService.settings.notViewedContracts[j].time = this.currentContract.expiration_time;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.notViewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: 110,\r\n time: this.currentContract.expiration_time\r\n });\r\n }\r\n this.currentContract.is_new = true;\r\n this.currentContract.state = 110;\r\n this.currentContract.time = this.currentContract.expiration_time;\r\n\r\n this.variablesService.currentWallet.recountNewContracts();\r\n this.modalService.prepareModal('info', 'PURCHASE.IGNORED_ACCEPT');\r\n this.back();\r\n }\r\n\r\n productNotGot() {\r\n this.backend.releaseProposal(this.currentWalletId, this.currentContract.contract_id, 'REL_B', (release_status) => {\r\n if (release_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.BURN_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsFinish() {\r\n this.backend.releaseProposal(this.currentWalletId, this.currentContract.contract_id, 'REL_N', (release_status) => {\r\n if (release_status) {\r\n this.modalService.prepareModal('success', 'PURCHASE.SUCCESS_FINISH_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsCancel() {\r\n this.backend.requestCancelContract(this.currentWalletId, this.currentContract.contract_id, this.purchaseForm.get('timeCancel').value, (cancel_status) => {\r\n if (cancel_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.SEND_CANCEL_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsDontCanceling() {\r\n this.variablesService.settings.notViewedContracts = this.variablesService.settings.notViewedContracts ? this.variablesService.settings.notViewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.notViewedContracts[j].state = 130;\r\n this.variablesService.settings.notViewedContracts[j].time = this.currentContract.cancel_expiration_time;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.notViewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: 130,\r\n time: this.currentContract.cancel_expiration_time\r\n });\r\n }\r\n this.currentContract.is_new = true;\r\n this.currentContract.state = 130;\r\n this.currentContract.time = this.currentContract.cancel_expiration_time;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n this.modalService.prepareModal('info', 'PURCHASE.IGNORED_CANCEL');\r\n this.back();\r\n }\r\n\r\n dealsDetailsSellerCancel() {\r\n this.backend.acceptCancelContract(this.currentWalletId, this.currentContract.contract_id, (accept_status) => {\r\n if (accept_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.DEALS_CANCELED_WAIT');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.subRouting.unsubscribe();\r\n this.heightAppEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n \\\"qr-code\\\"\\r\\n
\\r\\n
{{variablesService.currentWallet.address}}
\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-qr {\\n display: flex;\\n flex-direction: column;\\n align-items: center; }\\n\\n.wrap-qr img {\\n margin: 4rem 0; }\\n\\n.wrap-qr .wrap-address {\\n display: flex;\\n align-items: center;\\n font-size: 1.4rem;\\n line-height: 2.7rem; }\\n\\n.wrap-qr .wrap-address .btn-copy-address {\\n margin-left: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copy {\\n -webkit-mask: url('copy.svg') no-repeat center;\\n mask: url('copy.svg') no-repeat center; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copy:hover {\\n opacity: 0.75; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copied {\\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\\n mask: url('complete-testwallet.svg') no-repeat center; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVjZWl2ZS9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxyZWNlaXZlXFxyZWNlaXZlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixtQkFBbUIsRUFBQTs7QUFIckI7SUFNSSxjQUFjLEVBQUE7O0FBTmxCO0lBVUksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQixpQkFBaUI7SUFDakIsbUJBQW1CLEVBQUE7O0FBYnZCO01BZ0JNLG1CQUFtQjtNQUNuQixhQUFhO01BQ2IsY0FBYyxFQUFBOztBQWxCcEI7UUFxQlEsOENBQXVEO2dCQUF2RCxzQ0FBdUQsRUFBQTs7QUFyQi9EO1VBd0JVLGFBQWEsRUFBQTs7QUF4QnZCO1FBNkJRLDZEQUFzRTtnQkFBdEUscURBQXNFLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9yZWNlaXZlL3JlY2VpdmUuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi53cmFwLXFyIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuXHJcbiAgaW1nIHtcclxuICAgIG1hcmdpbjogNHJlbSAwO1xyXG4gIH1cclxuXHJcbiAgLndyYXAtYWRkcmVzcyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAuYnRuLWNvcHktYWRkcmVzcyB7XHJcbiAgICAgIG1hcmdpbi1sZWZ0OiAxLjJyZW07XHJcbiAgICAgIHdpZHRoOiAxLjdyZW07XHJcbiAgICAgIGhlaWdodDogMS43cmVtO1xyXG5cclxuICAgICAgJi5jb3B5IHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2NvcHkuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG5cclxuICAgICAgICAmOmhvdmVyIHtcclxuICAgICAgICAgIG9wYWNpdHk6IDAuNzU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmNvcGllZCB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, OnDestroy} from '@angular/core';\r\nimport QRCode from 'qrcode';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-receive',\r\n templateUrl: './receive.component.html',\r\n styleUrls: ['./receive.component.scss']\r\n})\r\nexport class ReceiveComponent implements OnInit, OnDestroy {\r\n qrImageSrc: string;\r\n parentRouting;\r\n copyAnimation = false;\r\n copyAnimationTimeout;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n QRCode.toDataURL(this.variablesService.currentWallet.address, {\r\n width: 106,\r\n height: 106\r\n }).then(url => {\r\n this.qrImageSrc = url;\r\n }).catch(err => {\r\n console.error(err);\r\n });\r\n });\r\n }\r\n\r\n public copyAddress() {\r\n this.backend.setClipboard(this.variablesService.currentWallet.address);\r\n this.copyAnimation = true;\r\n this.copyAnimationTimeout = window.setTimeout(() => {\r\n this.copyAnimation = false;\r\n }, 2000);\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n clearTimeout(this.copyAnimationTimeout);\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.RESTORE_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.KEY_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.KEY_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.form-restore {\\n margin: 2.4rem 0;\\n width: 100%; }\\n\\n.form-restore .input-block.half-block {\\n width: 50%; }\\n\\n.form-restore .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem;\\n width: 50%; }\\n\\n.form-restore .wrap-buttons button {\\n margin: 0 0.7rem; }\\n\\n.form-restore .wrap-buttons button.transparent-button {\\n flex-basis: 50%; }\\n\\n.form-restore .wrap-buttons button.select-button {\\n flex-basis: 60%; }\\n\\n.form-restore .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVzdG9yZS13YWxsZXQvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxccmVzdG9yZS13YWxsZXRcXHJlc3RvcmUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsZ0JBQWdCO0VBQ2hCLFdBQVcsRUFBQTs7QUFGYjtJQU9NLFVBQVUsRUFBQTs7QUFQaEI7SUFZSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLFVBQVUsRUFBQTs7QUFkZDtNQWlCTSxnQkFBZ0IsRUFBQTs7QUFqQnRCO1FBb0JRLGVBQWUsRUFBQTs7QUFwQnZCO1FBd0JRLGVBQWUsRUFBQTs7QUF4QnZCO1FBNEJRLGFBQWEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3Jlc3RvcmUtd2FsbGV0L3Jlc3RvcmUtd2FsbGV0LmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxufVxyXG5cclxuLmZvcm0tcmVzdG9yZSB7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgLmlucHV0LWJsb2NrIHtcclxuXHJcbiAgICAmLmhhbGYtYmxvY2sge1xyXG4gICAgICB3aWR0aDogNTAlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuICAgIHdpZHRoOiA1MCU7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuXHJcbiAgICAgICYudHJhbnNwYXJlbnQtYnV0dG9uIHtcclxuICAgICAgICBmbGV4LWJhc2lzOiA1MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuc2VsZWN0LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNjAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmNyZWF0ZS1idXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDEgMSA1MCU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-restore-wallet',\r\n templateUrl: './restore-wallet.component.html',\r\n styleUrls: ['./restore-wallet.component.scss']\r\n})\r\nexport class RestoreWalletComponent implements OnInit {\r\n\r\n restoreForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n key: new FormControl('', Validators.required),\r\n password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n confirm: new FormControl('')\r\n }, function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirm').value ? null : {'confirm_mismatch': true};\r\n });\r\n\r\n wallet = {\r\n id: ''\r\n };\r\n\r\n walletSaved = false;\r\n walletSavedName = '';\r\n progressWidth = '9rem';\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {}\r\n\r\n ngOnInit() {}\r\n\r\n createWallet() {\r\n this.ngZone.run(() => {\r\n this.progressWidth = '100%';\r\n this.router.navigate(['/seed-phrase'], {queryParams: {wallet_id: this.wallet.id}});\r\n });\r\n }\r\n\r\n saveWallet() {\r\n if (this.restoreForm.valid && this.restoreForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.isValidRestoreWalletText(this.restoreForm.get('key').value, (valid_status, valid_data) => {\r\n if (valid_data !== 'TRUE') {\r\n this.ngZone.run(() => {\r\n this.restoreForm.get('key').setErrors({key_not_valid: true});\r\n });\r\n } else {\r\n this.backend.saveFileDialog(this.translate.instant('RESTORE_WALLET.CHOOSE_PATH'), '*', this.variablesService.settings.default_path, (save_status, save_data) => {\r\n if (save_status) {\r\n this.variablesService.settings.default_path = save_data.path.substr(0, save_data.path.lastIndexOf('/'));\r\n this.walletSavedName = save_data.path.substr(save_data.path.lastIndexOf('/') + 1, save_data.path.length - 1);\r\n this.backend.restoreWallet(save_data.path, this.restoreForm.get('password').value, this.restoreForm.get('key').value, (restore_status, restore_data) => {\r\n if (restore_status) {\r\n this.wallet.id = restore_data.wallet_id;\r\n this.variablesService.opening_wallet = new Wallet(\r\n restore_data.wallet_id,\r\n this.restoreForm.get('name').value,\r\n this.restoreForm.get('password').value,\r\n restore_data['wi'].path,\r\n restore_data['wi'].address,\r\n restore_data['wi'].balance,\r\n restore_data['wi'].unlocked_balance,\r\n restore_data['wi'].mined_total,\r\n restore_data['wi'].tracking_hey\r\n );\r\n this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(this.variablesService.opening_wallet.address);\r\n if (restore_data.recent_history && restore_data.recent_history.history) {\r\n this.variablesService.opening_wallet.prepareHistory(restore_data.recent_history.history);\r\n }\r\n this.backend.getContracts(this.variablesService.opening_wallet.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n this.variablesService.opening_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.ngZone.run(() => {\r\n this.walletSaved = true;\r\n this.progressWidth = '50%';\r\n });\r\n } else {\r\n this.modalService.prepareModal('error', 'RESTORE_WALLET.NOT_CORRECT_FILE_OR_PASSWORD');\r\n }\r\n });\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.SAVE_PHRASE' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'SEED_PHRASE.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n
{{(index + 1) + '. ' + word}}
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.seed-phrase-title {\\n line-height: 2.2rem;\\n padding: 2.2rem 0; }\\n\\n.seed-phrase-content {\\n display: flex;\\n flex-direction: column;\\n flex-wrap: wrap;\\n padding: 1.4rem;\\n width: 100%;\\n height: 12rem; }\\n\\n.seed-phrase-content .word {\\n line-height: 2.2rem;\\n max-width: 13rem; }\\n\\n.wrap-buttons {\\n display: flex; }\\n\\n.wrap-buttons .seed-phrase-button {\\n margin: 2.8rem 0;\\n width: 25%;\\n min-width: 1.5rem; }\\n\\n.wrap-buttons .copy-button {\\n margin: 2.8rem 1rem;\\n width: 25%;\\n min-width: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VlZC1waHJhc2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2VlZC1waHJhc2VcXHNlZWQtcGhyYXNlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7O0FBR3BCO0VBQ0UsbUJBQW1CO0VBQ25CLGlCQUFpQixFQUFBOztBQUduQjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsZUFBZTtFQUNmLGVBQWU7RUFDZixXQUFXO0VBQ1gsYUFBYSxFQUFBOztBQU5mO0lBU0ksbUJBQW1CO0lBQ25CLGdCQUFnQixFQUFBOztBQUlwQjtFQUNFLGFBQWEsRUFBQTs7QUFEZjtJQUlJLGdCQUFnQjtJQUNoQixVQUFVO0lBQ1YsaUJBQWlCLEVBQUE7O0FBTnJCO0lBVUksbUJBQW1CO0lBQ25CLFVBQVU7SUFDVixpQkFBaUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3NlZWQtcGhyYXNlL3NlZWQtcGhyYXNlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxufVxyXG5cclxuLnNlZWQtcGhyYXNlLXRpdGxlIHtcclxuICBsaW5lLWhlaWdodDogMi4ycmVtO1xyXG4gIHBhZGRpbmc6IDIuMnJlbSAwO1xyXG59XHJcblxyXG4uc2VlZC1waHJhc2UtY29udGVudCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGZsZXgtd3JhcDogd3JhcDtcclxuICBwYWRkaW5nOiAxLjRyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMnJlbTtcclxuXHJcbiAgLndvcmQge1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuMnJlbTtcclxuICAgIG1heC13aWR0aDogMTNyZW07XHJcbiAgfVxyXG59XHJcblxyXG4ud3JhcC1idXR0b25zIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAuc2VlZC1waHJhc2UtYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMi44cmVtIDA7XHJcbiAgICB3aWR0aDogMjUlO1xyXG4gICAgbWluLXdpZHRoOiAxLjVyZW07XHJcbiAgfVxyXG5cclxuICAuY29weS1idXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjhyZW0gMXJlbTtcclxuICAgIHdpZHRoOiAyNSU7XHJcbiAgICBtaW4td2lkdGg6IDEuNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbiJdfQ== */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-seed-phrase',\r\n templateUrl: './seed-phrase.component.html',\r\n styleUrls: ['./seed-phrase.component.scss']\r\n})\r\nexport class SeedPhraseComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n seedPhrase = '';\r\n wallet_id: number;\r\n seedPhraseCopied = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private location: Location,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.wallet_id) {\r\n this.wallet_id = params.wallet_id;\r\n this.backend.getSmartWalletInfo(params.wallet_id, (status, data) => {\r\n if (data.hasOwnProperty('restore_key')) {\r\n this.ngZone.run(() => {\r\n this.seedPhrase = data['restore_key'].trim();\r\n });\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n runWallet() {\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === this.variablesService.opening_wallet.address) {\r\n exists = true;\r\n }\r\n });\r\n if (!exists) {\r\n this.backend.runWallet(this.wallet_id, (run_status, run_data) => {\r\n if (run_status) {\r\n this.variablesService.wallets.push(this.variablesService.opening_wallet);\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet_id]);\r\n });\r\n } else {\r\n console.log(run_data['error_code']);\r\n }\r\n });\r\n } else {\r\n this.variablesService.opening_wallet = null;\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(this.wallet_id, () => {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n });\r\n }\r\n }\r\n\r\n copySeedPhrase() {\r\n this.backend.setClipboard(this.seedPhrase, () => {\r\n this.ngZone.run(() => {\r\n this.seedPhraseCopied = true;\r\n });\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'CONFIRM.TITLE' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.SEND' | translate }}
\\r\\n
{{ form.get('amount').value }} {{variablesService.defaultCurrency}}
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.FROM' | translate }}
\\r\\n
{{ variablesService.currentWallet.address }}
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.TO' | translate }}
\\r\\n
{{ form.get('address').value }}
\\r\\n
\\r\\n \\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.COMMENT' | translate }}
\\r\\n
{{ form.get('comment').value }}
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 0.3rem 3rem 3rem 3rem;\\n width: 64rem; }\\n\\n.modal .title {\\n padding: 1.4rem 0;\\n font-size: 1.8rem;\\n line-height: 3rem; }\\n\\n.modal .content {\\n display: flex;\\n font-size: 1.4rem; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin: 1.4rem 3rem 6.2rem 0; }\\n\\n.modal .content .message-container .message-block {\\n display: flex;\\n margin-bottom: 1rem; }\\n\\n.modal .content .message-container .message-block:first-child .message-label {\\n line-height: 4rem; }\\n\\n.modal .content .message-container .message-block:first-child .message-text {\\n line-height: 4rem; }\\n\\n.modal .content .message-container .message-block:last-child {\\n margin-bottom: 0; }\\n\\n.modal .content .message-container .message-block .message-label {\\n min-width: 6.7rem;\\n line-height: 2rem; }\\n\\n.modal .content .message-container .message-block .message-text {\\n overflow-wrap: break-word;\\n margin-left: 4.8rem;\\n width: 43.4rem;\\n line-height: 2rem; }\\n\\n.modal .wrapper-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n\\n.modal .wrapper-buttons button {\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC1tb2RhbC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzZW5kLW1vZGFsXFxzZW5kLW1vZGFsLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZUFBZTtFQUNmLE1BQU07RUFDTixTQUFTO0VBQ1QsT0FBTztFQUNQLFFBQVE7RUFDUixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLHVCQUF1QjtFQUN2QixxQ0FBcUMsRUFBQTs7QUFFdkM7RUFDRSxrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLDhCQUE4QjtFQUM5QixZQUFZLEVBQUE7O0FBUGQ7SUFVSSxpQkFBaUI7SUFDakIsaUJBQWlCO0lBQ2pCLGlCQUFpQixFQUFBOztBQVpyQjtJQWdCSSxhQUFhO0lBQ2IsaUJBQWlCLEVBQUE7O0FBakJyQjtNQW9CTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLHVCQUF1QjtNQUN2Qix1QkFBdUI7TUFDdkIsNEJBQTRCLEVBQUE7O0FBeEJsQztRQTJCUSxhQUFhO1FBQ2IsbUJBQW1CLEVBQUE7O0FBNUIzQjtVQWlDWSxpQkFBaUIsRUFBQTs7QUFqQzdCO1VBcUNZLGlCQUFpQixFQUFBOztBQXJDN0I7VUEwQ1UsZ0JBQWdCLEVBQUE7O0FBMUMxQjtVQThDVSxpQkFBaUI7VUFDakIsaUJBQWlCLEVBQUE7O0FBL0MzQjtVQW1EVSx5QkFBeUI7VUFDekIsbUJBQW1CO1VBQ25CLGNBQWM7VUFDZCxpQkFBaUIsRUFBQTs7QUF0RDNCO0lBOERJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCLEVBQUE7O0FBaEVsQztNQW1FTSxXQUFXO01BQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZW5kLW1vZGFsL3NlbmQtbW9kYWwuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IGZpeGVkO1xyXG4gIHRvcDogMDtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICByaWdodDogMDtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcclxufVxyXG4ubW9kYWwge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xyXG4gIGJhY2tncm91bmQtc2l6ZTogMjAwJTtcclxuICBwYWRkaW5nOiAwLjNyZW0gM3JlbSAzcmVtIDNyZW07XHJcbiAgd2lkdGg6IDY0cmVtO1xyXG5cclxuICAudGl0bGUge1xyXG4gICAgcGFkZGluZzogMS40cmVtIDA7XHJcbiAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAzcmVtO1xyXG4gIH1cclxuXHJcbiAgLmNvbnRlbnQge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xyXG5cclxuICAgIC5tZXNzYWdlLWNvbnRhaW5lciB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAxLjRyZW0gM3JlbSA2LjJyZW0gMDtcclxuICAgICAgXHJcbiAgICAgIC5tZXNzYWdlLWJsb2NrIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcblxyXG4gICAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG5cclxuICAgICAgICAgIC5tZXNzYWdlLWxhYmVsIHtcclxuICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDRyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLm1lc3NhZ2UtdGV4dCB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiA0cmVtO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICAgIG1hcmdpbi1ib3R0b206IDA7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubWVzc2FnZS1sYWJlbCB7XHJcbiAgICAgICAgICBtaW4td2lkdGg6IDYuN3JlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLm1lc3NhZ2UtdGV4dCB7XHJcbiAgICAgICAgICBvdmVyZmxvdy13cmFwOiBicmVhay13b3JkO1xyXG4gICAgICAgICAgbWFyZ2luLWxlZnQ6IDQuOHJlbTtcclxuICAgICAgICAgIHdpZHRoOiA0My40cmVtO1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndyYXBwZXItYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG59XHJcbiJdfQ== */\"","import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';\r\nimport { FormGroup } from '@angular/forms';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\n\r\n\r\n@Component({\r\n selector: 'app-send-modal',\r\n templateUrl: './send-modal.component.html',\r\n styleUrls: ['./send-modal.component.scss']\r\n})\r\nexport class SendModalComponent implements OnInit {\r\n\r\n @Input() form: FormGroup;\r\n @Output() confirmed: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n public variablesService: VariablesService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n confirm() {\r\n this.confirmed.emit(true);\r\n }\r\n\r\n onClose() {\r\n this.confirmed.emit(false);\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n \\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
{{item.name}}
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ADDRESS_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ADDRESS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ALIAS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_ZERO' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'SEND.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.FEE_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.FEE_MINIMUM' | translate : {fee: variablesService.default_fee} }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.form-send .input-blocks-row {\\n display: flex; }\\n\\n.form-send .input-blocks-row > div {\\n flex-basis: 50%; }\\n\\n.form-send .input-blocks-row > div:first-child {\\n margin-right: 1.5rem; }\\n\\n.form-send .input-blocks-row > div:last-child {\\n margin-left: 1.5rem; }\\n\\n.form-send .send-select {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n line-height: 1.3rem;\\n margin: 1.5rem 0 0;\\n padding: 0;\\n width: 100%;\\n max-width: 15rem;\\n height: 1.3rem; }\\n\\n.form-send .send-select .arrow {\\n margin-left: 1rem;\\n width: 0.8rem;\\n height: 0.8rem; }\\n\\n.form-send .send-select .arrow.down {\\n -webkit-mask: url('arrow-down.svg') no-repeat center;\\n mask: url('arrow-down.svg') no-repeat center; }\\n\\n.form-send .send-select .arrow.up {\\n -webkit-mask: url('arrow-up.svg') no-repeat center;\\n mask: url('arrow-up.svg') no-repeat center; }\\n\\n.form-send .additional-details {\\n display: flex;\\n margin-top: 1.5rem;\\n padding: 0.5rem 0 2rem; }\\n\\n.form-send .additional-details > div {\\n flex-basis: 25%; }\\n\\n.form-send .additional-details > div:first-child {\\n padding-left: 1.5rem;\\n padding-right: 1rem; }\\n\\n.form-send .additional-details > div:last-child {\\n padding-left: 1rem;\\n padding-right: 1.5rem; }\\n\\n.form-send .additional-details .checkbox-block {\\n flex-basis: 50%; }\\n\\n.form-send .additional-details .checkbox-block > label {\\n top: 3.5rem; }\\n\\n.form-send button {\\n margin: 2.4rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzZW5kXFxzZW5kLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsV0FBVyxFQUFBOztBQUdiO0VBR0ksYUFBYSxFQUFBOztBQUhqQjtJQU1NLGVBQWUsRUFBQTs7QUFOckI7TUFTUSxvQkFBb0IsRUFBQTs7QUFUNUI7TUFhUSxtQkFBbUIsRUFBQTs7QUFiM0I7RUFtQkksYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIsWUFBWTtFQUNaLGlCQUFpQjtFQUNqQixtQkFBbUI7RUFDbkIsa0JBQWtCO0VBQ2xCLFVBQVU7RUFDVixXQUFXO0VBQ1gsZ0JBQWdCO0VBQ2hCLGNBQWMsRUFBQTs7QUE3QmxCO0lBZ0NNLGlCQUFpQjtJQUNqQixhQUFhO0lBQ2IsY0FBYyxFQUFBOztBQWxDcEI7TUFxQ1Esb0RBQTREO2NBQTVELDRDQUE0RCxFQUFBOztBQXJDcEU7TUF5Q1Esa0RBQTBEO2NBQTFELDBDQUEwRCxFQUFBOztBQXpDbEU7RUErQ0ksYUFBYTtFQUNiLGtCQUFrQjtFQUNsQixzQkFBc0IsRUFBQTs7QUFqRDFCO0lBb0RNLGVBQWUsRUFBQTs7QUFwRHJCO01BdURRLG9CQUFvQjtNQUNwQixtQkFBbUIsRUFBQTs7QUF4RDNCO01BNERRLGtCQUFrQjtNQUNsQixxQkFBcUIsRUFBQTs7QUE3RDdCO0lBa0VNLGVBQWUsRUFBQTs7QUFsRXJCO01BcUVRLFdBQVcsRUFBQTs7QUFyRW5CO0VBMkVJLGdCQUFnQjtFQUNoQixXQUFXO0VBQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZW5kL3NlbmQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi5mb3JtLXNlbmQge1xyXG5cclxuICAuaW5wdXQtYmxvY2tzLXJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAgID4gZGl2IHtcclxuICAgICAgZmxleC1iYXNpczogNTAlO1xyXG5cclxuICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnNlbmQtc2VsZWN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBtYXJnaW46IDEuNXJlbSAwIDA7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgaGVpZ2h0OiAxLjNyZW07XHJcblxyXG4gICAgLmFycm93IHtcclxuICAgICAgbWFyZ2luLWxlZnQ6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAwLjhyZW07XHJcbiAgICAgIGhlaWdodDogMC44cmVtO1xyXG5cclxuICAgICAgJi5kb3duIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctZG93bi5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYudXAge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy11cC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbi10b3A6IDEuNXJlbTtcclxuICAgIHBhZGRpbmc6IDAuNXJlbSAwIDJyZW07XHJcblxyXG4gICAgPiBkaXYge1xyXG4gICAgICBmbGV4LWJhc2lzOiAyNSU7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxcmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuY2hlY2tib3gtYmxvY2sge1xyXG4gICAgICBmbGV4LWJhc2lzOiA1MCU7XHJcblxyXG4gICAgICA+IGxhYmVsIHtcclxuICAgICAgICB0b3A6IDMuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, OnDestroy, NgZone, HostListener, Input} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-send',\r\n templateUrl: './send.component.html',\r\n styleUrls: ['./send.component.scss']\r\n})\r\nexport class SendComponent implements OnInit, OnDestroy {\r\n\r\n isOpen = false;\r\n localAliases = [];\r\n isModalDialogVisible = false;\r\n\r\n currentWalletId = null;\r\n parentRouting;\r\n sendForm = new FormGroup({\r\n address: new FormControl('', [Validators.required, (g: FormControl) => {\r\n this.localAliases = [];\r\n if (g.value) {\r\n if (g.value.indexOf('@') !== 0) {\r\n this.isOpen = false;\r\n this.backend.validateAddress(g.value, (valid_status) => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(Object.assign({'address_not_valid': true}, g.errors));\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return (g.hasError('address_not_valid')) ? {'address_not_valid': true} : null;\r\n } else {\r\n this.isOpen = true;\r\n this.localAliases = this.variablesService.aliases.filter((item) => {\r\n return item.name.indexOf(g.value) > -1;\r\n });\r\n if (!(/^@?[a-z0-9\\.\\-]{6,25}$/.test(g.value))) {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n } else {\r\n this.backend.getAliasByName(g.value.replace('@', ''), (alias_status) => {\r\n this.ngZone.run(() => {\r\n if (alias_status) {\r\n if (g.hasError('alias_not_valid')) {\r\n delete g.errors['alias_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n } else {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n }\r\n });\r\n });\r\n }\r\n return (g.hasError('alias_not_valid')) ? {'alias_not_valid': true} : null;\r\n }\r\n }\r\n return null;\r\n }]),\r\n amount: new FormControl(null, [Validators.required, (g: FormControl) => {\r\n if (new BigNumber(g.value).eq(0)) {\r\n return {'zero': true};\r\n }\r\n return null;\r\n }]),\r\n comment: new FormControl(''),\r\n mixin: new FormControl(0, Validators.required),\r\n fee: new FormControl(this.variablesService.default_fee, [Validators.required, (g: FormControl) => {\r\n if ((new BigNumber(g.value)).isLessThan(this.variablesService.default_fee)) {\r\n return {'less_min': true};\r\n }\r\n return null;\r\n }]),\r\n hide: new FormControl(false)\r\n });\r\n additionalOptions = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {\r\n }\r\n\r\n addressMouseDown(e) {\r\n if (e['button'] === 0 && this.sendForm.get('address').value && this.sendForm.get('address').value.indexOf('@') === 0) {\r\n this.isOpen = true;\r\n }\r\n }\r\n\r\n setAlias(alias) {\r\n this.sendForm.get('address').setValue(alias);\r\n }\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement) {\r\n if (targetElement.id !== 'send-address' && this.isOpen) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n this.currentWalletId = params['id'];\r\n this.sendForm.reset({\r\n address: this.variablesService.currentWallet.send_data['address'],\r\n amount: this.variablesService.currentWallet.send_data['amount'],\r\n comment: this.variablesService.currentWallet.send_data['comment'],\r\n mixin: this.variablesService.currentWallet.send_data['mixin'] || 0,\r\n fee: this.variablesService.currentWallet.send_data['fee'] || this.variablesService.default_fee,\r\n hide: this.variablesService.currentWallet.send_data['hide'] || false\r\n });\r\n });\r\n }\r\n\r\n showDialog() {\r\n this.isModalDialogVisible = true;\r\n }\r\n\r\n confirmed(confirmed: boolean) {\r\n if (confirmed) {\r\n this.onSend();\r\n }\r\n this.isModalDialogVisible = false;\r\n }\r\n\r\n onSend() {\r\n if (this.sendForm.valid) {\r\n if (this.sendForm.get('address').value.indexOf('@') !== 0) {\r\n this.backend.validateAddress(this.sendForm.get('address').value, (valid_status) => {\r\n if (valid_status === false) {\r\n this.ngZone.run(() => {\r\n this.sendForm.get('address').setErrors({'address_not_valid': true});\r\n });\r\n } else {\r\n this.backend.sendMoney(\r\n this.currentWalletId,\r\n this.sendForm.get('address').value,\r\n this.sendForm.get('amount').value,\r\n this.sendForm.get('fee').value,\r\n this.sendForm.get('mixin').value,\r\n this.sendForm.get('comment').value,\r\n this.sendForm.get('hide').value,\r\n (send_status) => {\r\n if (send_status) {\r\n this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');\r\n this.variablesService.currentWallet.send_data = {address: null, amount: null, comment: null, mixin: null, fee: null, hide: null};\r\n this.sendForm.reset({address: null, amount: null, comment: null, mixin: 0, fee: this.variablesService.default_fee, hide: false});\r\n }\r\n });\r\n }\r\n });\r\n } else {\r\n this.backend.getAliasByName(this.sendForm.get('address').value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status === false) {\r\n this.ngZone.run(() => {\r\n this.sendForm.get('address').setErrors({'alias_not_valid': true});\r\n });\r\n } else {\r\n this.backend.sendMoney(\r\n this.currentWalletId,\r\n alias_data.address, // this.sendForm.get('address').value,\r\n this.sendForm.get('amount').value,\r\n this.sendForm.get('fee').value,\r\n this.sendForm.get('mixin').value,\r\n this.sendForm.get('comment').value,\r\n this.sendForm.get('hide').value,\r\n (send_status) => {\r\n if (send_status) {\r\n this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');\r\n this.variablesService.currentWallet.send_data = {address: null, amount: null, comment: null, mixin: null, fee: null, hide: null};\r\n this.sendForm.reset({address: null, amount: null, comment: null, mixin: 0, fee: this.variablesService.default_fee, hide: false});\r\n }\r\n });\r\n }\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n toggleOptions() {\r\n this.additionalOptions = !this.additionalOptions;\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.variablesService.currentWallet.send_data = {\r\n address: this.sendForm.get('address').value,\r\n amount: this.sendForm.get('amount').value,\r\n comment: this.sendForm.get('comment').value,\r\n mixin: this.sendForm.get('mixin').value,\r\n fee: this.sendForm.get('fee').value,\r\n hide: this.sendForm.get('hide').value\r\n };\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'SETTINGS.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.language | translate}}\\r\\n \\r\\n \\r\\n {{item.language | translate}}\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.name | translate}}\\r\\n \\r\\n \\r\\n {{item.name | translate}}\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n {{ 'SETTINGS.MASTER_PASSWORD.TITLE' | translate }}\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n {{ 'SETTINGS.FORM_ERRORS.PASS_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n {{ 'SETTINGS.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
{{ 'SETTINGS.LAST_BUILD' | translate : {value: currentBuild} }}
\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".head {\\n justify-content: flex-end; }\\n\\n.settings-title {\\n font-size: 1.7rem; }\\n\\n.theme-selection {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.theme-selection .radio-block {\\n display: flex;\\n align-items: center;\\n justify-content: flex-start;\\n font-size: 1.3rem;\\n line-height: 2.7rem; }\\n\\n.lock-selection {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.lock-selection .lock-selection-title {\\n display: flex;\\n font-size: 1.5rem;\\n line-height: 2.7rem;\\n margin-bottom: 1rem; }\\n\\n.scale-selection {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n padding: 0 0 4rem;\\n width: 50%;\\n height: 0.5rem; }\\n\\n.scale-selection .button-block {\\n position: relative;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 0 auto;\\n margin: 0 0.2rem;\\n padding: 0;\\n height: 0.5rem; }\\n\\n.scale-selection .button-block .label {\\n position: absolute;\\n bottom: -1rem;\\n left: 50%;\\n transform: translate(-50%, 100%);\\n font-size: 1rem;\\n white-space: nowrap; }\\n\\n.master-password {\\n width: 50%; }\\n\\n.master-password .master-password-title {\\n display: flex;\\n font-size: 1.5rem;\\n line-height: 2.7rem;\\n margin-bottom: 1rem; }\\n\\n.master-password button {\\n margin: 2.5rem auto;\\n width: 100%;\\n max-width: 15rem; }\\n\\n.last-build {\\n font-size: 1rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2V0dGluZ3MvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2V0dGluZ3NcXHNldHRpbmdzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UseUJBQXlCLEVBQUE7O0FBRzNCO0VBQ0UsaUJBQWlCLEVBQUE7O0FBR25CO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0Qix1QkFBdUI7RUFDdkIsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFMWjtJQVFJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsMkJBQTJCO0lBQzNCLGlCQUFpQjtJQUNqQixtQkFBbUIsRUFBQTs7QUFJdkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLHVCQUF1QjtFQUN2QixnQkFBZ0I7RUFDaEIsVUFBVSxFQUFBOztBQUxaO0lBUUksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsbUJBQW1CLEVBQUE7O0FBSXZCO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQiw4QkFBOEI7RUFDOUIsaUJBQWlCO0VBQ2pCLFVBQVU7RUFDVixjQUFjLEVBQUE7O0FBTmhCO0lBU0ksa0JBQWtCO0lBQ2xCLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLGNBQWM7SUFDZCxnQkFBZ0I7SUFDaEIsVUFBVTtJQUNWLGNBQWMsRUFBQTs7QUFoQmxCO01BbUJNLGtCQUFrQjtNQUNsQixhQUFhO01BQ2IsU0FBUztNQUNULGdDQUFnQztNQUNoQyxlQUFlO01BQ2YsbUJBQW1CLEVBQUE7O0FBS3pCO0VBQ0UsVUFBVSxFQUFBOztBQURaO0lBSUksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsbUJBQW1CLEVBQUE7O0FBUHZCO0lBV0ksbUJBQW1CO0lBQ25CLFdBQVc7SUFDWCxnQkFBZ0IsRUFBQTs7QUFJcEI7RUFDRSxlQUFlLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZXR0aW5ncy9zZXR0aW5ncy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5oZWFkIHtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtZW5kO1xyXG59XHJcblxyXG4uc2V0dGluZ3MtdGl0bGUge1xyXG4gIGZvbnQtc2l6ZTogMS43cmVtO1xyXG59XHJcblxyXG4udGhlbWUtc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAucmFkaW8tYmxvY2sge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcbiAgfVxyXG59XHJcblxyXG4ubG9jay1zZWxlY3Rpb24ge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC5sb2NrLXNlbGVjdGlvbi10aXRsZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gICAgbWFyZ2luLWJvdHRvbTogMXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5zY2FsZS1zZWxlY3Rpb24ge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgcGFkZGluZzogMCAwIDRyZW07XHJcbiAgd2lkdGg6IDUwJTtcclxuICBoZWlnaHQ6IDAuNXJlbTtcclxuXHJcbiAgLmJ1dHRvbi1ibG9jayB7XHJcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleDogMSAwIGF1dG87XHJcbiAgICBtYXJnaW46IDAgMC4ycmVtO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIGhlaWdodDogMC41cmVtO1xyXG5cclxuICAgIC5sYWJlbCB7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogNTAlO1xyXG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAxMDAlKTtcclxuICAgICAgZm9udC1zaXplOiAxcmVtO1xyXG4gICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLm1hc3Rlci1wYXNzd29yZCB7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLm1hc3Rlci1wYXNzd29yZC10aXRsZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gICAgbWFyZ2luLWJvdHRvbTogMXJlbTtcclxuICB9XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuNXJlbSBhdXRvO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmxhc3QtYnVpbGQge1xyXG4gIGZvbnQtc2l6ZTogMXJlbTtcclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit, Renderer2} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {FormControl, FormGroup, Validators} from '@angular/forms';\r\nimport {Location} from '@angular/common';\r\nimport { TranslateService } from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-settings',\r\n templateUrl: './settings.component.html',\r\n styleUrls: ['./settings.component.scss']\r\n})\r\nexport class SettingsComponent implements OnInit {\r\n\r\n theme: string;\r\n scale: number;\r\n changeForm: any;\r\n languagesOptions = [\r\n {\r\n name: 'en',\r\n language: 'SETTINGS.LANGUAGE.EN'\r\n },\r\n {\r\n name: 'fr',\r\n language: 'SETTINGS.LANGUAGE.FR'\r\n },\r\n {\r\n name: 'de',\r\n language: 'SETTINGS.LANGUAGE.DE'\r\n },\r\n {\r\n name: 'it',\r\n language: 'SETTINGS.LANGUAGE.IT'\r\n },\r\n {\r\n name: 'pt',\r\n language: 'SETTINGS.LANGUAGE.PT'\r\n }\r\n ];\r\n appLockOptions = [\r\n {\r\n id: 5,\r\n name: 'SETTINGS.APP_LOCK.TIME1'\r\n },\r\n {\r\n id: 15,\r\n name: 'SETTINGS.APP_LOCK.TIME2'\r\n },\r\n {\r\n id: 60,\r\n name: 'SETTINGS.APP_LOCK.TIME3'\r\n },\r\n {\r\n id: 0,\r\n name: 'SETTINGS.APP_LOCK.TIME4'\r\n }\r\n ];\r\n appScaleOptions = [\r\n {\r\n id: 7.5,\r\n name: 'SETTINGS.SCALE.75'\r\n },\r\n {\r\n id: 10,\r\n name: 'SETTINGS.SCALE.100'\r\n },\r\n {\r\n id: 12.5,\r\n name: 'SETTINGS.SCALE.125'\r\n },\r\n {\r\n id: 15,\r\n name: 'SETTINGS.SCALE.150'\r\n }\r\n ];\r\n appLogOptions = [\r\n {\r\n id: -1\r\n },\r\n {\r\n id: 0\r\n },\r\n {\r\n id: 1\r\n },\r\n {\r\n id: 2\r\n },\r\n {\r\n id: 3\r\n },\r\n {\r\n id: 4\r\n }\r\n ];\r\n\r\n currentBuild = '';\r\n appPass: any;\r\n\r\n constructor(\r\n private renderer: Renderer2,\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private location: Location,\r\n public translate: TranslateService,\r\n private ngZone: NgZone\r\n ) {\r\n this.theme = this.variablesService.settings.theme;\r\n this.scale = this.variablesService.settings.scale;\r\n this.changeForm = new FormGroup({\r\n password: new FormControl(''),\r\n new_password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n new_confirmation: new FormControl('')\r\n }, [(g: FormGroup) => {\r\n return g.get('new_password').value === g.get('new_confirmation').value ? null : {'confirm_mismatch': true};\r\n }, (g: FormGroup) => {\r\n if (this.variablesService.appPass) {\r\n return g.get('password').value === this.variablesService.appPass ? null : {'pass_mismatch': true};\r\n }\r\n return null;\r\n }]);\r\n }\r\n\r\n ngOnInit() {\r\n this.backend.getVersion((version) => {\r\n this.ngZone.run(() => {\r\n this.currentBuild = version;\r\n });\r\n });\r\n }\r\n\r\n setTheme(theme) {\r\n this.renderer.removeClass(document.body, 'theme-' + this.theme);\r\n this.theme = theme;\r\n this.variablesService.settings.theme = this.theme;\r\n this.renderer.addClass(document.body, 'theme-' + this.theme);\r\n this.backend.storeAppData();\r\n }\r\n\r\n setScale(scale) {\r\n this.scale = scale;\r\n this.variablesService.settings.scale = this.scale;\r\n this.renderer.setStyle(document.documentElement, 'font-size', this.scale + 'px');\r\n this.backend.storeAppData();\r\n }\r\n\r\n onSubmitChangePass() {\r\n if (this.changeForm.valid) {\r\n this.variablesService.appPass = this.changeForm.get('new_password').value;\r\n if (this.variablesService.appPass) {\r\n this.backend.setMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.backend.storeSecureAppData({pass: this.variablesService.appPass});\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n } else {\r\n console.log(data['error_code']);\r\n }\r\n });\r\n } else {\r\n this.backend.dropSecureAppData();\r\n }\r\n this.changeForm.reset();\r\n }\r\n }\r\n\r\n onLockChange() {\r\n if (this.variablesService.appLogin) {\r\n this.variablesService.restartCountdown();\r\n }\r\n this.backend.storeAppData();\r\n }\r\n\r\n onLogChange() {\r\n this.backend.setLogLevel(this.variablesService.settings.appLog);\r\n this.backend.storeAppData();\r\n }\r\n\r\n onLanguageChange() {\r\n this.translate.use(this.variablesService.settings.language);\r\n this.backend.storeAppData();\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n

{{ 'SIDEBAR.TITLE' | translate }}

\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.OFFLINE' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.SYNCING' | translate }} {{ variablesService.height_app }}{{ 'SIDEBAR.SYNCHRONIZATION.SLASH' | translate }}{{ variablesService.height_max }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ONLINE' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
{{ variablesService.sync.progress_value_text }}%
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.STANDARD' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT' | translate }}\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.CRITICAL' | translate }}\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.TIME' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n justify-content: space-between;\\n flex: 0 0 25rem;\\n padding: 0 3rem;\\n max-width: 25rem; }\\n\\n.animated {\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n margin-right: 1.2rem; }\\n\\n.animated::ng-deep svg {\\n width: 2rem;\\n height: 2rem; }\\n\\n.animated::ng-deep svg path, .animated::ng-deep svg circle, .animated::ng-deep svg polygon {\\n fill: #4db1ff; }\\n\\n.sidebar-accounts {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto; }\\n\\n.sidebar-accounts .sidebar-accounts-header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n flex: 0 0 auto;\\n height: 8rem;\\n font-weight: 400; }\\n\\n.sidebar-accounts .sidebar-accounts-header h3 {\\n font-size: 1.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-header button {\\n background: transparent;\\n border: none;\\n outline: none; }\\n\\n.sidebar-accounts .sidebar-accounts-list {\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto;\\n margin: 0 -3rem;\\n overflow-y: overlay; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account {\\n display: flex;\\n flex-direction: column;\\n flex-shrink: 0;\\n cursor: pointer;\\n padding: 2rem 3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance {\\n line-height: 2.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance .title {\\n font-size: 1.5rem;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance .balance {\\n font-size: 1.8rem;\\n font-weight: 600;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias {\\n font-size: 1.3rem;\\n line-height: 3.4rem;\\n margin-bottom: 0.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .name {\\n display: flex;\\n align-items: center;\\n flex-shrink: 1;\\n line-height: 1.6rem;\\n padding-right: 1rem;\\n overflow: hidden; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .name span {\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .price {\\n flex-shrink: 0; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .icon {\\n margin-left: 0.5rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .icon.comment {\\n -webkit-mask: url('alert.svg') no-repeat center;\\n mask: url('alert.svg') no-repeat center; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-staking {\\n line-height: 2.9rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-staking .text {\\n font-size: 1.3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages {\\n line-height: 2.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages .text {\\n font-size: 1.3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages .indicator {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 1rem;\\n font-size: 1rem;\\n min-width: 2.4rem;\\n height: 1.6rem;\\n padding: 0 0.5rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\\n flex-direction: column;\\n height: 5.6rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .status {\\n align-self: flex-start;\\n font-size: 1.3rem;\\n line-height: 2.6rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container {\\n display: flex;\\n margin: 0.4rem 0;\\n height: 0.7rem;\\n width: 100%; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-bar {\\n flex: 1 0 auto; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-bar .fill {\\n height: 100%; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-percent {\\n flex: 0 0 auto;\\n font-size: 1.3rem;\\n line-height: 0.7rem;\\n padding-left: 0.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account:focus {\\n outline: none; }\\n\\n.sidebar-accounts:after {\\n content: '';\\n position: absolute;\\n bottom: 0;\\n left: -3rem;\\n width: calc(100% + 6rem);\\n height: 5rem; }\\n\\n.sidebar-settings {\\n flex: 0 0 auto;\\n padding-bottom: 1rem; }\\n\\n.sidebar-settings .wrap-button {\\n margin: 0 -3rem; }\\n\\n.sidebar-settings .wrap-button button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-weight: 400;\\n line-height: 3rem;\\n outline: none;\\n padding: 0 3rem;\\n width: 100%; }\\n\\n.sidebar-settings .wrap-button button.disabled {\\n cursor: url('not-allowed.svg'), not-allowed; }\\n\\n.sidebar-settings .wrap-button button .icon {\\n margin-right: 1.2rem;\\n width: 2rem;\\n height: 2rem; }\\n\\n.sidebar-settings .wrap-button button .icon.contacts {\\n -webkit-mask: url('contacts.svg') no-repeat center;\\n mask: url('contacts.svg') no-repeat center; }\\n\\n.sidebar-settings .wrap-button button .icon.settings {\\n -webkit-mask: url('settings.svg') no-repeat center;\\n mask: url('settings.svg') no-repeat center; }\\n\\n.sidebar-settings .wrap-button button .icon.logout {\\n -webkit-mask: url('logout.svg') no-repeat center;\\n mask: url('logout.svg') no-repeat center; }\\n\\n.sidebar-synchronization-status {\\n display: flex;\\n align-items: center;\\n justify-content: flex-start;\\n flex: 0 0 7rem;\\n font-size: 1.3rem; }\\n\\n.sidebar-synchronization-status .status-container {\\n position: relative;\\n flex-grow: 1;\\n text-align: left; }\\n\\n.sidebar-synchronization-status .status-container .offline, .sidebar-synchronization-status .status-container .online {\\n position: relative;\\n display: block;\\n line-height: 1.2rem;\\n padding-left: 2.2rem; }\\n\\n.sidebar-synchronization-status .status-container .offline:before, .sidebar-synchronization-status .status-container .online:before {\\n content: '';\\n position: absolute;\\n top: 0;\\n left: 0;\\n border-radius: 50%;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-synchronization-status .status-container .syncing, .sidebar-synchronization-status .status-container .loading {\\n line-height: 5rem; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n height: 0.7rem;\\n width: 100%; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing {\\n display: flex; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\\n flex: 1 0 auto; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\\n height: 100%; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-percent {\\n flex: 0 0 auto;\\n font-size: 1.3rem;\\n line-height: 0.7rem;\\n padding-left: 0.7rem; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .loading {\\n -webkit-animation: move 5s linear infinite;\\n animation: move 5s linear infinite;\\n background-image: -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.125, rgba(0, 0, 0, 0.15)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.1)), color-stop(0.375, rgba(0, 0, 0, 0.1)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.15)), color-stop(0.625, rgba(0, 0, 0, 0.15)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.1)), color-stop(0.875, rgba(0, 0, 0, 0.1)), color-stop(0.875, transparent), to(transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.125, rgba(0, 0, 0, 0.3)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.25)), color-stop(0.375, rgba(0, 0, 0, 0.25)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.3)), color-stop(0.625, rgba(0, 0, 0, 0.3)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.25)), color-stop(0.875, rgba(0, 0, 0, 0.25)), color-stop(0.875, transparent), to(transparent));\\n background-size: 7rem 7rem;\\n height: 100%; }\\n\\n.sidebar-synchronization-status .update-container {\\n display: flex;\\n flex-grow: 1;\\n margin-left: 1rem;\\n text-align: right; }\\n\\n.sidebar-synchronization-status .update-container .update-text {\\n flex: 1 1 auto;\\n font-size: 1.2rem;\\n line-height: 1.8rem;\\n text-align: left; }\\n\\n.sidebar-synchronization-status .update-container .update-text.time {\\n font-size: 1.1rem; }\\n\\n.sidebar-synchronization-status .update-container .icon {\\n flex: 1 0 auto;\\n margin: 0.3rem 0 0 0.6rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-synchronization-status .update-container .icon.update {\\n -webkit-mask: url('update.svg') no-repeat center;\\n mask: url('update.svg') no-repeat center; }\\n\\n.sidebar-synchronization-status .update-container .icon.time {\\n -webkit-mask: url('time.svg') no-repeat center;\\n mask: url('time.svg') no-repeat center; }\\n\\n@-webkit-keyframes move {\\n 0% {\\n background-position: 100% -7rem; }\\n 100% {\\n background-position: 100% 7rem; } }\\n\\n@keyframes move {\\n 0% {\\n background-position: 100% -7rem; }\\n 100% {\\n background-position: 100% 7rem; } }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2lkZWJhci9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzaWRlYmFyXFxzaWRlYmFyLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0Qiw4QkFBOEI7RUFDOUIsZUFBZTtFQUNmLGVBQWU7RUFDZixnQkFBZ0IsRUFBQTs7QUFHbEI7RUFDRSxhQUFhO0VBQ2IsdUJBQXVCO0VBQ3ZCLG1CQUFtQjtFQUNuQixvQkFBb0IsRUFBQTs7QUFKdEI7SUFRSSxXQUFXO0lBQ1gsWUFBWSxFQUFBOztBQVRoQjtNQVlNLGFBQWEsRUFBQTs7QUFLbkI7RUFDRSxrQkFBa0I7RUFDbEIsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixjQUFjLEVBQUE7O0FBSmhCO0lBT0ksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQiw4QkFBOEI7SUFDOUIsY0FBYztJQUNkLFlBQVk7SUFDWixnQkFBZ0IsRUFBQTs7QUFacEI7TUFlTSxpQkFBaUIsRUFBQTs7QUFmdkI7TUFtQk0sdUJBQXVCO01BQ3ZCLFlBQVk7TUFDWixhQUFhLEVBQUE7O0FBckJuQjtJQTBCSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLGNBQWM7SUFDZCxlQUFlO0lBQ2YsbUJBQW1CLEVBQUE7O0FBOUJ2QjtNQWlDTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLGNBQWM7TUFDZCxlQUFlO01BQ2Ysa0JBQWtCLEVBQUE7O0FBckN4QjtRQXdDUSxhQUFhO1FBQ2IsbUJBQW1CO1FBQ25CLDhCQUE4QixFQUFBOztBQTFDdEM7VUE2Q1UsbUJBQW1CLEVBQUE7O0FBN0M3QjtZQWdEWSxpQkFBaUI7WUFDakIsdUJBQXVCO1lBQ3ZCLGdCQUFnQjtZQUNoQixtQkFBbUIsRUFBQTs7QUFuRC9CO1lBdURZLGlCQUFpQjtZQUNqQixnQkFBZ0I7WUFDaEIsbUJBQW1CLEVBQUE7O0FBekQvQjtV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QUFyRnBCO0lBMkZJLGFBQWE7SUFDYixZQUFZO0lBQ1osaUJBQWlCO0lBQ2pCLGlCQUFpQixFQUFBOztBQTlGckI7TUFpR00sY0FBYztNQUNkLGlCQUFpQjtNQUNqQixtQkFBbUI7TUFDbkIsZ0JBQWdCLEVBQUE7O0FBcEd0QjtRQXVHUSxpQkFBaUIsRUFBQTs7QUF2R3pCO01BNEdNLGNBQWM7TUFDZCx5QkFBeUI7TUFDekIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUEvR3BCO1FBa0hRLGdEQUF5RDtnQkFBekQsd0NBQXlELEVBQUE7O0FBbEhqRTtRQXNIUSw4Q0FBdUQ7Z0JBQXZELHNDQUF1RCxFQUFBOztBQU0vRDtFQUNFO0lBQ0UsK0JBQStCLEVBQUE7RUFFakM7SUFDRSw4QkFBOEIsRUFBQSxFQUFBOztBQUxsQztFQUNFO0lBQ0UsK0JBQStCLEVBQUE7RUFFakM7SUFDRSw4QkFBOEIsRUFBQSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2lkZWJhci9zaWRlYmFyLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgZmxleDogMCAwIDI1cmVtO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICBtYXgtd2lkdGg6IDI1cmVtO1xyXG59XHJcblxyXG4uYW5pbWF0ZWQge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBtYXJnaW4tcmlnaHQ6IDEuMnJlbTtcclxuXHJcbiAgJjo6bmctZGVlcCBzdmcge1xyXG5cclxuICAgIHdpZHRoOiAycmVtO1xyXG4gICAgaGVpZ2h0OiAycmVtO1xyXG4gIFxyXG4gICAgcGF0aCwgY2lyY2xlLCBwb2x5Z29uIHtcclxuICAgICAgZmlsbDogIzRkYjFmZjtcclxuICAgIH1cclxuICB9IFxyXG59XHJcblxyXG4uc2lkZWJhci1hY2NvdW50cyB7XHJcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuXHJcbiAgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleDogMCAwIGF1dG87XHJcbiAgICBoZWlnaHQ6IDhyZW07XHJcbiAgICBmb250LXdlaWdodDogNDAwO1xyXG5cclxuICAgIGgzIHtcclxuICAgICAgZm9udC1zaXplOiAxLjdyZW07XHJcbiAgICB9XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICAgIGJvcmRlcjogbm9uZTtcclxuICAgICAgb3V0bGluZTogbm9uZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLWFjY291bnRzLWxpc3Qge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBmbGV4OiAxIDEgYXV0bztcclxuICAgIG1hcmdpbjogMCAtM3JlbTtcclxuICAgIG92ZXJmbG93LXk6IG92ZXJsYXk7XHJcblxyXG4gICAgLnNpZGViYXItYWNjb3VudCB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgIGZsZXgtc2hyaW5rOiAwO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIHBhZGRpbmc6IDJyZW0gM3JlbTtcclxuXHJcbiAgICAgIC5zaWRlYmFyLWFjY291bnQtcm93IHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG5cclxuICAgICAgICAmLmFjY291bnQtdGl0bGUtYmFsYW5jZSB7XHJcbiAgICAgICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG5cclxuICAgICAgICAgIC50aXRsZSB7XHJcbiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcclxuICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuYmFsYW5jZSB7XHJcbiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG4gICAgICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5hY2NvdW50LWFsaWFzIHtcclxuICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDMuNHJlbTtcclxuICAgICAgICAgIG1hcmdpbi1ib3R0b206IDAuN3JlbTtcclxuXHJcbiAgICAgICAgICAubmFtZSB7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgICAgIGZsZXgtc2hyaW5rOiAxO1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogMS42cmVtO1xyXG4gICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxcmVtO1xyXG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG5cclxuICAgICAgICAgICAgc3BhbiB7XHJcbiAgICAgICAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnByaWNlIHtcclxuICAgICAgICAgICAgZmxleC1zaHJpbms6IDA7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLmljb24ge1xyXG4gICAgICAgICAgICBtYXJnaW4tbGVmdDogMC41cmVtO1xyXG4gICAgICAgICAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEuMnJlbTtcclxuXHJcbiAgICAgICAgICAgICYuY29tbWVudCB7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWNjb3VudC1zdGFraW5nIHtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAyLjlyZW07XHJcblxyXG4gICAgICAgICAgLnRleHQge1xyXG4gICAgICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWNjb3VudC1tZXNzYWdlcyB7XHJcbiAgICAgICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG5cclxuICAgICAgICAgIC50ZXh0IHtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLmluZGljYXRvciB7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICAgICAgICBib3JkZXItcmFkaXVzOiAxcmVtO1xyXG4gICAgICAgICAgICBmb250LXNpemU6IDFyZW07XHJcbiAgICAgICAgICAgIG1pbi13aWR0aDogMi40cmVtO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEuNnJlbTtcclxuICAgICAgICAgICAgcGFkZGluZzogMCAwLjVyZW07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcclxuICAgICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICAgICAgICBoZWlnaHQ6IDUuNnJlbTtcclxuXHJcbiAgICAgICAgICAuc3RhdHVzIHtcclxuICAgICAgICAgICAgYWxpZ24tc2VsZjogZmxleC1zdGFydDtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAyLjZyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgICBtYXJnaW46IDAuNHJlbSAwO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDAuN3JlbTtcclxuICAgICAgICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICAgICAgICAucHJvZ3Jlc3MtYmFyIHtcclxuICAgICAgICAgICAgICBmbGV4OiAxIDAgYXV0bztcclxuXHJcbiAgICAgICAgICAgICAgLmZpbGwge1xyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLnByb2dyZXNzLXBlcmNlbnQge1xyXG4gICAgICAgICAgICAgIGZsZXg6IDAgMCBhdXRvO1xyXG4gICAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAwLjdyZW07XHJcbiAgICAgICAgICAgICAgcGFkZGluZy1sZWZ0OiAwLjdyZW07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6Zm9jdXMge1xyXG4gICAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICY6YWZ0ZXIge1xyXG4gICAgY29udGVudDogJyc7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICBib3R0b206IDA7XHJcbiAgICBsZWZ0OiAtM3JlbTtcclxuICAgIHdpZHRoOiBjYWxjKDEwMCUgKyA2cmVtKTtcclxuICAgIGhlaWdodDogNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5zaWRlYmFyLXNldHRpbmdzIHtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuICBwYWRkaW5nLWJvdHRvbTogMXJlbTtcclxuXHJcbiAgLndyYXAtYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMCAtM3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgICAgYm9yZGVyOiBub25lO1xyXG4gICAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgICBsaW5lLWhlaWdodDogM3JlbTtcclxuICAgICAgb3V0bGluZTogbm9uZTtcclxuICAgICAgcGFkZGluZzogMCAzcmVtO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgICYuZGlzYWJsZWQge1xyXG4gICAgICAgIGN1cnNvcjogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9ub3QtYWxsb3dlZC5zdmcpLCBub3QtYWxsb3dlZDtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMS4ycmVtO1xyXG4gICAgICAgIHdpZHRoOiAycmVtO1xyXG4gICAgICAgIGhlaWdodDogMnJlbTtcclxuXHJcbiAgICAgICAgJi5jb250YWN0cyB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2NvbnRhY3RzLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuc2V0dGluZ3Mge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZXR0aW5ncy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmxvZ291dCB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2xvZ291dC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4uc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O1xyXG4gIGZsZXg6IDAgMCA3cmVtO1xyXG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG5cclxuICAuc3RhdHVzLWNvbnRhaW5lciB7XHJcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG5cclxuICAgIC5vZmZsaW5lLCAub25saW5lIHtcclxuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgbGluZS1oZWlnaHQ6IDEuMnJlbTtcclxuICAgICAgcGFkZGluZy1sZWZ0OiAyLjJyZW07XHJcblxyXG4gICAgICAmOmJlZm9yZSB7XHJcbiAgICAgICAgY29udGVudDogJyc7XHJcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgIHRvcDogMDtcclxuICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcclxuICAgICAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgICAgIGhlaWdodDogMS4ycmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnN5bmNpbmcsIC5sb2FkaW5nIHtcclxuICAgICAgbGluZS1oZWlnaHQ6IDVyZW07XHJcbiAgICB9XHJcblxyXG4gICAgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIGJvdHRvbTogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgICAgaGVpZ2h0OiAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICAgLnN5bmNpbmcge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgICAgIC5wcm9ncmVzcy1iYXIge1xyXG4gICAgICAgICAgZmxleDogMSAwIGF1dG87XHJcblxyXG4gICAgICAgICAgLmZpbGwge1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAucHJvZ3Jlc3MtcGVyY2VudCB7XHJcbiAgICAgICAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDAuN3JlbTtcclxuICAgICAgICAgIHBhZGRpbmctbGVmdDogMC43cmVtO1xyXG4gICAgICAgIH0gICAgICAgXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5sb2FkaW5nIHtcclxuICAgICAgICBhbmltYXRpb246IG1vdmUgNXMgbGluZWFyIGluZmluaXRlO1xyXG4gICAgICAgIGJhY2tncm91bmQtaW1hZ2U6XHJcbiAgICAgICAgICAtd2Via2l0LWdyYWRpZW50KFxyXG4gICAgICAgICAgICAgIGxpbmVhciwgMCAwLCAxMDAlIDEwMCUsXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguMTI1LCByZ2JhKDAsIDAsIDAsIC4xNSkpLCBjb2xvci1zdG9wKC4xMjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC4yNTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguMjUwLCByZ2JhKDAsIDAsIDAsIC4xMCkpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjM3NSwgcmdiYSgwLCAwLCAwLCAuMTApKSwgY29sb3Itc3RvcCguMzc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguNTAwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjUwMCwgcmdiYSgwLCAwLCAwLCAuMTUpKSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC42MjUsIHJnYmEoMCwgMCwgMCwgLjE1KSksIGNvbG9yLXN0b3AoLjYyNSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjc1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC43NTAsIHJnYmEoMCwgMCwgMCwgLjEwKSksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguODc1LCByZ2JhKDAsIDAsIDAsIC4xMCkpLCBjb2xvci1zdG9wKC44NzUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICB0byh0cmFuc3BhcmVudClcclxuICAgICAgICAgICksXHJcbiAgICAgICAgICAtd2Via2l0LWdyYWRpZW50KFxyXG4gICAgICAgICAgICAgIGxpbmVhciwgMCAxMDAlLCAxMDAlIDAsXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguMTI1LCByZ2JhKDAsIDAsIDAsIC4zMCkpLCBjb2xvci1zdG9wKC4xMjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC4yNTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguMjUwLCByZ2JhKDAsIDAsIDAsIC4yNSkpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjM3NSwgcmdiYSgwLCAwLCAwLCAuMjUpKSwgY29sb3Itc3RvcCguMzc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguNTAwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjUwMCwgcmdiYSgwLCAwLCAwLCAuMzApKSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC42MjUsIHJnYmEoMCwgMCwgMCwgLjMwKSksIGNvbG9yLXN0b3AoLjYyNSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjc1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC43NTAsIHJnYmEoMCwgMCwgMCwgLjI1KSksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguODc1LCByZ2JhKDAsIDAsIDAsIC4yNSkpLCBjb2xvci1zdG9wKC44NzUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICB0byh0cmFuc3BhcmVudClcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgYmFja2dyb3VuZC1zaXplOiA3cmVtIDdyZW07XHJcbiAgICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudXBkYXRlLWNvbnRhaW5lciB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07XHJcbiAgICB0ZXh0LWFsaWduOiByaWdodDtcclxuXHJcbiAgICAudXBkYXRlLXRleHQge1xyXG4gICAgICBmbGV4OiAxIDEgYXV0bztcclxuICAgICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgIHRleHQtYWxpZ246IGxlZnQ7XHJcblxyXG4gICAgICAmLnRpbWUge1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMS4xcmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBmbGV4OiAxIDAgYXV0bztcclxuICAgICAgbWFyZ2luOiAwLjNyZW0gMCAwIDAuNnJlbTtcclxuICAgICAgd2lkdGg6IDEuMnJlbTtcclxuICAgICAgaGVpZ2h0OiAxLjJyZW07XHJcblxyXG4gICAgICAmLnVwZGF0ZSB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy91cGRhdGUuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnRpbWUge1xyXG4gICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvdGltZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbkBrZXlmcmFtZXMgbW92ZSB7XHJcbiAgMCUge1xyXG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMTAwJSAtN3JlbTtcclxuICB9XHJcbiAgMTAwJSB7XHJcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAxMDAlIDdyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {ActivatedRoute, NavigationStart, Router} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-sidebar',\r\n templateUrl: './sidebar.component.html',\r\n styleUrls: ['./sidebar.component.scss']\r\n})\r\nexport class SidebarComponent implements OnInit, OnDestroy {\r\n walletSubRouting;\r\n\r\n walletActive: number;\r\n\r\n contacts = icons.contacts;\r\n settings = icons.settings;\r\n exit = icons.exit;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private modal: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n if (this.router.url.indexOf('/wallet/') !== -1) {\r\n const localPathArr = this.router.url.split('/');\r\n if (localPathArr.length >= 3) {\r\n this.walletActive = parseInt(localPathArr[2], 10);\r\n }\r\n } else if (this.router.url.indexOf('/details') !== -1) {\r\n this.walletActive = this.variablesService.currentWallet.wallet_id;\r\n } else {\r\n this.walletActive = null;\r\n }\r\n\r\n this.walletSubRouting = this.router.events.subscribe((event) => {\r\n if (event instanceof NavigationStart) {\r\n if (event.url.indexOf('/wallet/') !== -1) {\r\n const localPathArr = event.url.split('/');\r\n if (localPathArr.length >= 3) {\r\n this.walletActive = parseInt(localPathArr[2], 10);\r\n }\r\n } else if (event.url.indexOf('/details') !== -1) {\r\n this.walletActive = this.variablesService.currentWallet.wallet_id;\r\n } else {\r\n this.walletActive = null;\r\n }\r\n }\r\n });\r\n }\r\n\r\n contactsRoute() {\r\n if (this.variablesService.appPass) {\r\n this.router.navigate(['/contacts']);\r\n } else {\r\n this.modal.prepareModal(\r\n 'error',\r\n 'CONTACTS.FORM_ERRORS.SET_MASTER_PASSWORD'\r\n );\r\n }\r\n }\r\n\r\n getUpdate() {\r\n this.backend.openUrlInBrowser('zano.org/downloads.html');\r\n }\r\n\r\n logOut() {\r\n this.variablesService.stopCountdown();\r\n this.variablesService.appLogin = false;\r\n this.variablesService.appPass = '';\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.walletSubRouting.unsubscribe();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE' | translate }}\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_PENDING' | translate }}\\r\\n {{pending.total | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_TOTAL' | translate }}\\r\\n {{total | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n
\\r\\n {{selectedDate.date | date : 'MMM. EEEE, dd, yyyy'}}\\r\\n {{selectedDate.amount}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_PERIOD' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n {{ 'STAKING.TITLE_GROUP' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.chart-header {\\n display: flex;\\n flex: 0 0 auto; }\\n\\n.chart-header .general {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n flex-grow: 1;\\n font-size: 1.3rem;\\n margin: -0.5rem 0; }\\n\\n.chart-header .general > div {\\n display: flex;\\n align-items: center;\\n margin: 0.5rem 0;\\n height: 2rem; }\\n\\n.chart-header .general > div .label {\\n display: inline-block;\\n width: 9rem; }\\n\\n.chart-header .selected {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-end;\\n justify-content: center;\\n flex-grow: 1;\\n font-size: 1.8rem; }\\n\\n.chart-header .selected span {\\n line-height: 2.9rem; }\\n\\n.chart {\\n position: relative;\\n display: flex;\\n align-items: center;\\n flex: 1 1 auto;\\n min-height: 40rem; }\\n\\n.chart > div {\\n position: absolute;\\n width: 100%;\\n height: 100%; }\\n\\n.chart-options {\\n display: flex;\\n align-items: center;\\n height: 2.4rem;\\n flex: 0 0 auto; }\\n\\n.chart-options .title {\\n font-size: 1.3rem;\\n padding: 0 1rem; }\\n\\n.chart-options .title:first-child {\\n padding-left: 0; }\\n\\n.chart-options .options {\\n display: flex;\\n justify-content: space-between;\\n flex-grow: 1;\\n height: 100%; }\\n\\n.chart-options .options button {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 1 auto;\\n cursor: pointer;\\n font-size: 1.3rem;\\n margin: 0 0.1rem;\\n padding: 0;\\n height: 100%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc3Rha2luZy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxzdGFraW5nXFxzdGFraW5nLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxhQUFhO0VBQ2IsY0FBYyxFQUFBOztBQUZoQjtJQUtJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsdUJBQXVCO0lBQ3ZCLHVCQUF1QjtJQUN2QixZQUFZO0lBQ1osaUJBQWlCO0lBQ2pCLGlCQUFpQixFQUFBOztBQVhyQjtNQWNNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsZ0JBQWdCO01BQ2hCLFlBQVksRUFBQTs7QUFqQmxCO1FBb0JRLHFCQUFxQjtRQUNyQixXQUFXLEVBQUE7O0FBckJuQjtJQTJCSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLHFCQUFxQjtJQUNyQix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQixFQUFBOztBQWhDckI7TUFtQ00sbUJBQW1CLEVBQUE7O0FBS3pCO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLGlCQUFpQixFQUFBOztBQUxuQjtJQVFJLGtCQUFrQjtJQUNsQixXQUFXO0lBQ1gsWUFBWSxFQUFBOztBQUloQjtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLGNBQWMsRUFBQTs7QUFKaEI7SUFPSSxpQkFBaUI7SUFDakIsZUFBZSxFQUFBOztBQVJuQjtNQVdNLGVBQWUsRUFBQTs7QUFYckI7SUFnQkksYUFBYTtJQUNiLDhCQUE4QjtJQUM5QixZQUFZO0lBQ1osWUFBWSxFQUFBOztBQW5CaEI7TUFzQk0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLGVBQWU7TUFDZixpQkFBaUI7TUFDakIsZ0JBQWdCO01BQ2hCLFVBQVU7TUFDVixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zdGFraW5nL3N0YWtpbmcuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uY2hhcnQtaGVhZGVyIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG5cclxuICAuZ2VuZXJhbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbjogLTAuNXJlbSAwO1xyXG5cclxuICAgID4gZGl2IHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgbWFyZ2luOiAwLjVyZW0gMDtcclxuICAgICAgaGVpZ2h0OiAycmVtO1xyXG5cclxuICAgICAgLmxhYmVsIHtcclxuICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XHJcbiAgICAgICAgd2lkdGg6IDlyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zZWxlY3RlZCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBmbGV4LWVuZDtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgZm9udC1zaXplOiAxLjhyZW07XHJcblxyXG4gICAgc3BhbiB7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjlyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4uY2hhcnQge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgZmxleDogMSAxIGF1dG87XHJcbiAgbWluLWhlaWdodDogNDByZW07XHJcblxyXG4gID4gZGl2IHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiAxMDAlO1xyXG4gIH1cclxufVxyXG5cclxuLmNoYXJ0LW9wdGlvbnMge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBoZWlnaHQ6IDIuNHJlbTtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgcGFkZGluZzogMCAxcmVtO1xyXG5cclxuICAgICY6Zmlyc3QtY2hpbGR7XHJcbiAgICAgIHBhZGRpbmctbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5vcHRpb25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBmbGV4LWdyb3c6IDE7XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIGZsZXg6IDEgMSBhdXRvO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICBtYXJnaW46IDAgMC4xcmVtO1xyXG4gICAgICBwYWRkaW5nOiAwO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Chart} from 'angular-highcharts';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-staking',\r\n templateUrl: './staking.component.html',\r\n styleUrls: ['./staking.component.scss']\r\n})\r\nexport class StakingComponent implements OnInit, OnDestroy {\r\n\r\n parentRouting;\r\n heightAppEvent;\r\n refreshStackingEvent;\r\n\r\n periods = [\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.WEEK1'),\r\n key: '1 week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.WEEK2'),\r\n key: '2 week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH1'),\r\n key: '1 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH3'),\r\n key: '3 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH6'),\r\n key: '6 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.YEAR'),\r\n key: '1 year',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.ALL'),\r\n key: 'All',\r\n active: true\r\n }\r\n ];\r\n\r\n groups = [\r\n {\r\n title: this.translate.instant('STAKING.GROUP.DAY'),\r\n key: 'day',\r\n active: true\r\n },\r\n {\r\n title: this.translate.instant('STAKING.GROUP.WEEK'),\r\n key: 'week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.GROUP.MONTH'),\r\n key: 'month',\r\n active: false\r\n }\r\n ];\r\n\r\n selectedDate = {\r\n date: null,\r\n amount: null\r\n };\r\n\r\n originalData = [];\r\n\r\n chart: Chart;\r\n\r\n total = new BigNumber(0);\r\n pending = {\r\n list: [],\r\n total: new BigNumber(0)\r\n };\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private variablesService: VariablesService,\r\n private backend: BackendService,\r\n private ngZone: NgZone,\r\n private intToMoneyPipe: IntToMoneyPipe,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n static makeGroupTime(key, date) {\r\n if (key === 'day') {\r\n return date.setHours(0, 0, 0, 0);\r\n } else if (key === 'week') {\r\n return new Date(date.setDate(date.getDate() - date.getDay())).setHours(0, 0, 0, 0);\r\n } else {\r\n return new Date(date.setDate(1)).setHours(0, 0, 0, 0);\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n this.getMiningHistory();\r\n });\r\n this.heightAppEvent = this.variablesService.getHeightAppEvent.subscribe((newHeight: number) => {\r\n if (!this.pending.total.isZero()) {\r\n const pendingCount = this.pending.list.length;\r\n for (let i = pendingCount - 1; i >= 0; i--) {\r\n if (newHeight - this.pending.list[i].h >= 10) {\r\n this.pending.list.splice(i, 1);\r\n }\r\n }\r\n if (pendingCount !== this.pending.list.length) {\r\n this.pending.total = new BigNumber(0);\r\n for (let i = 0; i < this.pending.list.length; i++) {\r\n this.pending.total = this.pending.total.plus(this.pending.list[i].a);\r\n }\r\n }\r\n }\r\n });\r\n this.refreshStackingEvent = this.variablesService.getRefreshStackingEvent.subscribe((wallet_id: number) => {\r\n if (this.variablesService.currentWallet.wallet_id === wallet_id) {\r\n this.getMiningHistory();\r\n }\r\n });\r\n }\r\n\r\n\r\n drawChart(data) {\r\n this.chart = new Chart({\r\n title: {text: ''},\r\n credits: {enabled: false},\r\n exporting: {enabled: false},\r\n legend: {enabled: false},\r\n chart: {\r\n type: 'line',\r\n backgroundColor: 'transparent',\r\n height: null,\r\n zoomType: null,\r\n events: {\r\n load: () => {\r\n this.changePeriod();\r\n }\r\n }\r\n },\r\n\r\n yAxis: {\r\n min: 0,\r\n tickAmount: 5,\r\n title: {\r\n text: ''\r\n },\r\n gridLineColor: '#2b3644',\r\n gridLineWidth: 2,\r\n lineColor: '#2b3644',\r\n lineWidth: 2,\r\n tickWidth: 2,\r\n tickLength: 120,\r\n tickColor: '#2b3644',\r\n labels: {\r\n y: -8,\r\n align: 'left',\r\n x: -120,\r\n style: {\r\n 'color': '#e0e0e0',\r\n 'fontSize': '13px'\r\n },\r\n format: '{value} ' + this.variablesService.defaultCurrency\r\n },\r\n showLastLabel: false,\r\n },\r\n\r\n xAxis: {\r\n type: 'datetime',\r\n gridLineColor: '#2b3644',\r\n lineColor: '#2b3644',\r\n lineWidth: 2,\r\n tickWidth: 2,\r\n tickLength: 10,\r\n tickColor: '#2b3644',\r\n labels: {\r\n style: {\r\n 'color': '#e0e0e0',\r\n 'fontSize': '13px'\r\n }\r\n },\r\n minPadding: 0,\r\n maxPadding: 0,\r\n minRange: 86400000,\r\n // tickInterval: 86400000,\r\n minTickInterval: 3600000,\r\n },\r\n\r\n tooltip: {\r\n enabled: false\r\n },\r\n\r\n plotOptions: {\r\n area: {\r\n fillColor: {\r\n linearGradient: {\r\n x1: 0,\r\n y1: 0,\r\n x2: 0,\r\n y2: 1\r\n },\r\n stops: [\r\n [0, 'rgba(124,181,236,0.2)'],\r\n [1, 'rgba(124,181,236,0)']\r\n ]\r\n },\r\n marker: {\r\n enabled: false,\r\n radius: 2\r\n },\r\n lineWidth: 2,\r\n threshold: null\r\n },\r\n\r\n series: {\r\n point: {\r\n events: {\r\n mouseOver: (obj) => {\r\n this.selectedDate.date = obj.target['x'];\r\n this.selectedDate.amount = obj.target['y'];\r\n }\r\n }\r\n },\r\n events: {\r\n mouseOut: () => {\r\n this.selectedDate.date = null;\r\n this.selectedDate.amount = null;\r\n }\r\n }\r\n }\r\n },\r\n series: [\r\n {\r\n type: 'area',\r\n data: data\r\n }\r\n ]\r\n });\r\n }\r\n\r\n\r\n getMiningHistory() {\r\n if (this.variablesService.currentWallet.loaded) {\r\n this.backend.getMiningHistory(this.variablesService.currentWallet.wallet_id, (status, data) => {\r\n this.total = new BigNumber(0);\r\n this.pending.list = [];\r\n this.pending.total = new BigNumber(0);\r\n this.originalData = [];\r\n if (data.mined_entries) {\r\n data.mined_entries.forEach((item, key) => {\r\n if (item.t.toString().length === 10) {\r\n data.mined_entries[key].t = (new Date(item.t * 1000)).setUTCMilliseconds(0);\r\n }\r\n });\r\n data.mined_entries.forEach((item) => {\r\n this.total = this.total.plus(item.a);\r\n if (this.variablesService.height_app - item.h < 10) {\r\n this.pending.list.push(item);\r\n this.pending.total = this.pending.total.plus(item.a);\r\n }\r\n this.originalData.push([parseInt(item.t, 10), parseFloat(this.intToMoneyPipe.transform(item.a))]);\r\n });\r\n this.originalData = this.originalData.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n }\r\n this.ngZone.run(() => {\r\n this.drawChart([]);\r\n });\r\n });\r\n }\r\n }\r\n\r\n changePeriod(period?) {\r\n if (period) {\r\n this.periods.forEach((p) => {\r\n p.active = false;\r\n });\r\n period.active = true;\r\n } else {\r\n period = this.periods.find((p) => p.active);\r\n }\r\n\r\n const d = new Date();\r\n let min = null;\r\n const newData = [];\r\n\r\n const group = this.groups.find((g) => g.active);\r\n\r\n if (period.key === '1 week') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate() - 7, 0, 0, 0, 0);\r\n } else if (period.key === '2 week') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate() - 14, 0, 0, 0, 0);\r\n } else if (period.key === '1 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 1, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '3 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 3, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '6 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 6, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '1 year') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear() - 1, d.getMonth(), d.getDate(), 0, 0, 0, 0);\r\n } else {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n }\r\n\r\n this.chart.ref.xAxis[0].setExtremes(min, null);\r\n }\r\n\r\n changeGroup(group) {\r\n this.groups.forEach((g) => {\r\n g.active = false;\r\n });\r\n group.active = true;\r\n this.changePeriod();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.heightAppEvent.unsubscribe();\r\n this.refreshStackingEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.TRANSFER_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
0 && (transferAddressAlias || !transferAddressValid || (transferAddressValid && !permissionSend) || notEnoughMoney)\\\">\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.WRONG_ADDRESS' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.ALIAS_EXISTS' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"TRANSFER_ALIAS.COST\\\" | translate : {value: variablesService.default_fee, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".form-transfer {\\n margin: 2.4rem 0; }\\n .form-transfer .alias-name {\\n width: 50%; }\\n .form-transfer .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-transfer .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-transfer .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHJhbnNmZXItYWxpYXMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcdHJhbnNmZXItYWxpYXNcXHRyYW5zZmVyLWFsaWFzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsZ0JBQWdCLEVBQUE7RUFEbEI7SUFJSSxVQUFVLEVBQUE7RUFKZDtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0IsRUFBQTtFQVRwQjtJQWFJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsc0JBQXNCLEVBQUE7RUFmMUI7TUFrQk0sZ0JBQWdCO01BQ2hCLFlBQVksRUFBQSIsImZpbGUiOiJzcmMvYXBwL3RyYW5zZmVyLWFsaWFzL3RyYW5zZmVyLWFsaWFzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmZvcm0tdHJhbnNmZXIge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\n@Component({\r\n selector: 'app-transfer-alias',\r\n templateUrl: './transfer-alias.component.html',\r\n styleUrls: ['./transfer-alias.component.scss']\r\n})\r\nexport class TransferAliasComponent implements OnInit {\r\n\r\n wallet: Wallet;\r\n alias: any;\r\n transferAddress = '';\r\n transferAddressValid: boolean;\r\n transferAddressAlias: boolean;\r\n permissionSend: boolean;\r\n notEnoughMoney: boolean;\r\n requestProcessing = false;\r\n\r\n constructor(\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n this.alias = {\r\n name: alias.name,\r\n address: alias.address,\r\n comment: alias.comment,\r\n tracking_key: alias.tracking_key\r\n };\r\n this.notEnoughMoney = this.wallet.unlocked_balance.isLessThan(this.variablesService.default_fee_big);\r\n }\r\n\r\n changeAddress() {\r\n this.backend.validateAddress(this.transferAddress, status => {\r\n this.transferAddressValid = status;\r\n if (status) {\r\n this.backend.getPoolInfo((statusPool, dataPool) => {\r\n if (dataPool.hasOwnProperty('aliases_que') && dataPool.aliases_que.length) {\r\n this.setStatus(!dataPool.aliases_que.some((el) => el.address === this.transferAddress));\r\n } else {\r\n this.setStatus(status);\r\n }\r\n });\r\n } else {\r\n this.setStatus(false);\r\n }\r\n });\r\n }\r\n\r\n setStatus(statusSet) {\r\n this.permissionSend = statusSet;\r\n if (statusSet) {\r\n this.backend.getAliasByAddress(this.transferAddress, (status) => {\r\n this.ngZone.run(() => {\r\n if (status) {\r\n this.transferAddressAlias = true;\r\n this.permissionSend = false;\r\n } else {\r\n this.transferAddressAlias = false;\r\n }\r\n });\r\n });\r\n } else {\r\n this.ngZone.run(() => {\r\n this.transferAddressAlias = false;\r\n });\r\n }\r\n }\r\n\r\n transferAlias() {\r\n if (this.requestProcessing || !this.permissionSend || !this.transferAddressValid || this.notEnoughMoney) {\r\n return;\r\n }\r\n this.requestProcessing = true;\r\n const newAlias = {\r\n name: this.alias.name,\r\n address: this.transferAddress,\r\n comment: this.alias.comment,\r\n tracking_key: this.alias.tracking_key\r\n };\r\n this.backend.updateAlias(this.wallet.wallet_id, newAlias, this.variablesService.default_fee, (status, data) => {\r\n if (status && data.hasOwnProperty('success') && data.success) {\r\n this.modalService.prepareModal('info', 'TRANSFER_ALIAS.REQUEST_SEND_REG');\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n this.requestProcessing = false;\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n @bitmain\\r\\n
\\r\\n \\r\\n \\r\\n {{ 'COMMON.BACK' | translate }}\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
10:39
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
11:44
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
12:15
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
13:13
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.head {\\n flex: 0 0 auto;\\n box-sizing: content-box;\\n margin: -3rem -3rem 0; }\\n\\n.messages-content {\\n display: flex;\\n flex-direction: column;\\n justify-content: space-between;\\n flex-grow: 1; }\\n\\n.messages-content .messages-list {\\n display: flex;\\n flex-direction: column;\\n font-size: 1.3rem;\\n margin: 1rem -3rem;\\n padding: 0 3rem;\\n overflow-y: overlay; }\\n\\n.messages-content .messages-list div {\\n margin: 0.7rem 0; }\\n\\n.messages-content .messages-list div.date {\\n text-align: center; }\\n\\n.messages-content .messages-list div.my, .messages-content .messages-list div.buddy {\\n position: relative;\\n padding: 1.8rem;\\n max-width: 60%; }\\n\\n.messages-content .messages-list div.buddy {\\n align-self: flex-end; }\\n\\n.messages-content .type-message {\\n display: flex;\\n flex: 0 0 auto;\\n width: 100%;\\n height: 4.2rem; }\\n\\n.messages-content .type-message .input-block {\\n width: 100%; }\\n\\n.messages-content .type-message .input-block > textarea {\\n min-height: 4.2rem; }\\n\\n.messages-content .type-message button {\\n flex: 0 0 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcdHlwaW5nLW1lc3NhZ2VcXHR5cGluZy1tZXNzYWdlLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixXQUFXLEVBQUE7O0FBR2I7RUFDRSxjQUFjO0VBQ2QsdUJBQXVCO0VBQ3ZCLHFCQUFxQixFQUFBOztBQUd2QjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsOEJBQThCO0VBQzlCLFlBQVksRUFBQTs7QUFKZDtJQU9JLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsaUJBQWlCO0lBQ2pCLGtCQUFrQjtJQUNsQixlQUFlO0lBQ2YsbUJBQW1CLEVBQUE7O0FBWnZCO01BZU0sZ0JBQWdCLEVBQUE7O0FBZnRCO1FBa0JRLGtCQUFrQixFQUFBOztBQWxCMUI7UUFzQlEsa0JBQWtCO1FBQ2xCLGVBQWU7UUFDZixjQUFjLEVBQUE7O0FBeEJ0QjtRQTRCUSxvQkFBb0IsRUFBQTs7QUE1QjVCO0lBa0NJLGFBQWE7SUFDYixjQUFjO0lBQ2QsV0FBVztJQUNYLGNBQWMsRUFBQTs7QUFyQ2xCO01Bd0NNLFdBQVcsRUFBQTs7QUF4Q2pCO1FBMkNRLGtCQUFrQixFQUFBOztBQTNDMUI7TUFnRE0sZUFBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvdHlwaW5nLW1lc3NhZ2UuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAgZmxleDogMCAwIGF1dG87XHJcbiAgYm94LXNpemluZzogY29udGVudC1ib3g7XHJcbiAgbWFyZ2luOiAtM3JlbSAtM3JlbSAwO1xyXG59XHJcblxyXG4ubWVzc2FnZXMtY29udGVudCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICBmbGV4LWdyb3c6IDE7XHJcblxyXG4gIC5tZXNzYWdlcy1saXN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW46IDFyZW0gLTNyZW07XHJcbiAgICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgICBvdmVyZmxvdy15OiBvdmVybGF5O1xyXG5cclxuICAgIGRpdiB7XHJcbiAgICAgIG1hcmdpbjogMC43cmVtIDA7XHJcblxyXG4gICAgICAmLmRhdGUge1xyXG4gICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5teSwgJi5idWRkeSB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIHBhZGRpbmc6IDEuOHJlbTtcclxuICAgICAgICBtYXgtd2lkdGg6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5idWRkeSB7XHJcbiAgICAgICAgYWxpZ24tc2VsZjogZmxleC1lbmQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC50eXBlLW1lc3NhZ2Uge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXg6IDAgMCBhdXRvO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDQuMnJlbTtcclxuXHJcbiAgICAuaW5wdXQtYmxvY2sge1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgID4gdGV4dGFyZWEge1xyXG4gICAgICAgIG1pbi1oZWlnaHQ6IDQuMnJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGZsZXg6IDAgMCAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbiJdfQ== */\"","import { Component, OnInit } from '@angular/core';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-typing-message',\r\n templateUrl: './typing-message.component.html',\r\n styleUrls: ['./typing-message.component.scss']\r\n})\r\nexport class TypingMessageComponent implements OnInit {\r\n\r\n messagesId: number;\r\n private subMessages: any;\r\n\r\n constructor(private route: ActivatedRoute) {\r\n this.route.params.subscribe( params => console.log(params) );\r\n }\r\n\r\n ngOnInit() {\r\n\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.name}}\\r\\n {{ 'BREADCRUMBS.WALLET_DETAILS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n
{{ 'WALLET_DETAILS.SEED_PHRASE_HINT' | translate }}
\\r\\n
\\r\\n \\r\\n
{{(index + 1) + '. ' + word}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".form-details {\\n margin-top: 1.8rem; }\\n .form-details .input-block:first-child {\\n width: 50%; }\\n .form-details .seed-phrase {\\n display: flex;\\n font-size: 1.4rem;\\n line-height: 1.5rem;\\n padding: 1.4rem;\\n width: 100%;\\n height: 8.8rem; }\\n .form-details .seed-phrase .seed-phrase-hint {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n cursor: pointer;\\n width: 100%;\\n height: 100%; }\\n .form-details .seed-phrase .seed-phrase-content {\\n display: flex;\\n flex-direction: column;\\n flex-wrap: wrap;\\n width: 100%;\\n height: 100%; }\\n .form-details .wallet-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n .form-details .wallet-buttons button {\\n margin: 2.9rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0LWRldGFpbHMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcd2FsbGV0LWRldGFpbHNcXHdhbGxldC1kZXRhaWxzLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCLEVBQUE7RUFEcEI7SUFNTSxVQUFVLEVBQUE7RUFOaEI7SUFXSSxhQUFhO0lBQ2IsaUJBQWlCO0lBQ2pCLG1CQUFtQjtJQUNuQixlQUFlO0lBQ2YsV0FBVztJQUNYLGNBQWMsRUFBQTtFQWhCbEI7TUFtQk0sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7RUF4QmxCO01BNEJNLGFBQWE7TUFDYixzQkFBc0I7TUFDdEIsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7RUFoQ2xCO0lBcUNJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCLEVBQUE7RUF2Q2xDO01BMENNLGdCQUFnQjtNQUNoQixXQUFXO01BQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC93YWxsZXQtZGV0YWlscy93YWxsZXQtZGV0YWlscy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWRldGFpbHMge1xyXG4gIG1hcmdpbi10b3A6IDEuOHJlbTtcclxuXHJcbiAgLmlucHV0LWJsb2NrIHtcclxuXHJcbiAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgd2lkdGg6IDUwJTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zZWVkLXBocmFzZSB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS41cmVtO1xyXG4gICAgcGFkZGluZzogMS40cmVtO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDguOHJlbTtcclxuXHJcbiAgICAuc2VlZC1waHJhc2UtaGludCB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcblxyXG4gICAgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBmbGV4LXdyYXA6IHdyYXA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAud2FsbGV0LWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAyLjlyZW0gMDtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Router} from '@angular/router';\r\nimport {Location} from '@angular/common';\r\n\r\n@Component({\r\n selector: 'app-wallet-details',\r\n templateUrl: './wallet-details.component.html',\r\n styleUrls: ['./wallet-details.component.scss']\r\n})\r\nexport class WalletDetailsComponent implements OnInit, OnDestroy {\r\n seedPhrase = '';\r\n showSeed = false;\r\n\r\n detailsForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n return {'same': true};\r\n } else {\r\n return {'duplicate': true};\r\n }\r\n }\r\n }\r\n return null;\r\n }]),\r\n path: new FormControl('')\r\n });\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private location: Location\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.showSeed = false;\r\n this.detailsForm.get('name').setValue(this.variablesService.currentWallet.name);\r\n this.detailsForm.get('path').setValue(this.variablesService.currentWallet.path);\r\n this.backend.getSmartWalletInfo(this.variablesService.currentWallet.wallet_id, (status, data) => {\r\n if (data.hasOwnProperty('restore_key')) {\r\n this.ngZone.run(() => {\r\n this.seedPhrase = data['restore_key'].trim();\r\n });\r\n }\r\n });\r\n }\r\n\r\n showSeedPhrase() {\r\n this.showSeed = true;\r\n }\r\n\r\n onSubmitEdit() {\r\n if (this.detailsForm.value) {\r\n this.variablesService.currentWallet.name = this.detailsForm.get('name').value;\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n });\r\n }\r\n }\r\n\r\n closeWallet() {\r\n this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {\r\n for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n this.variablesService.wallets.splice(i, 1);\r\n }\r\n }\r\n this.ngZone.run(() => {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.currentWallet = this.variablesService.wallets[0];\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n } else {\r\n this.router.navigate(['/']);\r\n }\r\n });\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {}\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n

{{variablesService.currentWallet.name}}

\\r\\n \\r\\n
\\r\\n {{variablesService.currentWallet.alias['name']}}\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.address}}\\r\\n \\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.balance | intToMoney : '3'}} {{variablesService.defaultCurrency}}\\r\\n $ {{variablesService.currentWallet.getMoneyEquivalent(variablesService.moneyEquivalent) | intToMoney | number : '1.2-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ tab.title | translate }}\\r\\n {{variablesService.currentWallet.new_contracts}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n padding: 0 3rem 3rem;\\n min-width: 95rem;\\n width: 100%;\\n height: 100%; }\\n\\n.header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n flex: 0 0 auto;\\n height: 8rem; }\\n\\n.header > div {\\n display: flex;\\n align-items: center; }\\n\\n.header > div :not(:last-child) {\\n margin-right: 3.2rem; }\\n\\n.header h3 {\\n font-size: 1.7rem;\\n font-weight: 600;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap;\\n max-width: 50rem;\\n line-height: 2.7rem; }\\n\\n.header button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n cursor: pointer;\\n font-weight: 400;\\n outline: none;\\n padding: 0; }\\n\\n.header button .icon {\\n margin-right: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.header button .icon.account {\\n height: 1.6rem;\\n -webkit-mask: url('account.svg') no-repeat center;\\n mask: url('account.svg') no-repeat center; }\\n\\n.header button .icon.lock {\\n -webkit-mask: url('lock.svg') no-repeat center;\\n mask: url('lock.svg') no-repeat center; }\\n\\n.header button .icon.details {\\n -webkit-mask: url('details-settings.svg') no-repeat center;\\n mask: url('details-settings.svg') no-repeat center;\\n margin-right: 0;\\n height: 1.8rem; }\\n\\n.header button .icon.close-wallet {\\n -webkit-mask: url('close-wallet.svg') no-repeat center;\\n mask: url('close-wallet.svg') no-repeat center;\\n margin-right: 0; }\\n\\n.header .alias {\\n display: flex;\\n align-items: center;\\n font-size: 1.3rem; }\\n\\n.header .alias .icon {\\n cursor: pointer;\\n margin-right: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.header .alias .icon.edit {\\n -webkit-mask: url('details.svg') no-repeat center;\\n mask: url('details.svg') no-repeat center; }\\n\\n.header .alias .icon.transfer {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.address {\\n display: flex;\\n align-items: center;\\n flex: 0 0 auto;\\n font-size: 1.4rem;\\n line-height: 1.7rem; }\\n\\n.address .icon {\\n cursor: pointer;\\n margin-left: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.address .icon.copy {\\n width: 1.8rem;\\n -webkit-mask: url('copy.svg') no-repeat center;\\n mask: url('copy.svg') no-repeat center; }\\n\\n.address .icon.copy:hover {\\n opacity: 0.75; }\\n\\n.address .icon.copied {\\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\\n mask: url('complete-testwallet.svg') no-repeat center; }\\n\\n.balance {\\n display: flex;\\n align-items: flex-end;\\n justify-content: flex-start;\\n flex: 0 0 auto;\\n margin: 2.6rem 0; }\\n\\n.balance :first-child {\\n font-size: 3.3rem;\\n font-weight: 600;\\n line-height: 2.4rem;\\n margin-right: 3.5rem; }\\n\\n.balance :last-child {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 1.3rem; }\\n\\n.tabs {\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto; }\\n\\n.tabs .tabs-header {\\n display: flex;\\n justify-content: space-between;\\n flex: 0 0 auto; }\\n\\n.tabs .tabs-header .tab {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 0 auto;\\n cursor: pointer;\\n padding: 0 1rem;\\n height: 5rem; }\\n\\n.tabs .tabs-header .tab .animated {\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n margin-right: 1.3rem; }\\n\\n.tabs .tabs-header .tab .animated ::ng-deep svg {\\n width: 2rem;\\n height: 2rem; }\\n\\n.tabs .tabs-header .tab .animated ::ng-deep svg path, .tabs .tabs-header .tab .animated ::ng-deep svg circle, .tabs .tabs-header .tab .animated ::ng-deep svg polygon {\\n fill: #4db1ff; }\\n\\n.tabs .tabs-header .tab .icon {\\n margin-right: 1.3rem;\\n width: 2rem;\\n height: 2rem; }\\n\\n.tabs .tabs-header .tab .icon.send {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.receive {\\n -webkit-mask: url('receive.svg') no-repeat center;\\n mask: url('receive.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.history {\\n -webkit-mask: url('history.svg') no-repeat center;\\n mask: url('history.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.contracts {\\n -webkit-mask: url('contracts.svg') no-repeat center;\\n mask: url('contracts.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.messages {\\n -webkit-mask: url('message.svg') no-repeat center;\\n mask: url('message.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.staking {\\n -webkit-mask: url('staking.svg') no-repeat center;\\n mask: url('staking.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .indicator {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 1rem;\\n font-size: 1rem;\\n font-weight: 600;\\n margin-left: 1.3rem;\\n padding: 0 0.5rem;\\n min-width: 1.6rem;\\n height: 1.6rem; }\\n\\n.tabs .tabs-header .tab.disabled {\\n cursor: url('not-allowed.svg'), not-allowed; }\\n\\n.tabs .tabs-header .tab:not(:last-child) {\\n margin-right: 0.3rem; }\\n\\n.tabs .tabs-content {\\n display: flex;\\n padding: 3rem;\\n flex: 1 1 auto;\\n overflow-x: hidden;\\n overflow-y: overlay; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0L0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHdhbGxldFxcd2FsbGV0LmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsb0JBQW9CO0VBQ3BCLGdCQUFnQjtFQUNoQixXQUFXO0VBQ1gsWUFBWSxFQUFBOztBQUdkO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQiw4QkFBOEI7RUFDOUIsY0FBYztFQUNkLFlBQVksRUFBQTs7QUFMZDtJQVFJLGFBQWE7SUFDYixtQkFBbUIsRUFBQTs7QUFUdkI7TUFZTSxvQkFBb0IsRUFBQTs7QUFaMUI7SUFpQkksaUJBQWlCO0lBQ2pCLGdCQUFnQjtJQUNoQix1QkFBdUI7SUFDdkIsZ0JBQWdCO0lBQ2hCLG1CQUFtQjtJQUNuQixnQkFBZ0I7SUFDaEIsbUJBQW1CLEVBQUE7O0FBdkJ2QjtJQTJCSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixZQUFZO0lBQ1osZUFBZTtJQUNmLGdCQUFnQjtJQUNoQixhQUFhO0lBQ2IsVUFBVSxFQUFBOztBQWxDZDtNQXFDTSxvQkFBb0I7TUFDcEIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUF2Q3BCO1FBMENRLGNBQWM7UUFDZCxpREFBMEQ7Z0JBQTFELHlDQUEwRCxFQUFBOztBQTNDbEU7UUErQ1EsOENBQXVEO2dCQUF2RCxzQ0FBdUQsRUFBQTs7QUEvQy9EO1FBbURRLDBEQUFtRTtnQkFBbkUsa0RBQW1FO1FBQ25FLGVBQWU7UUFDZixjQUFjLEVBQUE7O0FBckR0QjtRQXlEUSxzREFBK0Q7Z0JBQS9ELDhDQUErRDtRQUMvRCxlQUFlLEVBQUE7O0FBMUR2QjtJQWdFSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLGlCQUFpQixFQUFBOztBQWxFckI7TUFxRU0sZUFBZTtNQUNmLG9CQUFvQjtNQUNwQixhQUFhO01BQ2IsY0FBYyxFQUFBOztBQXhFcEI7UUEyRVEsaURBQTBEO2dCQUExRCx5Q0FBMEQsRUFBQTs7QUEzRWxFO1FBK0VRLDhDQUF1RDtnQkFBdkQsc0NBQXVELEVBQUE7O0FBTS9EO0VBQ0UsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQixjQUFjO0VBQ2QsaUJBQWlCO0VBQ2pCLG1CQUFtQixFQUFBOztBQUxyQjtJQVFJLGVBQWU7SUFDZixtQkFBbUI7SUFDbkIsYUFBYTtJQUNiLGNBQWMsRUFBQTs7QUFYbEI7TUFjTSxhQUFhO01BQ2IsOENBQXVEO2NBQXZELHNDQUF1RCxFQUFBOztBQWY3RDtRQWtCUSxhQUFhLEVBQUE7O0FBbEJyQjtNQXVCTSw2REFBc0U7Y0FBdEUscURBQXNFLEVBQUE7O0FBSzVFO0VBQ0UsYUFBYTtFQUNiLHFCQUFxQjtFQUNyQiwyQkFBMkI7RUFDM0IsY0FBYztFQUNkLGdCQUFnQixFQUFBOztBQUxsQjtJQVFJLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsbUJBQW1CO0lBQ25CLG9CQUFvQixFQUFBOztBQVh4QjtJQWVJLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsbUJBQW1CLEVBQUE7O0FBSXZCO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QixjQUFjLEVBQUE7O0FBSGhCO0lBTUksYUFBYTtJQUNiLDhCQUE4QjtJQUM5QixjQUFjLEVBQUE7O0FBUmxCO01BV00sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLGVBQWU7TUFDZixlQUFlO01BQ2YsWUFBWSxFQUFBOztBQWpCbEI7UUFvQlEsYUFBYTtRQUNiLHVCQUF1QjtRQUN2QixtQkFBbUI7UUFDbkIsb0JBQW9CLEVBQUE7O0FBdkI1QjtRQTRCUSxXQUFXO1FBQ1gsWUFBWSxFQUFBOztBQTdCcEI7VUFnQ1UsYUFBYSxFQUFBOztBQWhDdkI7UUFxQ1Esb0JBQW9CO1FBQ3BCLFdBQVc7UUFDWCxZQUFZLEVBQUE7O0FBdkNwQjtVQTBDVSw4Q0FBdUQ7a0JBQXZELHNDQUF1RCxFQUFBOztBQTFDakU7VUE4Q1UsaURBQTBEO2tCQUExRCx5Q0FBMEQsRUFBQTs7QUE5Q3BFO1VBa0RVLGlEQUEwRDtrQkFBMUQseUNBQTBELEVBQUE7O0FBbERwRTtVQXNEVSxtREFBNEQ7a0JBQTVELDJDQUE0RCxFQUFBOztBQXREdEU7VUEwRFUsaURBQTBEO2tCQUExRCx5Q0FBMEQsRUFBQTs7QUExRHBFO1VBOERVLGlEQUEwRDtrQkFBMUQseUNBQTBELEVBQUE7O0FBOURwRTtRQW1FUSxhQUFhO1FBQ2IsbUJBQW1CO1FBQ25CLHVCQUF1QjtRQUN2QixtQkFBbUI7UUFDbkIsZUFBZTtRQUNmLGdCQUFnQjtRQUNoQixtQkFBbUI7UUFDbkIsaUJBQWlCO1FBQ2pCLGlCQUFpQjtRQUNqQixjQUFjLEVBQUE7O0FBNUV0QjtRQWdGUSwyQ0FBNEQsRUFBQTs7QUFoRnBFO1FBb0ZRLG9CQUFvQixFQUFBOztBQXBGNUI7SUEwRkksYUFBYTtJQUNiLGFBQWE7SUFDYixjQUFjO0lBQ2Qsa0JBQWtCO0lBQ2xCLG1CQUFtQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvd2FsbGV0L3dhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIHBhZGRpbmc6IDAgM3JlbSAzcmVtO1xyXG4gIG1pbi13aWR0aDogOTVyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZGVyIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGhlaWdodDogOHJlbTtcclxuXHJcbiAgPiBkaXYge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcblxyXG4gICAgOm5vdCg6bGFzdC1jaGlsZCkge1xyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDMuMnJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGgzIHtcclxuICAgIGZvbnQtc2l6ZTogMS43cmVtO1xyXG4gICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICBtYXgtd2lkdGg6IDUwcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICB9XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAxLjJyZW07XHJcbiAgICAgIHdpZHRoOiAxLjdyZW07XHJcbiAgICAgIGhlaWdodDogMS43cmVtO1xyXG5cclxuICAgICAgJi5hY2NvdW50IHtcclxuICAgICAgICBoZWlnaHQ6IDEuNnJlbTtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2FjY291bnQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmxvY2sge1xyXG4gICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvbG9jay5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuZGV0YWlscyB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9kZXRhaWxzLXNldHRpbmdzLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDA7XHJcbiAgICAgICAgaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuY2xvc2Utd2FsbGV0IHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2Nsb3NlLXdhbGxldC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAwO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYWxpYXMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAxLjJyZW07XHJcbiAgICAgIHdpZHRoOiAxLjdyZW07XHJcbiAgICAgIGhlaWdodDogMS43cmVtO1xyXG5cclxuICAgICAgJi5lZGl0IHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2RldGFpbHMuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnRyYW5zZmVyIHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3NlbmQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4uYWRkcmVzcyB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGZvbnQtc2l6ZTogMS40cmVtO1xyXG4gIGxpbmUtaGVpZ2h0OiAxLjdyZW07XHJcblxyXG4gIC5pY29uIHtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIG1hcmdpbi1sZWZ0OiAxLjJyZW07XHJcbiAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgaGVpZ2h0OiAxLjdyZW07XHJcblxyXG4gICAgJi5jb3B5IHtcclxuICAgICAgd2lkdGg6IDEuOHJlbTtcclxuICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9jb3B5LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuXHJcbiAgICAgICY6aG92ZXIge1xyXG4gICAgICAgIG9wYWNpdHk6IDAuNzU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLmNvcGllZCB7XHJcbiAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvY29tcGxldGUtdGVzdHdhbGxldC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4uYmFsYW5jZSB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIG1hcmdpbjogMi42cmVtIDA7XHJcblxyXG4gIDpmaXJzdC1jaGlsZCB7XHJcbiAgICBmb250LXNpemU6IDMuM3JlbTtcclxuICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICBsaW5lLWhlaWdodDogMi40cmVtO1xyXG4gICAgbWFyZ2luLXJpZ2h0OiAzLjVyZW07XHJcbiAgfVxyXG5cclxuICA6bGFzdC1jaGlsZCB7XHJcbiAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICBsaW5lLWhlaWdodDogMS4zcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLnRhYnMge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuXHJcbiAgLnRhYnMtaGVhZGVyIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBmbGV4OiAwIDAgYXV0bztcclxuXHJcbiAgICAudGFiIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIGZsZXg6IDEgMCBhdXRvO1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgaGVpZ2h0OiA1cmVtO1xyXG5cclxuICAgICAgLmFuaW1hdGVkIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjNyZW07XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIC5hbmltYXRlZCA6Om5nLWRlZXAgc3ZnIHtcclxuICAgICAgXHJcbiAgICAgICAgd2lkdGg6IDJyZW07XHJcbiAgICAgICAgaGVpZ2h0OiAycmVtO1xyXG4gICAgICBcclxuICAgICAgICBwYXRoLCBjaXJjbGUsIHBvbHlnb24ge1xyXG4gICAgICAgICAgZmlsbDogIzRkYjFmZjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuM3JlbTtcclxuICAgICAgICB3aWR0aDogMnJlbTtcclxuICAgICAgICBoZWlnaHQ6IDJyZW07XHJcblxyXG4gICAgICAgICYuc2VuZCB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3NlbmQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5yZWNlaXZlIHtcclxuICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvcmVjZWl2ZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmhpc3Rvcnkge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9oaXN0b3J5LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuY29udHJhY3RzIHtcclxuICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvY29udHJhY3RzLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYubWVzc2FnZXMge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9tZXNzYWdlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuc3Rha2luZyB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3N0YWtpbmcuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmluZGljYXRvciB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDFyZW07XHJcbiAgICAgICAgZm9udC1zaXplOiAxcmVtO1xyXG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDEuM3JlbTtcclxuICAgICAgICBwYWRkaW5nOiAwIDAuNXJlbTtcclxuICAgICAgICBtaW4td2lkdGg6IDEuNnJlbTtcclxuICAgICAgICBoZWlnaHQ6IDEuNnJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5kaXNhYmxlZCB7XHJcbiAgICAgICAgY3Vyc29yOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL25vdC1hbGxvd2VkLnN2ZyksIG5vdC1hbGxvd2VkO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOm5vdCg6bGFzdC1jaGlsZCkge1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMC4zcmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGFicy1jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBwYWRkaW5nOiAzcmVtO1xyXG4gICAgZmxleDogMSAxIGF1dG87XHJcbiAgICBvdmVyZmxvdy14OiBoaWRkZW47XHJcbiAgICBvdmVyZmxvdy15OiBvdmVybGF5O1xyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, OnDestroy, NgZone, ViewChild, ElementRef} from '@angular/core';\r\nimport {ActivatedRoute, Router, RoutesRecognized} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {Subscription} from 'rxjs';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-wallet',\r\n templateUrl: './wallet.component.html',\r\n styleUrls: ['./wallet.component.scss']\r\n})\r\nexport class WalletComponent implements OnInit, OnDestroy {\r\n subRouting1;\r\n subRouting2;\r\n queryRouting;\r\n walletID;\r\n copyAnimation = false;\r\n copyAnimationTimeout;\r\n balanceTooltip;\r\n isModalDialogVisible = false;\r\n\r\n @ViewChild('scrolledContent') private scrolledContent: ElementRef;\r\n\r\n tabs = [\r\n {\r\n title: 'WALLET.TABS.HISTORY',\r\n icon: 'history',\r\n link: '/history',\r\n indicator: false,\r\n active: true,\r\n animated: icons.history,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.SEND',\r\n icon: 'send',\r\n link: '/send',\r\n indicator: false,\r\n active: false,\r\n animated: icons.send,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.RECEIVE',\r\n icon: 'receive',\r\n link: '/receive',\r\n indicator: false,\r\n active: false,\r\n animated: icons.receive,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.CONTRACTS',\r\n icon: 'contracts',\r\n link: '/contracts',\r\n indicator: 1,\r\n active: false,\r\n animated: icons.contracts,\r\n itemHovered: false\r\n },\r\n /*{\r\n title: 'WALLET.TABS.MESSAGES',\r\n icon: 'messages',\r\n link: '/messages',\r\n indicator: 32,\r\n active: false,\r\n animated: icons.messages,\r\n itemHovered: false\r\n },*/\r\n {\r\n title: 'WALLET.TABS.STAKING',\r\n icon: 'staking',\r\n link: '/staking',\r\n indicator: false,\r\n active: false,\r\n animated: icons.staking,\r\n itemHovered: false\r\n }\r\n ];\r\n aliasSubscription: Subscription;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService,\r\n private intToMoneyPipe: IntToMoneyPipe\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.subRouting1 = this.route.params.subscribe(params => {\r\n this.walletID = +params['id'];\r\n this.variablesService.setCurrentWallet(this.walletID);\r\n this.scrolledContent.nativeElement.scrollTop = 0;\r\n clearTimeout(this.copyAnimationTimeout);\r\n this.copyAnimation = false;\r\n });\r\n this.subRouting2 = this.router.events.subscribe(val => {\r\n if (val instanceof RoutesRecognized) {\r\n if ( val.state.root.firstChild && val.state.root.firstChild.firstChild ) {\r\n for (let i = 0; i < this.tabs.length; i++) {\r\n this.tabs[i].active = (this.tabs[i].link === '/' + val.state.root.firstChild.firstChild.url[0].path);\r\n }\r\n }\r\n }\r\n });\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.send) {\r\n this.tabs.forEach((tab, index) => {\r\n if (tab.link === '/send') {\r\n this.changeTab(index);\r\n }\r\n });\r\n }\r\n });\r\n if (this.variablesService.currentWallet.alias.hasOwnProperty('name')) {\r\n this.variablesService.currentWallet.wakeAlias = false;\r\n }\r\n this.aliasSubscription = this.variablesService.getAliasChangedEvent.subscribe(() => {\r\n if (this.variablesService.currentWallet.alias.hasOwnProperty('name')) {\r\n this.variablesService.currentWallet.wakeAlias = false;\r\n }\r\n });\r\n }\r\n\r\n changeTab(index) {\r\n if ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts' || this.tabs[index].link === '/staking') && (this.variablesService.daemon_state !== 2 || !this.variablesService.currentWallet.loaded)) {\r\n return;\r\n }\r\n this.tabs.forEach((tab) => {\r\n tab.active = false;\r\n });\r\n this.tabs[index].active = true;\r\n this.ngZone.run( () => {\r\n this.scrolledContent.nativeElement.scrollTop = 0;\r\n this.router.navigate(['wallet/' + this.walletID + this.tabs[index].link]);\r\n });\r\n }\r\n\r\n itemHovered(index, state: boolean) {\r\n this.tabs[index].itemHovered = state;\r\n }\r\n\r\n copyAddress() {\r\n this.backend.setClipboard(this.variablesService.currentWallet.address);\r\n this.copyAnimation = true;\r\n this.copyAnimationTimeout = window.setTimeout(() => {\r\n this.copyAnimation = false;\r\n }, 2000);\r\n }\r\n\r\n getTooltip() {\r\n this.balanceTooltip = document.createElement('div');\r\n const available = document.createElement('span');\r\n available.setAttribute('class', 'available');\r\n available.innerHTML = this.translate.instant('WALLET.AVAILABLE_BALANCE', {available: this.intToMoneyPipe.transform(this.variablesService.currentWallet.unlocked_balance), currency: this.variablesService.defaultCurrency});\r\n this.balanceTooltip.appendChild(available);\r\n const locked = document.createElement('span');\r\n locked.setAttribute('class', 'locked');\r\n locked.innerHTML = this.translate.instant('WALLET.LOCKED_BALANCE', {locked: this.intToMoneyPipe.transform(this.variablesService.currentWallet.balance.minus(this.variablesService.currentWallet.unlocked_balance)), currency: this.variablesService.defaultCurrency});\r\n this.balanceTooltip.appendChild(locked);\r\n const link = document.createElement('span');\r\n link.setAttribute('class', 'link');\r\n link.innerHTML = this.translate.instant('WALLET.LOCKED_BALANCE_LINK');\r\n link.addEventListener('click', () => {\r\n this.openInBrowser('docs.zano.org/docs/locked-balance');\r\n });\r\n this.balanceTooltip.appendChild(link);\r\n return this.balanceTooltip;\r\n }\r\n\r\n onHideTooltip() {\r\n this.balanceTooltip = null;\r\n }\r\n\r\n openInBrowser(link) {\r\n this.backend.openUrlInBrowser(link);\r\n }\r\n\r\n showDialog() {\r\n this.isModalDialogVisible = true;\r\n }\r\n\r\n confirmed(confirmed: boolean) {\r\n if (confirmed) {\r\n this.closeWallet();\r\n }\r\n this.isModalDialogVisible = false;\r\n }\r\n\r\n closeWallet() {\r\n this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {\r\n for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n this.variablesService.wallets.splice(i, 1);\r\n }\r\n }\r\n this.ngZone.run(() => {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.currentWallet = this.variablesService.wallets[0];\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n } else {\r\n this.router.navigate(['/']);\r\n }\r\n });\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.subRouting1.unsubscribe();\r\n this.subRouting2.unsubscribe();\r\n this.queryRouting.unsubscribe();\r\n this.aliasSubscription.unsubscribe();\r\n clearTimeout(this.copyAnimationTimeout);\r\n }\r\n\r\n}\r\n","// This file can be replaced during build by using the `fileReplacements` array.\r\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\r\n// The list of file replacements can be found in `angular.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n\r\n/*\r\n * For easier debugging in development mode, you can import the following file\r\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\r\n *\r\n * This import should be commented out in production mode because it will have a negative impact\r\n * on performance if an error is thrown.\r\n */\r\n// import 'zone.js/dist/zone-error'; // Included with Angular CLI.\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\n\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from './environments/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule)\r\n .catch(err => console.error(err));\r\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///./src/$_lazy_route_resource lazy namespace object","webpack:///./src/app/_helpers/directives/confirm-modal/confirm-modal.component.html","webpack:///./src/app/_helpers/directives/confirm-modal/confirm-modal.component.scss","webpack:///./src/app/_helpers/directives/confirm-modal/confirm-modal.component.ts","webpack:///./src/app/_helpers/directives/input-disable-selection/input-disable-selection.directive.ts","webpack:///./src/app/_helpers/directives/input-validate/input-validate.directive.ts","webpack:///./src/app/_helpers/directives/modal-container/modal-container.component.html","webpack:///./src/app/_helpers/directives/modal-container/modal-container.component.scss","webpack:///./src/app/_helpers/directives/modal-container/modal-container.component.ts","webpack:///./src/app/_helpers/directives/progress-container/progress-container.component.html","webpack:///./src/app/_helpers/directives/progress-container/progress-container.component.scss","webpack:///./src/app/_helpers/directives/progress-container/progress-container.component.ts","webpack:///./src/app/_helpers/directives/staking-switch/staking-switch.component.html","webpack:///./src/app/_helpers/directives/staking-switch/staking-switch.component.scss","webpack:///./src/app/_helpers/directives/staking-switch/staking-switch.component.ts","webpack:///./src/app/_helpers/directives/tooltip.directive.ts","webpack:///./src/app/_helpers/directives/transaction-details/transaction-details.component.html","webpack:///./src/app/_helpers/directives/transaction-details/transaction-details.component.scss","webpack:///./src/app/_helpers/directives/transaction-details/transaction-details.component.ts","webpack:///./src/app/_helpers/models/transaction.model.ts","webpack:///./src/app/_helpers/models/wallet.model.ts","webpack:///./src/app/_helpers/pipes/contract-status-messages.pipe.ts","webpack:///./src/app/_helpers/pipes/contract-time-left.pipe.ts","webpack:///./src/app/_helpers/pipes/history-type-messages.pipe.ts","webpack:///./src/app/_helpers/pipes/int-to-money.pipe.ts","webpack:///./src/app/_helpers/pipes/money-to-int.pipe.ts","webpack:///./src/app/_helpers/pipes/safe-html.pipe.ts","webpack:///./src/app/_helpers/services/backend.service.ts","webpack:///./src/app/_helpers/services/modal.service.ts","webpack:///./src/app/_helpers/services/variables.service.ts","webpack:///./src/app/add-contacts/add-contacts.component.html","webpack:///./src/app/add-contacts/add-contacts.component.scss","webpack:///./src/app/add-contacts/add-contacts.component.ts","webpack:///./src/app/app-routing.module.ts","webpack:///./src/app/app.component.html","webpack:///./src/app/app.component.scss","webpack:///./src/app/app.component.ts","webpack:///./src/app/app.module.ts","webpack:///./src/app/assign-alias/assign-alias.component.html","webpack:///./src/app/assign-alias/assign-alias.component.scss","webpack:///./src/app/assign-alias/assign-alias.component.ts","webpack:///./src/app/contact-send/contact-send.component.html","webpack:///./src/app/contact-send/contact-send.component.scss","webpack:///./src/app/contact-send/contact-send.component.ts","webpack:///./src/app/contacts/contacts.component.html","webpack:///./src/app/contacts/contacts.component.scss","webpack:///./src/app/contacts/contacts.component.ts","webpack:///./src/app/contracts/contracts.component.html","webpack:///./src/app/contracts/contracts.component.scss","webpack:///./src/app/contracts/contracts.component.ts","webpack:///./src/app/create-wallet/create-wallet.component.html","webpack:///./src/app/create-wallet/create-wallet.component.scss","webpack:///./src/app/create-wallet/create-wallet.component.ts","webpack:///./src/app/edit-alias/edit-alias.component.html","webpack:///./src/app/edit-alias/edit-alias.component.scss","webpack:///./src/app/edit-alias/edit-alias.component.ts","webpack:///./src/app/export-import/export-import.component.html","webpack:///./src/app/export-import/export-import.component.scss","webpack:///./src/app/export-import/export-import.component.ts","webpack:///./src/app/history/history.component.html","webpack:///./src/app/history/history.component.scss","webpack:///./src/app/history/history.component.ts","webpack:///./src/app/login/login.component.html","webpack:///./src/app/login/login.component.scss","webpack:///./src/app/login/login.component.ts","webpack:///./src/app/main/main.component.html","webpack:///./src/app/main/main.component.scss","webpack:///./src/app/main/main.component.ts","webpack:///./src/app/messages/messages.component.html","webpack:///./src/app/messages/messages.component.scss","webpack:///./src/app/messages/messages.component.ts","webpack:///./src/app/open-wallet-modal/open-wallet-modal.component.html","webpack:///./src/app/open-wallet-modal/open-wallet-modal.component.scss","webpack:///./src/app/open-wallet-modal/open-wallet-modal.component.ts","webpack:///./src/app/open-wallet/open-wallet.component.html","webpack:///./src/app/open-wallet/open-wallet.component.scss","webpack:///./src/app/open-wallet/open-wallet.component.ts","webpack:///./src/app/purchase/purchase.component.html","webpack:///./src/app/purchase/purchase.component.scss","webpack:///./src/app/purchase/purchase.component.ts","webpack:///./src/app/receive/receive.component.html","webpack:///./src/app/receive/receive.component.scss","webpack:///./src/app/receive/receive.component.ts","webpack:///./src/app/restore-wallet/restore-wallet.component.html","webpack:///./src/app/restore-wallet/restore-wallet.component.scss","webpack:///./src/app/restore-wallet/restore-wallet.component.ts","webpack:///./src/app/seed-phrase/seed-phrase.component.html","webpack:///./src/app/seed-phrase/seed-phrase.component.scss","webpack:///./src/app/seed-phrase/seed-phrase.component.ts","webpack:///./src/app/send-modal/send-modal.component.html","webpack:///./src/app/send-modal/send-modal.component.scss","webpack:///./src/app/send-modal/send-modal.component.ts","webpack:///./src/app/send/send.component.html","webpack:///./src/app/send/send.component.scss","webpack:///./src/app/send/send.component.ts","webpack:///./src/app/settings/settings.component.html","webpack:///./src/app/settings/settings.component.scss","webpack:///./src/app/settings/settings.component.ts","webpack:///./src/app/sidebar/sidebar.component.html","webpack:///./src/app/sidebar/sidebar.component.scss","webpack:///./src/app/sidebar/sidebar.component.ts","webpack:///./src/app/staking/staking.component.html","webpack:///./src/app/staking/staking.component.scss","webpack:///./src/app/staking/staking.component.ts","webpack:///./src/app/transfer-alias/transfer-alias.component.html","webpack:///./src/app/transfer-alias/transfer-alias.component.scss","webpack:///./src/app/transfer-alias/transfer-alias.component.ts","webpack:///./src/app/typing-message/typing-message.component.html","webpack:///./src/app/typing-message/typing-message.component.scss","webpack:///./src/app/typing-message/typing-message.component.ts","webpack:///./src/app/wallet-details/wallet-details.component.html","webpack:///./src/app/wallet-details/wallet-details.component.scss","webpack:///./src/app/wallet-details/wallet-details.component.ts","webpack:///./src/app/wallet/wallet.component.html","webpack:///./src/app/wallet/wallet.component.scss","webpack:///./src/app/wallet/wallet.component.ts","webpack:///./src/environments/environment.ts","webpack:///./src/main.ts"],"names":[],"mappings":"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","file":"main.js","sourcesContent":["function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(function() {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = function() { return []; };\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nmodule.exports = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = \"./src/$$_lazy_route_resource lazy recursive\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n
\\r\\n {{title}}\\r\\n {{message}}\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 3rem;\\n min-width: 34rem;\\n max-width: 60rem; }\\n\\n.modal .content {\\n display: flex; }\\n\\n.modal .content .icon {\\n flex: 0 0 auto;\\n width: 4.4rem;\\n height: 4.4rem; }\\n\\n.modal .content .icon.info {\\n -webkit-mask: url('modal-info.svg') no-repeat center;\\n mask: url('modal-info.svg') no-repeat center; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin-left: 2rem; }\\n\\n.modal .content .message-container .title {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 2.2rem; }\\n\\n.modal .content .message-container .message {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n margin-top: 0.4rem; }\\n\\n.modal .wrap-btn {\\n display: flex;\\n justify-content: space-between;\\n width: 100%;\\n margin-top: 3.5rem; }\\n\\n.modal .action-button {\\n width: 10rem;\\n height: 2.4rem; }\\n\\n.modal .close-button {\\n position: absolute;\\n top: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: transparent;\\n margin: 0;\\n padding: 0;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n.modal .close-button .icon {\\n -webkit-mask: url('close.svg') no-repeat center;\\n mask: url('close.svg') no-repeat center;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9jb25maXJtLW1vZGFsL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxfaGVscGVyc1xcZGlyZWN0aXZlc1xcY29uZmlybS1tb2RhbFxcY29uZmlybS1tb2RhbC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBRXZDO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsMkJBQTJCO0VBQzNCLHFCQUFxQjtFQUNyQixhQUFhO0VBQ2IsZ0JBQWdCO0VBQ2hCLGdCQUFnQixFQUFBOztBQVJsQjtJQVdJLGFBQWEsRUFBQTs7QUFYakI7TUFjTSxjQUFjO01BQ2QsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUFoQnBCO1FBbUJRLG9EQUE0RDtnQkFBNUQsNENBQTRELEVBQUE7O0FBbkJwRTtNQXdCTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLHVCQUF1QjtNQUN2Qix1QkFBdUI7TUFDdkIsaUJBQWlCLEVBQUE7O0FBNUJ2QjtRQStCUSxpQkFBaUI7UUFDakIsZ0JBQWdCO1FBQ2hCLG1CQUFtQixFQUFBOztBQWpDM0I7UUFxQ1EsaUJBQWlCO1FBQ2pCLG1CQUFtQjtRQUNuQixrQkFBa0IsRUFBQTs7QUF2QzFCO0lBNkNJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsV0FBVztJQUNYLGtCQUFrQixFQUFBOztBQWhEdEI7SUFvREksWUFBWTtJQUNaLGNBQWMsRUFBQTs7QUFyRGxCO0lBeURJLGtCQUFrQjtJQUNsQixNQUFNO0lBQ04sUUFBUTtJQUNSLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLHVCQUF1QjtJQUN2QixTQUFTO0lBQ1QsVUFBVTtJQUNWLGFBQWE7SUFDYixjQUFjLEVBQUE7O0FBbkVsQjtNQXNFTSwrQ0FBdUQ7Y0FBdkQsdUNBQXVEO01BQ3ZELGFBQWE7TUFDYixjQUFjLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9faGVscGVycy9kaXJlY3RpdmVzL2NvbmZpcm0tbW9kYWwvY29uZmlybS1tb2RhbC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogZml4ZWQ7XHJcbiAgdG9wOiAwO1xyXG4gIGJvdHRvbTogMDtcclxuICBsZWZ0OiAwO1xyXG4gIHJpZ2h0OiAwO1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMjUpO1xyXG59XHJcbi5tb2RhbCB7XHJcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7XHJcbiAgYmFja2dyb3VuZC1zaXplOiAyMDAlO1xyXG4gIHBhZGRpbmc6IDNyZW07XHJcbiAgbWluLXdpZHRoOiAzNHJlbTtcclxuICBtYXgtd2lkdGg6IDYwcmVtO1xyXG5cclxuICAuY29udGVudCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgZmxleDogMCAwIGF1dG87XHJcbiAgICAgIHdpZHRoOiA0LjRyZW07XHJcbiAgICAgIGhlaWdodDogNC40cmVtO1xyXG5cclxuICAgICAgJi5pbmZvIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvbW9kYWwtaW5mby5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAubWVzc2FnZS1jb250YWluZXIge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbi1sZWZ0OiAycmVtO1xyXG5cclxuICAgICAgLnRpdGxlIHtcclxuICAgICAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICAgIGxpbmUtaGVpZ2h0OiAyLjJyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5tZXNzYWdlIHtcclxuICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgICAgIG1hcmdpbi10b3A6IDAuNHJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndyYXAtYnRuIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIG1hcmdpbi10b3A6IDMuNXJlbTtcclxuICB9XHJcbiAgXHJcbiAgLmFjdGlvbi1idXR0b24ge1xyXG4gICAgd2lkdGg6IDEwcmVtO1xyXG4gICAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgfVxyXG5cclxuICAuY2xvc2UtYnV0dG9uIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogMDtcclxuICAgIHJpZ2h0OiAwO1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgbWFyZ2luOiAwO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIHdpZHRoOiAyLjRyZW07XHJcbiAgICBoZWlnaHQ6IDIuNHJlbTtcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jbG9zZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIHdpZHRoOiAyLjRyZW07XHJcbiAgICAgIGhlaWdodDogMi40cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-confirm-modal',\r\n templateUrl: './confirm-modal.component.html',\r\n styleUrls: ['./confirm-modal.component.scss']\r\n})\r\nexport class ConfirmModalComponent implements OnInit {\r\n\r\n @Input() title: string;\r\n @Input() message: string;\r\n @Output() confirmed: EventEmitter = new EventEmitter();\r\n @ViewChild('btn') button: ElementRef;\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n this.button.nativeElement.focus();\r\n }\r\n\r\n onSubmit() {\r\n this.confirmed.emit(true);\r\n }\r\n\r\n onClose() {\r\n this.confirmed.emit(false);\r\n }\r\n}\r\n","import {Directive, HostListener} from '@angular/core';\r\n\r\n@Directive({\r\n selector: 'input'\r\n})\r\nexport class InputDisableSelectionDirective {\r\n\r\n constructor() {}\r\n\r\n @HostListener('mousedown', ['$event'])\r\n handleInput(event: Event) {\r\n if ((event.target).readOnly) {\r\n event.preventDefault();\r\n }\r\n }\r\n}\r\n","import {Directive, ElementRef, Input, HostListener} from '@angular/core';\r\nimport {VariablesService} from '../../services/variables.service';\r\n\r\n@Directive({\r\n selector: '[appInputValidate]'\r\n})\r\nexport class InputValidateDirective {\r\n\r\n private type: string;\r\n\r\n constructor(private el: ElementRef, private variablesService: VariablesService) {\r\n }\r\n\r\n @Input('appInputValidate')\r\n public set defineInputType(type: string) {\r\n this.type = type;\r\n }\r\n\r\n @HostListener('input', ['$event'])\r\n handleInput(event: Event) {\r\n if ( this.type === 'money' ) {\r\n this.moneyValidation(event);\r\n } else if ( this.type === 'integer' ) {\r\n this.integerValidation(event);\r\n }\r\n }\r\n\r\n private moneyValidation(event: Event) {\r\n let currentValue = (event.target).value;\r\n const originalValue = currentValue;\r\n const OnlyD = /[^\\d\\.]/g;\r\n const _has_error = currentValue.match(OnlyD);\r\n if (_has_error && _has_error.length) {\r\n currentValue = currentValue.replace(',', '.').replace(OnlyD, '');\r\n }\r\n const _double_separator = currentValue.match(/\\./g);\r\n if (_double_separator && _double_separator.length > 1) {\r\n currentValue = currentValue.substr(0, currentValue.lastIndexOf('.'));\r\n }\r\n if (currentValue.indexOf('.') === 0) {\r\n currentValue = '0' + currentValue;\r\n }\r\n const _zero_fill = currentValue.split('.');\r\n if (_zero_fill[0].length > 7) {\r\n _zero_fill[0] = _zero_fill[0].substr(0, 7);\r\n }\r\n\r\n if (1 in _zero_fill && _zero_fill[1].length) {\r\n _zero_fill[1] = _zero_fill[1].substr(0, this.variablesService.digits);\r\n }\r\n currentValue = _zero_fill.join('.');\r\n if (currentValue !== originalValue) {\r\n const cursorPosition = (event.target).selectionEnd;\r\n (event.target).value = currentValue;\r\n (event.target).setSelectionRange(cursorPosition, cursorPosition);\r\n (event.target).dispatchEvent(new Event('input'));\r\n }\r\n }\r\n\r\n private integerValidation(event: Event) {\r\n let currentValue = (event.target).value;\r\n const originalValue = currentValue;\r\n const OnlyD = /[^\\d]/g;\r\n const _has_error = currentValue.match(OnlyD);\r\n if (_has_error && _has_error.length) {\r\n currentValue = currentValue.replace(OnlyD, '');\r\n }\r\n if (currentValue !== originalValue) {\r\n const cursorPosition = (event.target).selectionEnd;\r\n (event.target).value = currentValue;\r\n (event.target).setSelectionRange(cursorPosition, cursorPosition);\r\n }\r\n }\r\n\r\n}\r\n\r\n\r\n\r\n\r\n","module.exports = \"
\\r\\n
\\r\\n \\r\\n
\\r\\n {{title}}\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 2rem;\\n min-width: 34rem;\\n max-width: 60rem; }\\n\\n.modal .content {\\n display: flex;\\n margin: 1.2rem 0; }\\n\\n.modal .content .icon {\\n flex: 0 0 auto;\\n width: 4.4rem;\\n height: 4.4rem; }\\n\\n.modal .content .icon.error {\\n -webkit-mask: url('modal-alert.svg') no-repeat center;\\n mask: url('modal-alert.svg') no-repeat center; }\\n\\n.modal .content .icon.success {\\n -webkit-mask: url('modal-success.svg') no-repeat center;\\n mask: url('modal-success.svg') no-repeat center; }\\n\\n.modal .content .icon.info {\\n -webkit-mask: url('modal-info.svg') no-repeat center;\\n mask: url('modal-info.svg') no-repeat center; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin-left: 2rem; }\\n\\n.modal .content .message-container .title {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 2.2rem; }\\n\\n.modal .content .message-container .message {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n margin-top: 0.4rem; }\\n\\n.modal .action-button {\\n margin: 1.2rem auto 0.6rem;\\n width: 10rem;\\n height: 2.4rem; }\\n\\n.modal .close-button {\\n position: absolute;\\n top: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: transparent;\\n margin: 0;\\n padding: 0;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n.modal .close-button .icon {\\n -webkit-mask: url('close.svg') no-repeat center;\\n mask: url('close.svg') no-repeat center;\\n width: 2.4rem;\\n height: 2.4rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9tb2RhbC1jb250YWluZXIvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXF9oZWxwZXJzXFxkaXJlY3RpdmVzXFxtb2RhbC1jb250YWluZXJcXG1vZGFsLWNvbnRhaW5lci5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBRXZDO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsMkJBQTJCO0VBQzNCLHFCQUFxQjtFQUNyQixhQUFhO0VBQ2IsZ0JBQWdCO0VBQ2hCLGdCQUFnQixFQUFBOztBQVJsQjtJQVdJLGFBQWE7SUFDYixnQkFBZ0IsRUFBQTs7QUFacEI7TUFlTSxjQUFjO01BQ2QsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUFqQnBCO1FBb0JRLHFEQUE2RDtnQkFBN0QsNkNBQTZELEVBQUE7O0FBcEJyRTtRQXdCUSx1REFBK0Q7Z0JBQS9ELCtDQUErRCxFQUFBOztBQXhCdkU7UUE0QlEsb0RBQTREO2dCQUE1RCw0Q0FBNEQsRUFBQTs7QUE1QnBFO01BaUNNLGFBQWE7TUFDYixzQkFBc0I7TUFDdEIsdUJBQXVCO01BQ3ZCLHVCQUF1QjtNQUN2QixpQkFBaUIsRUFBQTs7QUFyQ3ZCO1FBd0NRLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsbUJBQW1CLEVBQUE7O0FBMUMzQjtRQThDUSxpQkFBaUI7UUFDakIsbUJBQW1CO1FBQ25CLGtCQUFrQixFQUFBOztBQWhEMUI7SUFzREksMEJBQTBCO0lBQzFCLFlBQVk7SUFDWixjQUFjLEVBQUE7O0FBeERsQjtJQTRESSxrQkFBa0I7SUFDbEIsTUFBTTtJQUNOLFFBQVE7SUFDUixhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2Qix1QkFBdUI7SUFDdkIsU0FBUztJQUNULFVBQVU7SUFDVixhQUFhO0lBQ2IsY0FBYyxFQUFBOztBQXRFbEI7TUF5RU0sK0NBQXVEO2NBQXZELHVDQUF1RDtNQUN2RCxhQUFhO01BQ2IsY0FBYyxFQUFBIiwiZmlsZSI6InNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9tb2RhbC1jb250YWluZXIvbW9kYWwtY29udGFpbmVyLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuLm1vZGFsIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogMnJlbTtcclxuICBtaW4td2lkdGg6IDM0cmVtO1xyXG4gIG1heC13aWR0aDogNjByZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBtYXJnaW46IDEuMnJlbSAwO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgZmxleDogMCAwIGF1dG87XHJcbiAgICAgIHdpZHRoOiA0LjRyZW07XHJcbiAgICAgIGhlaWdodDogNC40cmVtO1xyXG5cclxuICAgICAgJi5lcnJvciB7XHJcbiAgICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL21vZGFsLWFsZXJ0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5zdWNjZXNzIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvbW9kYWwtc3VjY2Vzcy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuaW5mbyB7XHJcbiAgICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL21vZGFsLWluZm8uc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm1lc3NhZ2UtY29udGFpbmVyIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBtYXJnaW4tbGVmdDogMnJlbTtcclxuXHJcbiAgICAgIC50aXRsZSB7XHJcbiAgICAgICAgZm9udC1zaXplOiAxLjhyZW07XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgICAgICBsaW5lLWhlaWdodDogMi4ycmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAubWVzc2FnZSB7XHJcbiAgICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcclxuICAgICAgICBtYXJnaW4tdG9wOiAwLjRyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5hY3Rpb24tYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMS4ycmVtIGF1dG8gMC42cmVtO1xyXG4gICAgd2lkdGg6IDEwcmVtO1xyXG4gICAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgfVxyXG5cclxuICAuY2xvc2UtYnV0dG9uIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogMDtcclxuICAgIHJpZ2h0OiAwO1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgbWFyZ2luOiAwO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIHdpZHRoOiAyLjRyZW07XHJcbiAgICBoZWlnaHQ6IDIuNHJlbTtcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jbG9zZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIHdpZHRoOiAyLjRyZW07XHJcbiAgICAgIGhlaWdodDogMi40cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-modal-container',\r\n templateUrl: './modal-container.component.html',\r\n styleUrls: ['./modal-container.component.scss']\r\n})\r\nexport class ModalContainerComponent implements OnInit {\r\n\r\n public title: string;\r\n @Input() type: string;\r\n @Input() message: string;\r\n @Output() close = new EventEmitter();\r\n @ViewChild('btn') button: ElementRef;\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n ngOnInit() {\r\n this.button.nativeElement.focus();\r\n switch (this.type) {\r\n case 'error': this.title = this.translate.instant('MODALS.ERROR'); break;\r\n case 'success': this.title = this.translate.instant('MODALS.SUCCESS'); break;\r\n case 'info': this.title = this.translate.instant('MODALS.INFO'); break;\r\n }\r\n }\r\n\r\n onClose() {\r\n this.close.emit();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n {{ label | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \".progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n padding: 0 3rem;\\n width: 100%;\\n height: 3rem; }\\n .progress-bar-container .progress-bar {\\n position: absolute;\\n top: -0.7rem;\\n left: 0;\\n margin: 0 3rem;\\n width: calc(100% - 6rem);\\n height: 0.7rem; }\\n .progress-bar-container .progress-bar .progress-bar-full {\\n height: 0.7rem; }\\n .progress-bar-container .progress-labels {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n font-size: 1.2rem;\\n height: 100%; }\\n .progress-bar-container .progress-labels span {\\n flex: 1 0 0;\\n text-align: center; }\\n .progress-bar-container .progress-labels span:first-child {\\n text-align: left; }\\n .progress-bar-container .progress-labels span:last-child {\\n text-align: right; }\\n .progress-bar-container .progress-time {\\n position: absolute;\\n top: -3rem;\\n left: 50%;\\n transform: translateX(-50%);\\n font-size: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9wcm9ncmVzcy1jb250YWluZXIvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXF9oZWxwZXJzXFxkaXJlY3RpdmVzXFxwcm9ncmVzcy1jb250YWluZXJcXHByb2dyZXNzLWNvbnRhaW5lci5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQjtFQUNsQixTQUFTO0VBQ1QsT0FBTztFQUNQLGVBQWU7RUFDZixXQUFXO0VBQ1gsWUFBWSxFQUFBO0VBTmQ7SUFTSSxrQkFBa0I7SUFDbEIsWUFBWTtJQUNaLE9BQU87SUFDUCxjQUFjO0lBQ2Qsd0JBQXdCO0lBQ3hCLGNBQWMsRUFBQTtFQWRsQjtNQWlCTSxjQUFjLEVBQUE7RUFqQnBCO0lBc0JJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCO0lBQzlCLGlCQUFpQjtJQUNqQixZQUFZLEVBQUE7RUExQmhCO01BNkJNLFdBQVc7TUFDWCxrQkFBa0IsRUFBQTtFQTlCeEI7UUFpQ1EsZ0JBQWdCLEVBQUE7RUFqQ3hCO1FBcUNRLGlCQUFpQixFQUFBO0VBckN6QjtJQTJDSSxrQkFBa0I7SUFDbEIsVUFBVTtJQUNWLFNBQVM7SUFDVCwyQkFBMkI7SUFDM0IsaUJBQWlCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9faGVscGVycy9kaXJlY3RpdmVzL3Byb2dyZXNzLWNvbnRhaW5lci9wcm9ncmVzcy1jb250YWluZXIuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcbiAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gIGJvdHRvbTogMDtcclxuICBsZWZ0OiAwO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIC5wcm9ncmVzcy1iYXIge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiAtMC43cmVtO1xyXG4gICAgbGVmdDogMDtcclxuICAgIG1hcmdpbjogMCAzcmVtO1xyXG4gICAgd2lkdGg6IGNhbGMoMTAwJSAtIDZyZW0pO1xyXG4gICAgaGVpZ2h0OiAwLjdyZW07XHJcblxyXG4gICAgLnByb2dyZXNzLWJhci1mdWxsIHtcclxuICAgICAgaGVpZ2h0OiAwLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtbGFiZWxzIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcblxyXG4gICAgc3BhbiB7XHJcbiAgICAgIGZsZXg6IDEgMCAwO1xyXG4gICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIHRleHQtYWxpZ246IHJpZ2h0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtdGltZSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IC0zcmVtO1xyXG4gICAgbGVmdDogNTAlO1xyXG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import { Component, Input, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-progress-container',\r\n templateUrl: './progress-container.component.html',\r\n styleUrls: ['./progress-container.component.scss']\r\n})\r\nexport class ProgressContainerComponent implements OnInit {\r\n\r\n @Input() width: string;\r\n @Input() labels: [];\r\n\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n}\r\n","module.exports = \"
\\r\\n {{ 'STAKING.SWITCH.ON' | translate }}\\r\\n \\r\\n {{ 'STAKING.SWITCH.OFF' | translate }}\\r\\n
\\r\\n\"","module.exports = \".switch {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n border-radius: 1rem;\\n cursor: pointer;\\n font-size: 1rem;\\n padding: 0.5rem;\\n width: 5rem;\\n height: 2rem; }\\n .switch .circle {\\n border-radius: 1rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n .switch .option {\\n margin: 0 0.2rem;\\n line-height: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy9zdGFraW5nLXN3aXRjaC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcX2hlbHBlcnNcXGRpcmVjdGl2ZXNcXHN0YWtpbmctc3dpdGNoXFxzdGFraW5nLXN3aXRjaC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsOEJBQThCO0VBQzlCLG1CQUFtQjtFQUNuQixlQUFlO0VBQ2YsZUFBZTtFQUNmLGVBQWU7RUFDZixXQUFXO0VBQ1gsWUFBWSxFQUFBO0VBVGQ7SUFZSSxtQkFBbUI7SUFDbkIsYUFBYTtJQUNiLGNBQWMsRUFBQTtFQWRsQjtJQWtCSSxnQkFBZ0I7SUFDaEIsbUJBQW1CLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9faGVscGVycy9kaXJlY3RpdmVzL3N0YWtpbmctc3dpdGNoL3N0YWtpbmctc3dpdGNoLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLnN3aXRjaCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICBib3JkZXItcmFkaXVzOiAxcmVtO1xyXG4gIGN1cnNvcjogcG9pbnRlcjtcclxuICBmb250LXNpemU6IDFyZW07XHJcbiAgcGFkZGluZzogMC41cmVtO1xyXG4gIHdpZHRoOiA1cmVtO1xyXG4gIGhlaWdodDogMnJlbTtcclxuXHJcbiAgLmNpcmNsZSB7XHJcbiAgICBib3JkZXItcmFkaXVzOiAxcmVtO1xyXG4gICAgd2lkdGg6IDEuMnJlbTtcclxuICAgIGhlaWdodDogMS4ycmVtO1xyXG4gIH1cclxuXHJcbiAgLm9wdGlvbiB7XHJcbiAgICBtYXJnaW46IDAgMC4ycmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuMnJlbTtcclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, Input, Output, EventEmitter} from '@angular/core';\r\nimport {BackendService} from '../../services/backend.service';\r\nimport {VariablesService} from '../../services/variables.service';\r\n\r\n@Component({\r\n selector: 'app-staking-switch',\r\n templateUrl: './staking-switch.component.html',\r\n styleUrls: ['./staking-switch.component.scss']\r\n})\r\nexport class StakingSwitchComponent implements OnInit {\r\n\r\n @Input() wallet_id: boolean;\r\n @Input() staking: boolean;\r\n @Output() stakingChange = new EventEmitter();\r\n\r\n constructor(private backend: BackendService, private variablesService: VariablesService) {}\r\n\r\n ngOnInit() {}\r\n\r\n toggleStaking() {\r\n const wallet = this.variablesService.getWallet(this.wallet_id);\r\n if (wallet && wallet.loaded) {\r\n this.stakingChange.emit(!this.staking);\r\n if (!this.staking) {\r\n this.backend.startPosMining(this.wallet_id);\r\n } else {\r\n this.backend.stopPosMining(this.wallet_id);\r\n }\r\n }\r\n }\r\n}\r\n","import {Directive, Input, Output, ElementRef, HostListener, Renderer2, HostBinding, OnDestroy, EventEmitter} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\n\r\n@Directive({\r\n selector: '[tooltip]'\r\n})\r\n\r\nexport class TooltipDirective implements OnDestroy {\r\n\r\n @HostBinding('style.cursor') cursor;\r\n\r\n @Input('tooltip') tooltipInner: any;\r\n @Input() placement: string;\r\n @Input() tooltipClass: string;\r\n @Input() timeout = 0;\r\n @Input() timeDelay = 0;\r\n @Input() delay = 0;\r\n @Input() showWhenNoOverflow = true;\r\n @Output() onHide = new EventEmitter();\r\n tooltip: HTMLElement;\r\n private enter: (event: MouseEvent) => void;\r\n private leave: (event: MouseEvent) => void;\r\n\r\n removeTooltipTimeout;\r\n removeTooltipTimeoutInner;\r\n\r\n removeTooltipTimeDelay;\r\n\r\n constructor(private el: ElementRef, private renderer: Renderer2, private route: ActivatedRoute) {\r\n }\r\n\r\n @HostListener('mouseenter') onMouseEnter() {\r\n if (this.showWhenNoOverflow || (!this.showWhenNoOverflow && this.el.nativeElement.offsetWidth < this.el.nativeElement.scrollWidth)) {\r\n this.cursor = 'pointer';\r\n if (!this.tooltip) {\r\n if (this.timeDelay !== 0) {\r\n this.removeTooltipTimeDelay = setTimeout(() => {\r\n this.show();\r\n }, this.timeDelay);\r\n } else {\r\n this.show();\r\n }\r\n } else {\r\n this.cancelHide();\r\n }\r\n }\r\n }\r\n\r\n @HostListener('mouseleave') onMouseLeave() {\r\n clearTimeout(this.removeTooltipTimeDelay);\r\n if (this.tooltip) {\r\n this.hide();\r\n }\r\n }\r\n\r\n show() {\r\n this.create();\r\n this.placement = this.placement === null ? 'top' : this.placement;\r\n this.setPosition(this.placement);\r\n }\r\n\r\n hide() {\r\n this.removeTooltipTimeout = setTimeout(() => {\r\n this.renderer.setStyle(this.tooltip, 'opacity', '0');\r\n this.removeTooltipTimeoutInner = setTimeout(() => {\r\n this.renderer.removeChild(document.body, this.tooltip);\r\n this.tooltip.removeEventListener('mouseenter', this.enter);\r\n this.tooltip.removeEventListener('mouseleave', this.leave);\r\n this.tooltip = null;\r\n this.onHide.emit(true);\r\n }, this.delay);\r\n }, this.timeout);\r\n }\r\n\r\n cancelHide() {\r\n clearTimeout(this.removeTooltipTimeout);\r\n clearTimeout(this.removeTooltipTimeoutInner);\r\n this.renderer.setStyle(this.tooltip, 'opacity', '1');\r\n }\r\n\r\n create() {\r\n this.tooltip = this.renderer.createElement('div');\r\n let innerBlock = this.renderer.createElement('div');\r\n if (typeof this.tooltipInner === 'string') {\r\n innerBlock.innerHTML = this.tooltipInner;\r\n } else {\r\n innerBlock = this.tooltipInner;\r\n }\r\n this.renderer.addClass(innerBlock, 'tooltip-inner');\r\n this.renderer.addClass(innerBlock, 'scrolled-content');\r\n this.renderer.appendChild(this.tooltip, innerBlock);\r\n this.renderer.appendChild(document.body, this.tooltip);\r\n\r\n this.enter = () => {\r\n this.cancelHide();\r\n };\r\n this.tooltip.addEventListener('mouseenter', this.enter);\r\n this.leave = () => {\r\n if (this.tooltip) {\r\n this.hide();\r\n }\r\n };\r\n this.tooltip.addEventListener('mouseleave', this.leave);\r\n\r\n this.renderer.setStyle(document.body, 'position', 'relative');\r\n this.renderer.setStyle(this.tooltip, 'position', 'absolute');\r\n if (this.tooltipClass !== null) {\r\n const classes = this.tooltipClass.split(' ');\r\n for (let i = 0; i < classes.length; i++) {\r\n this.renderer.addClass(this.tooltip, classes[i]);\r\n }\r\n }\r\n this.renderer.setStyle(this.tooltip, 'opacity', '0');\r\n this.renderer.setStyle(this.tooltip, '-webkit-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, '-moz-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, '-o-transition', `opacity ${this.delay}ms`);\r\n this.renderer.setStyle(this.tooltip, 'transition', `opacity ${this.delay}ms`);\r\n window.setTimeout(() => {\r\n this.renderer.setStyle(this.tooltip, 'opacity', '1');\r\n }, 0);\r\n }\r\n\r\n setPosition(placement) {\r\n const hostPos = this.el.nativeElement.getBoundingClientRect();\r\n this.renderer.addClass(this.tooltip, 'ng-tooltip-' + placement);\r\n const topExit = hostPos.top - this.tooltip.getBoundingClientRect().height - parseInt(getComputedStyle(this.tooltip).marginTop, 10) < 0;\r\n const bottomExit = window.innerHeight < hostPos.bottom + this.tooltip.getBoundingClientRect().height + parseInt(getComputedStyle(this.tooltip).marginTop, 10);\r\n\r\n switch (placement) {\r\n case 'top':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + (hostPos.right - hostPos.left) / 2 - this.tooltip.getBoundingClientRect().width / 2 + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'top-left':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom-left');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'top-right':\r\n if (topExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('bottom-right');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right - this.tooltip.offsetWidth + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top - this.tooltip.getBoundingClientRect().height + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + (hostPos.right - hostPos.left) / 2 - this.tooltip.getBoundingClientRect().width / 2 + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom-left':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top-left');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'bottom-right':\r\n if (bottomExit) {\r\n this.renderer.removeClass(this.tooltip, 'ng-tooltip-' + placement);\r\n this.setPosition('top-right');\r\n return;\r\n } else {\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right - this.tooltip.offsetWidth + 'px');\r\n this.checkSides();\r\n }\r\n break;\r\n case 'left':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + (hostPos.bottom - hostPos.top) / 2 - this.tooltip.getBoundingClientRect().height / 2 + 'px');\r\n break;\r\n case 'left-top':\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n break;\r\n case 'left-bottom':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.left - this.tooltip.getBoundingClientRect().width + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom - this.tooltip.getBoundingClientRect().height + 'px');\r\n break;\r\n case 'right':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + (hostPos.bottom - hostPos.top) / 2 - this.tooltip.getBoundingClientRect().height / 2 + 'px');\r\n break;\r\n case 'right-top':\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.top + 'px');\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n break;\r\n case 'right-bottom':\r\n this.renderer.setStyle(this.tooltip, 'left', hostPos.right + 'px');\r\n this.renderer.setStyle(this.tooltip, 'top', hostPos.bottom - this.tooltip.getBoundingClientRect().height + 'px');\r\n break;\r\n }\r\n }\r\n\r\n checkSides() {\r\n if (this.tooltip.getBoundingClientRect().left < 0) {\r\n this.renderer.setStyle(this.tooltip, 'left', 0);\r\n }\r\n if (this.tooltip.getBoundingClientRect().right > window.innerWidth) {\r\n this.renderer.setStyle(this.tooltip, 'left', window.innerWidth - this.tooltip.getBoundingClientRect().width + 'px');\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n clearTimeout(this.removeTooltipTimeout);\r\n clearTimeout(this.removeTooltipTimeoutInner);\r\n clearTimeout(this.removeTooltipTimeDelay);\r\n if (this.tooltip) {\r\n this.renderer.removeChild(document.body, this.tooltip);\r\n this.tooltip = null;\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.ID' | translate }}\\r\\n {{transaction.tx_hash}}\\r\\n {{ 'HISTORY.DETAILS.SIZE' | translate }}\\r\\n {{ 'HISTORY.DETAILS.SIZE_VALUE' | translate : {value: transaction.tx_blob_size} }}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.HEIGHT' | translate }}\\r\\n {{transaction.height}}\\r\\n {{ 'HISTORY.DETAILS.CONFIRMATION' | translate }}\\r\\n {{transaction.height === 0 ? 0 : variablesService.height_app - transaction.height}}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.INPUTS' | translate }}\\r\\n {{inputs.join(', ')}}\\r\\n {{ 'HISTORY.DETAILS.OUTPUTS' | translate }}\\r\\n {{outputs.join(', ')}}\\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.PAYMENT_ID' | translate }}\\r\\n \\r\\n {{transaction.payment_id}}\\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'HISTORY.DETAILS.COMMENT' | translate }}\\r\\n \\r\\n {{transaction.comment}}\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%; }\\n\\n.table {\\n border-top: 0.2rem solid #ebebeb;\\n margin: 0 3rem;\\n padding: 0.5rem 0; }\\n\\n.table .row {\\n display: flex;\\n justify-content: flex-start;\\n align-items: center;\\n border-top: none;\\n line-height: 3rem;\\n margin: 0 -3rem;\\n width: 100%;\\n height: 3rem; }\\n\\n.table .row .cell {\\n flex-shrink: 0;\\n flex-grow: 0;\\n padding: 0 1rem;\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n\\n.table .row .cell:first-child {\\n padding-left: 3rem; }\\n\\n.table .row .cell:last-child {\\n padding-right: 3rem; }\\n\\n.table .row .cell.key-value {\\n cursor: pointer; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvX2hlbHBlcnMvZGlyZWN0aXZlcy90cmFuc2FjdGlvbi1kZXRhaWxzL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxfaGVscGVyc1xcZGlyZWN0aXZlc1xcdHJhbnNhY3Rpb24tZGV0YWlsc1xcdHJhbnNhY3Rpb24tZGV0YWlscy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQjtFQUNsQixNQUFNO0VBQ04sT0FBTztFQUNQLFdBQVcsRUFBQTs7QUFHYjtFQUNFLGdDQUFnQztFQUNoQyxjQUFjO0VBQ2QsaUJBQWlCLEVBQUE7O0FBSG5CO0lBTUksYUFBYTtJQUNiLDJCQUEyQjtJQUMzQixtQkFBbUI7SUFDbkIsZ0JBQWdCO0lBQ2hCLGlCQUFpQjtJQUNqQixlQUFlO0lBQ2YsV0FBVztJQUNYLFlBQVksRUFBQTs7QUFiaEI7TUFnQk0sY0FBYztNQUNkLFlBQVk7TUFDWixlQUFlO01BQ2YsZ0JBQWdCO01BQ2hCLHVCQUF1QixFQUFBOztBQXBCN0I7UUF1QlEsa0JBQWtCLEVBQUE7O0FBdkIxQjtRQTJCUSxtQkFBbUIsRUFBQTs7QUEzQjNCO1FBK0JRLGVBQWUsRUFBQSIsImZpbGUiOiJzcmMvYXBwL19oZWxwZXJzL2RpcmVjdGl2ZXMvdHJhbnNhY3Rpb24tZGV0YWlscy90cmFuc2FjdGlvbi1kZXRhaWxzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICB0b3A6IDA7XHJcbiAgbGVmdDogMDtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLnRhYmxlIHtcclxuICBib3JkZXItdG9wOiAwLjJyZW0gc29saWQgI2ViZWJlYjtcclxuICBtYXJnaW46IDAgM3JlbTtcclxuICBwYWRkaW5nOiAwLjVyZW0gMDtcclxuXHJcbiAgLnJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGJvcmRlci10b3A6IG5vbmU7XHJcbiAgICBsaW5lLWhlaWdodDogM3JlbTtcclxuICAgIG1hcmdpbjogMCAtM3JlbTtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiAzcmVtO1xyXG5cclxuICAgIC5jZWxsIHtcclxuICAgICAgZmxleC1zaHJpbms6IDA7XHJcbiAgICAgIGZsZXgtZ3JvdzogMDtcclxuICAgICAgcGFkZGluZzogMCAxcmVtO1xyXG4gICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcclxuXHJcbiAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogM3JlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAzcmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmtleS12YWx1ZSB7XHJcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, OnDestroy, Input} from '@angular/core';\r\nimport {Transaction} from '../../models/transaction.model';\r\nimport {VariablesService} from '../../services/variables.service';\r\nimport {BackendService} from '../../services/backend.service';\r\nimport {IntToMoneyPipe} from '../../pipes/int-to-money.pipe';\r\n\r\n@Component({\r\n selector: 'app-transaction-details',\r\n templateUrl: './transaction-details.component.html',\r\n styleUrls: ['./transaction-details.component.scss']\r\n})\r\nexport class TransactionDetailsComponent implements OnInit, OnDestroy {\r\n\r\n @Input() transaction: Transaction;\r\n @Input() sizes: Array;\r\n inputs: Array = [];\r\n outputs: Array = [];\r\n\r\n constructor(public variablesService: VariablesService, private backendService: BackendService, private intToMoneyPipe: IntToMoneyPipe) {}\r\n\r\n ngOnInit() {\r\n for (const input in this.transaction.td['spn']) {\r\n if (this.transaction.td['spn'].hasOwnProperty(input)) {\r\n this.inputs.push(this.intToMoneyPipe.transform(this.transaction.td['spn'][input]));\r\n }\r\n }\r\n for (const output in this.transaction.td['rcv']) {\r\n if (this.transaction.td['rcv'].hasOwnProperty(output)) {\r\n this.outputs.push(this.intToMoneyPipe.transform(this.transaction.td['rcv'][output]));\r\n }\r\n }\r\n }\r\n\r\n openInBrowser(tr) {\r\n this.backendService.openUrlInBrowser('explorer.zano.org/transaction/' + tr);\r\n }\r\n\r\n ngOnDestroy() {}\r\n}\r\n","import {BigNumber} from 'bignumber.js';\r\n\r\nexport class Transaction {\r\n amount: BigNumber;\r\n comment: string;\r\n contract: any[];\r\n fee: BigNumber;\r\n height: number;\r\n is_income: boolean;\r\n is_mining: boolean;\r\n is_mixing: boolean;\r\n is_service: boolean;\r\n payment_id: string;\r\n show_sender: boolean;\r\n td: object;\r\n timestamp: number;\r\n tx_blob_size: number;\r\n tx_hash: string;\r\n tx_type: number;\r\n unlock_time: number;\r\n\r\n sortAmount?: BigNumber;\r\n sortFee?: BigNumber;\r\n}\r\n","import {Contract} from './contract.model';\r\nimport {Transaction} from './transaction.model';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\nexport class Wallet {\r\n wallet_id: number;\r\n name: string;\r\n pass: string;\r\n path: string;\r\n address: string;\r\n balance: BigNumber;\r\n unlocked_balance: BigNumber;\r\n mined_total: number;\r\n tracking_hey: string;\r\n alias_available: boolean;\r\n\r\n alias?: object;\r\n wakeAlias?: boolean;\r\n staking?: boolean;\r\n new_messages?: number;\r\n new_contracts?: number;\r\n\r\n history: Array = [];\r\n excluded_history: Array = [];\r\n\r\n contracts: Array = [];\r\n\r\n progress?: number;\r\n loaded?: boolean;\r\n\r\n send_data?: any = {\r\n address: null,\r\n amount: null,\r\n comment: null,\r\n mixin: null,\r\n fee: null,\r\n hide: null\r\n };\r\n\r\n constructor(id, name, pass, path, address, balance, unlocked_balance, mined = 0, tracking = '') {\r\n this.wallet_id = id;\r\n this.name = name;\r\n this.pass = pass;\r\n this.path = path;\r\n this.address = address;\r\n this.balance = balance;\r\n this.unlocked_balance = unlocked_balance;\r\n this.mined_total = mined;\r\n this.tracking_hey = tracking;\r\n\r\n this.alias = {};\r\n this.staking = false;\r\n this.new_messages = 0;\r\n this.new_contracts = 0;\r\n\r\n this.history = [];\r\n this.excluded_history = [];\r\n\r\n this.progress = 0;\r\n this.loaded = false;\r\n }\r\n\r\n getMoneyEquivalent(equivalent) {\r\n return this.balance.multipliedBy(equivalent).toFixed(0);\r\n }\r\n\r\n havePass(): boolean {\r\n return (this.pass !== '' && this.pass !== null);\r\n }\r\n\r\n isActive(id): boolean {\r\n return this.wallet_id === id;\r\n }\r\n\r\n prepareHistoryItem(item: Transaction): any {\r\n if (item.tx_type === 4) {\r\n item.sortFee = item.amount.plus(item.fee).negated();\r\n item.sortAmount = new BigNumber(0);\r\n } else if (item.tx_type === 3) {\r\n item.sortFee = new BigNumber(0);\r\n } else if ((item.hasOwnProperty('contract') && (item.contract[0].state === 3 || item.contract[0].state === 6 || item.contract[0].state === 601) && !item.contract[0].is_a)) {\r\n item.sortFee = item.fee.negated();\r\n item.sortAmount = item.amount;\r\n } else {\r\n if (!item.is_income) {\r\n item.sortFee = item.fee.negated();\r\n item.sortAmount = item.amount.negated();\r\n } else {\r\n item.sortAmount = item.amount;\r\n }\r\n }\r\n return item;\r\n }\r\n\r\n prepareHistory(items: Transaction[]): void {\r\n for (let i = 0; i < items.length; i++) {\r\n if ((items[i].tx_type === 7 && items[i].is_income) || (items[i].tx_type === 11 && items[i].is_income) || (items[i].amount.eq(0) && items[i].fee.eq(0))) {\r\n let exists = false;\r\n for (let j = 0; j < this.excluded_history.length; j++) {\r\n if (this.excluded_history[j].tx_hash === items[i].tx_hash) {\r\n exists = true;\r\n if (this.excluded_history[j].height !== items[i].height) {\r\n this.excluded_history[j] = items[i];\r\n }\r\n break;\r\n }\r\n }\r\n if (!exists) {\r\n this.excluded_history.push(items[i]);\r\n }\r\n } else {\r\n let exists = false;\r\n for (let j = 0; j < this.history.length; j++) {\r\n if (this.history[j].tx_hash === items[i].tx_hash) {\r\n exists = true;\r\n if (this.history[j].height !== items[i].height) {\r\n this.history[j] = this.prepareHistoryItem(items[i]);\r\n }\r\n break;\r\n }\r\n }\r\n if (!exists) {\r\n if (this.history.length && items[i].timestamp >= this.history[0].timestamp) {\r\n this.history.unshift(this.prepareHistoryItem(items[i]));\r\n } else {\r\n this.history.push(this.prepareHistoryItem(items[i]));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n removeFromHistory(hash: string): void {\r\n for (let i = 0; i < this.history.length; i++) {\r\n if (this.history[i].tx_hash === hash) {\r\n this.history.splice(i, 1);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n prepareContractsAfterOpen(items: any[], exp_med_ts, height_app, viewedContracts, notViewedContracts): void {\r\n const wallet = this;\r\n for (let i = 0; i < items.length; i++) {\r\n const contract = items[i];\r\n let contractTransactionExist = false;\r\n if (wallet && wallet.history) {\r\n contractTransactionExist = wallet.history.some(elem => elem.contract && elem.contract.length && elem.contract[0].contract_id === contract.contract_id);\r\n }\r\n if (!contractTransactionExist && wallet && wallet.excluded_history) {\r\n contractTransactionExist = wallet.excluded_history.some(elem => elem.contract && elem.contract.length && elem.contract[0].contract_id === contract.contract_id);\r\n }\r\n\r\n if (!contractTransactionExist) {\r\n contract.state = 140;\r\n } else if (contract.state === 1 && contract.expiration_time < exp_med_ts) {\r\n contract.state = 110;\r\n } else if (contract.state === 2 && contract.cancel_expiration_time !== 0 && contract.cancel_expiration_time < exp_med_ts && contract.height === 0) {\r\n const searchResult1 = viewedContracts.some(elem => elem.state === 2 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (!searchResult1) {\r\n contract.state = 130;\r\n contract.is_new = true;\r\n }\r\n } else if (contract.state === 1) {\r\n const searchResult2 = notViewedContracts.find(elem => elem.state === 110 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult2) {\r\n if (searchResult2.time === contract.expiration_time) {\r\n contract.state = 110;\r\n } else {\r\n for (let j = 0; j < notViewedContracts.length; j++) {\r\n if (notViewedContracts[j].contract_id === contract.contract_id && notViewedContracts[j].is_a === contract.is_a) {\r\n notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < viewedContracts.length; j++) {\r\n if (viewedContracts[j].contract_id === contract.contract_id && viewedContracts[j].is_a === contract.is_a) {\r\n viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 2 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 201;\r\n } else if (contract.state === 2) {\r\n const searchResult3 = viewedContracts.some(elem => elem.state === 120 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult3) {\r\n contract.state = 120;\r\n }\r\n } else if (contract.state === 5) {\r\n const searchResult4 = notViewedContracts.find(elem => elem.state === 130 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult4) {\r\n if (searchResult4.time === contract.cancel_expiration_time) {\r\n contract.state = 130;\r\n } else {\r\n for (let j = 0; j < notViewedContracts.length; j++) {\r\n if (notViewedContracts[j].contract_id === contract.contract_id && notViewedContracts[j].is_a === contract.is_a) {\r\n notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < viewedContracts.length; j++) {\r\n if (viewedContracts[j].contract_id === contract.contract_id && viewedContracts[j].is_a === contract.is_a) {\r\n viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 6 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 601;\r\n }\r\n const searchResult = viewedContracts.some(elem => elem.state === contract.state && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n contract.is_new = !searchResult;\r\n\r\n wallet.contracts.push(contract);\r\n }\r\n this.recountNewContracts();\r\n }\r\n\r\n recountNewContracts() {\r\n this.new_contracts = (this.contracts.filter(item => item.is_new === true )).length;\r\n }\r\n\r\n getContract(id): Contract {\r\n for (let i = 0; i < this.contracts.length; i++) {\r\n if (this.contracts[i].contract_id === id) {\r\n return this.contracts[i];\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'contractStatusMessages'\r\n})\r\nexport class ContractStatusMessagesPipe implements PipeTransform {\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n getStateSeller(stateNum: number): string {\r\n const state = {part1: '', part2: ''};\r\n switch (stateNum) {\r\n case 1:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NEW_CONTRACT');\r\n break;\r\n case 110:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.IGNORED');\r\n break;\r\n case 201:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.ACCEPTED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.WAIT');\r\n break;\r\n case 2:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.WAITING_BUYER');\r\n break;\r\n case 3:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.COMPLETED');\r\n break;\r\n case 4:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NOT_RECEIVED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.NULLIFIED');\r\n break;\r\n case 5:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.PROPOSAL_CANCEL');\r\n break;\r\n case 601:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.BEING_CANCELLED');\r\n break;\r\n case 6:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.CANCELLED');\r\n break;\r\n case 130:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.IGNORED_CANCEL');\r\n break;\r\n case 140:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.SELLER.EXPIRED');\r\n break;\r\n }\r\n return state.part1 + (state.part2.length ? '. ' + state.part2 : '');\r\n }\r\n\r\n getStateBuyer(stateNum: number): string {\r\n const state = {part1: '', part2: ''};\r\n switch (stateNum) {\r\n case 1:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING');\r\n break;\r\n case 110:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.IGNORED');\r\n break;\r\n case 201:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.ACCEPTED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAIT');\r\n break;\r\n case 2:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.ACCEPTED');\r\n break;\r\n case 120:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING_SELLER');\r\n break;\r\n case 3:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.COMPLETED');\r\n break;\r\n case 4:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.NOT_RECEIVED');\r\n state.part2 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.NULLIFIED');\r\n break;\r\n case 5:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.WAITING_CANCEL');\r\n break;\r\n case 601:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.BEING_CANCELLED');\r\n break;\r\n case 6:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.CANCELLED');\r\n break;\r\n case 130:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.IGNORED_CANCEL');\r\n break;\r\n case 140:\r\n state.part1 = this.translate.instant('CONTRACTS.STATUS_MESSAGES.BUYER.EXPIRED');\r\n break;\r\n }\r\n return state.part1 + (state.part2.length ? '. ' + state.part2 : '');\r\n }\r\n\r\n transform(state: number, is_a?: boolean): any {\r\n if (is_a) {\r\n return this.getStateBuyer(state);\r\n } else {\r\n return this.getStateSeller(state);\r\n }\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'contractTimeLeft'\r\n})\r\nexport class ContractTimeLeftPipe implements PipeTransform {\r\n\r\n constructor(private service: VariablesService, private translate: TranslateService) {}\r\n\r\n transform(value: any, arg?: any): any {\r\n const time = parseInt(((parseInt(value, 10) - this.service.exp_med_ts) / 3600).toFixed(0), 10);\r\n const type = arg || 0;\r\n if (time === 0) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_LESS_ONE');\r\n }\r\n if (this.service.settings.language === 'en') {\r\n if (type === 0) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY', {time: time});\r\n }\r\n } else if (type === 1) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_RESPONSE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_RESPONSE', {time: time});\r\n }\r\n } else if (type === 2) {\r\n if (time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_WAITING', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_WAITING', {time: time});\r\n }\r\n }\r\n } else {\r\n const rest = time % 10;\r\n if (type === 0) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT', {time: time});\r\n }\r\n } else if (type === 1) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_RESPONSE', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_RESPONSE', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT_RESPONSE', {time: time});\r\n }\r\n } else if (type === 2) {\r\n if (((time > 20 ) && (rest === 1)) || time === 1) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_ONE_WAITING', {time: time});\r\n } else if ((time > 1) && (time < 5) || ((time > 20 ) && (rest === 2 || rest === 3 || rest === 4))) {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_WAITING', {time: time});\r\n } else {\r\n return this.translate.instant('CONTRACTS.TIME_LEFT.REMAINING_MANY_ALT_WAITING', {time: time});\r\n }\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Pipe({\r\n name: 'historyTypeMessages'\r\n})\r\nexport class HistoryTypeMessagesPipe implements PipeTransform {\r\n\r\n constructor(private translate: TranslateService) {}\r\n\r\n transform(item: any, args?: any): any {\r\n\r\n if (item.tx_type === 0) {\r\n if (item.remote_addresses && item.remote_addresses[0]) {\r\n return item.remote_addresses[0];\r\n } else {\r\n if (item.is_income) {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.HIDDEN');\r\n } else {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UNDEFINED');\r\n }\r\n }\r\n } else if (item.tx_type === 6 && item.height === 0) {\r\n return 'unknown';\r\n } else if (item.tx_type === 9) {\r\n if (item.hasOwnProperty('contract') && item.contract[0].is_a) {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.COMPLETE_BUYER');\r\n } else {\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.COMPLETE_SELLER');\r\n }\r\n } else {\r\n switch (item.tx_type) {\r\n // case 0:\r\n // return '';\r\n // case 1:\r\n // return '';\r\n // case 2:\r\n // return '';\r\n // case 3:\r\n // return '';\r\n case 4:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CREATE_ALIAS');\r\n case 5:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UPDATE_ALIAS');\r\n case 6:\r\n return (item.td['spn'] && item.td['spn'].length) ? this.translate.instant('HISTORY.TYPE_MESSAGES.POS_REWARD') : this.translate.instant('HISTORY.TYPE_MESSAGES.POW_REWARD');\r\n case 7:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CREATE_CONTRACT');\r\n case 8:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.PLEDGE_CONTRACT');\r\n // case 9:\r\n // return '';\r\n case 10:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.NULLIFY_CONTRACT');\r\n case 11:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.PROPOSAL_CANCEL_CONTRACT');\r\n case 12:\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.CANCEL_CONTRACT');\r\n }\r\n }\r\n\r\n return this.translate.instant('HISTORY.TYPE_MESSAGES.UNDEFINED');\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Pipe({\r\n name: 'intToMoney'\r\n})\r\nexport class IntToMoneyPipe implements PipeTransform {\r\n\r\n constructor(private variablesService: VariablesService) {}\r\n\r\n transform(value: any, args?: any): any {\r\n if (value === 0 || value === undefined) {\r\n return '0';\r\n }\r\n let maxFraction = this.variablesService.digits;\r\n if (args) {\r\n maxFraction = parseInt(args, 10);\r\n }\r\n const power = Math.pow(10, this.variablesService.digits);\r\n let str = (new BigNumber(value)).div(power).toFixed(maxFraction);\r\n\r\n for (let i = str.length - 1; i >= 0; i--) {\r\n if (str[i] !== '0') {\r\n str = str.substr(0, i + 1);\r\n break;\r\n }\r\n }\r\n if (str[str.length - 1] === '.') {\r\n str = str.substr(0, str.length - 1);\r\n }\r\n return str;\r\n }\r\n\r\n}\r\n","import {Pipe, PipeTransform} from '@angular/core';\r\nimport {VariablesService} from '../services/variables.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Pipe({\r\n name: 'moneyToInt'\r\n})\r\nexport class MoneyToIntPipe implements PipeTransform {\r\n\r\n constructor(private variablesService: VariablesService) {}\r\n\r\n transform(value: any, args?: any): any {\r\n const CURRENCY_DISPLAY_DECIMAL_POINT = this.variablesService.digits;\r\n let result;\r\n if (value) {\r\n let am_str = value.toString().trim();\r\n const point_index = am_str.indexOf('.');\r\n let fraction_size = 0;\r\n if (-1 !== point_index) {\r\n fraction_size = am_str.length - point_index - 1;\r\n while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' === am_str[am_str.length - 1]) {\r\n am_str = am_str.slice(0, am_str.length - 1);\r\n --fraction_size;\r\n }\r\n if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size) {\r\n return undefined;\r\n }\r\n am_str = am_str.slice(0, point_index) + am_str.slice(point_index + 1, am_str.length);\r\n } else {\r\n fraction_size = 0;\r\n }\r\n if (!am_str.length) {\r\n return undefined;\r\n }\r\n if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT) {\r\n for (let i = 0; i !== CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size; i++) {\r\n am_str = am_str + '0';\r\n }\r\n }\r\n result = (new BigNumber(am_str)).integerValue();\r\n }\r\n return result;\r\n }\r\n\r\n}\r\n","import { Pipe, PipeTransform } from '@angular/core';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\n\r\n@Pipe({\r\n name: 'safeHTML'\r\n})\r\nexport class SafeHTMLPipe implements PipeTransform {\r\n\r\n constructor(private sanitizer: DomSanitizer) { }\r\n\r\n transform(html: string) {\r\n return this.sanitizer.bypassSecurityTrustHtml(html);\r\n }\r\n\r\n}\r\n","import {Injectable} from '@angular/core';\r\nimport {Observable} from 'rxjs';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {VariablesService} from './variables.service';\r\nimport {ModalService} from './modal.service';\r\nimport {MoneyToIntPipe} from '../pipes/money-to-int.pipe';\r\nimport JSONBigNumber from 'json-bignumber';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Injectable()\r\nexport class BackendService {\r\n\r\n backendObject: any;\r\n backendLoaded = false;\r\n\r\n constructor(\r\n private translate: TranslateService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private moneyToIntPipe: MoneyToIntPipe\r\n ) {\r\n }\r\n\r\n static bigNumberParser(key, val) {\r\n if (val.constructor.name === 'BigNumber' && ['balance', 'unlocked_balance', 'amount', 'fee', 'b_fee', 'to_pay', 'a_pledge', 'b_pledge', 'coast', 'a'].indexOf(key) === -1) {\r\n return val.toNumber();\r\n }\r\n if (key === 'rcv' || key === 'spn') {\r\n for (let i = 0; i < val.length; i++) {\r\n val[i] = new BigNumber(val[i]);\r\n }\r\n }\r\n return val;\r\n }\r\n\r\n static Debug(type, message) {\r\n switch (type) {\r\n case 0:\r\n console.error(message);\r\n break;\r\n case 1:\r\n console.warn(message);\r\n break;\r\n case 2:\r\n console.log(message);\r\n break;\r\n default:\r\n console.log(message);\r\n break;\r\n }\r\n }\r\n\r\n private informerRun(error, params, command) {\r\n let error_translate = '';\r\n\r\n switch (error) {\r\n case 'NOT_ENOUGH_MONEY':\r\n error_translate = 'ERRORS.NOT_ENOUGH_MONEY';\r\n break;\r\n case 'CORE_BUSY':\r\n if (command !== 'get_all_aliases') {\r\n error_translate = 'ERRORS.CORE_BUSY';\r\n }\r\n break;\r\n case 'OVERFLOW':\r\n if (command !== 'get_all_aliases') {\r\n error_translate = '';\r\n }\r\n break;\r\n case 'INTERNAL_ERROR:daemon is busy':\r\n error_translate = 'ERRORS.DAEMON_BUSY';\r\n break;\r\n case 'INTERNAL_ERROR:not enough money':\r\n case 'INTERNAL_ERROR:NOT_ENOUGH_MONEY':\r\n if (command === 'cancel_offer') {\r\n error_translate = this.translate.instant('ERRORS.NO_MONEY_REMOVE_OFFER', {\r\n 'fee': this.variablesService.default_fee,\r\n 'currency': this.variablesService.defaultCurrency\r\n });\r\n } else {\r\n error_translate = 'ERRORS.NO_MONEY';\r\n }\r\n break;\r\n case 'INTERNAL_ERROR:not enough outputs to mix':\r\n error_translate = 'ERRORS.NOT_ENOUGH_OUTPUTS_TO_MIX';\r\n break;\r\n case 'INTERNAL_ERROR:transaction is too big':\r\n error_translate = 'ERRORS.TRANSACTION_IS_TO_BIG';\r\n break;\r\n case 'INTERNAL_ERROR:Transfer attempt while daemon offline':\r\n error_translate = 'ERRORS.TRANSFER_ATTEMPT';\r\n break;\r\n case 'ACCESS_DENIED':\r\n error_translate = 'ERRORS.ACCESS_DENIED';\r\n break;\r\n case 'INTERNAL_ERROR:transaction was rejected by daemon':\r\n // if (command === 'request_alias_registration') {\r\n // error_translate = 'INFORMER.ALIAS_IN_REGISTER';\r\n // } else {\r\n error_translate = 'ERRORS.TRANSACTION_ERROR';\r\n // }\r\n break;\r\n case 'INTERNAL_ERROR':\r\n error_translate = 'ERRORS.TRANSACTION_ERROR';\r\n break;\r\n case 'BAD_ARG':\r\n error_translate = 'ERRORS.BAD_ARG';\r\n break;\r\n case 'WALLET_WRONG_ID':\r\n error_translate = 'ERRORS.WALLET_WRONG_ID';\r\n break;\r\n case 'WRONG_PASSWORD':\r\n case 'WRONG_PASSWORD:invalid password':\r\n params = JSON.parse(params);\r\n if (!params.testEmpty) {\r\n error_translate = 'ERRORS.WRONG_PASSWORD';\r\n }\r\n break;\r\n case 'FILE_RESTORED':\r\n if (command === 'open_wallet') {\r\n error_translate = 'ERRORS.FILE_RESTORED';\r\n }\r\n break;\r\n case 'FILE_NOT_FOUND':\r\n if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {\r\n error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');\r\n params = JSON.parse(params);\r\n if (params.path) {\r\n error_translate += ': ' + params.path;\r\n }\r\n }\r\n break;\r\n case 'NOT_FOUND':\r\n if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {\r\n error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');\r\n params = JSON.parse(params);\r\n if (params.path) {\r\n error_translate += ': ' + params.path;\r\n }\r\n }\r\n break;\r\n case 'CANCELED':\r\n case '':\r\n break;\r\n case 'FAIL':\r\n if (command === 'create_proposal' || command === 'accept_proposal' || command === 'release_contract' || command === 'request_cancel_contract' || command === 'accept_cancel_contract') {\r\n error_translate = ' ';\r\n }\r\n break;\r\n case 'ALREADY_EXISTS':\r\n error_translate = 'ERRORS.FILE_EXIST';\r\n break;\r\n default:\r\n error_translate = error;\r\n }\r\n if (error.indexOf('FAIL:failed to save file') > -1) {\r\n error_translate = 'ERRORS.FILE_NOT_SAVED';\r\n }\r\n if (error.indexOf('FAILED:failed to open binary wallet file for saving') > -1 && command === 'generate_wallet') {\r\n error_translate = '';\r\n }\r\n if (error_translate !== '') {\r\n this.modalService.prepareModal('error', error_translate);\r\n }\r\n }\r\n\r\n\r\n private commandDebug(command, params, result) {\r\n BackendService.Debug(2, '----------------- ' + command + ' -----------------');\r\n const debug = {\r\n _send_params: params,\r\n _result: result\r\n };\r\n BackendService.Debug(2, debug);\r\n try {\r\n BackendService.Debug(2, JSONBigNumber.parse(result, BackendService.bigNumberParser));\r\n } catch (e) {\r\n BackendService.Debug(2, {response_data: result, error_code: 'OK'});\r\n }\r\n }\r\n\r\n private backendCallback(resultStr, params, callback, command) {\r\n let Result = resultStr;\r\n if (command !== 'get_clipboard') {\r\n if (!resultStr || resultStr === '') {\r\n Result = {};\r\n } else {\r\n try {\r\n Result = JSONBigNumber.parse(resultStr, BackendService.bigNumberParser);\r\n } catch (e) {\r\n Result = {response_data: resultStr, error_code: 'OK'};\r\n }\r\n }\r\n } else {\r\n Result = {\r\n error_code: 'OK',\r\n response_data: Result\r\n };\r\n }\r\n\r\n const Status = (Result.error_code === 'OK' || Result.error_code === 'TRUE');\r\n\r\n if (!Status && Status !== undefined && Result.error_code !== undefined) {\r\n BackendService.Debug(1, 'API error for command: \"' + command + '\". Error code: ' + Result.error_code);\r\n }\r\n const data = ((typeof Result === 'object') && 'response_data' in Result) ? Result.response_data : Result;\r\n\r\n let res_error_code = false;\r\n if (typeof Result === 'object' && 'error_code' in Result && Result.error_code !== 'OK' && Result.error_code !== 'TRUE' && Result.error_code !== 'FALSE') {\r\n this.informerRun(Result.error_code, params, command);\r\n res_error_code = Result.error_code;\r\n }\r\n\r\n // if ( command === 'get_offers_ex' ){\r\n // Service.printLog( \"get_offers_ex offers count \"+((data.offers)?data.offers.length:0) );\r\n // }\r\n\r\n if (typeof callback === 'function') {\r\n callback(Status, data, res_error_code);\r\n } else {\r\n return data;\r\n }\r\n }\r\n\r\n\r\n private runCommand(command, params?, callback?) {\r\n if (this.backendObject) {\r\n const Action = this.backendObject[command];\r\n if (!Action) {\r\n BackendService.Debug(0, 'Run Command Error! Command \"' + command + '\" don\\'t found in backendObject');\r\n } else {\r\n const that = this;\r\n params = (typeof params === 'string') ? params : JSONBigNumber.stringify(params);\r\n if (params === undefined || params === '{}') {\r\n Action(function (resultStr) {\r\n that.commandDebug(command, params, resultStr);\r\n return that.backendCallback(resultStr, params, callback, command);\r\n });\r\n } else {\r\n Action(params, function (resultStr) {\r\n that.commandDebug(command, params, resultStr);\r\n return that.backendCallback(resultStr, params, callback, command);\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n\r\n eventSubscribe(command, callback) {\r\n if (command === 'on_core_event') {\r\n this.backendObject[command].connect(callback);\r\n } else {\r\n this.backendObject[command].connect((str) => {\r\n callback(JSONBigNumber.parse(str, BackendService.bigNumberParser));\r\n });\r\n }\r\n }\r\n\r\n\r\n initService() {\r\n return new Observable(\r\n observer => {\r\n if (!this.backendLoaded) {\r\n this.backendLoaded = true;\r\n const that = this;\r\n (window).QWebChannel((window).qt.webChannelTransport, function (channel) {\r\n that.backendObject = channel.objects.mediator_object;\r\n observer.next('ok');\r\n });\r\n } else {\r\n if (!this.backendObject) {\r\n observer.error('error');\r\n observer.error('error');\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n\r\n webkitLaunchedScript() {\r\n return this.runCommand('webkit_launched_script');\r\n }\r\n\r\n quitRequest() {\r\n return this.runCommand('on_request_quit');\r\n }\r\n\r\n getAppData(callback) {\r\n this.runCommand('get_app_data', {}, callback);\r\n }\r\n\r\n storeAppData(callback?) {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.settings.wallets = [];\r\n this.variablesService.wallets.forEach((wallet) => {\r\n this.variablesService.settings.wallets.push({name: wallet.name, path: wallet.path});\r\n });\r\n }\r\n this.runCommand('store_app_data', this.variablesService.settings, callback);\r\n }\r\n\r\n getSecureAppData(pass, callback) {\r\n this.runCommand('get_secure_app_data', pass, callback);\r\n }\r\n\r\n setMasterPassword(pass, callback) {\r\n this.runCommand('set_master_password', pass, callback);\r\n }\r\n\r\n checkMasterPassword(pass, callback) {\r\n this.runCommand('check_master_password', pass, callback);\r\n }\r\n storeSecureAppData(callback?) {\r\n let data;\r\n const wallets = [];\r\n const contacts = [];\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallets.push({name: wallet.name, pass: wallet.pass, path: wallet.path, staking: wallet.staking});\r\n });\r\n this.variablesService.contacts.forEach((contact) => {\r\n contacts.push({name: contact.name, address: contact.address, notes: contact.notes});\r\n });\r\n data = {wallets: wallets, contacts: contacts};\r\n this.backendObject['store_secure_app_data'](JSON.stringify(data), this.variablesService.appPass, (dataStore) => {\r\n this.backendCallback(dataStore, {}, callback, 'store_secure_app_data');\r\n });\r\n }\r\n\r\n dropSecureAppData(callback?) {\r\n this.backendObject['drop_secure_app_data']((dataStore) => {\r\n this.backendCallback(dataStore, {}, callback, 'drop_secure_app_data');\r\n });\r\n }\r\n\r\n haveSecureAppData(callback) {\r\n this.runCommand('have_secure_app_data', {}, callback);\r\n }\r\n\r\n saveFileDialog(caption, fileMask, default_path, callback) {\r\n const dir = default_path ? default_path : '/';\r\n const params = {\r\n caption: caption,\r\n filemask: fileMask,\r\n default_dir: dir\r\n };\r\n this.runCommand('show_savefile_dialog', params, callback);\r\n }\r\n\r\n openFileDialog(caption, fileMask, default_path, callback) {\r\n const dir = default_path ? default_path : '/';\r\n const params = {\r\n caption: caption,\r\n filemask: fileMask,\r\n default_dir: dir\r\n };\r\n this.runCommand('show_openfile_dialog', params, callback);\r\n }\r\n\r\n storeFile(path, buff) {\r\n this.backendObject['store_to_file'](path, buff);\r\n }\r\n\r\n loadFile(path, callback) {\r\n this.runCommand('load_from_file', path, callback);\r\n }\r\n\r\n generateWallet(path, pass, callback) {\r\n const params = {\r\n path: path,\r\n pass: pass\r\n };\r\n this.runCommand('generate_wallet', params, callback);\r\n }\r\n\r\n openWallet(path, pass, testEmpty, callback) {\r\n const params = {\r\n path: path,\r\n pass: pass\r\n };\r\n params['testEmpty'] = !!(testEmpty);\r\n this.runCommand('open_wallet', params, callback);\r\n }\r\n\r\n closeWallet(wallet_id, callback?) {\r\n this.runCommand('close_wallet', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n getSmartWalletInfo(wallet_id, callback) {\r\n this.runCommand('get_smart_wallet_info', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n runWallet(wallet_id, callback?) {\r\n this.runCommand('run_wallet', {wallet_id: +wallet_id}, callback);\r\n }\r\n\r\n isValidRestoreWalletText(text, callback) {\r\n this.runCommand('is_valid_restore_wallet_text', text, callback);\r\n }\r\n\r\n restoreWallet(path, pass, restore_key, callback) {\r\n const params = {\r\n restore_key: restore_key,\r\n path: path,\r\n pass: pass\r\n };\r\n this.runCommand('restore_wallet', params, callback);\r\n }\r\n\r\n sendMoney(from_wallet_id, to_address, amount, fee, mixin, comment, hide, callback) {\r\n const params = {\r\n wallet_id: parseInt(from_wallet_id, 10),\r\n destinations: [\r\n {\r\n address: to_address,\r\n amount: amount\r\n }\r\n ],\r\n mixin_count: (mixin) ? parseInt(mixin, 10) : 0,\r\n lock_time: 0,\r\n fee: this.moneyToIntPipe.transform(fee),\r\n comment: comment,\r\n push_payer: !hide\r\n };\r\n this.runCommand('transfer', params, callback);\r\n }\r\n\r\n validateAddress(address, callback) {\r\n this.runCommand('validate_address', address, callback);\r\n }\r\n\r\n setClipboard(str, callback?) {\r\n return this.runCommand('set_clipboard', str, callback);\r\n }\r\n\r\n getClipboard(callback) {\r\n return this.runCommand('get_clipboard', {}, callback);\r\n }\r\n\r\n createProposal(wallet_id, title, comment, a_addr, b_addr, to_pay, a_pledge, b_pledge, time, payment_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n details: {\r\n t: title,\r\n c: comment,\r\n a_addr: a_addr,\r\n b_addr: b_addr,\r\n to_pay: this.moneyToIntPipe.transform(to_pay),\r\n a_pledge: this.moneyToIntPipe.transform(a_pledge),\r\n b_pledge: this.moneyToIntPipe.transform(b_pledge)\r\n },\r\n payment_id: payment_id,\r\n expiration_period: parseInt(time, 10) * 60 * 60,\r\n fee: this.variablesService.default_fee_big,\r\n b_fee: this.variablesService.default_fee_big\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('create_proposal', params, callback);\r\n }\r\n\r\n getContracts(wallet_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10)\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('get_contracts', params, callback);\r\n }\r\n\r\n acceptProposal(wallet_id, contract_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('accept_proposal', params, callback);\r\n }\r\n\r\n releaseProposal(wallet_id, contract_id, release_type, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id,\r\n release_type: release_type // \"normal\" or \"burn\"\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('release_contract', params, callback);\r\n }\r\n\r\n requestCancelContract(wallet_id, contract_id, time, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id,\r\n fee: this.variablesService.default_fee_big,\r\n expiration_period: parseInt(time, 10) * 60 * 60\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('request_cancel_contract', params, callback);\r\n }\r\n\r\n acceptCancelContract(wallet_id, contract_id, callback) {\r\n const params = {\r\n wallet_id: parseInt(wallet_id, 10),\r\n contract_id: contract_id\r\n };\r\n BackendService.Debug(1, params);\r\n this.runCommand('accept_cancel_contract', params, callback);\r\n }\r\n\r\n getMiningHistory(wallet_id, callback) {\r\n this.runCommand('get_mining_history', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n startPosMining(wallet_id, callback?) {\r\n this.runCommand('start_pos_mining', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n stopPosMining(wallet_id, callback?) {\r\n this.runCommand('stop_pos_mining', {wallet_id: parseInt(wallet_id, 10)}, callback);\r\n }\r\n\r\n openUrlInBrowser(url, callback?) {\r\n this.runCommand('open_url_in_browser', url, callback);\r\n }\r\n\r\n start_backend(node, host, port, callback) {\r\n const params = {\r\n configure_for_remote_node: node,\r\n remote_node_host: host,\r\n remote_node_port: parseInt(port, 10)\r\n };\r\n this.runCommand('start_backend', params, callback);\r\n }\r\n\r\n getDefaultFee(callback) {\r\n this.runCommand('get_default_fee', {}, callback);\r\n }\r\n\r\n setBackendLocalization(stringsArray, title, callback?) {\r\n const params = {\r\n strings: stringsArray,\r\n language_title: title\r\n };\r\n this.runCommand('set_localization_strings', params, callback);\r\n }\r\n\r\n registerAlias(wallet_id, alias, address, fee, comment, reward, callback) {\r\n const params = {\r\n wallet_id: wallet_id,\r\n alias: {\r\n alias: alias,\r\n address: address,\r\n tracking_key: '',\r\n comment: comment\r\n },\r\n fee: this.moneyToIntPipe.transform(fee),\r\n reward: this.moneyToIntPipe.transform(reward)\r\n };\r\n this.runCommand('request_alias_registration', params, callback);\r\n }\r\n\r\n updateAlias(wallet_id, alias, fee, callback) {\r\n const params = {\r\n wallet_id: wallet_id,\r\n alias: {\r\n alias: alias.name.replace('@', ''),\r\n address: alias.address,\r\n tracking_key: '',\r\n comment: alias.comment\r\n },\r\n fee: this.moneyToIntPipe.transform(fee)\r\n };\r\n this.runCommand('request_alias_update', params, callback);\r\n }\r\n\r\n getAllAliases(callback) {\r\n this.runCommand('get_all_aliases', {}, callback);\r\n }\r\n\r\n getAliasByName(value, callback) {\r\n return this.runCommand('get_alias_info_by_name', value, callback);\r\n }\r\n\r\n getAliasByAddress(value, callback) {\r\n return this.runCommand('get_alias_info_by_address', value, callback);\r\n }\r\n\r\n getAliasCoast(alias, callback) {\r\n this.runCommand('get_alias_coast', {v: alias}, callback);\r\n }\r\n\r\n getWalletAlias(address) {\r\n if (address !== null && this.variablesService.daemon_state === 2) {\r\n if (this.variablesService.aliasesChecked[address] == null) {\r\n this.variablesService.aliasesChecked[address] = {};\r\n if (this.variablesService.aliases.length) {\r\n for (let i = 0, length = this.variablesService.aliases.length; i < length; i++) {\r\n if (i in this.variablesService.aliases && this.variablesService.aliases[i]['address'] === address) {\r\n this.variablesService.aliasesChecked[address]['name'] = this.variablesService.aliases[i].name;\r\n this.variablesService.aliasesChecked[address]['address'] = this.variablesService.aliases[i].address;\r\n this.variablesService.aliasesChecked[address]['comment'] = this.variablesService.aliases[i].comment;\r\n return this.variablesService.aliasesChecked[address];\r\n }\r\n }\r\n }\r\n this.getAliasByAddress(address, (status, data) => {\r\n if (status) {\r\n this.variablesService.aliasesChecked[data.address]['name'] = '@' + data.alias;\r\n this.variablesService.aliasesChecked[data.address]['address'] = data.address;\r\n this.variablesService.aliasesChecked[data.address]['comment'] = data.comment;\r\n }\r\n });\r\n }\r\n return this.variablesService.aliasesChecked[address];\r\n }\r\n return {};\r\n }\r\n\r\n getContactAlias() {\r\n if (this.variablesService.contacts.length && this.variablesService.daemon_state === 2) {\r\n this.variablesService.contacts.map(contact => {\r\n this.getAliasByAddress(contact.address, (status, data) => {\r\n if (status) {\r\n if (data.alias) {\r\n contact.alias = '@' + data.alias;\r\n }\r\n } else {\r\n contact.alias = null;\r\n }\r\n });\r\n });\r\n }\r\n }\r\n\r\n getPoolInfo(callback) {\r\n this.runCommand('get_tx_pool_info', {}, callback);\r\n }\r\n\r\n getVersion(callback) {\r\n this.runCommand('get_version', {}, (status, version) => {\r\n callback(version);\r\n });\r\n }\r\n\r\n setLogLevel(level) {\r\n return this.runCommand('set_log_level', {v: level});\r\n }\r\n\r\n}\r\n\r\n\r\n/*\r\n\r\n toggleAutoStart: function (value) {\r\n return this.runCommand('toggle_autostart', asVal(value));\r\n },\r\n\r\n getOptions: function (callback) {\r\n return this.runCommand('get_options', {}, callback);\r\n },\r\n\r\n isFileExist: function (path, callback) {\r\n return this.runCommand('is_file_exist', path, callback);\r\n },\r\n\r\n isAutoStartEnabled: function (callback) {\r\n this.runCommand('is_autostart_enabled', {}, function (status, data) {\r\n if (angular.isFunction(callback)) {\r\n callback('error_code' in data && data.error_code !== 'FALSE')\r\n }\r\n });\r\n },\r\n\r\n resetWalletPass: function (wallet_id, pass, callback) {\r\n this.runCommand('reset_wallet_password', {wallet_id: wallet_id, pass: pass}, callback);\r\n },\r\n\r\n\r\n\r\n getOsVersion: function (callback) {\r\n this.runCommand('get_os_version', {}, function (status, version) {\r\n callback(version)\r\n })\r\n },\r\n\r\n getLogFile: function (callback) {\r\n this.runCommand('get_log_file', {}, function (status, version) {\r\n callback(version)\r\n })\r\n },\r\n\r\n resync_wallet: function (wallet_id, callback) {\r\n this.runCommand('resync_wallet', {wallet_id: wallet_id}, callback);\r\n },\r\n\r\n storeFile: function (path, buff, callback) {\r\n this.backendObject['store_to_file'](path, (typeof buff === 'string' ? buff : JSON.stringify(buff)), function (data) {\r\n backendCallback(data, {}, callback, 'store_to_file');\r\n });\r\n },\r\n\r\n getMiningEstimate: function (amount_coins, time, callback) {\r\n var params = {\r\n \"amount_coins\": $filter('money_to_int')(amount_coins),\r\n \"time\": parseInt(time)\r\n };\r\n this.runCommand('get_mining_estimate', params, callback);\r\n },\r\n\r\n backupWalletKeys: function (wallet_id, path, callback) {\r\n var params = {\r\n \"wallet_id\": wallet_id,\r\n \"path\": path\r\n };\r\n this.runCommand('backup_wallet_keys', params, callback);\r\n },\r\n\r\n setBlockedIcon: function (enabled, callback) {\r\n var mode = (enabled) ? \"blocked\" : \"normal\";\r\n Service.runCommand('bool_toggle_icon', mode, callback);\r\n },\r\n\r\n getWalletInfo: function (wallet_id, callback) {\r\n this.runCommand('get_wallet_info', {wallet_id: wallet_id}, callback);\r\n },\r\n\r\n printText: function (content) {\r\n return this.runCommand('print_text', {html_text: content});\r\n },\r\n\r\n printLog: function (msg, log_level) {\r\n return this.runCommand('print_log', {msg: msg, log_level: log_level});\r\n },\r\n\r\n*/\r\n\r\n","import {Injectable, Injector, ComponentFactoryResolver, EmbeddedViewRef, ApplicationRef, NgZone} from '@angular/core';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {ModalContainerComponent} from '../directives/modal-container/modal-container.component';\r\n\r\n@Injectable()\r\nexport class ModalService {\r\n\r\n private components: any[] = [];\r\n\r\n constructor(\r\n private componentFactoryResolver: ComponentFactoryResolver,\r\n private appRef: ApplicationRef,\r\n private injector: Injector,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {}\r\n\r\n prepareModal(type, message) {\r\n const length = this.components.push(\r\n this.componentFactoryResolver.resolveComponentFactory(ModalContainerComponent).create(this.injector)\r\n );\r\n\r\n this.components[length - 1].instance['type'] = type;\r\n this.components[length - 1].instance['message'] = message.length ? this.translate.instant(message) : '';\r\n this.components[length - 1].instance['close'].subscribe(() => {\r\n this.removeModal(length - 1);\r\n });\r\n\r\n this.ngZone.run(() => {\r\n this.appendModal(length - 1);\r\n });\r\n }\r\n\r\n appendModal(index) {\r\n this.appRef.attachView(this.components[index].hostView);\r\n const domElem = (this.components[index].hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement;\r\n document.body.appendChild(domElem);\r\n }\r\n\r\n removeModal(index) {\r\n if (this.components[index]) {\r\n this.appRef.detachView(this.components[index].hostView);\r\n this.components[index].destroy();\r\n this.components.splice(index, 1);\r\n } else {\r\n const last = this.components.length - 1;\r\n this.appRef.detachView(this.components[last].hostView);\r\n this.components[last].destroy();\r\n this.components.splice(last, 1);\r\n }\r\n }\r\n}\r\n","import {Injectable, NgZone} from '@angular/core';\r\nimport {Wallet} from '../models/wallet.model';\r\nimport {Contact} from '../models/contact.model';\r\nimport {BehaviorSubject} from 'rxjs';\r\nimport {Idle} from 'idlejs/dist';\r\nimport {Router} from '@angular/router';\r\nimport {ContextMenuComponent, ContextMenuService} from 'ngx-contextmenu';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class VariablesService {\r\n\r\n public digits = 12;\r\n public appPass = '';\r\n public appLogin = false;\r\n public moneyEquivalent = 0;\r\n public defaultTheme = 'dark';\r\n public defaultCurrency = 'ZANO';\r\n public opening_wallet: Wallet;\r\n public exp_med_ts = 0;\r\n public net_time_delta_median = 0;\r\n public height_app = 0;\r\n public height_max = 0;\r\n public last_build_available = '';\r\n public last_build_displaymode = 0;\r\n public daemon_state = 3;\r\n public sync = {\r\n progress_value: 0,\r\n progress_value_text: '0'\r\n };\r\n public default_fee = '0.010000000000';\r\n public default_fee_big = new BigNumber('10000000000');\r\n\r\n public settings = {\r\n appLockTime: 15,\r\n appLog: 0,\r\n theme: '',\r\n scale: 10,\r\n language: 'en',\r\n default_path: '/',\r\n viewedContracts: [],\r\n notViewedContracts: [],\r\n wallets: []\r\n };\r\n\r\n public wallets: Array = [];\r\n public currentWallet: Wallet;\r\n public selectWallet: number;\r\n public aliases: any = [];\r\n public aliasesChecked: any = {};\r\n public enableAliasSearch = false;\r\n public maxWalletNameLength = 25;\r\n public maxCommentLength = 255;\r\n public dataIsLoaded = false;\r\n\r\n public contacts: Array = [];\r\n public newContact: Contact = {name: null, address: null, notes: null};\r\n\r\n public pattern = '^[a-zA-Z0-9_.\\\\\\]\\*\\|\\~\\!\\?\\@\\#\\$\\%\\^\\&\\+\\{\\}\\(\\)\\<\\>\\:\\;\\\"\\'\\-\\=\\/\\,\\[\\\\\\\\]*$';\r\n\r\n getExpMedTsEvent = new BehaviorSubject(null);\r\n getHeightAppEvent = new BehaviorSubject(null);\r\n getHeightMaxEvent = new BehaviorSubject(null);\r\n getRefreshStackingEvent = new BehaviorSubject(null);\r\n getAliasChangedEvent = new BehaviorSubject(null);\r\n\r\n public idle = new Idle()\r\n .whenNotInteractive()\r\n .do(() => {\r\n if (this.appPass == '') {\r\n this.restartCountdown();\r\n } else {\r\n this.ngZone.run(() => {\r\n this.idle.stop();\r\n this.appPass = '';\r\n this.appLogin = false;\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n }\r\n });\r\n\r\n public allContextMenu: ContextMenuComponent;\r\n public onlyCopyContextMenu: ContextMenuComponent;\r\n public pasteSelectContextMenu: ContextMenuComponent;\r\n\r\n constructor(private router: Router, private ngZone: NgZone, private contextMenuService: ContextMenuService) {\r\n }\r\n\r\n setExpMedTs(timestamp: number) {\r\n if (timestamp !== this.exp_med_ts) {\r\n this.exp_med_ts = timestamp;\r\n this.getExpMedTsEvent.next(timestamp);\r\n }\r\n }\r\n\r\n setHeightApp(height: number) {\r\n if (height !== this.height_app) {\r\n this.height_app = height;\r\n this.getHeightAppEvent.next(height);\r\n }\r\n }\r\n\r\n setHeightMax(height: number) {\r\n if (height !== this.height_max) {\r\n this.height_max = height;\r\n this.getHeightMaxEvent.next(height);\r\n }\r\n }\r\n\r\n setRefreshStacking(wallet_id: number) {\r\n this.getHeightAppEvent.next(wallet_id);\r\n }\r\n\r\n changeAliases() {\r\n this.getAliasChangedEvent.next(true);\r\n }\r\n\r\n setCurrentWallet(id): void {\r\n this.wallets.forEach((wallet) => {\r\n if (wallet.wallet_id === id) {\r\n this.currentWallet = wallet;\r\n }\r\n });\r\n }\r\n\r\n getWallet(id): Wallet {\r\n for (let i = 0; i < this.wallets.length; i++) {\r\n if (this.wallets[i].wallet_id === id) {\r\n return this.wallets[i];\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n startCountdown() {\r\n this.idle.within(this.settings.appLockTime).start();\r\n }\r\n\r\n stopCountdown() {\r\n this.idle.stop();\r\n }\r\n\r\n restartCountdown() {\r\n this.idle.within(this.settings.appLockTime).restart();\r\n }\r\n\r\n public onContextMenu($event: MouseEvent): void {\r\n $event.target['contextSelectionStart'] = $event.target['selectionStart'];\r\n $event.target['contextSelectionEnd'] = $event.target['selectionEnd'];\r\n if ($event.target && ($event.target['nodeName'].toUpperCase() === 'TEXTAREA' || $event.target['nodeName'].toUpperCase() === 'INPUT') && !$event.target['readOnly']) {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.allContextMenu,\r\n event: $event,\r\n item: $event.target,\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n }\r\n\r\n public onContextMenuOnlyCopy($event: MouseEvent, copyText?: string): void {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.onlyCopyContextMenu,\r\n event: $event,\r\n item: copyText\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n\r\n public onContextMenuPasteSelect($event: MouseEvent): void {\r\n $event.target['contextSelectionStart'] = $event.target['selectionStart'];\r\n $event.target['contextSelectionEnd'] = $event.target['selectionEnd'];\r\n\r\n console.warn($event.target);\r\n console.warn($event.target['disabled']);\r\n\r\n\r\n if ($event.target && ($event.target['nodeName'].toUpperCase() === 'TEXTAREA' || $event.target['nodeName'].toUpperCase() === 'INPUT') && !$event.target['readOnly']) {\r\n this.contextMenuService.show.next({\r\n contextMenu: this.pasteSelectContextMenu,\r\n event: $event,\r\n item: $event.target,\r\n });\r\n $event.preventDefault();\r\n $event.stopPropagation();\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.TITLE' | translate }}\\r\\n {{ 'CONTACTS.ADD' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.NAME_DUBLICATED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.ADDRESS_DUBLICATED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CONTACTS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \".form-add {\\n margin-top: 3rem; }\\n .form-add .input-block-name {\\n width: 50%; }\\n .form-add button {\\n margin-top: 3rem;\\n width: 100%;\\n max-width: 18rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYWRkLWNvbnRhY3RzL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxhZGQtY29udGFjdHNcXGFkZC1jb250YWN0cy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxnQkFBZ0I7SUFDaEIsV0FBVztJQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvYWRkLWNvbnRhY3RzL2FkZC1jb250YWN0cy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLWFkZCB7XHJcbiAgbWFyZ2luLXRvcDogM3JlbTtcclxuXHJcbiAgLmlucHV0LWJsb2NrLW5hbWUge1xyXG4gICAgd2lkdGg6IDUwJTtcclxuICB9XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBtYXJnaW4tdG9wOiAzcmVtO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE4cmVtO1xyXG4gIH1cclxufSJdfQ== */\"","import { Component, OnInit, NgZone, OnDestroy } from '@angular/core';\r\nimport { FormGroup, FormControl, Validators } from '@angular/forms';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\nimport { Location } from '@angular/common';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-add-contacts',\r\n templateUrl: './add-contacts.component.html',\r\n styleUrls: ['./add-contacts.component.scss']\r\n})\r\nexport class AddContactsComponent implements OnInit, OnDestroy {\r\n id: number;\r\n queryRouting;\r\n addContactForm = new FormGroup({\r\n address: new FormControl('', [\r\n Validators.required,\r\n (g: FormControl) => {\r\n if (g.value) {\r\n this.backend.validateAddress(g.value, valid_status => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(\r\n Object.assign({ address_not_valid: true }, g.errors)\r\n );\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return g.hasError('address_not_valid')\r\n ? { address_not_valid: true }\r\n : null;\r\n }\r\n return null;\r\n },\r\n (g: FormControl) => {\r\n const isDublicated = this.variablesService.contacts.findIndex(\r\n contact => contact.address === g.value\r\n );\r\n if (isDublicated !== -1 && !(this.id === isDublicated)) {\r\n return { dublicated: true };\r\n }\r\n return null;\r\n }\r\n ]),\r\n notes: new FormControl('', [\r\n (g: FormControl) => {\r\n if (g.value) {\r\n if (g.value.length > this.variablesService.maxCommentLength) {\r\n return { maxLength: true };\r\n } else {\r\n return null;\r\n }\r\n } else {\r\n return null;\r\n }\r\n }\r\n ]),\r\n name: new FormControl('', [\r\n Validators.required,\r\n Validators.minLength(4),\r\n Validators.maxLength(25),\r\n (g: FormControl) => {\r\n if (g.value) {\r\n const isDublicated = this.variablesService.contacts.findIndex(\r\n contact => contact.name === g.value.trim()\r\n );\r\n if (isDublicated !== -1 && !(this.id === isDublicated)) {\r\n return { dublicated: true };\r\n }\r\n return null;\r\n }\r\n }\r\n ])\r\n });\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private location: Location\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.id) {\r\n this.id = parseInt(params.id, 10);\r\n this.addContactForm.reset({\r\n name: this.variablesService.contacts[params.id]['name'],\r\n address: this.variablesService.contacts[params.id]['address'],\r\n notes: this.variablesService.contacts[params.id]['notes']\r\n });\r\n } else {\r\n this.addContactForm.reset({\r\n name: this.variablesService.newContact['name'],\r\n address: this.variablesService.newContact['address'],\r\n notes: this.variablesService.newContact['notes']\r\n });\r\n }\r\n });\r\n }\r\n\r\n add() {\r\n if (!this.variablesService.appPass) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.FORM_ERRORS.SET_MASTER_PASSWORD'\r\n );\r\n } else {\r\n if (this.addContactForm.valid) {\r\n this.backend.validateAddress(\r\n this.addContactForm.get('address').value,\r\n valid_status => {\r\n if (valid_status === false) {\r\n this.ngZone.run(() => {\r\n this.addContactForm\r\n .get('address')\r\n .setErrors({ address_not_valid: true });\r\n });\r\n } else {\r\n if (this.id || this.id === 0) {\r\n this.variablesService.contacts.forEach((contact, index) => {\r\n if (index === this.id) {\r\n contact.name = this.addContactForm.get('name').value.trim();\r\n contact.address = this.addContactForm.get('address').value;\r\n contact.notes =\r\n this.addContactForm.get('notes').value || '';\r\n }\r\n });\r\n this.backend.storeSecureAppData();\r\n this.backend.getContactAlias();\r\n this.modalService.prepareModal(\r\n 'success',\r\n 'CONTACTS.SUCCESS_SAVE'\r\n );\r\n } else {\r\n this.variablesService.contacts.push({\r\n name: this.addContactForm.get('name').value.trim(),\r\n address: this.addContactForm.get('address').value,\r\n notes: this.addContactForm.get('notes').value || ''\r\n });\r\n this.backend.storeSecureAppData();\r\n this.backend.getContactAlias();\r\n this.modalService.prepareModal(\r\n 'success',\r\n 'CONTACTS.SUCCESS_SENT'\r\n );\r\n this.variablesService.newContact = {\r\n name: null,\r\n address: null,\r\n notes: null\r\n };\r\n this.addContactForm.reset({\r\n name: null,\r\n address: null,\r\n notes: null\r\n });\r\n }\r\n }\r\n }\r\n );\r\n }\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n if (!(this.id || this.id === 0)) {\r\n this.variablesService.newContact = {\r\n name: this.addContactForm.get('name').value,\r\n address: this.addContactForm.get('address').value,\r\n notes: this.addContactForm.get('notes').value\r\n };\r\n }\r\n this.queryRouting.unsubscribe();\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { Routes, RouterModule } from '@angular/router';\r\n\r\n// Components\r\nimport { MainComponent } from './main/main.component';\r\nimport { LoginComponent } from './login/login.component';\r\nimport { WalletComponent } from './wallet/wallet.component';\r\nimport { SendComponent } from './send/send.component';\r\nimport { ReceiveComponent } from './receive/receive.component';\r\nimport { HistoryComponent } from './history/history.component';\r\nimport { ContractsComponent } from './contracts/contracts.component';\r\nimport { PurchaseComponent } from './purchase/purchase.component';\r\nimport { MessagesComponent } from './messages/messages.component';\r\nimport { TypingMessageComponent } from './typing-message/typing-message.component';\r\nimport { StakingComponent } from './staking/staking.component';\r\nimport { SettingsComponent } from './settings/settings.component';\r\nimport { CreateWalletComponent } from './create-wallet/create-wallet.component';\r\nimport { OpenWalletComponent } from './open-wallet/open-wallet.component';\r\nimport { RestoreWalletComponent } from './restore-wallet/restore-wallet.component';\r\nimport { SeedPhraseComponent } from './seed-phrase/seed-phrase.component';\r\nimport { WalletDetailsComponent } from './wallet-details/wallet-details.component';\r\nimport { AssignAliasComponent } from './assign-alias/assign-alias.component';\r\nimport { EditAliasComponent } from './edit-alias/edit-alias.component';\r\nimport { TransferAliasComponent } from './transfer-alias/transfer-alias.component';\r\nimport { ContactsComponent } from './contacts/contacts.component';\r\nimport { AddContactsComponent } from './add-contacts/add-contacts.component';\r\nimport { ContactSendComponent } from './contact-send/contact-send.component';\r\nimport { ExportImportComponent } from './export-import/export-import.component';\r\n\r\nconst routes: Routes = [\r\n {\r\n path: '',\r\n component: MainComponent\r\n },\r\n {\r\n path: 'main',\r\n component: MainComponent\r\n },\r\n {\r\n path: 'login',\r\n component: LoginComponent\r\n },\r\n {\r\n path: 'wallet/:id',\r\n component: WalletComponent,\r\n children: [\r\n {\r\n path: 'send',\r\n component: SendComponent\r\n },\r\n {\r\n path: 'receive',\r\n component: ReceiveComponent\r\n },\r\n {\r\n path: 'history',\r\n component: HistoryComponent\r\n },\r\n {\r\n path: 'contracts',\r\n component: ContractsComponent,\r\n },\r\n {\r\n path: 'purchase',\r\n component: PurchaseComponent\r\n },\r\n {\r\n path: 'purchase/:id',\r\n component: PurchaseComponent\r\n },\r\n {\r\n path: 'messages',\r\n component: MessagesComponent,\r\n },\r\n {\r\n path: 'messages/:id',\r\n component: TypingMessageComponent,\r\n },\r\n {\r\n path: 'staking',\r\n component: StakingComponent\r\n },\r\n {\r\n path: '',\r\n redirectTo: 'history',\r\n pathMatch: 'full'\r\n }\r\n ]\r\n },\r\n {\r\n path: 'create',\r\n component: CreateWalletComponent\r\n },\r\n {\r\n path: 'open',\r\n component: OpenWalletComponent\r\n },\r\n {\r\n path: 'restore',\r\n component: RestoreWalletComponent\r\n },\r\n {\r\n path: 'seed-phrase',\r\n component: SeedPhraseComponent\r\n },\r\n {\r\n path: 'details',\r\n component: WalletDetailsComponent\r\n },\r\n {\r\n path: 'assign-alias',\r\n component: AssignAliasComponent\r\n },\r\n {\r\n path: 'edit-alias',\r\n component: EditAliasComponent\r\n },\r\n {\r\n path: 'transfer-alias',\r\n component: TransferAliasComponent\r\n },\r\n {\r\n path: 'settings',\r\n component: SettingsComponent\r\n },\r\n {\r\n path: 'contacts',\r\n component: ContactsComponent\r\n },\r\n {\r\n path: 'add-contacts',\r\n component: AddContactsComponent\r\n },\r\n {\r\n path: 'edit-contacts/:id',\r\n component: AddContactsComponent\r\n },\r\n {\r\n path: 'contact-send/:id',\r\n component: ContactSendComponent\r\n },\r\n {\r\n path: 'import',\r\n component: ExportImportComponent\r\n },\r\n {\r\n path: '',\r\n redirectTo: '/',\r\n pathMatch: 'full'\r\n }\r\n];\r\n\r\n@NgModule({\r\n imports: [RouterModule.forRoot(routes)],\r\n exports: [RouterModule]\r\n})\r\n\r\n\r\nexport class AppRoutingModule { }\r\n","module.exports = \"\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}\\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n {{ 'CONTEXT_MENU.COPY' | translate }}\\r\\n {{ 'CONTEXT_MENU.PASTE' | translate }}\\r\\n {{ 'CONTEXT_MENU.SELECT' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n {{ 'CONTEXT_MENU.COPY' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n {{ 'CONTEXT_MENU.PASTE' | translate }}\\r\\n {{ 'CONTEXT_MENU.SELECT' | translate }}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\"","module.exports = \"/*\\r\\n* Implementation of themes\\r\\n*/\\n.app-content {\\n display: flex;\\n overflow-x: overlay;\\n overflow-y: hidden;\\n width: 100%; }\\n.app-content .preloader {\\n align-self: center;\\n color: #fff;\\n font-size: 2rem;\\n margin: 0 auto;\\n text-align: center;\\n width: 50%; }\\n.app-content .preloader .loading-bar {\\n display: block;\\n -webkit-animation: move 5s linear infinite;\\n animation: move 5s linear infinite;\\n background-image: -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.125, rgba(0, 0, 0, 0.15)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.1)), color-stop(0.375, rgba(0, 0, 0, 0.1)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.15)), color-stop(0.625, rgba(0, 0, 0, 0.15)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.1)), color-stop(0.875, rgba(0, 0, 0, 0.1)), color-stop(0.875, transparent), to(transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.125, rgba(0, 0, 0, 0.3)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.25)), color-stop(0.375, rgba(0, 0, 0, 0.25)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.3)), color-stop(0.625, rgba(0, 0, 0, 0.3)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.25)), color-stop(0.875, rgba(0, 0, 0, 0.25)), color-stop(0.875, transparent), to(transparent));\\n background-size: 10rem 10rem;\\n margin-top: 2rem;\\n width: 100%;\\n height: 1rem; }\\n@-webkit-keyframes move {\\n 0% {\\n background-position: 100% -10rem; }\\n 100% {\\n background-position: 100% 10rem; } }\\n@keyframes move {\\n 0% {\\n background-position: 100% -10rem; }\\n 100% {\\n background-position: 100% 10rem; } }\\n\\r\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGJhc2VcXF9taXhpbnMuc2NzcyIsInNyYy9hcHAvYXBwLmNvbXBvbmVudC5zY3NzIiwic3JjL2FwcC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcYXBwLmNvbXBvbmVudC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQThFQTs7Q0M1RUM7QUNBRDtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsa0JBQWtCO0VBQ2xCLFdBQVcsRUFBQTtBQUpiO0lBT0ksa0JBQWtCO0lBQ2xCLFdBQVc7SUFDWCxlQUFlO0lBQ2YsY0FBYztJQUNkLGtCQUFrQjtJQUNsQixVQUFVLEVBQUE7QUFaZDtNQWVNLGNBQWM7TUFDZCwwQ0FBa0M7Y0FBbEMsa0NBQWtDO01BQ2xDLCtsQ0FzQkc7TUFDSCw0QkFBNEI7TUFDNUIsZ0JBQWdCO01BQ2hCLFdBQVc7TUFDWCxZQUFZLEVBQUE7QUFJaEI7RUFDRTtJQUNFLGdDQUFnQyxFQUFBO0VBRWxDO0lBQ0UsK0JBQStCLEVBQUEsRUFBQTtBQUxuQztFQUNFO0lBQ0UsZ0NBQWdDLEVBQUE7RUFFbEM7SUFDRSwrQkFBK0IsRUFBQSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvYXBwLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQG1peGluIHRleHQtdHJ1bmNhdGUge1xyXG4gIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxufVxyXG5AbWl4aW4gdGV4dFdyYXAge1xyXG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XHJcbiAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgd29yZC1icmVhazogYnJlYWstYWxsO1xyXG4gIGxpbmUtYnJlYWs6IHN0cmljdDtcclxuICAtd2Via2l0LWh5cGhlbnM6IGF1dG87XHJcbiAgLW1zLWh5cGhlbnM6IGF1dG87XHJcbiAgaHlwaGVuczogYXV0bztcclxufVxyXG5AbWl4aW4gY292ZXJCb3gge1xyXG5cdHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuXHR0b3A6IDA7XHJcblx0bGVmdDogMDtcclxuXHR3aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IDEwMCU7XHJcbn1cclxuQG1peGluIGFicyAoJHRvcDogYXV0bywgJHJpZ2h0OiBhdXRvLCAkYm90dG9tOiBhdXRvLCAkbGVmdDogYXV0bykge1xyXG4gIHRvcDogJHRvcDtcclxuICByaWdodDogJHJpZ2h0O1xyXG4gIGJvdHRvbTogJGJvdHRvbTtcclxuICBsZWZ0OiAkbGVmdDtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbn1cclxuQG1peGluIGNvdmVySW1nIHtcclxuXHRiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0O1xyXG5cdC13ZWJraXQtYmFja2dyb3VuZC1zaXplOiBjb3ZlcjtcclxuXHQtby1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG5cdGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcblx0YmFja2dyb3VuZC1wb3NpdGlvbjogNTAlIDUwJTtcclxufVxyXG5AbWl4aW4gdmFsaW5nQm94IHtcclxuXHRwb3NpdGlvbjogYWJzb2x1dGU7XHJcblx0dG9wOiAgNTAlO1xyXG5cdGxlZnQ6IDUwJTtcclxuXHR0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTtcclxufVxyXG5AbWl4aW4gdW5TZWxlY3Qge1xyXG5cdC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcclxuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcclxuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcclxuICB1c2VyLXNlbGVjdDogbm9uZTtcclxufVxyXG5AbWl4aW4gbWF4MTE5OSB7IC8vIG1ha2V0IDExNzFcclxuICBAbWVkaWEgKG1heC13aWR0aDogMTE5OXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDExNzAgeyAvLyBtYWtldHMgOTkyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExNzBweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXg5OTEgeyAvLyBtYWtldHMgNzYyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDk5MXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDc2MSB7IC8vIG1ha2V0cyA1NzZcclxuICBAbWVkaWEgKG1heC13aWR0aDogNzYxcHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbWF4NTc1IHsgLy8gbWFrZXRzIDQwMFxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA1NzVweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtb2JpbGUge1xyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiAzOTlweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBpY29DZW50ZXIge1xyXG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcclxuICAgIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlciBjZW50ZXI7XHJcbn1cclxuQG1peGluIHBzZXVkbyAoJGRpc3BsYXk6IGJsb2NrLCAkcG9zOiBhYnNvbHV0ZSwgJGNvbnRlbnQ6ICcnKXtcclxuICBjb250ZW50OiAkY29udGVudDtcclxuICBkaXNwbGF5OiAkZGlzcGxheTtcclxuICBwb3NpdGlvbjogJHBvcztcclxufVxyXG5cclxuLypcclxuKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGVtZXNcclxuKi9cclxuQG1peGluIHRoZW1pZnkoJHRoZW1lczogJHRoZW1lcykge1xyXG4gIEBlYWNoICR0aGVtZSwgJG1hcCBpbiAkdGhlbWVzIHtcclxuICAgIC50aGVtZS0jeyR0aGVtZX0gJiB7XHJcbiAgICAgICR0aGVtZS1tYXA6ICgpICFnbG9iYWw7XHJcbiAgICAgIEBlYWNoICRrZXksICRzdWJtYXAgaW4gJG1hcCB7XHJcbiAgICAgICAgJHZhbHVlOiBtYXAtZ2V0KG1hcC1nZXQoJHRoZW1lcywgJHRoZW1lKSwgJyN7JGtleX0nKTtcclxuICAgICAgICAkdGhlbWUtbWFwOiBtYXAtbWVyZ2UoJHRoZW1lLW1hcCwgKCRrZXk6ICR2YWx1ZSkpICFnbG9iYWw7XHJcbiAgICAgIH1cclxuICAgICAgQGNvbnRlbnQ7XHJcbiAgICAgICR0aGVtZS1tYXA6IG51bGwgIWdsb2JhbDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbkBmdW5jdGlvbiB0aGVtZWQoJGtleSkge1xyXG4gIEByZXR1cm4gbWFwLWdldCgkdGhlbWUtbWFwLCAka2V5KTtcclxufVxyXG4iLCIvKlxyXG4qIEltcGxlbWVudGF0aW9uIG9mIHRoZW1lc1xyXG4qL1xuLmFwcC1jb250ZW50IHtcbiAgZGlzcGxheTogZmxleDtcbiAgb3ZlcmZsb3cteDogb3ZlcmxheTtcbiAgb3ZlcmZsb3cteTogaGlkZGVuO1xuICB3aWR0aDogMTAwJTsgfVxuICAuYXBwLWNvbnRlbnQgLnByZWxvYWRlciB7XG4gICAgYWxpZ24tc2VsZjogY2VudGVyO1xuICAgIGNvbG9yOiAjZmZmO1xuICAgIGZvbnQtc2l6ZTogMnJlbTtcbiAgICBtYXJnaW46IDAgYXV0bztcbiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gICAgd2lkdGg6IDUwJTsgfVxuICAgIC5hcHAtY29udGVudCAucHJlbG9hZGVyIC5sb2FkaW5nLWJhciB7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIGFuaW1hdGlvbjogbW92ZSA1cyBsaW5lYXIgaW5maW5pdGU7XG4gICAgICBiYWNrZ3JvdW5kLWltYWdlOiAtd2Via2l0LWdyYWRpZW50KGxpbmVhciwgMCAwLCAxMDAlIDEwMCUsIGNvbG9yLXN0b3AoMC4xMjUsIHJnYmEoMCwgMCwgMCwgMC4xNSkpLCBjb2xvci1zdG9wKDAuMTI1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC4yNSwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKDAuMjUsIHJnYmEoMCwgMCwgMCwgMC4xKSksIGNvbG9yLXN0b3AoMC4zNzUsIHJnYmEoMCwgMCwgMCwgMC4xKSksIGNvbG9yLXN0b3AoMC4zNzUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjUsIHJnYmEoMCwgMCwgMCwgMC4xNSkpLCBjb2xvci1zdG9wKDAuNjI1LCByZ2JhKDAsIDAsIDAsIDAuMTUpKSwgY29sb3Itc3RvcCgwLjYyNSwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKDAuNzUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjc1LCByZ2JhKDAsIDAsIDAsIDAuMSkpLCBjb2xvci1zdG9wKDAuODc1LCByZ2JhKDAsIDAsIDAsIDAuMSkpLCBjb2xvci1zdG9wKDAuODc1LCB0cmFuc3BhcmVudCksIHRvKHRyYW5zcGFyZW50KSksIC13ZWJraXQtZ3JhZGllbnQobGluZWFyLCAwIDEwMCUsIDEwMCUgMCwgY29sb3Itc3RvcCgwLjEyNSwgcmdiYSgwLCAwLCAwLCAwLjMpKSwgY29sb3Itc3RvcCgwLjEyNSwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKDAuMjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjI1LCByZ2JhKDAsIDAsIDAsIDAuMjUpKSwgY29sb3Itc3RvcCgwLjM3NSwgcmdiYSgwLCAwLCAwLCAwLjI1KSksIGNvbG9yLXN0b3AoMC4zNzUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjUsIHJnYmEoMCwgMCwgMCwgMC4zKSksIGNvbG9yLXN0b3AoMC42MjUsIHJnYmEoMCwgMCwgMCwgMC4zKSksIGNvbG9yLXN0b3AoMC42MjUsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCgwLjc1LCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoMC43NSwgcmdiYSgwLCAwLCAwLCAwLjI1KSksIGNvbG9yLXN0b3AoMC44NzUsIHJnYmEoMCwgMCwgMCwgMC4yNSkpLCBjb2xvci1zdG9wKDAuODc1LCB0cmFuc3BhcmVudCksIHRvKHRyYW5zcGFyZW50KSk7XG4gICAgICBiYWNrZ3JvdW5kLXNpemU6IDEwcmVtIDEwcmVtO1xuICAgICAgbWFyZ2luLXRvcDogMnJlbTtcbiAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgaGVpZ2h0OiAxcmVtOyB9XG5cbkBrZXlmcmFtZXMgbW92ZSB7XG4gIDAlIHtcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAxMDAlIC0xMHJlbTsgfVxuICAxMDAlIHtcbiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAxMDAlIDEwcmVtOyB9IH1cbiIsIkBpbXBvcnQgJ35zcmMvYXNzZXRzL3Njc3MvYmFzZS9taXhpbnMnO1xyXG5cclxuLmFwcC1jb250ZW50IHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIG92ZXJmbG93LXg6IG92ZXJsYXk7XHJcbiAgb3ZlcmZsb3cteTogaGlkZGVuO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG5cclxuICAucHJlbG9hZGVyIHtcclxuICAgIGFsaWduLXNlbGY6IGNlbnRlcjtcclxuICAgIGNvbG9yOiAjZmZmO1xyXG4gICAgZm9udC1zaXplOiAycmVtO1xyXG4gICAgbWFyZ2luOiAwIGF1dG87XHJcbiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcbiAgICB3aWR0aDogNTAlO1xyXG5cclxuICAgIC5sb2FkaW5nLWJhciB7XHJcbiAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICBhbmltYXRpb246IG1vdmUgNXMgbGluZWFyIGluZmluaXRlO1xyXG4gICAgICBiYWNrZ3JvdW5kLWltYWdlOlxyXG4gICAgICAgIC13ZWJraXQtZ3JhZGllbnQoXHJcbiAgICAgICAgICAgIGxpbmVhciwgMCAwLCAxMDAlIDEwMCUsXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjEyNSwgcmdiYSgwLCAwLCAwLCAuMTUpKSwgY29sb3Itc3RvcCguMTI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjI1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC4yNTAsIHJnYmEoMCwgMCwgMCwgLjEwKSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjM3NSwgcmdiYSgwLCAwLCAwLCAuMTApKSwgY29sb3Itc3RvcCguMzc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjUwMCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC41MDAsIHJnYmEoMCwgMCwgMCwgLjE1KSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjYyNSwgcmdiYSgwLCAwLCAwLCAuMTUpKSwgY29sb3Itc3RvcCguNjI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjc1MCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC43NTAsIHJnYmEoMCwgMCwgMCwgLjEwKSksXHJcbiAgICAgICAgICAgIGNvbG9yLXN0b3AoLjg3NSwgcmdiYSgwLCAwLCAwLCAuMTApKSwgY29sb3Itc3RvcCguODc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgIHRvKHRyYW5zcGFyZW50KVxyXG4gICAgICAgICksXHJcbiAgICAgICAgLXdlYmtpdC1ncmFkaWVudChcclxuICAgICAgICAgICAgbGluZWFyLCAwIDEwMCUsIDEwMCUgMCxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguMTI1LCByZ2JhKDAsIDAsIDAsIC4zMCkpLCBjb2xvci1zdG9wKC4xMjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguMjUwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjI1MCwgcmdiYSgwLCAwLCAwLCAuMjUpKSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguMzc1LCByZ2JhKDAsIDAsIDAsIC4yNSkpLCBjb2xvci1zdG9wKC4zNzUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguNTAwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjUwMCwgcmdiYSgwLCAwLCAwLCAuMzApKSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguNjI1LCByZ2JhKDAsIDAsIDAsIC4zMCkpLCBjb2xvci1zdG9wKC42MjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguNzUwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjc1MCwgcmdiYSgwLCAwLCAwLCAuMjUpKSxcclxuICAgICAgICAgICAgY29sb3Itc3RvcCguODc1LCByZ2JhKDAsIDAsIDAsIC4yNSkpLCBjb2xvci1zdG9wKC44NzUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgdG8odHJhbnNwYXJlbnQpXHJcbiAgICAgICAgKTtcclxuICAgICAgYmFja2dyb3VuZC1zaXplOiAxMHJlbSAxMHJlbTtcclxuICAgICAgbWFyZ2luLXRvcDogMnJlbTtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgIGhlaWdodDogMXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBrZXlmcmFtZXMgbW92ZSB7XHJcbiAgICAwJSB7XHJcbiAgICAgIGJhY2tncm91bmQtcG9zaXRpb246IDEwMCUgLTEwcmVtO1xyXG4gICAgfVxyXG4gICAgMTAwJSB7XHJcbiAgICAgIGJhY2tncm91bmQtcG9zaXRpb246IDEwMCUgMTByZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, NgZone, Renderer2, OnDestroy, ViewChild} from '@angular/core';\r\nimport {HttpClient} from '@angular/common/http';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {BackendService} from './_helpers/services/backend.service';\r\nimport {Router} from '@angular/router';\r\nimport {VariablesService} from './_helpers/services/variables.service';\r\nimport {ContextMenuComponent} from 'ngx-contextmenu';\r\nimport {IntToMoneyPipe} from './_helpers/pipes/int-to-money.pipe';\r\nimport {BigNumber} from 'bignumber.js';\r\nimport {ModalService} from './_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.scss']\r\n})\r\nexport class AppComponent implements OnInit, OnDestroy {\r\n \r\n intervalUpdatePriceState;\r\n intervalUpdateContractsState;\r\n expMedTsEvent;\r\n onQuitRequest = false;\r\n firstOnlineState = false;\r\n translateUsed = false;\r\n\r\n needOpenWallets = [];\r\n\r\n @ViewChild('allContextMenu') public allContextMenu: ContextMenuComponent;\r\n @ViewChild('onlyCopyContextMenu') public onlyCopyContextMenu: ContextMenuComponent;\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private renderer: Renderer2,\r\n public translate: TranslateService,\r\n private backend: BackendService,\r\n private router: Router,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private intToMoneyPipe: IntToMoneyPipe,\r\n private modalService: ModalService\r\n ) {\r\n translate.addLangs(['en', 'fr', 'de', 'it', 'pt']);\r\n translate.setDefaultLang('en');\r\n // const browserLang = translate.getBrowserLang();\r\n // translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');\r\n translate.use('en').subscribe(() => {\r\n this.translateUsed = true;\r\n });\r\n }\r\n\r\n setBackendLocalization() {\r\n if (this.translateUsed) {\r\n const stringsArray = [\r\n this.translate.instant('BACKEND_LOCALIZATION.QUIT'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_RECEIVED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_CONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.INCOME_TRANSFER_UNCONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.INCOME_TRANSFER_CONFIRMED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.MINED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.LOCKED'),\r\n this.translate.instant('BACKEND_LOCALIZATION.IS_MINIMIZE'),\r\n this.translate.instant('BACKEND_LOCALIZATION.RESTORE'),\r\n this.translate.instant('BACKEND_LOCALIZATION.TRAY_MENU_SHOW'),\r\n this.translate.instant('BACKEND_LOCALIZATION.TRAY_MENU_MINIMIZE')\r\n ];\r\n this.backend.setBackendLocalization(stringsArray, this.variablesService.settings.language);\r\n } else {\r\n console.warn('wait translate use');\r\n setTimeout(() => {\r\n this.setBackendLocalization();\r\n }, 10000);\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.variablesService.allContextMenu = this.allContextMenu;\r\n this.variablesService.onlyCopyContextMenu = this.onlyCopyContextMenu;\r\n\r\n this.backend.initService().subscribe(initMessage => {\r\n console.log('Init message: ', initMessage);\r\n\r\n this.backend.webkitLaunchedScript();\r\n\r\n this.backend.start_backend(false, '127.0.0.1', 11512, (st2, dd2) => {\r\n console.log(st2, dd2);\r\n });\r\n\r\n this.backend.eventSubscribe('quit_requested', () => {\r\n if (!this.onQuitRequest) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n this.needOpenWallets = [];\r\n this.variablesService.daemon_state = 5;\r\n const saveFunction = () => {\r\n this.backend.storeAppData(() => {\r\n const recursionCloseWallets = () => {\r\n if (this.variablesService.wallets.length) {\r\n const lastIndex = this.variablesService.wallets.length - 1;\r\n this.backend.closeWallet(this.variablesService.wallets[lastIndex].wallet_id, () => {\r\n this.variablesService.wallets.splice(lastIndex, 1);\r\n recursionCloseWallets();\r\n });\r\n } else {\r\n this.backend.quitRequest();\r\n }\r\n };\r\n recursionCloseWallets();\r\n });\r\n };\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData(() => {\r\n saveFunction();\r\n });\r\n } else {\r\n saveFunction();\r\n }\r\n }\r\n this.onQuitRequest = true;\r\n });\r\n\r\n this.backend.eventSubscribe('update_wallet_status', (data) => {\r\n console.log('----------------- update_wallet_status -----------------');\r\n console.log(data);\r\n\r\n const wallet_state = data.wallet_state;\r\n const is_mining = data.is_mining;\r\n const wallet = this.variablesService.getWallet(data.wallet_id);\r\n\r\n // 1-synch, 2-ready, 3 - error\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n wallet.loaded = false;\r\n wallet.staking = is_mining;\r\n if (wallet_state === 2) { // ready\r\n wallet.loaded = true;\r\n }\r\n if (wallet_state === 3) { // error\r\n // wallet.error = true;\r\n }\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n wallet.mined_total = data.minied_total;\r\n wallet.alias_available = data.is_alias_operations_available;\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('wallet_sync_progress', (data) => {\r\n console.log('----------------- wallet_sync_progress -----------------');\r\n console.log(data);\r\n\r\n const wallet = this.variablesService.getWallet(data.wallet_id);\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n wallet.progress = (data.progress < 0) ? 0 : ((data.progress > 100) ? 100 : data.progress);\r\n if (wallet.progress === 0) {\r\n wallet.loaded = false;\r\n } else if (wallet.progress === 100) {\r\n wallet.loaded = true;\r\n }\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('update_daemon_state', (data) => {\r\n console.log('----------------- update_daemon_state -----------------');\r\n console.log('DAEMON:' + data.daemon_network_state);\r\n console.log(data);\r\n // this.variablesService.exp_med_ts = data['expiration_median_timestamp'] + 600 + 1;\r\n this.variablesService.setExpMedTs(data['expiration_median_timestamp'] + 600 + 1);\r\n this.variablesService.net_time_delta_median = data.net_time_delta_median;\r\n this.variablesService.last_build_available = data.last_build_available;\r\n this.variablesService.last_build_displaymode = data.last_build_displaymode;\r\n this.variablesService.setHeightApp(data.height);\r\n this.variablesService.setHeightMax(data.max_net_seen_height);\r\n this.backend.getContactAlias();\r\n this.ngZone.run(() => {\r\n this.variablesService.daemon_state = data['daemon_network_state'];\r\n if (data['daemon_network_state'] === 1) {\r\n const max = data['max_net_seen_height'] - data['synchronization_start_height'];\r\n const current = data.height - data['synchronization_start_height'];\r\n const return_val = Math.floor((current * 100 / max) * 100) / 100;\r\n if (max === 0 || return_val < 0) {\r\n this.variablesService.sync.progress_value = 0;\r\n this.variablesService.sync.progress_value_text = '0.00';\r\n } else if (return_val >= 100) {\r\n this.variablesService.sync.progress_value = 100;\r\n this.variablesService.sync.progress_value_text = '99.99';\r\n } else {\r\n this.variablesService.sync.progress_value = return_val;\r\n this.variablesService.sync.progress_value_text = return_val.toFixed(2);\r\n }\r\n }\r\n });\r\n if (!this.firstOnlineState && data['daemon_network_state'] === 2) {\r\n this.getAliases();\r\n this.backend.getContactAlias();\r\n this.backend.getDefaultFee((status_fee, data_fee) => {\r\n this.variablesService.default_fee_big = new BigNumber(data_fee);\r\n this.variablesService.default_fee = this.intToMoneyPipe.transform(data_fee);\r\n });\r\n this.firstOnlineState = true;\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('money_transfer', (data) => {\r\n console.log('----------------- money_transfer -----------------');\r\n console.log(data);\r\n\r\n if (!data.ti) {\r\n return;\r\n }\r\n\r\n const wallet_id = data.wallet_id;\r\n const tr_info = data.ti;\r\n\r\n const wallet = this.variablesService.getWallet(wallet_id);\r\n\r\n if (wallet) {\r\n this.ngZone.run(() => {\r\n\r\n if (!wallet.loaded) {\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n } else {\r\n wallet.balance = data.balance;\r\n wallet.unlocked_balance = data.unlocked_balance;\r\n }\r\n\r\n if (tr_info.tx_type === 6) {\r\n this.variablesService.setRefreshStacking(wallet_id);\r\n }\r\n\r\n let tr_exists = wallet.excluded_history.some(elem => elem.tx_hash === tr_info.tx_hash);\r\n tr_exists = (!tr_exists) ? wallet.history.some(elem => elem.tx_hash === tr_info.tx_hash) : tr_exists;\r\n\r\n wallet.prepareHistory([tr_info]);\r\n\r\n if (tr_info.hasOwnProperty('contract')) {\r\n const exp_med_ts = this.variablesService.exp_med_ts;\r\n const height_app = this.variablesService.height_app;\r\n\r\n const contract = tr_info.contract[0];\r\n\r\n if (tr_exists) {\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === contract.contract_id && wallet.contracts[i].is_a === contract.is_a) {\r\n wallet.contracts[i].cancel_expiration_time = contract.cancel_expiration_time;\r\n wallet.contracts[i].expiration_time = contract.expiration_time;\r\n wallet.contracts[i].height = contract.height;\r\n wallet.contracts[i].timestamp = contract.timestamp;\r\n break;\r\n }\r\n }\r\n // $rootScope.getContractsRecount();\r\n return;\r\n }\r\n\r\n if (contract.state === 1 && contract.expiration_time < exp_med_ts) {\r\n contract.state = 110;\r\n } else if (contract.state === 5 && contract.cancel_expiration_time < exp_med_ts) {\r\n contract.state = 130;\r\n } else if (contract.state === 1) {\r\n const searchResult2 = this.variablesService.settings.notViewedContracts.find(elem => elem.state === 110 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult2) {\r\n if (searchResult2.time === contract.expiration_time) {\r\n contract.state = 110;\r\n } else {\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 2 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 201;\r\n } else if (contract.state === 2) {\r\n const searchResult3 = this.variablesService.settings.viewedContracts.some(elem => elem.state === 120 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult3) {\r\n contract.state = 120;\r\n }\r\n } else if (contract.state === 5) {\r\n const searchResult4 = this.variablesService.settings.notViewedContracts.find(elem => elem.state === 130 && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n if (searchResult4) {\r\n if (searchResult4.time === contract.cancel_expiration_time) {\r\n contract.state = 130;\r\n } else {\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.notViewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === contract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === contract.is_a) {\r\n this.variablesService.settings.viewedContracts.splice(j, 1);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } else if (contract.state === 6 && (contract.height === 0 || (height_app - contract.height) < 10)) {\r\n contract.state = 601;\r\n }\r\n\r\n const searchResult = this.variablesService.settings.viewedContracts.some(elem => elem.state === contract.state && elem.is_a === contract.is_a && elem.contract_id === contract.contract_id);\r\n contract.is_new = !searchResult;\r\n\r\n let findContract = false;\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === contract.contract_id && wallet.contracts[i].is_a === contract.is_a) {\r\n for (const prop in contract) {\r\n if (contract.hasOwnProperty(prop)) {\r\n wallet.contracts[i][prop] = contract[prop];\r\n }\r\n }\r\n findContract = true;\r\n break;\r\n }\r\n }\r\n if (findContract === false) {\r\n wallet.contracts.push(contract);\r\n }\r\n wallet.recountNewContracts();\r\n }\r\n\r\n });\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('money_transfer_cancel', (data) => {\r\n console.log('----------------- money_transfer_cancel -----------------');\r\n console.log(data);\r\n\r\n if (!data.ti) {\r\n return;\r\n }\r\n\r\n const wallet_id = data.wallet_id;\r\n const tr_info = data.ti;\r\n const wallet = this.variablesService.getWallet(wallet_id);\r\n\r\n if (wallet) {\r\n if (tr_info.hasOwnProperty('contract')) {\r\n for (let i = 0; i < wallet.contracts.length; i++) {\r\n if (wallet.contracts[i].contract_id === tr_info.contract[0].contract_id && wallet.contracts[i].is_a === tr_info.contract[0].is_a) {\r\n if (wallet.contracts[i].state === 1 || wallet.contracts[i].state === 110) {\r\n wallet.contracts[i].is_new = true;\r\n wallet.contracts[i].state = 140;\r\n wallet.recountNewContracts();\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n\r\n wallet.removeFromHistory(tr_info.tx_hash);\r\n\r\n let error_tr = '';\r\n switch (tr_info.tx_type) {\r\n case 0:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_NORMAL') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NORMAL_TO') + ' ' + this.intToMoneyPipe.transform(tr_info.amount) + ' ' +\r\n this.translate.instant('ERRORS.TX_TYPE_NORMAL_END');\r\n break;\r\n case 1:\r\n // this.translate.instant('ERRORS.TX_TYPE_PUSH_OFFER');\r\n break;\r\n case 2:\r\n // this.translate.instant('ERRORS.TX_TYPE_UPDATE_OFFER');\r\n break;\r\n case 3:\r\n // this.translate.instant('ERRORS.TX_TYPE_CANCEL_OFFER');\r\n break;\r\n case 4:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS_END');\r\n break;\r\n case 5:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_UPDATE_ALIAS') + '
' +\r\n tr_info.tx_hash + '
' + wallet.name + '
' + wallet.address + '
' +\r\n this.translate.instant('ERRORS.TX_TYPE_NEW_ALIAS_END');\r\n break;\r\n case 6:\r\n error_tr = this.translate.instant('ERRORS.TX_TYPE_COIN_BASE');\r\n break;\r\n }\r\n if (error_tr) {\r\n this.modalService.prepareModal('error', error_tr);\r\n }\r\n }\r\n });\r\n\r\n this.backend.eventSubscribe('on_core_event', (data) => {\r\n console.log('----------------- on_core_event -----------------');\r\n console.log(data);\r\n\r\n data = JSON.parse(data);\r\n\r\n if (data.events != null) {\r\n for (let i = 0, length = data.events.length; i < length; i++) {\r\n\r\n switch (data.events[i].method) {\r\n case 'CORE_EVENT_BLOCK_ADDED':\r\n break;\r\n case 'CORE_EVENT_ADD_ALIAS':\r\n if (this.variablesService.aliasesChecked[data.events[i].details.address] != null) {\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['name'] = '@' + data.events[i].details.alias;\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['address'] = data.events[i].details.address;\r\n this.variablesService.aliasesChecked[data.events[i].details.address]['comment'] = data.events[i].details.comment;\r\n }\r\n if (this.variablesService.enableAliasSearch) {\r\n const newAlias = {\r\n name: '@' + data.events[i].details.alias,\r\n address: data.events[i].details.address,\r\n comment: data.events[i].details.comment\r\n };\r\n this.variablesService.aliases = this.variablesService.aliases.concat(newAlias);\r\n this.variablesService.changeAliases();\r\n }\r\n break;\r\n case 'CORE_EVENT_UPDATE_ALIAS':\r\n for (const address in this.variablesService.aliasesChecked) {\r\n if (this.variablesService.aliasesChecked.hasOwnProperty(address)) {\r\n if (this.variablesService.aliasesChecked[address].name === '@' + data.events[i].details.alias) {\r\n if (this.variablesService.aliasesChecked[address].address !== data.events[i].details.details.address) {\r\n delete this.variablesService.aliasesChecked[address]['name'];\r\n delete this.variablesService.aliasesChecked[address]['address'];\r\n delete this.variablesService.aliasesChecked[address]['comment'];\r\n } else {\r\n this.variablesService.aliasesChecked[address].comment = data.events[i].details.details.comment;\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n if (this.variablesService.aliasesChecked[data.events[i].details.details.address] != null) {\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['name'] = '@' + data.events[i].details.alias;\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['address'] = data.events[i].details.details.address;\r\n this.variablesService.aliasesChecked[data.events[i].details.details.address]['comment'] = data.events[i].details.details.comment;\r\n }\r\n if (this.variablesService.enableAliasSearch) {\r\n const CurrentAlias = this.variablesService.aliases.find((element) => element.name === '@' + data.events[i].details.alias);\r\n if (CurrentAlias) {\r\n CurrentAlias.address = data.events[i].details.details.address;\r\n CurrentAlias.comment = data.events[i].details.details.comment;\r\n }\r\n }\r\n this.variablesService.changeAliases();\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.intervalUpdateContractsState = setInterval(() => {\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallet.contracts.forEach((contract) => {\r\n if (contract.state === 201 && contract.height !== 0 && (this.variablesService.height_app - contract.height) >= 10) {\r\n contract.state = 2;\r\n contract.is_new = true;\r\n console.warn('need check state in contracts');\r\n } else if (contract.state === 601 && contract.height !== 0 && (this.variablesService.height_app - contract.height) >= 10) {\r\n contract.state = 6;\r\n contract.is_new = true;\r\n }\r\n });\r\n });\r\n }, 30000);\r\n\r\n this.expMedTsEvent = this.variablesService.getExpMedTsEvent.subscribe((newTimestamp: number) => {\r\n this.variablesService.wallets.forEach((wallet) => {\r\n wallet.contracts.forEach((contract) => {\r\n if (contract.state === 1 && contract.expiration_time <= newTimestamp) {\r\n contract.state = 110;\r\n contract.is_new = true;\r\n wallet.recountNewContracts();\r\n } else if (contract.state === 5 && contract.cancel_expiration_time <= newTimestamp) {\r\n contract.state = 130;\r\n contract.is_new = true;\r\n wallet.recountNewContracts();\r\n }\r\n });\r\n });\r\n });\r\n\r\n\r\n this.backend.getAppData((status, data) => {\r\n if (data && Object.keys(data).length > 0) {\r\n for (const key in data) {\r\n if (data.hasOwnProperty(key) && this.variablesService.settings.hasOwnProperty(key)) {\r\n this.variablesService.settings[key] = data[key];\r\n }\r\n }\r\n if (this.variablesService.settings.hasOwnProperty('theme') && ['dark', 'white', 'gray'].indexOf(this.variablesService.settings.theme) !== -1) {\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.settings.theme);\r\n } else {\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.defaultTheme);\r\n }\r\n if (this.variablesService.settings.hasOwnProperty('scale') && [7.5, 10, 12.5, 15].indexOf(this.variablesService.settings.scale) !== -1) {\r\n this.renderer.setStyle(document.documentElement, 'font-size', this.variablesService.settings.scale + 'px');\r\n }\r\n } else {\r\n this.variablesService.settings.theme = this.variablesService.defaultTheme;\r\n this.renderer.addClass(document.body, 'theme-' + this.variablesService.settings.theme);\r\n }\r\n this.translate.use(this.variablesService.settings.language);\r\n this.setBackendLocalization();\r\n\r\n this.backend.setLogLevel(this.variablesService.settings.appLog);\r\n\r\n if (this.router.url !== '/login') {\r\n this.backend.haveSecureAppData((statusPass) => {\r\n if (statusPass) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n } else {\r\n if (Object.keys(data).length !== 0) {\r\n this.needOpenWallets = JSON.parse(JSON.stringify(this.variablesService.settings.wallets));\r\n this.ngZone.run(() => {\r\n this.variablesService.appLogin = true;\r\n this.router.navigate(['/']);\r\n });\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'reg'}});\r\n });\r\n }\r\n }\r\n });\r\n }\r\n });\r\n }, error => {\r\n console.log(error);\r\n });\r\n this.getMoneyEquivalent();\r\n\r\n this.intervalUpdatePriceState = setInterval(() => {\r\n this.getMoneyEquivalent();\r\n }, 30000);\r\n }\r\n\r\n getMoneyEquivalent() {\r\n this.http.get('https://api.coingecko.com/api/v3/ping').subscribe(\r\n () => {\r\n this.http.get('https://api.coingecko.com/api/v3/simple/price?ids=zano&vs_currencies=usd').subscribe(\r\n data => {\r\n this.variablesService.moneyEquivalent = data['zano']['usd'];\r\n },\r\n error => {\r\n console.warn('api.coingecko.com price error: ', error);\r\n }\r\n );\r\n },\r\n error => {\r\n console.warn('api.coingecko.com error: ', error);\r\n setTimeout(() => {\r\n this.getMoneyEquivalent();\r\n }, 30000);\r\n }\r\n )\r\n }\r\n\r\n getAliases() {\r\n this.backend.getAllAliases((status, data, error) => {\r\n\r\n console.warn(error);\r\n\r\n if (error === 'CORE_BUSY') {\r\n window.setTimeout(() => {\r\n this.getAliases();\r\n }, 10000);\r\n } else if (error === 'OVERFLOW') {\r\n this.variablesService.aliases = [];\r\n this.variablesService.enableAliasSearch = false;\r\n this.variablesService.wallets.forEach(wallet => {\r\n wallet.alias = this.backend.getWalletAlias(wallet.address);\r\n });\r\n } else {\r\n this.variablesService.enableAliasSearch = true;\r\n if (data.aliases && data.aliases.length) {\r\n this.variablesService.aliases = [];\r\n data.aliases.forEach(alias => {\r\n const newAlias = {\r\n name: '@' + alias.alias,\r\n address: alias.address,\r\n comment: alias.comment\r\n };\r\n this.variablesService.aliases.push(newAlias);\r\n });\r\n this.variablesService.wallets.forEach(wallet => {\r\n wallet.alias = this.backend.getWalletAlias(wallet.address);\r\n });\r\n this.variablesService.aliases = this.variablesService.aliases.sort((a, b) => {\r\n if (a.name.length > b.name.length) {\r\n return 1;\r\n }\r\n if (a.name.length < b.name.length) {\r\n return -1;\r\n }\r\n if (a.name > b.name) {\r\n return 1;\r\n }\r\n if (a.name < b.name) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n this.variablesService.changeAliases();\r\n }\r\n }\r\n });\r\n }\r\n\r\n contextMenuCopy(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n const start = (target['contextSelectionStart']) ? 'contextSelectionStart' : 'selectionStart';\r\n const end = (target['contextSelectionEnd']) ? 'contextSelectionEnd' : 'selectionEnd';\r\n const canUseSelection = ((target[start]) || (target[start] === '0'));\r\n const SelectedText = (canUseSelection) ? target['value'].substring(target[start], target[end]) : target['value'];\r\n this.backend.setClipboard(String(SelectedText));\r\n }\r\n }\r\n\r\n contextMenuOnlyCopy(text) {\r\n if (text) {\r\n this.backend.setClipboard(String(text));\r\n }\r\n }\r\n\r\n contextMenuPaste(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n this.backend.getClipboard((status, clipboard) => {\r\n clipboard = String(clipboard);\r\n if (typeof clipboard !== 'string' || clipboard.length) {\r\n const start = (target['contextSelectionStart']) ? 'contextSelectionStart' : 'selectionStart';\r\n const end = (target['contextSelectionEnd']) ? 'contextSelectionEnd' : 'selectionEnd';\r\n const _pre = target['value'].substring(0, target[start]);\r\n const _aft = target['value'].substring(target[end], target['value'].length);\r\n let text = _pre + clipboard + _aft;\r\n const cursorPosition = (_pre + clipboard).length;\r\n if (target['maxLength'] && parseInt(target['maxLength'], 10) > 0) {\r\n text = text.substr(0, parseInt(target['maxLength'], 10));\r\n }\r\n target['value'] = text;\r\n target.setSelectionRange(cursorPosition, cursorPosition);\r\n target.dispatchEvent(new Event('input'));\r\n target['focus']();\r\n }\r\n });\r\n }\r\n }\r\n\r\n contextMenuSelect(target) {\r\n if (target && (target['nodeName'].toUpperCase() === 'TEXTAREA' || target['nodeName'].toUpperCase() === 'INPUT')) {\r\n target['focus']();\r\n setTimeout(() => {\r\n target['select']();\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.intervalUpdateContractsState) {\r\n clearInterval(this.intervalUpdateContractsState);\r\n }\r\n if (this.intervalUpdatePriceState) {\r\n clearInterval(this.intervalUpdatePriceState);\r\n }\r\n this.expMedTsEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { NgModule } from '@angular/core';\r\n\r\nimport { AppRoutingModule } from './app-routing.module';\r\n\r\nimport { AppComponent } from './app.component';\r\nimport { LoginComponent } from './login/login.component';\r\nimport { SettingsComponent } from './settings/settings.component';\r\nimport { SidebarComponent } from './sidebar/sidebar.component';\r\nimport { MainComponent } from './main/main.component';\r\nimport { CreateWalletComponent } from './create-wallet/create-wallet.component';\r\nimport { OpenWalletComponent } from './open-wallet/open-wallet.component';\r\nimport { OpenWalletModalComponent } from './open-wallet-modal/open-wallet-modal.component';\r\nimport { RestoreWalletComponent } from './restore-wallet/restore-wallet.component';\r\nimport { SeedPhraseComponent } from './seed-phrase/seed-phrase.component';\r\nimport { WalletDetailsComponent } from './wallet-details/wallet-details.component';\r\nimport { AssignAliasComponent } from './assign-alias/assign-alias.component';\r\nimport { EditAliasComponent } from './edit-alias/edit-alias.component';\r\nimport { TransferAliasComponent } from './transfer-alias/transfer-alias.component';\r\nimport { WalletComponent } from './wallet/wallet.component';\r\nimport { SendComponent } from './send/send.component';\r\nimport { ReceiveComponent } from './receive/receive.component';\r\nimport { HistoryComponent } from './history/history.component';\r\nimport { ContractsComponent } from './contracts/contracts.component';\r\nimport { PurchaseComponent } from './purchase/purchase.component';\r\nimport { MessagesComponent } from './messages/messages.component';\r\nimport { TypingMessageComponent } from './typing-message/typing-message.component';\r\nimport { StakingComponent } from './staking/staking.component';\r\n\r\nimport { HttpClient, HttpClientModule } from '@angular/common/http';\r\nimport { TranslateLoader, TranslateModule } from '@ngx-translate/core';\r\nimport { TranslateHttpLoader } from '@ngx-translate/http-loader';\r\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { NgSelectModule } from '@ng-select/ng-select';\r\n\r\nimport { BackendService } from './_helpers/services/backend.service';\r\nimport { ModalService } from './_helpers/services/modal.service';\r\nimport { MoneyToIntPipe } from './_helpers/pipes/money-to-int.pipe';\r\nimport { IntToMoneyPipe } from './_helpers/pipes/int-to-money.pipe';\r\nimport { HistoryTypeMessagesPipe } from './_helpers/pipes/history-type-messages.pipe';\r\nimport { ContractStatusMessagesPipe } from './_helpers/pipes/contract-status-messages.pipe';\r\nimport { ContractTimeLeftPipe } from './_helpers/pipes/contract-time-left.pipe';\r\nimport { SafeHTMLPipe } from './_helpers/pipes/safe-html.pipe';\r\nimport { TooltipDirective } from './_helpers/directives/tooltip.directive';\r\nimport { InputValidateDirective } from './_helpers/directives/input-validate/input-validate.directive';\r\nimport { StakingSwitchComponent } from './_helpers/directives/staking-switch/staking-switch.component';\r\nimport { ModalContainerComponent } from './_helpers/directives/modal-container/modal-container.component';\r\nimport { TransactionDetailsComponent } from './_helpers/directives/transaction-details/transaction-details.component';\r\nimport { ContextMenuModule } from 'ngx-contextmenu';\r\nimport { ChartModule, HIGHCHARTS_MODULES } from 'angular-highcharts';\r\nimport * as highcharts from 'highcharts';\r\nimport exporting from 'highcharts/modules/exporting.src';\r\nimport { ProgressContainerComponent } from './_helpers/directives/progress-container/progress-container.component';\r\nimport { InputDisableSelectionDirective } from './_helpers/directives/input-disable-selection/input-disable-selection.directive';\r\nimport { SendModalComponent } from './send-modal/send-modal.component';\r\nimport { ContactsComponent } from './contacts/contacts.component';\r\nimport { AddContactsComponent } from './add-contacts/add-contacts.component';\r\nimport { ContactSendComponent } from './contact-send/contact-send.component';\r\nimport { ExportImportComponent } from './export-import/export-import.component';\r\nimport { ConfirmModalComponent } from './_helpers/directives/confirm-modal/confirm-modal.component';\r\n\r\nexport function HttpLoaderFactory(httpClient: HttpClient) {\r\n return new TranslateHttpLoader(httpClient, './assets/i18n/', '.json');\r\n}\r\n\r\nimport { PapaParseModule } from 'ngx-papaparse';\r\n\r\n// import * as more from 'highcharts/highcharts-more.src';\r\n// import * as exporting from 'highcharts/modules/exporting.src';\r\n// import * as highstock from 'highcharts/modules/stock.src';\r\n\r\nexport function highchartsFactory() {\r\n // Default options.\r\n highcharts.setOptions({\r\n time: {\r\n useUTC: false\r\n }\r\n });\r\n\r\n return [exporting];\r\n}\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n LoginComponent,\r\n SettingsComponent,\r\n SidebarComponent,\r\n MainComponent,\r\n CreateWalletComponent,\r\n OpenWalletComponent,\r\n OpenWalletModalComponent,\r\n RestoreWalletComponent,\r\n SeedPhraseComponent,\r\n WalletDetailsComponent,\r\n AssignAliasComponent,\r\n EditAliasComponent,\r\n TransferAliasComponent,\r\n WalletComponent,\r\n SendComponent,\r\n ReceiveComponent,\r\n HistoryComponent,\r\n ContractsComponent,\r\n PurchaseComponent,\r\n MessagesComponent,\r\n StakingComponent,\r\n TypingMessageComponent,\r\n MoneyToIntPipe,\r\n IntToMoneyPipe,\r\n StakingSwitchComponent,\r\n HistoryTypeMessagesPipe,\r\n ContractStatusMessagesPipe,\r\n ContractTimeLeftPipe,\r\n TooltipDirective,\r\n InputValidateDirective,\r\n ModalContainerComponent,\r\n TransactionDetailsComponent,\r\n ProgressContainerComponent,\r\n InputDisableSelectionDirective,\r\n SendModalComponent,\r\n ContactsComponent,\r\n AddContactsComponent,\r\n ContactSendComponent,\r\n ExportImportComponent,\r\n SafeHTMLPipe,\r\n ConfirmModalComponent\r\n ],\r\n imports: [\r\n BrowserModule,\r\n AppRoutingModule,\r\n HttpClientModule,\r\n TranslateModule.forRoot({\r\n loader: {\r\n provide: TranslateLoader,\r\n useFactory: HttpLoaderFactory,\r\n deps: [HttpClient]\r\n }\r\n }),\r\n FormsModule,\r\n ReactiveFormsModule,\r\n NgSelectModule,\r\n ChartModule,\r\n PapaParseModule,\r\n ContextMenuModule.forRoot()\r\n ],\r\n providers: [\r\n BackendService,\r\n ModalService,\r\n MoneyToIntPipe,\r\n IntToMoneyPipe,\r\n { provide: HIGHCHARTS_MODULES, useFactory: highchartsFactory }\r\n // {provide: HIGHCHARTS_MODULES, useFactory: () => [ highstock, more, exporting ] }\r\n ],\r\n entryComponents: [\r\n ModalContainerComponent,\r\n SendModalComponent,\r\n ConfirmModalComponent\r\n ],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.ASSIGN_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
6 && assignForm.get('name').value.length <= 25\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_WRONG' | translate }}\\r\\n
\\r\\n
25\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NAME_EXISTS' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'ASSIGN_ALIAS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"ASSIGN_ALIAS.COST\\\" | translate : {value: alias.price | intToMoney, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\"","module.exports = \".form-assign {\\n margin: 2.4rem 0; }\\n .form-assign .alias-name {\\n width: 50%; }\\n .form-assign .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-assign .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-assign .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n .assign-alias-tooltip {\\n font-size: 1.3rem;\\n line-height: 2rem;\\n padding: 1rem 1.5rem;\\n max-width: 46rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvYXNzaWduLWFsaWFzL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxhc3NpZ24tYWxpYXNcXGFzc2lnbi1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUE7RUFLbEI7RUFDRSxpQkFBaUI7RUFDakIsaUJBQWlCO0VBQ2pCLG9CQUFvQjtFQUNwQixnQkFBZ0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2Fzc2lnbi1hbGlhcy9hc3NpZ24tYWxpYXMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1hc3NpZ24ge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcblxyXG4gIC5hbGlhcy1uYW1lIHtcclxuICAgIHdpZHRoOiA1MCU7XHJcbiAgfVxyXG5cclxuICAuYWxpYXMtY29zdCB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIG1hcmdpbi10b3A6IDJyZW07XHJcbiAgfVxyXG5cclxuICAud3JhcC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICBtYXJnaW46IDIuNXJlbSAtMC43cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcbiAgICAgIHdpZHRoOiAxNXJlbTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi5hc3NpZ24tYWxpYXMtdG9vbHRpcCB7XHJcbiAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgbGluZS1oZWlnaHQ6IDJyZW07XHJcbiAgcGFkZGluZzogMXJlbSAxLjVyZW07XHJcbiAgbWF4LXdpZHRoOiA0NnJlbTtcclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {MoneyToIntPipe} from '../_helpers/pipes/money-to-int.pipe';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport BigNumber from 'bignumber.js';\r\nimport {Subscription} from 'rxjs';\r\n\r\n@Component({\r\n selector: 'app-assign-alias',\r\n templateUrl: './assign-alias.component.html',\r\n styleUrls: ['./assign-alias.component.scss']\r\n})\r\nexport class AssignAliasComponent implements OnInit, OnDestroy {\r\n\r\n wallet: Wallet;\r\n assignForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, Validators.pattern(/^@?[a-z0-9\\.\\-]{6,25}$/)]),\r\n comment: new FormControl('', [(g: FormControl) => {\r\n if (g.value > this.variablesService.maxCommentLength) {\r\n return {'maxLength': true};\r\n } else {\r\n return null;\r\n }\r\n }])\r\n });\r\n assignFormSubscription: Subscription;\r\n alias = {\r\n name: '',\r\n fee: this.variablesService.default_fee,\r\n price: new BigNumber(0),\r\n reward: '0',\r\n rewardOriginal: '0',\r\n comment: '',\r\n exists: false\r\n };\r\n canRegister = false;\r\n notEnoughMoney = false;\r\n\r\n constructor(\r\n private ngZone: NgZone,\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private moneyToInt: MoneyToIntPipe,\r\n private intToMoney: IntToMoneyPipe\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n this.assignFormSubscription = this.assignForm.get('name').valueChanges.subscribe(value => {\r\n this.canRegister = false;\r\n this.alias.exists = false;\r\n const newName = value.toLowerCase().replace('@', '');\r\n if (!(this.assignForm.controls['name'].errors && this.assignForm.controls['name'].errors.hasOwnProperty('pattern')) && newName.length >= 6 && newName.length <= 25) {\r\n this.backend.getAliasByName(newName, status => {\r\n this.ngZone.run(() => {\r\n this.alias.exists = status;\r\n });\r\n if (!status) {\r\n this.alias.price = new BigNumber(0);\r\n this.backend.getAliasCoast(newName, (statusPrice, dataPrice) => {\r\n this.ngZone.run(() => {\r\n if (statusPrice) {\r\n this.alias.price = BigNumber.sum(dataPrice['coast'], this.variablesService.default_fee_big);\r\n }\r\n this.notEnoughMoney = this.alias.price.isGreaterThan(this.wallet.unlocked_balance);\r\n this.alias.reward = this.intToMoney.transform(this.alias.price, false);\r\n this.alias.rewardOriginal = this.intToMoney.transform(dataPrice['coast'], false);\r\n this.canRegister = !this.notEnoughMoney;\r\n });\r\n });\r\n } else {\r\n this.notEnoughMoney = false;\r\n this.alias.reward = '0';\r\n this.alias.rewardOriginal = '0';\r\n }\r\n });\r\n } else {\r\n this.notEnoughMoney = false;\r\n this.alias.reward = '0';\r\n this.alias.rewardOriginal = '0';\r\n }\r\n this.alias.name = newName;\r\n });\r\n }\r\n\r\n assignAlias() {\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n if (alias.hasOwnProperty('name')) {\r\n this.modalService.prepareModal('info', 'ASSIGN_ALIAS.ONE_ALIAS');\r\n } else {\r\n this.alias.comment = this.assignForm.get('comment').value;\r\n this.backend.registerAlias(this.wallet.wallet_id, this.alias.name, this.wallet.address, this.alias.fee, this.alias.comment, this.alias.rewardOriginal, (status, data) => {\r\n if (status) {\r\n this.wallet.wakeAlias = true;\r\n this.modalService.prepareModal('info', 'ASSIGN_ALIAS.REQUEST_ADD_REG');\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.assignFormSubscription.unsubscribe();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{\\r\\n 'CONTACTS.TITLE' | translate\\r\\n }}\\r\\n {{ 'CONTACTS.SEND' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\"","module.exports = \".wallets-selection {\\n display: flex;\\n align-items: center;\\n margin-top: 2rem; }\\n .wallets-selection .input-block {\\n width: 18rem; }\\n .wallets-selection button {\\n padding: 2rem;\\n background: transparent;\\n border: none;\\n outline: none; }\\n .input-block {\\n width: 44rem; }\\n .input-block input {\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n .blue-button {\\n margin-top: 2.5rem;\\n width: 100%;\\n max-width: 18rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udGFjdC1zZW5kL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxjb250YWN0LXNlbmRcXGNvbnRhY3Qtc2VuZC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsZ0JBQWdCLEVBQUE7RUFIbEI7SUFNSSxZQUFZLEVBQUE7RUFOaEI7SUFVSSxhQUFhO0lBQ2IsdUJBQXVCO0lBQ3ZCLFlBQVk7SUFDWixhQUFhLEVBQUE7RUFJakI7RUFDRSxZQUFZLEVBQUE7RUFEZDtJQUlJLGdCQUFnQjtJQUNoQix1QkFBdUIsRUFBQTtFQUkzQjtFQUNFLGtCQUFrQjtFQUNsQixXQUFXO0VBQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9jb250YWN0LXNlbmQvY29udGFjdC1zZW5kLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLndhbGxldHMtc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgbWFyZ2luLXRvcDogMnJlbTtcclxuICBcclxuICAuaW5wdXQtYmxvY2sge1xyXG4gICAgd2lkdGg6IDE4cmVtO1xyXG4gIH1cclxuXHJcbiAgYnV0dG9uIHtcclxuICAgIHBhZGRpbmc6IDJyZW07XHJcbiAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlcjogbm9uZTtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgfVxyXG59XHJcblxyXG4uaW5wdXQtYmxvY2sge1xyXG4gIHdpZHRoOiA0NHJlbTtcclxuXHJcbiAgaW5wdXQge1xyXG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gIH1cclxufVxyXG5cclxuLmJsdWUtYnV0dG9uIHtcclxuICBtYXJnaW4tdG9wOiAyLjVyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgbWF4LXdpZHRoOiAxOHJlbTtcclxufVxyXG5cclxuXHJcbiJdfQ== */\"","import { Component, OnInit, OnDestroy } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n\r\n@Component({\r\n selector: 'app-contact-send',\r\n templateUrl: './contact-send.component.html',\r\n styleUrls: ['./contact-send.component.scss']\r\n})\r\nexport class ContactSendComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n address;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private route: ActivatedRoute\r\n ) { }\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.address) {\r\n this.address = params.address;\r\n }\r\n });\r\n }\r\n\r\n goToWallet(id) {\r\n this.variablesService.setCurrentWallet(id);\r\n this.variablesService.currentWallet.send_data['address'] = this.address;\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'CONTACTS.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n {{ 'CONTACTS.TABLE.NAME' | translate }}\\r\\n {{ 'CONTACTS.TABLE.ALIAS' | translate }}\\r\\n {{ 'CONTACTS.TABLE.ADDRESS' | translate }}\\r\\n {{ 'CONTACTS.TABLE.NOTES' | translate }}\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n {{ contact.name }}\\r\\n \\r\\n \\r\\n \\r\\n {{ contact.alias }}\\r\\n \\r\\n \\r\\n \\r\\n {{ contact.address }}\\r\\n \\r\\n \\r\\n {{ contact.notes }}\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n {{ 'CONTACTS.BUTTON.SEND' | translate }}\\r\\n \\r\\n \\r\\n \\r\\n {{ 'CONTACTS.BUTTON.EDIT' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n
\\r\\n {{ 'CONTACTS.TABLE.EMPTY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n min-width: 95rem;\\n width: 100%;\\n height: 100%; }\\n\\n.head {\\n justify-content: flex-end; }\\n\\n.contacts-title {\\n font-size: 1.7rem; }\\n\\n.wrap-table {\\n margin: 1rem -3rem; }\\n\\n.wrap-table table tbody tr td {\\n padding: 0 3rem 0 1rem;\\n overflow: hidden;\\n text-overflow: ellipsis; }\\n\\n.wrap-table table tbody tr td:first-child {\\n max-width: 10rem;\\n padding: 0 3rem 0 3rem; }\\n\\n.wrap-table table tbody tr td:nth-child(2) {\\n max-width: 10rem; }\\n\\n.wrap-table table tbody tr td .alias {\\n cursor: pointer; }\\n\\n.wrap-table table tbody tr td .button-wrapper {\\n display: flex; }\\n\\n.wrap-table table tbody tr td .button-wrapper button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n font-weight: 400;\\n line-height: 3rem;\\n outline: none;\\n padding: 0;\\n height: auto;\\n margin-right: 1.8rem; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon {\\n cursor: pointer;\\n margin-right: 0.8rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.edit {\\n -webkit-mask: url('edit.svg') no-repeat center;\\n mask: url('edit.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.transfer {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr td .button-wrapper button .icon.delete {\\n -webkit-mask: url('delete.svg') no-repeat center;\\n mask: url('delete.svg') no-repeat center; }\\n\\n.wrap-table .empty-list {\\n margin: 2.5rem 3rem; }\\n\\n.blue-button {\\n width: 100%;\\n max-width: 18rem;\\n margin-top: 3rem; }\\n\\n.footer {\\n position: absolute;\\n bottom: 3rem;\\n font-size: 1.3rem; }\\n\\n.footer .import-btn {\\n display: flex;\\n align-items: center;\\n background-color: transparent;\\n font-size: inherit;\\n font-weight: 400;\\n line-height: 1.3rem;\\n padding: 0;\\n height: auto; }\\n\\n.footer .import-btn .icon {\\n margin-right: 0.7rem;\\n -webkit-mask: url('import-export.svg') no-repeat center;\\n mask: url('import-export.svg') no-repeat center;\\n width: 0.9rem;\\n height: 0.9rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udGFjdHMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGNvbnRhY3RzXFxjb250YWN0cy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQjtFQUNoQixXQUFXO0VBQ1gsWUFBWSxFQUFBOztBQUdkO0VBQ0UseUJBQXlCLEVBQUE7O0FBRzNCO0VBQ0UsaUJBQWlCLEVBQUE7O0FBR25CO0VBQ0Usa0JBQWtCLEVBQUE7O0FBRHBCO0lBVVUsc0JBQXNCO0lBQ3RCLGdCQUFnQjtJQUNoQix1QkFBdUIsRUFBQTs7QUFaakM7TUFlWSxnQkFBZ0I7TUFDaEIsc0JBQXNCLEVBQUE7O0FBaEJsQztNQW9CWSxnQkFBZ0IsRUFBQTs7QUFwQjVCO01Bd0JZLGVBQWUsRUFBQTs7QUF4QjNCO01BNEJZLGFBQWEsRUFBQTs7QUE1QnpCO1FBK0JjLGFBQWE7UUFDYixtQkFBbUI7UUFDbkIsdUJBQXVCO1FBQ3ZCLFlBQVk7UUFDWixpQkFBaUI7UUFDakIsZ0JBQWdCO1FBQ2hCLGlCQUFpQjtRQUNqQixhQUFhO1FBQ2IsVUFBVTtRQUNWLFlBQVk7UUFDWixvQkFBb0IsRUFBQTs7QUF6Q2xDO1VBNENnQixlQUFlO1VBQ2Ysb0JBQW9CO1VBQ3BCLGFBQWE7VUFDYixjQUFjLEVBQUE7O0FBL0M5QjtZQWtEa0IsOENBQXVEO29CQUF2RCxzQ0FBdUQsRUFBQTs7QUFsRHpFO1lBc0RrQiw4Q0FBdUQ7b0JBQXZELHNDQUF1RCxFQUFBOztBQXREekU7WUEwRGtCLGdEQUF5RDtvQkFBekQsd0NBQXlELEVBQUE7O0FBMUQzRTtJQXFFSSxtQkFBbUIsRUFBQTs7QUFJdkI7RUFDRSxXQUFXO0VBQ1gsZ0JBQWdCO0VBQ2hCLGdCQUFnQixFQUFBOztBQUlsQjtFQUNFLGtCQUFrQjtFQUNsQixZQUFZO0VBQ1osaUJBQWlCLEVBQUE7O0FBSG5CO0lBTUksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQiw2QkFBNkI7SUFDN0Isa0JBQWtCO0lBQ2xCLGdCQUFnQjtJQUNoQixtQkFBbUI7SUFDbkIsVUFBVTtJQUNWLFlBQVksRUFBQTs7QUFiaEI7TUFnQk0sb0JBQW9CO01BQ3BCLHVEQUFnRTtjQUFoRSwrQ0FBZ0U7TUFDaEUsYUFBYTtNQUNiLGNBQWMsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2NvbnRhY3RzL2NvbnRhY3RzLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIG1pbi13aWR0aDogOTVyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxufVxyXG5cclxuLmNvbnRhY3RzLXRpdGxlIHtcclxuICBmb250LXNpemU6IDEuN3JlbTtcclxufVxyXG5cclxuLndyYXAtdGFibGUge1xyXG4gIG1hcmdpbjogMXJlbSAtM3JlbTtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5e1xyXG5cclxuICAgICAgdHIge1xyXG5cclxuICAgICAgICB0ZCB7XHJcbiAgICAgICAgICBwYWRkaW5nOiAwIDNyZW0gMCAxcmVtO1xyXG4gICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG5cclxuICAgICAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgICAgICBtYXgtd2lkdGg6IDEwcmVtO1xyXG4gICAgICAgICAgICBwYWRkaW5nOiAwIDNyZW0gMCAzcmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICY6bnRoLWNoaWxkKDIpIHtcclxuICAgICAgICAgICAgbWF4LXdpZHRoOiAxMHJlbTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuYWxpYXMge1xyXG4gICAgICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLmJ1dHRvbi13cmFwcGVyIHtcclxuICAgICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgICAgICAgZGlzcGxheTogZmxleDsgIFxyXG4gICAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgICAgICAgYm9yZGVyOiBub25lO1xyXG4gICAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDNyZW07XHJcbiAgICAgICAgICAgICAgb3V0bGluZTogbm9uZTtcclxuICAgICAgICAgICAgICBwYWRkaW5nOiAwO1xyXG4gICAgICAgICAgICAgIGhlaWdodDogYXV0bztcclxuICAgICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuOHJlbTtcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgICAgIC5pY29uIHtcclxuICAgICAgICAgICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICAgICAgICAgIG1hcmdpbi1yaWdodDogMC44cmVtO1xyXG4gICAgICAgICAgICAgICAgd2lkdGg6IDEuN3JlbTtcclxuICAgICAgICAgICAgICAgIGhlaWdodDogMS43cmVtO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICYuZWRpdCB7XHJcbiAgICAgICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvZWRpdC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgJi50cmFuc2ZlciB7XHJcbiAgICAgICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvc2VuZC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAmLmRlbGV0ZSB7XHJcbiAgICAgICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvZGVsZXRlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgXHJcbiAgLmVtcHR5LWxpc3Qge1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gM3JlbTtcclxuICB9ICBcclxufVxyXG5cclxuLmJsdWUtYnV0dG9uIHtcclxuICB3aWR0aDogMTAwJTtcclxuICBtYXgtd2lkdGg6IDE4cmVtO1xyXG4gIG1hcmdpbi10b3A6IDNyZW07XHJcbn1cclxuXHJcblxyXG4uZm9vdGVyIHtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgYm90dG9tOiAzcmVtO1xyXG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gIFxyXG4gIC5pbXBvcnQtYnRuIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XHJcbiAgICBmb250LXNpemU6IGluaGVyaXQ7XHJcbiAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuM3JlbTtcclxuICAgIHBhZGRpbmc6IDA7XHJcbiAgICBoZWlnaHQ6IGF1dG87XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDAuN3JlbTtcclxuICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9pbXBvcnQtZXhwb3J0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDAuOXJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjlyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\n\r\n@Component({\r\n selector: 'app-contacts',\r\n templateUrl: './contacts.component.html',\r\n styleUrls: ['./contacts.component.scss']\r\n})\r\nexport class ContactsComponent implements OnInit {\r\n calculatedWidth = [];\r\n @ViewChild('head') head: ElementRef;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private backend: BackendService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.backend.getContactAlias();\r\n }\r\n\r\n delete(index: number) {\r\n if (this.variablesService.appPass) {\r\n this.variablesService.contacts.splice(index, 1);\r\n this.backend.storeSecureAppData();\r\n }\r\n }\r\n\r\n calculateWidth() {\r\n this.calculatedWidth = [];\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[0].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[1].clientWidth +\r\n this.head.nativeElement.childNodes[2].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[3].clientWidth\r\n );\r\n this.calculatedWidth.push(\r\n this.head.nativeElement.childNodes[4].clientWidth\r\n );\r\n }\r\n\r\n // openInBrowser(alias: string) {\r\n // if (alias !== null) {\r\n // this.backend.openUrlInBrowser(\r\n // `explorer.zano.org/aliases/${alias.slice(1)}#modalOpen`\r\n // );\r\n // }\r\n // }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n {{ 'CONTRACTS.EMPTY' | translate }}\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'CONTRACTS.CONTRACTS' | translate }}{{ 'CONTRACTS.DATE' | translate }}{{ 'CONTRACTS.AMOUNT' | translate }}{{ 'CONTRACTS.STATUS' | translate }}{{ 'CONTRACTS.COMMENTS' | translate }}
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.private_detailes.t}}\\r\\n
\\r\\n
\\r\\n
{{item.timestamp * 1000 | date : 'dd-MM-yyyy HH:mm'}}
\\r\\n
\\r\\n
{{item.private_detailes.to_pay | intToMoney}} {{variablesService.defaultCurrency}}
\\r\\n
\\r\\n
\\r\\n {{item.state | contractStatusMessages : item.is_a}}\\r\\n
\\r\\n
\\r\\n
\\r\\n {{item.private_detailes.c}}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.empty-contracts {\\n font-size: 1.5rem; }\\n\\n.wrap-table {\\n margin: -3rem -3rem 0 -3rem;\\n overflow-x: auto; }\\n\\n.wrap-table table tbody tr {\\n cursor: pointer;\\n outline: none !important; }\\n\\n.wrap-table table tbody tr .contract {\\n position: relative;\\n display: flex;\\n align-items: center; }\\n\\n.wrap-table table tbody tr .contract .icon {\\n flex-shrink: 0; }\\n\\n.wrap-table table tbody tr .contract .icon.new, .wrap-table table tbody tr .contract .icon.alert {\\n position: absolute;\\n top: 0; }\\n\\n.wrap-table table tbody tr .contract .icon.new {\\n left: -2.3rem;\\n -webkit-mask: url('new.svg') no-repeat center;\\n mask: url('new.svg') no-repeat center;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr .contract .icon.alert {\\n top: 0.2rem;\\n left: -2.1rem;\\n -webkit-mask: url('alert.svg') no-repeat center;\\n mask: url('alert.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.wrap-table table tbody tr .contract .icon.purchase, .wrap-table table tbody tr .contract .icon.sell {\\n margin-right: 1rem;\\n width: 1.5rem;\\n height: 1.5rem; }\\n\\n.wrap-table table tbody tr .contract .icon.purchase {\\n -webkit-mask: url('purchase.svg') no-repeat center;\\n mask: url('purchase.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .contract .icon.sell {\\n -webkit-mask: url('sell.svg') no-repeat center;\\n mask: url('sell.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .contract span {\\n text-overflow: ellipsis;\\n overflow: hidden; }\\n\\n.wrap-table table tbody tr .status, .wrap-table table tbody tr .comment {\\n display: inline-block;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n max-width: 100%; }\\n\\n.contracts-buttons {\\n display: flex;\\n margin: 3rem 0;\\n width: 50%; }\\n\\n.contracts-buttons button {\\n flex: 0 1 50%;\\n margin-right: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY29udHJhY3RzL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFxjb250cmFjdHNcXGNvbnRyYWN0cy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUNFLGlCQUFpQixFQUFBOztBQUduQjtFQUNFLDJCQUEyQjtFQUMzQixnQkFBZ0IsRUFBQTs7QUFGbEI7SUFTUSxlQUFlO0lBQ2Ysd0JBQXdCLEVBQUE7O0FBVmhDO01BYVUsa0JBQWtCO01BQ2xCLGFBQWE7TUFDYixtQkFBbUIsRUFBQTs7QUFmN0I7UUFrQlksY0FBYyxFQUFBOztBQWxCMUI7VUFxQmMsa0JBQWtCO1VBQ2xCLE1BQU0sRUFBQTs7QUF0QnBCO1VBMEJjLGFBQWE7VUFDYiw2Q0FBc0Q7a0JBQXRELHFDQUFzRDtVQUN0RCxhQUFhO1VBQ2IsY0FBYyxFQUFBOztBQTdCNUI7VUFpQ2MsV0FBVztVQUNYLGFBQWE7VUFDYiwrQ0FBd0Q7a0JBQXhELHVDQUF3RDtVQUN4RCxhQUFhO1VBQ2IsY0FBYyxFQUFBOztBQXJDNUI7VUF5Q2Msa0JBQWtCO1VBQ2xCLGFBQWE7VUFDYixjQUFjLEVBQUE7O0FBM0M1QjtVQStDYyxrREFBMkQ7a0JBQTNELDBDQUEyRCxFQUFBOztBQS9DekU7VUFtRGMsOENBQXVEO2tCQUF2RCxzQ0FBdUQsRUFBQTs7QUFuRHJFO1FBd0RZLHVCQUF1QjtRQUN2QixnQkFBZ0IsRUFBQTs7QUF6RDVCO01BOERVLHFCQUFxQjtNQUNyQix1QkFBdUI7TUFDdkIsZ0JBQWdCO01BQ2hCLGVBQWUsRUFBQTs7QUFPekI7RUFDRSxhQUFhO0VBQ2IsY0FBYztFQUNkLFVBQVUsRUFBQTs7QUFIWjtJQU1JLGFBQWE7SUFDYixvQkFBb0IsRUFBQSIsImZpbGUiOiJzcmMvYXBwL2NvbnRyYWN0cy9jb250cmFjdHMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbn1cclxuXHJcbi5lbXB0eS1jb250cmFjdHMge1xyXG4gIGZvbnQtc2l6ZTogMS41cmVtO1xyXG59XHJcblxyXG4ud3JhcC10YWJsZSB7XHJcbiAgbWFyZ2luOiAtM3JlbSAtM3JlbSAwIC0zcmVtO1xyXG4gIG92ZXJmbG93LXg6IGF1dG87XHJcblxyXG4gIHRhYmxlIHtcclxuXHJcbiAgICB0Ym9keSB7XHJcblxyXG4gICAgICB0ciB7XHJcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICAgIG91dGxpbmU6IG5vbmUgIWltcG9ydGFudDtcclxuXHJcbiAgICAgICAgLmNvbnRyYWN0IHtcclxuICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuICAgICAgICAgICAgZmxleC1zaHJpbms6IDA7XHJcblxyXG4gICAgICAgICAgICAmLm5ldywgJi5hbGVydCB7XHJcbiAgICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5uZXcge1xyXG4gICAgICAgICAgICAgIGxlZnQ6IC0yLjNyZW07XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9uZXcuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgICAgICAgIHdpZHRoOiAxLjdyZW07XHJcbiAgICAgICAgICAgICAgaGVpZ2h0OiAxLjdyZW07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICYuYWxlcnQge1xyXG4gICAgICAgICAgICAgIHRvcDogMC4ycmVtO1xyXG4gICAgICAgICAgICAgIGxlZnQ6IC0yLjFyZW07XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgICAgd2lkdGg6IDEuMnJlbTtcclxuICAgICAgICAgICAgICBoZWlnaHQ6IDEuMnJlbTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5wdXJjaGFzZSwgJi5zZWxsIHtcclxuICAgICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDFyZW07XHJcbiAgICAgICAgICAgICAgd2lkdGg6IDEuNXJlbTtcclxuICAgICAgICAgICAgICBoZWlnaHQ6IDEuNXJlbTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5wdXJjaGFzZSB7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9wdXJjaGFzZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICYuc2VsbCB7XHJcbiAgICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZWxsLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcclxuICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zdGF0dXMsIC5jb21tZW50IHtcclxuICAgICAgICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcclxuICAgICAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgIG1heC13aWR0aDogMTAwJTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi5jb250cmFjdHMtYnV0dG9ucyB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBtYXJnaW46IDNyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICBidXR0b24ge1xyXG4gICAgZmxleDogMCAxIDUwJTtcclxuICAgIG1hcmdpbi1yaWdodDogMS41cmVtO1xyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, OnDestroy} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\n\r\n@Component({\r\n selector: 'app-contracts',\r\n templateUrl: './contracts.component.html',\r\n styleUrls: ['./contracts.component.scss']\r\n})\r\nexport class ContractsComponent implements OnInit, OnDestroy {\r\n\r\n parentRouting;\r\n walletId;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n public variablesService: VariablesService\r\n ) {\r\n }\r\n\r\n public get sortedArrayContracts(): any[] {\r\n return this.variablesService.currentWallet.contracts.sort((a, b) => {\r\n if (a.is_new < b.is_new) {\r\n return 1;\r\n }\r\n if (a.is_new > b.is_new) {\r\n return -1;\r\n }\r\n if (a.timestamp < b.timestamp) {\r\n return 1;\r\n }\r\n if (a.timestamp > b.timestamp) {\r\n return -1;\r\n }\r\n if (a.contract_id < b.contract_id) {\r\n return 1;\r\n }\r\n if (a.contract_id > b.contract_id) {\r\n return -1;\r\n }\r\n return 0;\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n if (params.hasOwnProperty('id')) {\r\n this.walletId = params['id'];\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.CREATE_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'CREATE_WALLET.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.form-create {\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.form-create .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem; }\\n\\n.form-create .wrap-buttons button {\\n margin: 0 0.7rem; }\\n\\n.form-create .wrap-buttons button.transparent-button {\\n flex-basis: 50%; }\\n\\n.form-create .wrap-buttons button.select-button {\\n flex-basis: 60%; }\\n\\n.form-create .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvY3JlYXRlLXdhbGxldC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcY3JlYXRlLXdhbGxldFxcY3JlYXRlLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7O0FBRlo7SUFLSSxhQUFhO0lBQ2Isc0JBQXNCLEVBQUE7O0FBTjFCO01BU00sZ0JBQWdCLEVBQUE7O0FBVHRCO1FBWVEsZUFBZSxFQUFBOztBQVp2QjtRQWdCUSxlQUFlLEVBQUE7O0FBaEJ2QjtRQW9CUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9jcmVhdGUtd2FsbGV0L2NyZWF0ZS13YWxsZXQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG59XHJcblxyXG4uZm9ybS1jcmVhdGUge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG5cclxuICAgICAgJi50cmFuc3BhcmVudC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDUwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5zZWxlY3QtYnV0dG9uIHtcclxuICAgICAgICBmbGV4LWJhc2lzOiA2MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuY3JlYXRlLWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAxIDUwJTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Router} from '@angular/router';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-create-wallet',\r\n templateUrl: './create-wallet.component.html',\r\n styleUrls: ['./create-wallet.component.scss']\r\n})\r\nexport class CreateWalletComponent implements OnInit {\r\n\r\n createForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n confirm: new FormControl('')\r\n }, function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirm').value ? null : {'confirm_mismatch': true};\r\n });\r\n\r\n wallet = {\r\n id: ''\r\n };\r\n\r\n walletSaved = false;\r\n walletSavedName = '';\r\n progressWidth = '9rem';\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n createWallet() {\r\n this.ngZone.run(() => {\r\n this.progressWidth = '100%';\r\n this.router.navigate(['/seed-phrase'], {queryParams: {wallet_id: this.wallet.id}});\r\n });\r\n }\r\n\r\n saveWallet() {\r\n if (this.createForm.valid && this.createForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.saveFileDialog(this.translate.instant('CREATE_WALLET.TITLE_SAVE'), '*', this.variablesService.settings.default_path, (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(0, file_data.path.lastIndexOf('/'));\r\n this.walletSavedName = file_data.path.substr(file_data.path.lastIndexOf('/') + 1, file_data.path.length - 1);\r\n this.backend.generateWallet(file_data.path, this.createForm.get('password').value, (generate_status, generate_data, errorCode) => {\r\n if (generate_status) {\r\n this.wallet.id = generate_data.wallet_id;\r\n this.variablesService.opening_wallet = new Wallet(\r\n generate_data.wallet_id,\r\n this.createForm.get('name').value,\r\n this.createForm.get('password').value,\r\n generate_data['wi'].path,\r\n generate_data['wi'].address,\r\n generate_data['wi'].balance,\r\n generate_data['wi'].unlocked_balance,\r\n generate_data['wi'].mined_total,\r\n generate_data['wi'].tracking_hey\r\n );\r\n this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(generate_data['wi'].address);\r\n this.ngZone.run(() => {\r\n this.walletSaved = true;\r\n this.progressWidth = '50%';\r\n });\r\n } else {\r\n if (errorCode && errorCode === 'ALREADY_EXISTS') {\r\n this.modalService.prepareModal('error', 'CREATE_WALLET.ERROR_CANNOT_SAVE_TOP');\r\n } else {\r\n this.modalService.prepareModal('error', 'CREATE_WALLET.ERROR_CANNOT_SAVE_SYSTEM');\r\n }\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.EDIT_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
0 && notEnoughMoney\\\">\\r\\n {{ 'EDIT_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'EDIT_ALIAS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"EDIT_ALIAS.COST\\\" | translate : {value: variablesService.default_fee, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \".form-edit {\\n margin: 2.4rem 0; }\\n .form-edit .alias-name {\\n width: 50%; }\\n .form-edit .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-edit .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-edit .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZWRpdC1hbGlhcy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcZWRpdC1hbGlhc1xcZWRpdC1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9lZGl0LWFsaWFzL2VkaXQtYWxpYXMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1lZGl0IHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG5cclxuICAuYWxpYXMtbmFtZSB7XHJcbiAgICB3aWR0aDogNTAlO1xyXG4gIH1cclxuXHJcbiAgLmFsaWFzLWNvc3Qge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW4tdG9wOiAycmVtO1xyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG4gICAgICB3aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\n@Component({\r\n selector: 'app-edit-alias',\r\n templateUrl: './edit-alias.component.html',\r\n styleUrls: ['./edit-alias.component.scss']\r\n})\r\nexport class EditAliasComponent implements OnInit {\r\n\r\n wallet: Wallet;\r\n alias: any;\r\n oldAliasComment: string;\r\n notEnoughMoney: boolean;\r\n requestProcessing = false;\r\n\r\n constructor(\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n this.alias = {\r\n name: alias.name,\r\n address: alias.address,\r\n comment: alias.comment\r\n };\r\n this.oldAliasComment = alias.comment;\r\n this.notEnoughMoney = this.wallet.unlocked_balance.isLessThan(this.variablesService.default_fee_big);\r\n }\r\n\r\n updateAlias() {\r\n if (this.requestProcessing || this.notEnoughMoney || this.oldAliasComment === this.alias.comment || this.alias.comment.length > this.variablesService.maxCommentLength) {\r\n return;\r\n }\r\n this.requestProcessing = true;\r\n this.backend.updateAlias(this.wallet.wallet_id, this.alias, this.variablesService.default_fee, (status) => {\r\n if (status) {\r\n this.modalService.prepareModal('success', '');\r\n this.wallet.alias['comment'] = this.alias.comment;\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n this.requestProcessing = false;\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'CONTACTS.IMPORT_EXPORT' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.head {\\n justify-content: flex-end; }\\n\\n.contacts-title {\\n font-size: 1.7rem;\\n margin-bottom: 1rem; }\\n\\n.btn-wrapper {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 0 -0.5rem;\\n padding: 1.5rem 0; }\\n\\n.btn-wrapper button {\\n flex: 1 0 auto;\\n margin: 0 0.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvZXhwb3J0LWltcG9ydC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcZXhwb3J0LWltcG9ydFxcZXhwb3J0LWltcG9ydC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUNFLHlCQUF5QixFQUFBOztBQUczQjtFQUNFLGlCQUFpQjtFQUNqQixtQkFBbUIsRUFBQTs7QUFHckI7RUFDRSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLDhCQUE4QjtFQUM5QixpQkFBaUI7RUFDakIsaUJBQWlCLEVBQUE7O0FBTG5CO0lBUUksY0FBYztJQUNkLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvZXhwb3J0LWltcG9ydC9leHBvcnQtaW1wb3J0LmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uaGVhZCB7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxufVxyXG5cclxuLmNvbnRhY3RzLXRpdGxlIHtcclxuICBmb250LXNpemU6IDEuN3JlbTtcclxuICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG59XHJcblxyXG4uYnRuLXdyYXBwZXIge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgbWFyZ2luOiAwIC0wLjVyZW07XHJcbiAgcGFkZGluZzogMS41cmVtIDA7XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBmbGV4OiAxIDAgYXV0bztcclxuICAgIG1hcmdpbjogMCAwLjVyZW07XHJcbiAgfVxyXG59Il19 */\"","import { Component, OnInit, NgZone } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\nimport { BackendService } from '../_helpers/services/backend.service';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\nimport { Contact } from '../_helpers/models/contact.model';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\nimport { Papa } from 'ngx-papaparse';\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { Router } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-export-import',\r\n templateUrl: './export-import.component.html',\r\n styleUrls: ['./export-import.component.scss']\r\n})\r\nexport class ExportImportComponent implements OnInit {\r\n csvContent;\r\n\r\n constructor(\r\n private location: Location,\r\n private variablesService: VariablesService,\r\n private backend: BackendService,\r\n private modalService: ModalService,\r\n private papa: Papa,\r\n private translate: TranslateService,\r\n private router: Router,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {}\r\n\r\n import() {\r\n this.backend.openFileDialog(\r\n '',\r\n '*',\r\n this.variablesService.settings.default_path,\r\n (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(\r\n 0,\r\n file_data.path.lastIndexOf('/')\r\n );\r\n if (this.isValid(file_data.path)) {\r\n this.backend.loadFile(file_data.path, (status, data) => {\r\n if (!status) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.ERROR_IMPORT_EMPTY'\r\n );\r\n } else {\r\n const options = {\r\n header: true\r\n };\r\n const elements = this.papa.parse(data, options);\r\n const isArray = Array.isArray(elements.data);\r\n if (isArray && elements.data.length !== 0 && !elements.errors.length) {\r\n if (!this.variablesService.contacts.length) {\r\n elements.data.forEach(element => {\r\n this.variablesService.contacts.push(element);\r\n });\r\n } else {\r\n elements.data.forEach(element => {\r\n const indexName = this.variablesService.contacts.findIndex(\r\n contact => contact.name === element.name\r\n );\r\n const indexAddress = this.variablesService.contacts.findIndex(\r\n contact => contact.address === element.address\r\n );\r\n if (indexAddress === -1 && indexName === -1) {\r\n this.variablesService.contacts.push(element);\r\n }\r\n if (indexName !== -1 && indexAddress === -1) {\r\n this.variablesService.contacts.push({\r\n name: `${element.name} ${this.translate.instant(\r\n 'CONTACTS.COPY'\r\n )}`,\r\n address: element.address,\r\n notes: element.notes\r\n });\r\n }\r\n });\r\n }\r\n this.backend.getContactAlias();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/contacts']);\r\n });\r\n }\r\n if (elements.errors.length) {\r\n this.modalService.prepareModal(\r\n 'error',\r\n 'CONTACTS.ERROR_IMPORT'\r\n );\r\n console.log(elements.errors);\r\n }\r\n }\r\n });\r\n } else {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_TYPE_FILE');\r\n }\r\n }\r\n }\r\n );\r\n }\r\n\r\n export() {\r\n const contacts: Array = [];\r\n this.variablesService.contacts.forEach(contact => {\r\n delete contact.alias;\r\n contacts.push(contact);\r\n });\r\n\r\n this.backend.saveFileDialog(\r\n '',\r\n '*',\r\n this.variablesService.settings.default_path,\r\n (file_status, file_data) => {\r\n if (!this.variablesService.contacts.length && !(file_data.error_code === 'CANCELED')) {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_EMPTY_LIST');\r\n }\r\n const path = this.isValid(file_data.path) ? file_data.path : `${file_data.path}.csv`;\r\n if (file_status && this.isValid(path) && this.variablesService.contacts.length) {\r\n this.backend.storeFile(path, this.papa.unparse(contacts));\r\n }\r\n if (!(file_data.error_code === 'CANCELED') && !this.isValid(path)) {\r\n this.modalService.prepareModal('error', 'CONTACTS.ERROR_EXPORT');\r\n }\r\n }\r\n );\r\n }\r\n\r\n isValid(file) {\r\n return file.endsWith('.csv');\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'HISTORY.STATUS' | translate }}{{ 'HISTORY.DATE' | translate }}{{ 'HISTORY.AMOUNT' | translate }}{{ 'HISTORY.FEE' | translate }}{{ 'HISTORY.ADDRESS' | translate }}
\\r\\n
\\r\\n 0\\\">\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n 500000000\\\">\\r\\n 0\\\">\\r\\n \\r\\n \\r\\n \\r\\n 0\\\">\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n {{ (item.is_income ? 'HISTORY.RECEIVED' : 'HISTORY.SEND') | translate }}\\r\\n
\\r\\n
{{item.timestamp * 1000 | date : 'dd-MM-yyyy HH:mm'}}\\r\\n {{item.sortAmount | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n \\r\\n {{item.sortFee | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n \\r\\n {{item | historyTypeMessages}}\\r\\n {{item.remote_addresses[0]}}\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-table {\\n margin: -3rem; }\\n\\n.wrap-table table tbody tr td {\\n min-width: 10rem; }\\n\\n.wrap-table table tbody tr .status {\\n position: relative;\\n display: flex;\\n align-items: center; }\\n\\n.wrap-table table tbody tr .status .confirmation {\\n position: absolute;\\n top: 50%;\\n left: -2rem;\\n transform: translateY(-50%);\\n display: flex;\\n align-items: flex-end;\\n width: 0.7rem;\\n height: 1.5rem; }\\n\\n.wrap-table table tbody tr .status .confirmation .fill {\\n width: 100%; }\\n\\n.wrap-table table tbody tr .status .lock-transaction {\\n position: absolute;\\n left: -2rem;\\n -webkit-mask: url('lock-transaction.svg') no-repeat center;\\n mask: url('lock-transaction.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem;\\n margin-right: 1.1rem; }\\n\\n.wrap-table table tbody tr .status .unlock-transaction {\\n position: absolute;\\n left: -2rem;\\n -webkit-mask: url('unlock-transaction.svg') no-repeat center;\\n mask: url('unlock-transaction.svg') no-repeat center;\\n width: 1.2rem;\\n height: 1.2rem;\\n margin-right: 1.1rem; }\\n\\n.wrap-table table tbody tr .status .position {\\n position: static; }\\n\\n.wrap-table table tbody tr .status .status-transaction {\\n margin-right: 1rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-table table tbody tr .status.send .status-transaction {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .status.received .status-transaction {\\n -webkit-mask: url('receive.svg') no-repeat center;\\n mask: url('receive.svg') no-repeat center; }\\n\\n.wrap-table table tbody tr .remote-address {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n max-width: 25vw; }\\n\\n.wrap-table table tbody tr:not(.transaction-details) {\\n cursor: pointer; }\\n\\n.wrap-table table tbody tr.transaction-details {\\n transition: 0.5s height linear, 0s font-size;\\n transition-delay: 0s, 0.5s;\\n height: 0; }\\n\\n.wrap-table table tbody tr.transaction-details.open {\\n height: 16.2rem; }\\n\\n.wrap-table table tbody tr.transaction-details td {\\n position: relative;\\n overflow: hidden;\\n line-height: inherit;\\n padding-top: 0;\\n padding-bottom: 0; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvaGlzdG9yeS9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcaGlzdG9yeVxcaGlzdG9yeS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUNFLGFBQWEsRUFBQTs7QUFEZjtJQVVVLGdCQUFnQixFQUFBOztBQVYxQjtJQWNVLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsbUJBQW1CLEVBQUE7O0FBaEI3QjtNQW1CWSxrQkFBa0I7TUFDbEIsUUFBUTtNQUNSLFdBQVc7TUFDWCwyQkFBMkI7TUFDM0IsYUFBYTtNQUNiLHFCQUFxQjtNQUNyQixhQUFhO01BQ2IsY0FBYyxFQUFBOztBQTFCMUI7UUE2QmMsV0FBVyxFQUFBOztBQTdCekI7TUFrQ1ksa0JBQWtCO01BQ2xCLFdBQVc7TUFDWCwwREFBbUU7Y0FBbkUsa0RBQW1FO01BQ25FLGFBQWE7TUFDYixjQUFjO01BQ2Qsb0JBQW9CLEVBQUE7O0FBdkNoQztNQTJDWSxrQkFBa0I7TUFDbEIsV0FBVztNQUNYLDREQUFxRTtjQUFyRSxvREFBcUU7TUFDckUsYUFBYTtNQUNiLGNBQWM7TUFDZCxvQkFBb0IsRUFBQTs7QUFoRGhDO01Bb0RZLGdCQUFnQixFQUFBOztBQXBENUI7TUF3RFksa0JBQWtCO01BQ2xCLGFBQWE7TUFDYixjQUFjLEVBQUE7O0FBMUQxQjtNQWdFYyw4Q0FBdUQ7Y0FBdkQsc0NBQXVELEVBQUE7O0FBaEVyRTtNQXVFYyxpREFBMEQ7Y0FBMUQseUNBQTBELEVBQUE7O0FBdkV4RTtJQTZFVSxnQkFBZ0I7SUFDaEIsdUJBQXVCO0lBQ3ZCLGVBQWUsRUFBQTs7QUEvRXpCO0lBbUZVLGVBQWUsRUFBQTs7QUFuRnpCO0lBd0ZVLDRDQUE0QztJQUM1QywwQkFBMEI7SUFDMUIsU0FBUyxFQUFBOztBQTFGbkI7TUE2RlksZUFBZSxFQUFBOztBQTdGM0I7TUFpR1ksa0JBQWtCO01BQ2xCLGdCQUFnQjtNQUNoQixvQkFBb0I7TUFDcEIsY0FBYztNQUNkLGlCQUFpQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvaGlzdG9yeS9oaXN0b3J5LmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4ud3JhcC10YWJsZSB7XHJcbiAgbWFyZ2luOiAtM3JlbTtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgdGQge1xyXG4gICAgICAgICAgbWluLXdpZHRoOiAxMHJlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zdGF0dXMge1xyXG4gICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcblxyXG4gICAgICAgICAgLmNvbmZpcm1hdGlvbiB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgdG9wOiA1MCU7XHJcbiAgICAgICAgICAgIGxlZnQ6IC0ycmVtO1xyXG4gICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgICAgIGFsaWduLWl0ZW1zOiBmbGV4LWVuZDtcclxuICAgICAgICAgICAgd2lkdGg6IDAuN3JlbTtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxLjVyZW07XHJcblxyXG4gICAgICAgICAgICAuZmlsbCB7XHJcbiAgICAgICAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAubG9jay10cmFuc2FjdGlvbiB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgbGVmdDogLTJyZW07XHJcbiAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvbG9jay10cmFuc2FjdGlvbi5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIHdpZHRoOiAxLjJyZW07XHJcbiAgICAgICAgICAgIGhlaWdodDogMS4ycmVtO1xyXG4gICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuMXJlbTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAudW5sb2NrLXRyYW5zYWN0aW9uIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgICBsZWZ0OiAtMnJlbTtcclxuICAgICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy91bmxvY2stdHJhbnNhY3Rpb24uc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgICAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEuMnJlbTtcclxuICAgICAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjFyZW07XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnBvc2l0aW9uIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IHN0YXRpYztcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcclxuICAgICAgICAgICAgbWFyZ2luLXJpZ2h0OiAxcmVtO1xyXG4gICAgICAgICAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgICAgICAgICBoZWlnaHQ6IDEuN3JlbTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmLnNlbmQgIHtcclxuXHJcbiAgICAgICAgICAgIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xyXG4gICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvc2VuZC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmLnJlY2VpdmVkIHtcclxuXHJcbiAgICAgICAgICAgIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xyXG4gICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvcmVjZWl2ZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5yZW1vdGUtYWRkcmVzcyB7XHJcbiAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgICAgICAgICBtYXgtd2lkdGg6IDI1dnc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOm5vdCgudHJhbnNhY3Rpb24tZGV0YWlscykge1xyXG4gICAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi50cmFuc2FjdGlvbi1kZXRhaWxzIHtcclxuICAgICAgICAgIC13ZWJraXQtdHJhbnNpdGlvbjogMC41cyBoZWlnaHQgbGluZWFyLCAwcyBmb250LXNpemU7XHJcbiAgICAgICAgICB0cmFuc2l0aW9uOiAwLjVzIGhlaWdodCBsaW5lYXIsIDBzIGZvbnQtc2l6ZTtcclxuICAgICAgICAgIHRyYW5zaXRpb24tZGVsYXk6IDBzLCAwLjVzO1xyXG4gICAgICAgICAgaGVpZ2h0OiAwO1xyXG5cclxuICAgICAgICAgICYub3BlbiB7XHJcbiAgICAgICAgICAgIGhlaWdodDogMTYuMnJlbTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB0ZCB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgICAgICAgbGluZS1oZWlnaHQ6IGluaGVyaXQ7XHJcbiAgICAgICAgICAgIHBhZGRpbmctdG9wOiAwO1xyXG4gICAgICAgICAgICBwYWRkaW5nLWJvdHRvbTogMDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, OnDestroy, AfterViewChecked, ViewChild, ElementRef} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport { Transaction } from '../_helpers/models/transaction.model';\r\n\r\n@Component({\r\n selector: 'app-history',\r\n templateUrl: './history.component.html',\r\n styleUrls: ['./history.component.scss']\r\n})\r\nexport class HistoryComponent implements OnInit, OnDestroy, AfterViewChecked {\r\n parentRouting;\r\n openedDetails = false;\r\n calculatedWidth = [];\r\n @ViewChild('head') head: ElementRef;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n public variablesService: VariablesService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n this.openedDetails = false;\r\n });\r\n }\r\n\r\n ngAfterViewChecked() {\r\n this.calculateWidth();\r\n }\r\n\r\n getHeight(item) {\r\n if ((this.variablesService.height_app - item.height >= 10 && item.height !== 0) || (item.is_mining === true && item.height === 0)) {\r\n return 100;\r\n } else {\r\n if (item.height === 0 || this.variablesService.height_app - item.height < 0) {\r\n return 0;\r\n } else {\r\n return (this.variablesService.height_app - item.height) * 10;\r\n }\r\n }\r\n }\r\n\r\n openDetails(tx_hash) {\r\n if (tx_hash === this.openedDetails) {\r\n this.openedDetails = false;\r\n } else {\r\n this.openedDetails = tx_hash;\r\n }\r\n }\r\n\r\n calculateWidth() {\r\n this.calculatedWidth = [];\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[0].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[1].clientWidth + this.head.nativeElement.childNodes[2].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[3].clientWidth);\r\n this.calculatedWidth.push(this.head.nativeElement.childNodes[4].clientWidth);\r\n }\r\n\r\n time(item: Transaction) {\r\n const now = new Date().getTime();\r\n const unlockTime = now + ((item.unlock_time - this.variablesService.height_max) * 60 * 1000);\r\n return unlockTime;\r\n }\r\n\r\n isLocked(item: Transaction) {\r\n if ((item.unlock_time > 500000000) && (item.unlock_time > new Date().getTime() / 1000)) {\r\n return true;\r\n }\r\n if ((item.unlock_time < 500000000) && (item.unlock_time > this.variablesService.height_max)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'LOGIN.FORM_ERRORS.MISMATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 100%; }\\n :host .content {\\n display: flex; }\\n :host .content .wrap-login {\\n margin: auto;\\n width: 100%;\\n max-width: 40rem; }\\n :host .content .wrap-login .logo {\\n display: flex;\\n justify-content: center; }\\n :host .content .wrap-login .logo::ng-deep svg {\\n width: 15rem; }\\n :host .content .wrap-login .form-login {\\n display: flex;\\n flex-direction: column; }\\n :host .content .wrap-login .form-login .wrap-button {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n :host .content .wrap-login .form-login .wrap-button button {\\n margin: 2.5rem 0; }\\n :host .content .wrap-login .form-login button {\\n margin: 2.5rem auto;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbG9naW4vQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXGxvZ2luXFxsb2dpbi5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sT0FBTztFQUNQLFdBQVc7RUFDWCxZQUFZLEVBQUE7RUFMZDtJQVFJLGFBQWEsRUFBQTtFQVJqQjtNQVdNLFlBQVk7TUFDWixXQUFXO01BQ1gsZ0JBQWdCLEVBQUE7RUFidEI7UUFnQlEsYUFBYTtRQUNiLHVCQUF1QixFQUFBO0VBakIvQjtVQW9CVSxZQUFZLEVBQUE7RUFwQnRCO1FBeUJRLGFBQWE7UUFDYixzQkFBc0IsRUFBQTtFQTFCOUI7VUE2QlUsYUFBYTtVQUNiLG1CQUFtQjtVQUNuQiw4QkFBOEIsRUFBQTtFQS9CeEM7WUFrQ1ksZ0JBQWdCLEVBQUE7RUFsQzVCO1VBdUNVLG1CQUFtQjtVQUNuQixXQUFXO1VBQ1gsZ0JBQWdCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9sb2dpbi9sb2dpbi5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogZml4ZWQ7XHJcbiAgdG9wOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAxMDAlO1xyXG5cclxuICAuY29udGVudCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAgIC53cmFwLWxvZ2luIHtcclxuICAgICAgbWFyZ2luOiBhdXRvO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgbWF4LXdpZHRoOiA0MHJlbTtcclxuXHJcbiAgICAgIC5sb2dvIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG5cclxuICAgICAgICAmOjpuZy1kZWVwIHN2ZyB7XHJcbiAgICAgICAgICB3aWR0aDogMTVyZW07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuZm9ybS1sb2dpbiB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG5cclxuICAgICAgICAud3JhcC1idXR0b24ge1xyXG4gICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgICAgICAgYnV0dG9uIHtcclxuICAgICAgICAgICAgbWFyZ2luOiAyLjVyZW0gMDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgICBtYXJnaW46IDIuNXJlbSBhdXRvO1xyXG4gICAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-login',\r\n templateUrl: './login.component.html',\r\n styleUrls: ['./login.component.scss']\r\n})\r\nexport class LoginComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n\r\n regForm = new FormGroup({\r\n password: new FormControl('',\r\n Validators.pattern(this.variablesService.pattern)),\r\n confirmation: new FormControl('')\r\n }, [function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirmation').value ? null : {'mismatch': true};\r\n }\r\n]);\r\n\r\n authForm = new FormGroup({\r\n password: new FormControl('')\r\n });\r\n\r\n type = 'reg';\r\n\r\n logo = icons.logo;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.type) {\r\n this.type = params.type;\r\n }\r\n });\r\n }\r\n\r\n onSubmitCreatePass(): void {\r\n if (this.regForm.valid) {\r\n this.variablesService.appPass = this.regForm.get('password').value; // the pass what was written in input of login form by user\r\n\r\n this.backend.setMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.backend.storeSecureAppData({pass: this.variablesService.appPass});\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n } else {\r\n console.log(data['error_code']);\r\n }\r\n });\r\n }\r\n }\r\n\r\n onSkipCreatePass(): void {\r\n this.variablesService.appPass = '';\r\n this.ngZone.run(() => {\r\n this.variablesService.appLogin = true;\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n\r\n dropSecureAppData(): void {\r\n this.backend.dropSecureAppData(() => {\r\n this.onSkipCreatePass();\r\n });\r\n this.variablesService.wallets = [];\r\n this.variablesService.contacts = [];\r\n }\r\n\r\n onSubmitAuthPass(): void {\r\n if (this.authForm.valid) {\r\n this.variablesService.appPass = this.authForm.get('password').value;\r\n\r\n if (this.variablesService.dataIsLoaded) {\r\n this.backend.checkMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.variablesService.appLogin = true;\r\n this.variablesService.startCountdown();\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n });\r\n } else {\r\n this.getData(this.variablesService.appPass);\r\n }\r\n }\r\n }\r\n\r\n getData(appPass) {\r\n this.backend.getSecureAppData({pass: appPass}, (status, data) => {\r\n if (!data.error_code) {\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n this.variablesService.appPass = appPass;\r\n const isEmptyObject = Object.keys(data).length === 0 && data.constructor === Object;\r\n\r\n if (this.variablesService.wallets.length) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.variablesService.wallets[0].wallet_id]);\r\n });\r\n return;\r\n }\r\n if (data.hasOwnProperty('contacts')) {\r\n if (Object.keys(data['contacts']).length !== 0) {\r\n data['contacts'].map(contact => {\r\n this.variablesService.contacts.push(contact);\r\n });\r\n }\r\n }\r\n if (data.hasOwnProperty('wallets')) {\r\n if (Object.keys(data['wallets']).length !== 0) {\r\n this.getWalletData(data['wallets']);\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n if (!data.hasOwnProperty('wallets') && !data.hasOwnProperty('contacts')) {\r\n if (data.length !== 0 && !isEmptyObject) {\r\n this.getWalletData(data);\r\n } else {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n getWalletData(walletData) {\r\n let openWallets = 0;\r\n let runWallets = 0;\r\n walletData.forEach((wallet, wallet_index) => {\r\n this.backend.openWallet(wallet.path, wallet.pass, true, (open_status, open_data, open_error) => {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n openWallets++;\r\n this.ngZone.run(() => {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n wallet.name,\r\n wallet.pass,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (wallet.staking) {\r\n new_wallet.staking = true;\r\n this.backend.startPosMining(new_wallet.wallet_id);\r\n } else {\r\n new_wallet.staking = false;\r\n }\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n if (this.variablesService.wallets.length === 1) {\r\n this.router.navigate(['/wallet/' + this.variablesService.wallets[0].wallet_id]);\r\n }\r\n });\r\n this.backend.runWallet(open_data.wallet_id, (run_status) => {\r\n if (run_status) {\r\n runWallets++;\r\n } else {\r\n if (wallet_index === walletData.length - 1 && runWallets === 0) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n });\r\n } else {\r\n if (wallet_index === walletData.length - 1 && openWallets === 0) {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
0\\\">\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n

{{ 'MAIN.TITLE' | translate }}

\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'MAIN.HELP' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n flex: 1 0 auto;\\n padding: 3rem; }\\n\\n.content {\\n padding: 3rem;\\n min-height: 100%; }\\n\\n.content .head {\\n justify-content: flex-end; }\\n\\n.add-wallet .add-wallet-title {\\n margin-bottom: 1rem; }\\n\\n.add-wallet .add-wallet-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 0 -0.5rem;\\n padding: 1.5rem 0; }\\n\\n.add-wallet .add-wallet-buttons button {\\n flex: 1 0 auto;\\n margin: 0 0.5rem; }\\n\\n.add-wallet .add-wallet-help {\\n display: flex;\\n cursor: pointer;\\n font-size: 1.3rem;\\n line-height: 1.5rem; }\\n\\n.add-wallet .add-wallet-help .icon {\\n -webkit-mask: url('howto.svg') no-repeat center;\\n mask: url('howto.svg') no-repeat center;\\n margin-right: 0.8rem;\\n width: 1.5rem;\\n height: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbWFpbi9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcbWFpblxcbWFpbi5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGNBQWM7RUFDZCxhQUFhLEVBQUE7O0FBR2Y7RUFDRSxhQUFhO0VBQ2IsZ0JBQWdCLEVBQUE7O0FBRmxCO0lBS0kseUJBQXlCLEVBQUE7O0FBSTdCO0VBR0ksbUJBQW1CLEVBQUE7O0FBSHZCO0VBT0ksYUFBYTtFQUNiLG1CQUFtQjtFQUNuQiw4QkFBOEI7RUFDOUIsaUJBQWlCO0VBQ2pCLGlCQUFpQixFQUFBOztBQVhyQjtJQWNNLGNBQWM7SUFDZCxnQkFBZ0IsRUFBQTs7QUFmdEI7RUFvQkksYUFBYTtFQUNiLGVBQWU7RUFDZixpQkFBaUI7RUFDakIsbUJBQW1CLEVBQUE7O0FBdkJ2QjtJQTBCTSwrQ0FBd0Q7WUFBeEQsdUNBQXdEO0lBQ3hELG9CQUFvQjtJQUNwQixhQUFhO0lBQ2IsY0FBYyxFQUFBIiwiZmlsZSI6InNyYy9hcHAvbWFpbi9tYWluLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGZsZXg6IDEgMCBhdXRvO1xyXG4gIHBhZGRpbmc6IDNyZW07XHJcbn1cclxuXHJcbi5jb250ZW50IHtcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi1oZWlnaHQ6IDEwMCU7XHJcblxyXG4gIC5oZWFkIHtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XHJcbiAgfVxyXG59XHJcblxyXG4uYWRkLXdhbGxldCB7XHJcblxyXG4gIC5hZGQtd2FsbGV0LXRpdGxlIHtcclxuICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgfVxyXG5cclxuICAuYWRkLXdhbGxldC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgbWFyZ2luOiAwIC0wLjVyZW07XHJcbiAgICBwYWRkaW5nOiAxLjVyZW0gMDtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBmbGV4OiAxIDAgYXV0bztcclxuICAgICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5hZGQtd2FsbGV0LWhlbHAge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuNXJlbTtcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvaG93dG8uc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDAuOHJlbTtcclxuICAgICAgd2lkdGg6IDEuNXJlbTtcclxuICAgICAgaGVpZ2h0OiAxLjVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Router} from '@angular/router';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-main',\r\n templateUrl: './main.component.html',\r\n styleUrls: ['./main.component.scss']\r\n})\r\nexport class MainComponent implements OnInit {\r\n\r\n constructor(\r\n private router: Router,\r\n private location: Location,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n openWallet() {\r\n this.backend.openFileDialog(this.translate.instant('MAIN.CHOOSE_PATH'), '*', this.variablesService.settings.default_path, (file_status, file_data) => {\r\n if (file_status) {\r\n this.variablesService.settings.default_path = file_data.path.substr(0, file_data.path.lastIndexOf('/'));\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/open'], {queryParams: {path: file_data.path}});\r\n });\r\n } else {\r\n console.log(file_data['error_code']);\r\n }\r\n });\r\n }\r\n\r\n openInBrowser() {\r\n this.backend.openUrlInBrowser('docs.zano.org/docs/getting-started-1#section-create-new-wallet');\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
{{ 'MESSAGES.ADDRESS' | translate }}{{ 'MESSAGES.MESSAGE' | translate }}
\\r\\n {{message.address}}\\r\\n \\r\\n \\r\\n {{message.message}}\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-table {\\n margin: -3rem; }\\n\\n.wrap-table table tbody tr td:first-child {\\n position: relative;\\n padding-right: 5rem;\\n width: 18rem; }\\n\\n.wrap-table table tbody tr td:first-child span {\\n display: block;\\n line-height: 3.5rem;\\n max-width: 10rem; }\\n\\n.wrap-table table tbody tr td:first-child .icon {\\n position: absolute;\\n top: 50%;\\n right: 1rem;\\n transform: translateY(-50%);\\n display: block;\\n -webkit-mask: url('alert.svg') no-repeat 0;\\n mask: url('alert.svg') no-repeat 0;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvbWVzc2FnZXMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXG1lc3NhZ2VzXFxtZXNzYWdlcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUNFLGFBQWEsRUFBQTs7QUFEZjtJQVlZLGtCQUFrQjtJQUNsQixtQkFBbUI7SUFDbkIsWUFBWSxFQUFBOztBQWR4QjtNQWlCYyxjQUFjO01BQ2QsbUJBQW1CO01BQ25CLGdCQUFnQixFQUFBOztBQW5COUI7TUF1QmMsa0JBQWtCO01BQ2xCLFFBQVE7TUFDUixXQUFXO01BQ1gsMkJBQTJCO01BQzNCLGNBQWM7TUFDZCwwQ0FBbUQ7Y0FBbkQsa0NBQW1EO01BQ25ELGFBQWE7TUFDYixjQUFjLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9tZXNzYWdlcy9tZXNzYWdlcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLndyYXAtdGFibGUge1xyXG4gIG1hcmdpbjogLTNyZW07XHJcblxyXG4gIHRhYmxlIHtcclxuXHJcbiAgICB0Ym9keSB7XHJcblxyXG4gICAgICB0ciB7XHJcblxyXG4gICAgICAgIHRkIHtcclxuXHJcbiAgICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiA1cmVtO1xyXG4gICAgICAgICAgICB3aWR0aDogMThyZW07XHJcblxyXG4gICAgICAgICAgICBzcGFuIHtcclxuICAgICAgICAgICAgICBkaXNwbGF5OiBibG9jaztcclxuICAgICAgICAgICAgICBsaW5lLWhlaWdodDogMy41cmVtO1xyXG4gICAgICAgICAgICAgIG1heC13aWR0aDogMTByZW07XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5pY29uIHtcclxuICAgICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgICAgICAgdG9wOiA1MCU7XHJcbiAgICAgICAgICAgICAgcmlnaHQ6IDFyZW07XHJcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpO1xyXG4gICAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvYWxlcnQuc3ZnKSBuby1yZXBlYXQgMDtcclxuICAgICAgICAgICAgICB3aWR0aDogMS4ycmVtO1xyXG4gICAgICAgICAgICAgIGhlaWdodDogMS4ycmVtO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import { Component, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'app-messages',\r\n templateUrl: './messages.component.html',\r\n styleUrls: ['./messages.component.scss']\r\n})\r\nexport class MessagesComponent implements OnInit {\r\n\r\n messages = [\r\n {\r\n is_new: true,\r\n address: '@bitmap',\r\n message: 'No more miners for you!'\r\n },\r\n {\r\n is_new: false,\r\n address: 'Hjkwey36gHasdhkajshd4bxnb5mcvowyefb2633FdsFGGWbb',\r\n message: 'Hey! What’s with our BBR deal?'\r\n },\r\n {\r\n is_new: false,\r\n address: '@john',\r\n message: 'I’m coming!'\r\n }\r\n ];\r\n\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n\r\n}\r\n","module.exports = \"
\\r\\n

{{ 'OPEN_WALLET.MODAL.TITLE' | translate }}

\\r\\n
\\r\\n
{{ wallet.name }}
\\r\\n
{{ wallet.path }}
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.MODAL.NOT_FOUND' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 2rem;\\n min-width: 34rem;\\n max-width: 64rem; }\\n\\n.modal .title {\\n font-size: 1.8rem;\\n text-align: center; }\\n\\n.modal .open-form .wallet-path {\\n font-size: 1.3rem;\\n margin: 5rem 0 2rem;\\n word-wrap: break-word;\\n line-height: 2rem; }\\n\\n.modal .open-form .wrap-button {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin: 2rem -2rem 0; }\\n\\n.modal .open-form .wrap-button button {\\n flex: 1 0 0;\\n margin: 0 2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQtbW9kYWwvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXG9wZW4td2FsbGV0LW1vZGFsXFxvcGVuLXdhbGxldC1tb2RhbC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBR3ZDO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0QiwyQkFBMkI7RUFDM0IscUJBQXFCO0VBQ3JCLGFBQWE7RUFDYixnQkFBZ0I7RUFDaEIsZ0JBQWdCLEVBQUE7O0FBUGxCO0lBVUksaUJBQWlCO0lBQ2pCLGtCQUFrQixFQUFBOztBQVh0QjtJQWlCTSxpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLHFCQUFxQjtJQUNyQixpQkFBaUIsRUFBQTs7QUFwQnZCO0lBd0JNLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCO0lBQzlCLG9CQUFvQixFQUFBOztBQTNCMUI7TUE4QlEsV0FBVztNQUNYLGNBQWUsRUFBQSIsImZpbGUiOiJzcmMvYXBwL29wZW4td2FsbGV0LW1vZGFsL29wZW4td2FsbGV0LW1vZGFsLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuXHJcbi5tb2RhbCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogMnJlbTtcclxuICBtaW4td2lkdGg6IDM0cmVtO1xyXG4gIG1heC13aWR0aDogNjRyZW07XHJcblxyXG4gIC50aXRsZSB7XHJcbiAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcclxuICB9XHJcblxyXG4gIC5vcGVuLWZvcm0ge1xyXG5cclxuICAgIC53YWxsZXQtcGF0aCB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICBtYXJnaW46IDVyZW0gMCAycmVtO1xyXG4gICAgICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC53cmFwLWJ1dHRvbiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgICAgbWFyZ2luOiAycmVtIC0ycmVtIDA7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDEgMCAwO1xyXG4gICAgICAgIG1hcmdpbjogMCAycmVtIDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, Input, NgZone} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-open-wallet-modal',\r\n templateUrl: './open-wallet-modal.component.html',\r\n styleUrls: ['./open-wallet-modal.component.scss']\r\n})\r\nexport class OpenWalletModalComponent implements OnInit {\r\n\r\n @Input() wallets;\r\n\r\n wallet = {\r\n name: '',\r\n path: '',\r\n pass: '',\r\n notFound: false,\r\n emptyPass: false\r\n };\r\n\r\n constructor(\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private translate: TranslateService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n if (this.wallets.length) {\r\n this.wallet = this.wallets[0];\r\n this.wallet.pass = '';\r\n\r\n this.backend.openWallet(this.wallet.path, '', true, (status, data, error) => {\r\n if (error === 'FILE_NOT_FOUND') {\r\n this.wallet.notFound = true;\r\n }\r\n if (status) {\r\n this.wallet.pass = '';\r\n this.wallet.emptyPass = true;\r\n this.backend.closeWallet(data.wallet_id);\r\n this.openWallet();\r\n }\r\n });\r\n }\r\n }\r\n\r\n openWallet() {\r\n if (this.wallets.length === 0) {\r\n return;\r\n }\r\n this.backend.openWallet(this.wallet.path, this.wallet.pass, false, (open_status, open_data, open_error) => {\r\n if (open_error && open_error === 'FILE_NOT_FOUND') {\r\n let error_translate = this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND1');\r\n error_translate += ':
' + this.wallet.path;\r\n error_translate += this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND2');\r\n this.modalService.prepareModal('error', error_translate);\r\n } else {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === open_data['wi'].address) {\r\n exists = true;\r\n }\r\n });\r\n\r\n if (exists) {\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(open_data.wallet_id);\r\n } else {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n this.wallet.name,\r\n this.wallet.pass,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(\r\n contracts_data.contracts,\r\n this.variablesService.exp_med_ts,\r\n this.variablesService.height_app,\r\n this.variablesService.settings.viewedContracts,\r\n this.variablesService.settings.notViewedContracts\r\n );\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n this.backend.runWallet(open_data.wallet_id);\r\n this.skipWallet();\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n skipWallet() {\r\n if (this.wallets.length) {\r\n this.wallets.splice(0, 1);\r\n this.ngOnInit();\r\n }\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.OPEN_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'OPEN_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\"","module.exports = \".form-open {\\n margin: 2.4rem 0;\\n width: 50%; }\\n .form-open .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem; }\\n .form-open .wrap-buttons button {\\n margin: 0 0.7rem; }\\n .form-open .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvb3Blbi13YWxsZXQvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXG9wZW4td2FsbGV0XFxvcGVuLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7RUFGWjtJQUtJLGFBQWE7SUFDYixzQkFBc0IsRUFBQTtFQU4xQjtNQVNNLGdCQUFnQixFQUFBO0VBVHRCO1FBWVEsYUFBYSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvb3Blbi13YWxsZXQvb3Blbi13YWxsZXQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1vcGVuIHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgbWFyZ2luOiAwIDAuN3JlbTtcclxuXHJcbiAgICAgICYuY3JlYXRlLWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMSAxIDUwJTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-open-wallet',\r\n templateUrl: './open-wallet.component.html',\r\n styleUrls: ['./open-wallet.component.scss']\r\n})\r\nexport class OpenWalletComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n filePath: string;\r\n\r\n openForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n password: new FormControl('')\r\n });\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.path) {\r\n this.filePath = params.path;\r\n let filename = '';\r\n if (params.path.lastIndexOf('.') === -1) {\r\n filename = params.path.substr(params.path.lastIndexOf('/') + 1);\r\n } else {\r\n filename = params.path.substr(params.path.lastIndexOf('/') + 1, params.path.lastIndexOf('.') - 1 - params.path.lastIndexOf('/'));\r\n }\r\n if (filename.length > 25) {\r\n filename = filename.slice(0, 25);\r\n }\r\n this.openForm.get('name').setValue(filename);\r\n this.openForm.get('name').markAsTouched();\r\n }\r\n });\r\n }\r\n\r\n openWallet() {\r\n if (this.openForm.valid && this.openForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.openWallet(this.filePath, this.openForm.get('password').value, false, (open_status, open_data, open_error) => {\r\n if (open_error && open_error === 'FILE_NOT_FOUND') {\r\n let error_translate = this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND1');\r\n error_translate += ':
' + this.filePath;\r\n error_translate += this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND2');\r\n this.modalService.prepareModal('error', error_translate);\r\n } else {\r\n if (open_status || open_error === 'FILE_RESTORED') {\r\n\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === open_data['wi'].address) {\r\n exists = true;\r\n }\r\n });\r\n\r\n if (exists) {\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(open_data.wallet_id, () => {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n });\r\n } else {\r\n const new_wallet = new Wallet(\r\n open_data.wallet_id,\r\n this.openForm.get('name').value,\r\n this.openForm.get('password').value,\r\n open_data['wi'].path,\r\n open_data['wi'].address,\r\n open_data['wi'].balance,\r\n open_data['wi'].unlocked_balance,\r\n open_data['wi'].mined_total,\r\n open_data['wi'].tracking_hey\r\n );\r\n new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);\r\n if (open_data.recent_history && open_data.recent_history.history) {\r\n new_wallet.prepareHistory(open_data.recent_history.history);\r\n }\r\n this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n new_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.variablesService.wallets.push(new_wallet);\r\n this.backend.runWallet(open_data.wallet_id, (run_status, run_data) => {\r\n if (run_status) {\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + open_data.wallet_id]);\r\n });\r\n } else {\r\n console.log(run_data['error_code']);\r\n }\r\n });\r\n }\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'BREADCRUMBS.CONTRACTS' | translate }}\\r\\n {{ 'BREADCRUMBS.NEW_PURCHASE' | translate }}\\r\\n {{ 'BREADCRUMBS.OLD_PURCHASE' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.DESC_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
= 100\\\">\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.COMMENT_MAXIMUM' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
{{item.name}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_SAME' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.ALIAS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.AMOUNT_ZERO' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.YOUR_DEPOSIT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.SELLER_DEPOSIT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= 100\\\">\\r\\n
\\r\\n {{ 'PURCHASE.FORM_ERRORS.COMMENT_MAXIMUM' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n 1 {{ 'PURCHASE.HOUR' | translate }}\\r\\n \\r\\n {{title}} {{ 'PURCHASE.HOURS' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n {{ 'PURCHASE.NEED_MONEY' | translate }}\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n
{{'PURCHASE.NULLIFY_QUESTION' | translate}}
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
{{ 'PURCHASE.WAITING_TIME_QUESTION' | translate }}
\\r\\n \\r\\n
\\r\\n \\r\\n 1 {{ 'PURCHASE.HOUR' | translate }}\\r\\n \\r\\n {{title}} {{ 'PURCHASE.HOURS' | translate }}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NEW_PURCHASE' | translate }}\\r\\n \\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_DELIVERY' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_CANCEL_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.EXPIRED' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_SELLER' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_CONFIRMATION' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.COMPLETED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NOT_RECEIVED' | translate }}. {{ 'PURCHASE.STATUS_MESSAGES.NULLIFIED' | translate }}\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.PROPOSAL_CANCEL_SELLER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.CANCELLED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.BEING_CANCELLED' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.IGNORED_CANCEL_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.EXPIRED' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_DELIVERY' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.WAITING_CONFIRMATION' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.COMPLETED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.NOT_RECEIVED' | translate }}. {{ 'PURCHASE.STATUS_MESSAGES.NULLIFIED' | translate }}\\r\\n \\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.PROPOSAL_CANCEL_BUYER' | translate }}\\r\\n\\r\\n {{ 'PURCHASE.STATUS_MESSAGES.CANCELLED' | translate }}\\r\\n\\r\\n \\r\\n {{ 'PURCHASE.STATUS_MESSAGES.BEING_CANCELLED' | translate }}\\r\\n (0/10)\\r\\n ({{variablesService.height_app - currentContract.height}}/10)\\r\\n \\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n {{currentContract.expiration_time | contractTimeLeft: 0}}\\r\\n {{currentContract.cancel_expiration_time | contractTimeLeft: 2}}\\r\\n {{currentContract.expiration_time | contractTimeLeft: 1}}\\r\\n {{currentContract.cancel_expiration_time | contractTimeLeft: 1}}\\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.head {\\n flex: 0 0 auto;\\n box-sizing: content-box;\\n margin: -3rem -3rem 0; }\\n\\n.form-purchase {\\n flex: 1 1 auto;\\n margin: 1.5rem -3rem 0;\\n padding: 0 3rem;\\n overflow-y: overlay; }\\n\\n.form-purchase .input-blocks-row {\\n display: flex; }\\n\\n.form-purchase .input-blocks-row .input-block {\\n flex-basis: 50%; }\\n\\n.form-purchase .input-blocks-row .input-block:first-child {\\n margin-right: 1.5rem; }\\n\\n.form-purchase .input-blocks-row .input-block:last-child {\\n margin-left: 1.5rem; }\\n\\n.form-purchase .input-blocks-row .input-block .checkbox-block {\\n display: flex; }\\n\\n.form-purchase .purchase-select {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n line-height: 1.3rem;\\n margin: 1.5rem 0 0;\\n padding: 0;\\n width: 100%;\\n max-width: 15rem;\\n height: 1.3rem; }\\n\\n.form-purchase .purchase-select .arrow {\\n margin-left: 1rem;\\n width: 0.8rem;\\n height: 0.8rem; }\\n\\n.form-purchase .purchase-select .arrow.down {\\n -webkit-mask: url('arrow-down.svg') no-repeat center;\\n mask: url('arrow-down.svg') no-repeat center; }\\n\\n.form-purchase .purchase-select .arrow.up {\\n -webkit-mask: url('arrow-up.svg') no-repeat center;\\n mask: url('arrow-up.svg') no-repeat center; }\\n\\n.form-purchase .additional-details {\\n display: flex;\\n margin-top: 1.5rem;\\n padding: 0.5rem 0 2rem; }\\n\\n.form-purchase .additional-details > div {\\n flex-basis: 25%; }\\n\\n.form-purchase .additional-details > div:first-child {\\n padding-left: 1.5rem;\\n padding-right: 1rem; }\\n\\n.form-purchase .additional-details > div:last-child {\\n padding-left: 1rem;\\n padding-right: 1.5rem; }\\n\\n.form-purchase .purchase-states {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n font-size: 1.2rem;\\n line-height: 2.9rem; }\\n\\n.form-purchase .send-button {\\n margin: 2.4rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n.form-purchase .purchase-buttons {\\n display: flex;\\n justify-content: flex-start;\\n margin: 2.4rem -0.5rem; }\\n\\n.form-purchase .purchase-buttons button {\\n flex: 0 1 33%;\\n margin: 0 0.5rem; }\\n\\n.form-purchase .nullify-block-row {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center; }\\n\\n.form-purchase .nullify-block-row .nullify-block-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n margin: 1rem 0;\\n width: 100%; }\\n\\n.form-purchase .nullify-block-row .nullify-block-buttons button {\\n flex: 0 1 25%;\\n margin: 0 0.5rem; }\\n\\n.form-purchase .time-cancel-block-row {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-question {\\n margin-bottom: 1rem; }\\n\\n.form-purchase .time-cancel-block-row .input-block {\\n width: 25%; }\\n\\n.form-purchase .time-cancel-block-row label {\\n margin-bottom: 1rem; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n margin: 1rem 0;\\n width: 100%; }\\n\\n.form-purchase .time-cancel-block-row .time-cancel-block-buttons button {\\n flex: 0 1 25%;\\n margin: 0 0.5rem; }\\n\\n.progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n padding: 0 3rem;\\n width: 100%;\\n height: 3rem; }\\n\\n.progress-bar-container .progress-bar {\\n position: absolute;\\n top: -0.7rem;\\n left: 0;\\n margin: 0 3rem;\\n width: calc(100% - 6rem);\\n height: 0.7rem; }\\n\\n.progress-bar-container .progress-bar .progress-bar-full {\\n height: 0.7rem; }\\n\\n.progress-bar-container .progress-labels {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n font-size: 1.2rem;\\n height: 100%; }\\n\\n.progress-bar-container .progress-time {\\n position: absolute;\\n top: -3rem;\\n left: 50%;\\n transform: translateX(-50%);\\n font-size: 1.2rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcHVyY2hhc2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHB1cmNoYXNlXFxwdXJjaGFzZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsY0FBYztFQUNkLHVCQUF1QjtFQUN2QixxQkFBcUIsRUFBQTs7QUFHdkI7RUFDRSxjQUFjO0VBQ2Qsc0JBQXNCO0VBQ3RCLGVBQWU7RUFDZixtQkFBbUIsRUFBQTs7QUFKckI7SUFPSSxhQUFhLEVBQUE7O0FBUGpCO01BVU0sZUFBZSxFQUFBOztBQVZyQjtRQWFRLG9CQUFvQixFQUFBOztBQWI1QjtRQWlCUSxtQkFBbUIsRUFBQTs7QUFqQjNCO1FBcUJRLGFBQWEsRUFBQTs7QUFyQnJCO0lBMkJJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCO0lBQ3ZCLFlBQVk7SUFDWixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLGtCQUFrQjtJQUNsQixVQUFVO0lBQ1YsV0FBVztJQUNYLGdCQUFnQjtJQUNoQixjQUFjLEVBQUE7O0FBckNsQjtNQXdDTSxpQkFBaUI7TUFDakIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUExQ3BCO1FBNkNRLG9EQUE0RDtnQkFBNUQsNENBQTRELEVBQUE7O0FBN0NwRTtRQWlEUSxrREFBMEQ7Z0JBQTFELDBDQUEwRCxFQUFBOztBQWpEbEU7SUF1REksYUFBYTtJQUNiLGtCQUFrQjtJQUNsQixzQkFBc0IsRUFBQTs7QUF6RDFCO01BNERNLGVBQWUsRUFBQTs7QUE1RHJCO1FBK0RRLG9CQUFvQjtRQUNwQixtQkFBbUIsRUFBQTs7QUFoRTNCO1FBb0VRLGtCQUFrQjtRQUNsQixxQkFBcUIsRUFBQTs7QUFyRTdCO0lBMkVJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixpQkFBaUI7SUFDakIsbUJBQW1CLEVBQUE7O0FBaEZ2QjtJQW9GSSxnQkFBZ0I7SUFDaEIsV0FBVztJQUNYLGdCQUFnQixFQUFBOztBQXRGcEI7SUEwRkksYUFBYTtJQUNiLDJCQUEyQjtJQUMzQixzQkFBc0IsRUFBQTs7QUE1RjFCO01BK0ZNLGFBQWE7TUFDYixnQkFBZ0IsRUFBQTs7QUFoR3RCO0lBcUdJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QixFQUFBOztBQXhHM0I7TUEyR00sYUFBYTtNQUNiLG1CQUFtQjtNQUNuQix1QkFBdUI7TUFDdkIsY0FBYztNQUNkLFdBQVcsRUFBQTs7QUEvR2pCO1FBa0hRLGFBQWE7UUFDYixnQkFBZ0IsRUFBQTs7QUFuSHhCO0lBeUhJLGFBQWE7SUFDYixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHVCQUF1QixFQUFBOztBQTVIM0I7TUErSE0sbUJBQW1CLEVBQUE7O0FBL0h6QjtNQW1JTSxVQUFVLEVBQUE7O0FBbkloQjtNQXVJTSxtQkFBbUIsRUFBQTs7QUF2SXpCO01BMklNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGNBQWM7TUFDZCxXQUFXLEVBQUE7O0FBL0lqQjtRQWtKUSxhQUFhO1FBQ2IsZ0JBQWdCLEVBQUE7O0FBT3hCO0VBQ0Usa0JBQWtCO0VBQ2xCLFNBQVM7RUFDVCxPQUFPO0VBQ1AsZUFBZTtFQUNmLFdBQVc7RUFDWCxZQUFZLEVBQUE7O0FBTmQ7SUFTSSxrQkFBa0I7SUFDbEIsWUFBWTtJQUNaLE9BQU87SUFDUCxjQUFjO0lBQ2Qsd0JBQXdCO0lBQ3hCLGNBQWMsRUFBQTs7QUFkbEI7TUFpQk0sY0FBYyxFQUFBOztBQWpCcEI7SUFzQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsaUJBQWlCO0lBQ2pCLFlBQVksRUFBQTs7QUExQmhCO0lBOEJJLGtCQUFrQjtJQUNsQixVQUFVO0lBQ1YsU0FBUztJQUNULDJCQUEyQjtJQUMzQixpQkFBaUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3B1cmNoYXNlL3B1cmNoYXNlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmhlYWQge1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xyXG4gIG1hcmdpbjogLTNyZW0gLTNyZW0gMDtcclxufVxyXG5cclxuLmZvcm0tcHVyY2hhc2Uge1xyXG4gIGZsZXg6IDEgMSBhdXRvO1xyXG4gIG1hcmdpbjogMS41cmVtIC0zcmVtIDA7XHJcbiAgcGFkZGluZzogMCAzcmVtO1xyXG4gIG92ZXJmbG93LXk6IG92ZXJsYXk7XHJcblxyXG4gIC5pbnB1dC1ibG9ja3Mtcm93IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgZmxleC1iYXNpczogNTAlO1xyXG5cclxuICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmNoZWNrYm94LWJsb2NrIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHVyY2hhc2Utc2VsZWN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBtYXJnaW46IDEuNXJlbSAwIDA7XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgaGVpZ2h0OiAxLjNyZW07XHJcblxyXG4gICAgLmFycm93IHtcclxuICAgICAgbWFyZ2luLWxlZnQ6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAwLjhyZW07XHJcbiAgICAgIGhlaWdodDogMC44cmVtO1xyXG5cclxuICAgICAgJi5kb3duIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctZG93bi5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYudXAge1xyXG4gICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy11cC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbi10b3A6IDEuNXJlbTtcclxuICAgIHBhZGRpbmc6IDAuNXJlbSAwIDJyZW07XHJcblxyXG4gICAgPiBkaXYge1xyXG4gICAgICBmbGV4LWJhc2lzOiAyNSU7XHJcblxyXG4gICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLWxlZnQ6IDEuNXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxcmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIHBhZGRpbmctbGVmdDogMXJlbTtcclxuICAgICAgICBwYWRkaW5nLXJpZ2h0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1zdGF0ZXMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuMnJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjlyZW07XHJcbiAgfVxyXG5cclxuICAuc2VuZC1idXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICB9XHJcblxyXG4gIC5wdXJjaGFzZS1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGZsZXgtc3RhcnQ7XHJcbiAgICBtYXJnaW46IDIuNHJlbSAtMC41cmVtO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGZsZXg6IDAgMSAzMyU7XHJcbiAgICAgIG1hcmdpbjogMCAwLjVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAubnVsbGlmeS1ibG9jay1yb3cge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgLm51bGxpZnktYmxvY2stYnV0dG9ucyB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBtYXJnaW46IDFyZW0gMDtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG4gICAgICAgIGZsZXg6IDAgMSAyNSU7XHJcbiAgICAgICAgbWFyZ2luOiAwIDAuNXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRpbWUtY2FuY2VsLWJsb2NrLXJvdyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuXHJcbiAgICAudGltZS1jYW5jZWwtYmxvY2stcXVlc3Rpb24ge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC5pbnB1dC1ibG9jayB7XHJcbiAgICAgIHdpZHRoOiAyNSU7XHJcbiAgICB9XHJcblxyXG4gICAgbGFiZWwge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC50aW1lLWNhbmNlbC1ibG9jay1idXR0b25zIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMXJlbSAwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgIGJ1dHRvbiB7XHJcbiAgICAgICAgZmxleDogMCAxIDI1JTtcclxuICAgICAgICBtYXJnaW46IDAgMC41cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuLnByb2dyZXNzLWJhci1jb250YWluZXIge1xyXG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICBib3R0b206IDA7XHJcbiAgbGVmdDogMDtcclxuICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgd2lkdGg6IDEwMCU7XHJcbiAgaGVpZ2h0OiAzcmVtO1xyXG5cclxuICAucHJvZ3Jlc3MtYmFyIHtcclxuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgIHRvcDogLTAuN3JlbTtcclxuICAgIGxlZnQ6IDA7XHJcbiAgICBtYXJnaW46IDAgM3JlbTtcclxuICAgIHdpZHRoOiBjYWxjKDEwMCUgLSA2cmVtKTtcclxuICAgIGhlaWdodDogMC43cmVtO1xyXG5cclxuICAgIC5wcm9ncmVzcy1iYXItZnVsbCB7XHJcbiAgICAgIGhlaWdodDogMC43cmVtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnByb2dyZXNzLWxhYmVscyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtdGltZSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IC0zcmVtO1xyXG4gICAgbGVmdDogNTAlO1xyXG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xyXG4gICAgZm9udC1zaXplOiAxLjJyZW07XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, OnInit, OnDestroy, NgZone, HostListener} from '@angular/core';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {FormControl, FormGroup, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Location} from '@angular/common';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-purchase',\r\n templateUrl: './purchase.component.html',\r\n styleUrls: ['./purchase.component.scss']\r\n})\r\nexport class PurchaseComponent implements OnInit, OnDestroy {\r\n\r\n isOpen = false;\r\n localAliases = [];\r\n\r\n currentWalletId;\r\n newPurchase = false;\r\n parentRouting;\r\n subRouting;\r\n historyBlock;\r\n\r\n purchaseForm = new FormGroup({\r\n description: new FormControl('', Validators.required),\r\n seller: new FormControl('', [Validators.required, (g: FormControl) => {\r\n if (g.value === this.variablesService.currentWallet.address) {\r\n return {'address_same': true};\r\n }\r\n return null;\r\n }, (g: FormControl) => {\r\n this.localAliases = [];\r\n if (g.value) {\r\n if (g.value.indexOf('@') !== 0) {\r\n this.isOpen = false;\r\n this.backend.validateAddress(g.value, (valid_status) => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(Object.assign({'address_not_valid': true}, g.errors));\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return (g.hasError('address_not_valid')) ? {'address_not_valid': true} : null;\r\n } else {\r\n this.isOpen = true;\r\n this.localAliases = this.variablesService.aliases.filter((item) => {\r\n return item.name.indexOf(g.value) > -1;\r\n });\r\n if (!(/^@?[a-z0-9\\.\\-]{6,25}$/.test(g.value))) {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n } else {\r\n this.backend.getAliasByName(g.value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status) {\r\n if (alias_data.address === this.variablesService.currentWallet.address) {\r\n g.setErrors(Object.assign({'address_same': true}, g.errors));\r\n }\r\n if (g.hasError('alias_not_valid')) {\r\n delete g.errors['alias_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n } else {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n }\r\n });\r\n });\r\n }\r\n return (g.hasError('alias_not_valid')) ? {'alias_not_valid': true} : null;\r\n }\r\n }\r\n return null;\r\n }]),\r\n amount: new FormControl(null, [Validators.required, (g: FormControl) => {\r\n if (parseFloat(g.value) === 0) {\r\n return {'amount_zero': true};\r\n }\r\n return null;\r\n }]),\r\n yourDeposit: new FormControl(null, Validators.required),\r\n sellerDeposit: new FormControl(null, Validators.required),\r\n sameAmount: new FormControl({value: false, disabled: false}),\r\n comment: new FormControl(''),\r\n fee: new FormControl(this.variablesService.default_fee),\r\n time: new FormControl({value: 12, disabled: false}),\r\n timeCancel: new FormControl({value: 12, disabled: false}),\r\n payment: new FormControl('')\r\n });\r\n\r\n additionalOptions = false;\r\n currentContract = null;\r\n heightAppEvent;\r\n showTimeSelect = false;\r\n showNullify = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private location: Location,\r\n private intToMoneyPipe: IntToMoneyPipe\r\n ) {\r\n }\r\n\r\n checkAndChangeHistory() {\r\n if (this.currentContract.state === 201) {\r\n this.historyBlock = this.variablesService.currentWallet.history.find(item => item.tx_type === 8 && item.contract[0].contract_id === this.currentContract.contract_id && item.contract[0].is_a === this.currentContract.is_a);\r\n } else if (this.currentContract.state === 601) {\r\n this.historyBlock = this.variablesService.currentWallet.history.find(item => item.tx_type === 12 && item.contract[0].contract_id === this.currentContract.contract_id && item.contract[0].is_a === this.currentContract.is_a);\r\n }\r\n }\r\n\r\n addressMouseDown(e) {\r\n if (e['button'] === 0 && this.purchaseForm.get('seller').value && this.purchaseForm.get('seller').value.indexOf('@') === 0) {\r\n this.isOpen = true;\r\n }\r\n }\r\n\r\n setAlias(alias) {\r\n this.purchaseForm.get('seller').setValue(alias);\r\n }\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement) {\r\n if (targetElement.id !== 'purchase-seller' && this.isOpen) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n this.currentWalletId = params['id'];\r\n });\r\n this.subRouting = this.route.params.subscribe(params => {\r\n if (params.hasOwnProperty('id')) {\r\n this.currentContract = this.variablesService.currentWallet.getContract(params['id']);\r\n this.purchaseForm.controls['seller'].setValidators([]);\r\n this.purchaseForm.updateValueAndValidity();\r\n this.purchaseForm.setValue({\r\n description: this.currentContract.private_detailes.t,\r\n seller: this.currentContract.private_detailes.b_addr,\r\n amount: this.intToMoneyPipe.transform(this.currentContract.private_detailes.to_pay),\r\n yourDeposit: this.intToMoneyPipe.transform(this.currentContract.private_detailes.a_pledge),\r\n sellerDeposit: this.intToMoneyPipe.transform(this.currentContract.private_detailes.b_pledge),\r\n sameAmount: this.currentContract.private_detailes.to_pay.isEqualTo(this.currentContract.private_detailes.b_pledge),\r\n comment: this.currentContract.private_detailes.c,\r\n fee: this.variablesService.default_fee,\r\n time: 12,\r\n timeCancel: 12,\r\n payment: this.currentContract.payment_id\r\n });\r\n this.purchaseForm.get('sameAmount').disable();\r\n this.newPurchase = false;\r\n\r\n if (this.currentContract.is_new) {\r\n if (this.currentContract.is_a && this.currentContract.state === 2) {\r\n this.currentContract.state = 120;\r\n }\r\n if (this.currentContract.state === 130 && this.currentContract.cancel_expiration_time !== 0 && this.currentContract.cancel_expiration_time < this.variablesService.exp_med_ts) {\r\n this.currentContract.state = 2;\r\n }\r\n this.variablesService.settings.viewedContracts = (this.variablesService.settings.viewedContracts) ? this.variablesService.settings.viewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.viewedContracts.length; j++) {\r\n if (this.variablesService.settings.viewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.viewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.viewedContracts[j].state = this.currentContract.state;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.viewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: this.currentContract.state\r\n });\r\n }\r\n this.currentContract.is_new = false;\r\n setTimeout(() => {\r\n this.variablesService.currentWallet.recountNewContracts();\r\n }, 0);\r\n }\r\n this.checkAndChangeHistory();\r\n } else {\r\n this.newPurchase = true;\r\n }\r\n });\r\n this.heightAppEvent = this.variablesService.getHeightAppEvent.subscribe((newHeight: number) => {\r\n if (this.currentContract && this.currentContract.state === 201 && this.currentContract.height !== 0 && (newHeight - this.currentContract.height) >= 10) {\r\n this.currentContract.state = 2;\r\n this.currentContract.is_new = true;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n } else if (this.currentContract && this.currentContract.state === 601 && this.currentContract.height !== 0 && (newHeight - this.currentContract.height) >= 10) {\r\n this.currentContract.state = 6;\r\n this.currentContract.is_new = true;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n }\r\n });\r\n }\r\n\r\n toggleOptions() {\r\n this.additionalOptions = !this.additionalOptions;\r\n }\r\n\r\n getProgressBarWidth() {\r\n let progress = '0';\r\n if (!this.newPurchase) {\r\n if (this.currentContract) {\r\n if (this.currentContract.state === 1) {\r\n progress = '10%';\r\n }\r\n if (this.currentContract.state === 201) {\r\n progress = '25%';\r\n }\r\n if ([120, 2].indexOf(this.currentContract.state) !== -1) {\r\n progress = '50%';\r\n }\r\n if ([5, 601].indexOf(this.currentContract.state) !== -1) {\r\n progress = '75%';\r\n }\r\n if ([110, 130, 140, 3, 4, 6].indexOf(this.currentContract.state) !== -1) {\r\n progress = '100%';\r\n }\r\n }\r\n }\r\n return progress;\r\n }\r\n\r\n sameAmountChange() {\r\n if (this.purchaseForm.get('sameAmount').value) {\r\n this.purchaseForm.get('sellerDeposit').clearValidators();\r\n this.purchaseForm.get('sellerDeposit').updateValueAndValidity();\r\n } else {\r\n this.purchaseForm.get('sellerDeposit').setValidators([Validators.required]);\r\n this.purchaseForm.get('sellerDeposit').updateValueAndValidity();\r\n }\r\n }\r\n\r\n createPurchase() {\r\n if (this.purchaseForm.valid) {\r\n const sellerDeposit = this.purchaseForm.get('sameAmount').value ? this.purchaseForm.get('amount').value : this.purchaseForm.get('sellerDeposit').value;\r\n if (this.purchaseForm.get('seller').value.indexOf('@') !== 0) {\r\n this.backend.createProposal(\r\n this.variablesService.currentWallet.wallet_id,\r\n this.purchaseForm.get('description').value,\r\n this.purchaseForm.get('comment').value,\r\n this.variablesService.currentWallet.address,\r\n this.purchaseForm.get('seller').value,\r\n this.purchaseForm.get('amount').value,\r\n this.purchaseForm.get('yourDeposit').value,\r\n sellerDeposit,\r\n this.purchaseForm.get('time').value,\r\n this.purchaseForm.get('payment').value,\r\n (create_status) => {\r\n if (create_status) {\r\n this.back();\r\n }\r\n });\r\n } else {\r\n this.backend.getAliasByName(this.purchaseForm.get('seller').value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status === false) {\r\n this.ngZone.run(() => {\r\n this.purchaseForm.get('seller').setErrors({'alias_not_valid': true});\r\n });\r\n } else {\r\n this.backend.createProposal(\r\n this.variablesService.currentWallet.wallet_id,\r\n this.purchaseForm.get('description').value,\r\n this.purchaseForm.get('comment').value,\r\n this.variablesService.currentWallet.address,\r\n alias_data.address,\r\n this.purchaseForm.get('amount').value,\r\n this.purchaseForm.get('yourDeposit').value,\r\n sellerDeposit,\r\n this.purchaseForm.get('time').value,\r\n this.purchaseForm.get('payment').value,\r\n (create_status) => {\r\n if (create_status) {\r\n this.back();\r\n }\r\n });\r\n }\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n acceptState() {\r\n this.backend.acceptProposal(this.currentWalletId, this.currentContract.contract_id, (accept_status) => {\r\n if (accept_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.ACCEPT_STATE_WAIT_BIG');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n ignoredContract() {\r\n this.variablesService.settings.notViewedContracts = (this.variablesService.settings.notViewedContracts) ? this.variablesService.settings.notViewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.notViewedContracts[j].state = 110;\r\n this.variablesService.settings.notViewedContracts[j].time = this.currentContract.expiration_time;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.notViewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: 110,\r\n time: this.currentContract.expiration_time\r\n });\r\n }\r\n this.currentContract.is_new = true;\r\n this.currentContract.state = 110;\r\n this.currentContract.time = this.currentContract.expiration_time;\r\n\r\n this.variablesService.currentWallet.recountNewContracts();\r\n this.modalService.prepareModal('info', 'PURCHASE.IGNORED_ACCEPT');\r\n this.back();\r\n }\r\n\r\n productNotGot() {\r\n this.backend.releaseProposal(this.currentWalletId, this.currentContract.contract_id, 'REL_B', (release_status) => {\r\n if (release_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.BURN_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsFinish() {\r\n this.backend.releaseProposal(this.currentWalletId, this.currentContract.contract_id, 'REL_N', (release_status) => {\r\n if (release_status) {\r\n this.modalService.prepareModal('success', 'PURCHASE.SUCCESS_FINISH_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsCancel() {\r\n this.backend.requestCancelContract(this.currentWalletId, this.currentContract.contract_id, this.purchaseForm.get('timeCancel').value, (cancel_status) => {\r\n if (cancel_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.SEND_CANCEL_PROPOSAL');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n dealsDetailsDontCanceling() {\r\n this.variablesService.settings.notViewedContracts = this.variablesService.settings.notViewedContracts ? this.variablesService.settings.notViewedContracts : [];\r\n let findViewedCont = false;\r\n for (let j = 0; j < this.variablesService.settings.notViewedContracts.length; j++) {\r\n if (this.variablesService.settings.notViewedContracts[j].contract_id === this.currentContract.contract_id && this.variablesService.settings.notViewedContracts[j].is_a === this.currentContract.is_a) {\r\n this.variablesService.settings.notViewedContracts[j].state = 130;\r\n this.variablesService.settings.notViewedContracts[j].time = this.currentContract.cancel_expiration_time;\r\n findViewedCont = true;\r\n break;\r\n }\r\n }\r\n if (!findViewedCont) {\r\n this.variablesService.settings.notViewedContracts.push({\r\n contract_id: this.currentContract.contract_id,\r\n is_a: this.currentContract.is_a,\r\n state: 130,\r\n time: this.currentContract.cancel_expiration_time\r\n });\r\n }\r\n this.currentContract.is_new = true;\r\n this.currentContract.state = 130;\r\n this.currentContract.time = this.currentContract.cancel_expiration_time;\r\n this.variablesService.currentWallet.recountNewContracts();\r\n this.modalService.prepareModal('info', 'PURCHASE.IGNORED_CANCEL');\r\n this.back();\r\n }\r\n\r\n dealsDetailsSellerCancel() {\r\n this.backend.acceptCancelContract(this.currentWalletId, this.currentContract.contract_id, (accept_status) => {\r\n if (accept_status) {\r\n this.modalService.prepareModal('info', 'PURCHASE.DEALS_CANCELED_WAIT');\r\n this.back();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.subRouting.unsubscribe();\r\n this.heightAppEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n \\\"qr-code\\\"\\r\\n
\\r\\n
{{variablesService.currentWallet.address}}
\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.wrap-qr {\\n display: flex;\\n flex-direction: column;\\n align-items: center; }\\n\\n.wrap-qr img {\\n margin: 4rem 0; }\\n\\n.wrap-qr .wrap-address {\\n display: flex;\\n align-items: center;\\n font-size: 1.4rem;\\n line-height: 2.7rem; }\\n\\n.wrap-qr .wrap-address .btn-copy-address {\\n margin-left: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copy {\\n -webkit-mask: url('copy.svg') no-repeat center;\\n mask: url('copy.svg') no-repeat center; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copy:hover {\\n opacity: 0.75; }\\n\\n.wrap-qr .wrap-address .btn-copy-address.copied {\\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\\n mask: url('complete-testwallet.svg') no-repeat center; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVjZWl2ZS9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxccmVjZWl2ZVxccmVjZWl2ZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsbUJBQW1CLEVBQUE7O0FBSHJCO0lBTUksY0FBYyxFQUFBOztBQU5sQjtJQVVJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsaUJBQWlCO0lBQ2pCLG1CQUFtQixFQUFBOztBQWJ2QjtNQWdCTSxtQkFBbUI7TUFDbkIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUFsQnBCO1FBcUJRLDhDQUF1RDtnQkFBdkQsc0NBQXVELEVBQUE7O0FBckIvRDtVQXdCVSxhQUFhLEVBQUE7O0FBeEJ2QjtRQTZCUSw2REFBc0U7Z0JBQXRFLHFEQUFzRSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvcmVjZWl2ZS9yZWNlaXZlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4ud3JhcC1xciB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcblxyXG4gIGltZyB7XHJcbiAgICBtYXJnaW46IDRyZW0gMDtcclxuICB9XHJcblxyXG4gIC53cmFwLWFkZHJlc3Mge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcblxyXG4gICAgLmJ0bi1jb3B5LWFkZHJlc3Mge1xyXG4gICAgICBtYXJnaW4tbGVmdDogMS4ycmVtO1xyXG4gICAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuN3JlbTtcclxuXHJcbiAgICAgICYuY29weSB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9jb3B5LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuXHJcbiAgICAgICAgJjpob3ZlciB7XHJcbiAgICAgICAgICBvcGFjaXR5OiAwLjc1O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgJi5jb3BpZWQge1xyXG4gICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvY29tcGxldGUtdGVzdHdhbGxldC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, OnDestroy} from '@angular/core';\r\nimport QRCode from 'qrcode';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-receive',\r\n templateUrl: './receive.component.html',\r\n styleUrls: ['./receive.component.scss']\r\n})\r\nexport class ReceiveComponent implements OnInit, OnDestroy {\r\n qrImageSrc: string;\r\n parentRouting;\r\n copyAnimation = false;\r\n copyAnimationTimeout;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n QRCode.toDataURL(this.variablesService.currentWallet.address, {\r\n width: 106,\r\n height: 106\r\n }).then(url => {\r\n this.qrImageSrc = url;\r\n }).catch(err => {\r\n console.error(err);\r\n });\r\n });\r\n }\r\n\r\n public copyAddress() {\r\n this.backend.setClipboard(this.variablesService.currentWallet.address);\r\n this.copyAnimation = true;\r\n this.copyAnimationTimeout = window.setTimeout(() => {\r\n this.copyAnimation = false;\r\n }, 2000);\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n clearTimeout(this.copyAnimationTimeout);\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.RESTORE_WALLET' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.KEY_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'RESTORE_WALLET.FORM_ERRORS.KEY_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.form-restore {\\n margin: 2.4rem 0;\\n width: 100%; }\\n\\n.form-restore .input-block.half-block {\\n width: 50%; }\\n\\n.form-restore .wrap-buttons {\\n display: flex;\\n margin: 2.5rem -0.7rem;\\n width: 50%; }\\n\\n.form-restore .wrap-buttons button {\\n margin: 0 0.7rem; }\\n\\n.form-restore .wrap-buttons button.transparent-button {\\n flex-basis: 50%; }\\n\\n.form-restore .wrap-buttons button.select-button {\\n flex-basis: 60%; }\\n\\n.form-restore .wrap-buttons button.create-button {\\n flex: 1 1 50%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvcmVzdG9yZS13YWxsZXQvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHJlc3RvcmUtd2FsbGV0XFxyZXN0b3JlLXdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLGdCQUFnQjtFQUNoQixXQUFXLEVBQUE7O0FBRmI7SUFPTSxVQUFVLEVBQUE7O0FBUGhCO0lBWUksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixVQUFVLEVBQUE7O0FBZGQ7TUFpQk0sZ0JBQWdCLEVBQUE7O0FBakJ0QjtRQW9CUSxlQUFlLEVBQUE7O0FBcEJ2QjtRQXdCUSxlQUFlLEVBQUE7O0FBeEJ2QjtRQTRCUSxhQUFhLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9yZXN0b3JlLXdhbGxldC9yZXN0b3JlLXdhbGxldC5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5mb3JtLXJlc3RvcmUge1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDEwMCU7XHJcblxyXG4gIC5pbnB1dC1ibG9jayB7XHJcblxyXG4gICAgJi5oYWxmLWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDUwJTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC53cmFwLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIG1hcmdpbjogMi41cmVtIC0wLjdyZW07XHJcbiAgICB3aWR0aDogNTAlO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMCAwLjdyZW07XHJcblxyXG4gICAgICAmLnRyYW5zcGFyZW50LWJ1dHRvbiB7XHJcbiAgICAgICAgZmxleC1iYXNpczogNTAlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnNlbGVjdC1idXR0b24ge1xyXG4gICAgICAgIGZsZXgtYmFzaXM6IDYwJTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5jcmVhdGUtYnV0dG9uIHtcclxuICAgICAgICBmbGV4OiAxIDEgNTAlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\nimport {TranslateService} from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-restore-wallet',\r\n templateUrl: './restore-wallet.component.html',\r\n styleUrls: ['./restore-wallet.component.scss']\r\n})\r\nexport class RestoreWalletComponent implements OnInit {\r\n\r\n restoreForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n return {'duplicate': true};\r\n }\r\n }\r\n return null;\r\n }]),\r\n key: new FormControl('', Validators.required),\r\n password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n confirm: new FormControl('')\r\n }, function (g: FormGroup) {\r\n return g.get('password').value === g.get('confirm').value ? null : {'confirm_mismatch': true};\r\n });\r\n\r\n wallet = {\r\n id: ''\r\n };\r\n\r\n walletSaved = false;\r\n walletSavedName = '';\r\n progressWidth = '9rem';\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService\r\n ) {}\r\n\r\n ngOnInit() {}\r\n\r\n createWallet() {\r\n this.ngZone.run(() => {\r\n this.progressWidth = '100%';\r\n this.router.navigate(['/seed-phrase'], {queryParams: {wallet_id: this.wallet.id}});\r\n });\r\n }\r\n\r\n saveWallet() {\r\n if (this.restoreForm.valid && this.restoreForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {\r\n this.backend.isValidRestoreWalletText(this.restoreForm.get('key').value, (valid_status, valid_data) => {\r\n if (valid_data !== 'TRUE') {\r\n this.ngZone.run(() => {\r\n this.restoreForm.get('key').setErrors({key_not_valid: true});\r\n });\r\n } else {\r\n this.backend.saveFileDialog(this.translate.instant('RESTORE_WALLET.CHOOSE_PATH'), '*', this.variablesService.settings.default_path, (save_status, save_data) => {\r\n if (save_status) {\r\n this.variablesService.settings.default_path = save_data.path.substr(0, save_data.path.lastIndexOf('/'));\r\n this.walletSavedName = save_data.path.substr(save_data.path.lastIndexOf('/') + 1, save_data.path.length - 1);\r\n this.backend.restoreWallet(save_data.path, this.restoreForm.get('password').value, this.restoreForm.get('key').value, (restore_status, restore_data) => {\r\n if (restore_status) {\r\n this.wallet.id = restore_data.wallet_id;\r\n this.variablesService.opening_wallet = new Wallet(\r\n restore_data.wallet_id,\r\n this.restoreForm.get('name').value,\r\n this.restoreForm.get('password').value,\r\n restore_data['wi'].path,\r\n restore_data['wi'].address,\r\n restore_data['wi'].balance,\r\n restore_data['wi'].unlocked_balance,\r\n restore_data['wi'].mined_total,\r\n restore_data['wi'].tracking_hey\r\n );\r\n this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(this.variablesService.opening_wallet.address);\r\n if (restore_data.recent_history && restore_data.recent_history.history) {\r\n this.variablesService.opening_wallet.prepareHistory(restore_data.recent_history.history);\r\n }\r\n this.backend.getContracts(this.variablesService.opening_wallet.wallet_id, (contracts_status, contracts_data) => {\r\n if (contracts_status && contracts_data.hasOwnProperty('contracts')) {\r\n this.ngZone.run(() => {\r\n this.variablesService.opening_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);\r\n });\r\n }\r\n });\r\n this.ngZone.run(() => {\r\n this.walletSaved = true;\r\n this.progressWidth = '50%';\r\n });\r\n } else {\r\n this.modalService.prepareModal('error', 'RESTORE_WALLET.NOT_CORRECT_FILE_OR_PASSWORD');\r\n }\r\n });\r\n }\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'BREADCRUMBS.ADD_WALLET' | translate }}\\r\\n {{ 'BREADCRUMBS.SAVE_PHRASE' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'SEED_PHRASE.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n \\r\\n
{{(index + 1) + '. ' + word}}
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative; }\\n\\n.seed-phrase-title {\\n line-height: 2.2rem;\\n padding: 2.2rem 0; }\\n\\n.seed-phrase-content {\\n display: flex;\\n flex-direction: column;\\n flex-wrap: wrap;\\n padding: 1.4rem;\\n width: 100%;\\n height: 12rem; }\\n\\n.seed-phrase-content .word {\\n line-height: 2.2rem;\\n max-width: 13rem; }\\n\\n.wrap-buttons {\\n display: flex; }\\n\\n.wrap-buttons .seed-phrase-button {\\n margin: 2.8rem 0;\\n width: 25%;\\n min-width: 1.5rem; }\\n\\n.wrap-buttons .copy-button {\\n margin: 2.8rem 1rem;\\n width: 25%;\\n min-width: 1.5rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VlZC1waHJhc2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHNlZWQtcGhyYXNlXFxzZWVkLXBocmFzZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBOztBQUdwQjtFQUNFLG1CQUFtQjtFQUNuQixpQkFBaUIsRUFBQTs7QUFHbkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLGVBQWU7RUFDZixlQUFlO0VBQ2YsV0FBVztFQUNYLGFBQWEsRUFBQTs7QUFOZjtJQVNJLG1CQUFtQjtJQUNuQixnQkFBZ0IsRUFBQTs7QUFJcEI7RUFDRSxhQUFhLEVBQUE7O0FBRGY7SUFJSSxnQkFBZ0I7SUFDaEIsVUFBVTtJQUNWLGlCQUFpQixFQUFBOztBQU5yQjtJQVVJLG1CQUFtQjtJQUNuQixVQUFVO0lBQ1YsaUJBQWlCLEVBQUEiLCJmaWxlIjoic3JjL2FwcC9zZWVkLXBocmFzZS9zZWVkLXBocmFzZS5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbn1cclxuXHJcbi5zZWVkLXBocmFzZS10aXRsZSB7XHJcbiAgbGluZS1oZWlnaHQ6IDIuMnJlbTtcclxuICBwYWRkaW5nOiAyLjJyZW0gMDtcclxufVxyXG5cclxuLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBmbGV4LXdyYXA6IHdyYXA7XHJcbiAgcGFkZGluZzogMS40cmVtO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG4gIGhlaWdodDogMTJyZW07XHJcblxyXG4gIC53b3JkIHtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjJyZW07XHJcbiAgICBtYXgtd2lkdGg6IDEzcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLndyYXAtYnV0dG9ucyB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgLnNlZWQtcGhyYXNlLWJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuOHJlbSAwO1xyXG4gICAgd2lkdGg6IDI1JTtcclxuICAgIG1pbi13aWR0aDogMS41cmVtO1xyXG4gIH1cclxuXHJcbiAgLmNvcHktYnV0dG9uIHtcclxuICAgIG1hcmdpbjogMi44cmVtIDFyZW07XHJcbiAgICB3aWR0aDogMjUlO1xyXG4gICAgbWluLXdpZHRoOiAxLjVyZW07XHJcbiAgfVxyXG59XHJcblxyXG4iXX0= */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {ActivatedRoute, Router} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\n\r\n@Component({\r\n selector: 'app-seed-phrase',\r\n templateUrl: './seed-phrase.component.html',\r\n styleUrls: ['./seed-phrase.component.scss']\r\n})\r\nexport class SeedPhraseComponent implements OnInit, OnDestroy {\r\n\r\n queryRouting;\r\n seedPhrase = '';\r\n wallet_id: number;\r\n seedPhraseCopied = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private location: Location,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.wallet_id) {\r\n this.wallet_id = params.wallet_id;\r\n this.backend.getSmartWalletInfo(params.wallet_id, (status, data) => {\r\n if (data.hasOwnProperty('restore_key')) {\r\n this.ngZone.run(() => {\r\n this.seedPhrase = data['restore_key'].trim();\r\n });\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n runWallet() {\r\n let exists = false;\r\n this.variablesService.wallets.forEach((wallet) => {\r\n if (wallet.address === this.variablesService.opening_wallet.address) {\r\n exists = true;\r\n }\r\n });\r\n if (!exists) {\r\n this.backend.runWallet(this.wallet_id, (run_status, run_data) => {\r\n if (run_status) {\r\n this.variablesService.wallets.push(this.variablesService.opening_wallet);\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet_id]);\r\n });\r\n } else {\r\n console.log(run_data['error_code']);\r\n }\r\n });\r\n } else {\r\n this.variablesService.opening_wallet = null;\r\n this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');\r\n this.backend.closeWallet(this.wallet_id, () => {\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/']);\r\n });\r\n });\r\n }\r\n }\r\n\r\n copySeedPhrase() {\r\n this.backend.setClipboard(this.seedPhrase, () => {\r\n this.ngZone.run(() => {\r\n this.seedPhraseCopied = true;\r\n });\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.queryRouting.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n {{ 'CONFIRM.TITLE' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.SEND' | translate }}
\\r\\n
{{ form.get('amount').value }} {{variablesService.defaultCurrency}}
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.FROM' | translate }}
\\r\\n
{{ variablesService.currentWallet.address }}
\\r\\n
\\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.TO' | translate }}
\\r\\n
{{ form.get('address').value }}
\\r\\n
\\r\\n \\r\\n
\\r\\n
{{ 'CONFIRM.MESSAGE.COMMENT' | translate }}
\\r\\n
{{ form.get('comment').value }}
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n position: fixed;\\n top: 0;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: rgba(255, 255, 255, 0.25); }\\n\\n.modal {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n background-position: center;\\n background-size: 200%;\\n padding: 0.3rem 3rem 3rem 3rem;\\n width: 64rem; }\\n\\n.modal .title {\\n padding: 1.4rem 0;\\n font-size: 1.8rem;\\n line-height: 3rem; }\\n\\n.modal .content {\\n display: flex;\\n font-size: 1.4rem; }\\n\\n.modal .content .message-container {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n margin: 1.4rem 3rem 6.2rem 0; }\\n\\n.modal .content .message-container .message-block {\\n display: flex;\\n margin-bottom: 1rem; }\\n\\n.modal .content .message-container .message-block:first-child .message-label {\\n line-height: 4rem; }\\n\\n.modal .content .message-container .message-block:first-child .message-text {\\n line-height: 4rem; }\\n\\n.modal .content .message-container .message-block:last-child {\\n margin-bottom: 0; }\\n\\n.modal .content .message-container .message-block .message-label {\\n min-width: 6.7rem;\\n line-height: 2rem; }\\n\\n.modal .content .message-container .message-block .message-text {\\n overflow-wrap: break-word;\\n margin-left: 4.8rem;\\n width: 43.4rem;\\n line-height: 2rem; }\\n\\n.modal .wrapper-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n\\n.modal .wrapper-buttons button {\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC1tb2RhbC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2VuZC1tb2RhbFxcc2VuZC1tb2RhbC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGVBQWU7RUFDZixNQUFNO0VBQ04sU0FBUztFQUNULE9BQU87RUFDUCxRQUFRO0VBQ1IsYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix1QkFBdUI7RUFDdkIscUNBQXFDLEVBQUE7O0FBRXZDO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsMkJBQTJCO0VBQzNCLHFCQUFxQjtFQUNyQiw4QkFBOEI7RUFDOUIsWUFBWSxFQUFBOztBQVBkO0lBVUksaUJBQWlCO0lBQ2pCLGlCQUFpQjtJQUNqQixpQkFBaUIsRUFBQTs7QUFackI7SUFnQkksYUFBYTtJQUNiLGlCQUFpQixFQUFBOztBQWpCckI7TUFvQk0sYUFBYTtNQUNiLHNCQUFzQjtNQUN0Qix1QkFBdUI7TUFDdkIsdUJBQXVCO01BQ3ZCLDRCQUE0QixFQUFBOztBQXhCbEM7UUEyQlEsYUFBYTtRQUNiLG1CQUFtQixFQUFBOztBQTVCM0I7VUFpQ1ksaUJBQWlCLEVBQUE7O0FBakM3QjtVQXFDWSxpQkFBaUIsRUFBQTs7QUFyQzdCO1VBMENVLGdCQUFnQixFQUFBOztBQTFDMUI7VUE4Q1UsaUJBQWlCO1VBQ2pCLGlCQUFpQixFQUFBOztBQS9DM0I7VUFtRFUseUJBQXlCO1VBQ3pCLG1CQUFtQjtVQUNuQixjQUFjO1VBQ2QsaUJBQWlCLEVBQUE7O0FBdEQzQjtJQThESSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDhCQUE4QixFQUFBOztBQWhFbEM7TUFtRU0sV0FBVztNQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2VuZC1tb2RhbC9zZW5kLW1vZGFsLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHBvc2l0aW9uOiBmaXhlZDtcclxuICB0b3A6IDA7XHJcbiAgYm90dG9tOiAwO1xyXG4gIGxlZnQ6IDA7XHJcbiAgcmlnaHQ6IDA7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XHJcbn1cclxuLm1vZGFsIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjtcclxuICBiYWNrZ3JvdW5kLXNpemU6IDIwMCU7XHJcbiAgcGFkZGluZzogMC4zcmVtIDNyZW0gM3JlbSAzcmVtO1xyXG4gIHdpZHRoOiA2NHJlbTtcclxuXHJcbiAgLnRpdGxlIHtcclxuICAgIHBhZGRpbmc6IDEuNHJlbSAwO1xyXG4gICAgZm9udC1zaXplOiAxLjhyZW07XHJcbiAgICBsaW5lLWhlaWdodDogM3JlbTtcclxuICB9XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuXHJcbiAgICAubWVzc2FnZS1jb250YWluZXIge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMS40cmVtIDNyZW0gNi4ycmVtIDA7XHJcbiAgICAgIFxyXG4gICAgICAubWVzc2FnZS1ibG9jayB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxcmVtO1xyXG5cclxuICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuXHJcbiAgICAgICAgICAubWVzc2FnZS1sYWJlbCB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiA0cmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5tZXNzYWdlLXRleHQge1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogNHJlbTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLm1lc3NhZ2UtbGFiZWwge1xyXG4gICAgICAgICAgbWluLXdpZHRoOiA2LjdyZW07XHJcbiAgICAgICAgICBsaW5lLWhlaWdodDogMnJlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5tZXNzYWdlLXRleHQge1xyXG4gICAgICAgICAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICAgICAgICAgIG1hcmdpbi1sZWZ0OiA0LjhyZW07XHJcbiAgICAgICAgICB3aWR0aDogNDMuNHJlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAycmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC53cmFwcGVyLWJ1dHRvbnMge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgIG1heC13aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG4iXX0= */\"","import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';\r\nimport { FormGroup } from '@angular/forms';\r\nimport { VariablesService } from '../_helpers/services/variables.service';\r\n\r\n\r\n@Component({\r\n selector: 'app-send-modal',\r\n templateUrl: './send-modal.component.html',\r\n styleUrls: ['./send-modal.component.scss']\r\n})\r\nexport class SendModalComponent implements OnInit {\r\n\r\n @Input() form: FormGroup;\r\n @Output() confirmed: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n public variablesService: VariablesService\r\n ) {\r\n }\r\n\r\n ngOnInit() {\r\n }\r\n\r\n confirm() {\r\n this.confirmed.emit(true);\r\n }\r\n\r\n onClose() {\r\n this.confirmed.emit(false);\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n \\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
{{item.name}}
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ADDRESS_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ADDRESS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.ALIAS_NOT_VALID' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_ZERO' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
= variablesService.maxCommentLength\\\">\\r\\n {{ 'SEND.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.AMOUNT_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.FEE_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'SEND.FORM_ERRORS.FEE_MINIMUM' | translate : {fee: variablesService.default_fee} }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n\"","module.exports = \":host {\\n width: 100%; }\\n\\n.form-send .input-blocks-row {\\n display: flex; }\\n\\n.form-send .input-blocks-row > div {\\n flex-basis: 50%; }\\n\\n.form-send .input-blocks-row > div:first-child {\\n margin-right: 1.5rem; }\\n\\n.form-send .input-blocks-row > div:last-child {\\n margin-left: 1.5rem; }\\n\\n.form-send .send-select {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-size: 1.3rem;\\n line-height: 1.3rem;\\n margin: 1.5rem 0 0;\\n padding: 0;\\n width: 100%;\\n max-width: 15rem;\\n height: 1.3rem; }\\n\\n.form-send .send-select .arrow {\\n margin-left: 1rem;\\n width: 0.8rem;\\n height: 0.8rem; }\\n\\n.form-send .send-select .arrow.down {\\n -webkit-mask: url('arrow-down.svg') no-repeat center;\\n mask: url('arrow-down.svg') no-repeat center; }\\n\\n.form-send .send-select .arrow.up {\\n -webkit-mask: url('arrow-up.svg') no-repeat center;\\n mask: url('arrow-up.svg') no-repeat center; }\\n\\n.form-send .additional-details {\\n display: flex;\\n margin-top: 1.5rem;\\n padding: 0.5rem 0 2rem; }\\n\\n.form-send .additional-details > div {\\n flex-basis: 25%; }\\n\\n.form-send .additional-details > div:first-child {\\n padding-left: 1.5rem;\\n padding-right: 1rem; }\\n\\n.form-send .additional-details > div:last-child {\\n padding-left: 1rem;\\n padding-right: 1.5rem; }\\n\\n.form-send .additional-details .checkbox-block {\\n flex-basis: 50%; }\\n\\n.form-send .additional-details .checkbox-block > label {\\n top: 3.5rem; }\\n\\n.form-send button {\\n margin: 2.4rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2VuZC9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2VuZFxcc2VuZC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLFdBQVcsRUFBQTs7QUFHYjtFQUdJLGFBQWEsRUFBQTs7QUFIakI7SUFNTSxlQUFlLEVBQUE7O0FBTnJCO01BU1Esb0JBQW9CLEVBQUE7O0FBVDVCO01BYVEsbUJBQW1CLEVBQUE7O0FBYjNCO0VBbUJJLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsdUJBQXVCO0VBQ3ZCLFlBQVk7RUFDWixpQkFBaUI7RUFDakIsbUJBQW1CO0VBQ25CLGtCQUFrQjtFQUNsQixVQUFVO0VBQ1YsV0FBVztFQUNYLGdCQUFnQjtFQUNoQixjQUFjLEVBQUE7O0FBN0JsQjtJQWdDTSxpQkFBaUI7SUFDakIsYUFBYTtJQUNiLGNBQWMsRUFBQTs7QUFsQ3BCO01BcUNRLG9EQUE0RDtjQUE1RCw0Q0FBNEQsRUFBQTs7QUFyQ3BFO01BeUNRLGtEQUEwRDtjQUExRCwwQ0FBMEQsRUFBQTs7QUF6Q2xFO0VBK0NJLGFBQWE7RUFDYixrQkFBa0I7RUFDbEIsc0JBQXNCLEVBQUE7O0FBakQxQjtJQW9ETSxlQUFlLEVBQUE7O0FBcERyQjtNQXVEUSxvQkFBb0I7TUFDcEIsbUJBQW1CLEVBQUE7O0FBeEQzQjtNQTREUSxrQkFBa0I7TUFDbEIscUJBQXFCLEVBQUE7O0FBN0Q3QjtJQWtFTSxlQUFlLEVBQUE7O0FBbEVyQjtNQXFFUSxXQUFXLEVBQUE7O0FBckVuQjtFQTJFSSxnQkFBZ0I7RUFDaEIsV0FBVztFQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2VuZC9zZW5kLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIHdpZHRoOiAxMDAlO1xyXG59XHJcblxyXG4uZm9ybS1zZW5kIHtcclxuXHJcbiAgLmlucHV0LWJsb2Nrcy1yb3cge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuXHJcbiAgICA+IGRpdiB7XHJcbiAgICAgIGZsZXgtYmFzaXM6IDUwJTtcclxuXHJcbiAgICAgICY6Zmlyc3QtY2hpbGQge1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMS41cmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgIG1hcmdpbi1sZWZ0OiAxLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zZW5kLXNlbGVjdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS4zcmVtO1xyXG4gICAgbWFyZ2luOiAxLjVyZW0gMCAwO1xyXG4gICAgcGFkZGluZzogMDtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICAgIGhlaWdodDogMS4zcmVtO1xyXG5cclxuICAgIC5hcnJvdyB7XHJcbiAgICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG4gICAgICB3aWR0aDogMC44cmVtO1xyXG4gICAgICBoZWlnaHQ6IDAuOHJlbTtcclxuXHJcbiAgICAgICYuZG93biB7XHJcbiAgICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2Fycm93LWRvd24uc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLnVwIHtcclxuICAgICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctdXAuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYWRkaXRpb25hbC1kZXRhaWxzIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBtYXJnaW4tdG9wOiAxLjVyZW07XHJcbiAgICBwYWRkaW5nOiAwLjVyZW0gMCAycmVtO1xyXG5cclxuICAgID4gZGl2IHtcclxuICAgICAgZmxleC1iYXNpczogMjUlO1xyXG5cclxuICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAxLjVyZW07XHJcbiAgICAgICAgcGFkZGluZy1yaWdodDogMXJlbTtcclxuICAgICAgfVxyXG5cclxuICAgICAgJjpsYXN0LWNoaWxkIHtcclxuICAgICAgICBwYWRkaW5nLWxlZnQ6IDFyZW07XHJcbiAgICAgICAgcGFkZGluZy1yaWdodDogMS41cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmNoZWNrYm94LWJsb2NrIHtcclxuICAgICAgZmxleC1iYXNpczogNTAlO1xyXG5cclxuICAgICAgPiBsYWJlbCB7XHJcbiAgICAgICAgdG9wOiAzLjVyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDIuNHJlbSAwO1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, OnInit, OnDestroy, NgZone, HostListener, Input} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-send',\r\n templateUrl: './send.component.html',\r\n styleUrls: ['./send.component.scss']\r\n})\r\nexport class SendComponent implements OnInit, OnDestroy {\r\n\r\n isOpen = false;\r\n localAliases = [];\r\n isModalDialogVisible = false;\r\n\r\n currentWalletId = null;\r\n parentRouting;\r\n sendForm = new FormGroup({\r\n address: new FormControl('', [Validators.required, (g: FormControl) => {\r\n this.localAliases = [];\r\n if (g.value) {\r\n if (g.value.indexOf('@') !== 0) {\r\n this.isOpen = false;\r\n this.backend.validateAddress(g.value, (valid_status) => {\r\n this.ngZone.run(() => {\r\n if (valid_status === false) {\r\n g.setErrors(Object.assign({'address_not_valid': true}, g.errors));\r\n } else {\r\n if (g.hasError('address_not_valid')) {\r\n delete g.errors['address_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n }\r\n });\r\n });\r\n return (g.hasError('address_not_valid')) ? {'address_not_valid': true} : null;\r\n } else {\r\n this.isOpen = true;\r\n this.localAliases = this.variablesService.aliases.filter((item) => {\r\n return item.name.indexOf(g.value) > -1;\r\n });\r\n if (!(/^@?[a-z0-9\\.\\-]{6,25}$/.test(g.value))) {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n } else {\r\n this.backend.getAliasByName(g.value.replace('@', ''), (alias_status) => {\r\n this.ngZone.run(() => {\r\n if (alias_status) {\r\n if (g.hasError('alias_not_valid')) {\r\n delete g.errors['alias_not_valid'];\r\n if (Object.keys(g.errors).length === 0) {\r\n g.setErrors(null);\r\n }\r\n }\r\n } else {\r\n g.setErrors(Object.assign({'alias_not_valid': true}, g.errors));\r\n }\r\n });\r\n });\r\n }\r\n return (g.hasError('alias_not_valid')) ? {'alias_not_valid': true} : null;\r\n }\r\n }\r\n return null;\r\n }]),\r\n amount: new FormControl(null, [Validators.required, (g: FormControl) => {\r\n if (new BigNumber(g.value).eq(0)) {\r\n return {'zero': true};\r\n }\r\n return null;\r\n }]),\r\n comment: new FormControl(''),\r\n mixin: new FormControl(0, Validators.required),\r\n fee: new FormControl(this.variablesService.default_fee, [Validators.required, (g: FormControl) => {\r\n if ((new BigNumber(g.value)).isLessThan(this.variablesService.default_fee)) {\r\n return {'less_min': true};\r\n }\r\n return null;\r\n }]),\r\n hide: new FormControl(false)\r\n });\r\n additionalOptions = false;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {\r\n }\r\n\r\n addressMouseDown(e) {\r\n if (e['button'] === 0 && this.sendForm.get('address').value && this.sendForm.get('address').value.indexOf('@') === 0) {\r\n this.isOpen = true;\r\n }\r\n }\r\n\r\n setAlias(alias) {\r\n this.sendForm.get('address').setValue(alias);\r\n }\r\n\r\n @HostListener('document:click', ['$event.target'])\r\n public onClick(targetElement) {\r\n if (targetElement.id !== 'send-address' && this.isOpen) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(params => {\r\n this.currentWalletId = params['id'];\r\n this.sendForm.reset({\r\n address: this.variablesService.currentWallet.send_data['address'],\r\n amount: this.variablesService.currentWallet.send_data['amount'],\r\n comment: this.variablesService.currentWallet.send_data['comment'],\r\n mixin: this.variablesService.currentWallet.send_data['mixin'] || 0,\r\n fee: this.variablesService.currentWallet.send_data['fee'] || this.variablesService.default_fee,\r\n hide: this.variablesService.currentWallet.send_data['hide'] || false\r\n });\r\n });\r\n }\r\n\r\n showDialog() {\r\n this.isModalDialogVisible = true;\r\n }\r\n\r\n confirmed(confirmed: boolean) {\r\n if (confirmed) {\r\n this.onSend();\r\n }\r\n this.isModalDialogVisible = false;\r\n }\r\n\r\n onSend() {\r\n if (this.sendForm.valid) {\r\n if (this.sendForm.get('address').value.indexOf('@') !== 0) {\r\n this.backend.validateAddress(this.sendForm.get('address').value, (valid_status) => {\r\n if (valid_status === false) {\r\n this.ngZone.run(() => {\r\n this.sendForm.get('address').setErrors({'address_not_valid': true});\r\n });\r\n } else {\r\n this.backend.sendMoney(\r\n this.currentWalletId,\r\n this.sendForm.get('address').value,\r\n this.sendForm.get('amount').value,\r\n this.sendForm.get('fee').value,\r\n this.sendForm.get('mixin').value,\r\n this.sendForm.get('comment').value,\r\n this.sendForm.get('hide').value,\r\n (send_status) => {\r\n if (send_status) {\r\n this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');\r\n this.variablesService.currentWallet.send_data = {address: null, amount: null, comment: null, mixin: null, fee: null, hide: null};\r\n this.sendForm.reset({address: null, amount: null, comment: null, mixin: 0, fee: this.variablesService.default_fee, hide: false});\r\n }\r\n });\r\n }\r\n });\r\n } else {\r\n this.backend.getAliasByName(this.sendForm.get('address').value.replace('@', ''), (alias_status, alias_data) => {\r\n this.ngZone.run(() => {\r\n if (alias_status === false) {\r\n this.ngZone.run(() => {\r\n this.sendForm.get('address').setErrors({'alias_not_valid': true});\r\n });\r\n } else {\r\n this.backend.sendMoney(\r\n this.currentWalletId,\r\n alias_data.address, // this.sendForm.get('address').value,\r\n this.sendForm.get('amount').value,\r\n this.sendForm.get('fee').value,\r\n this.sendForm.get('mixin').value,\r\n this.sendForm.get('comment').value,\r\n this.sendForm.get('hide').value,\r\n (send_status) => {\r\n if (send_status) {\r\n this.modalService.prepareModal('success', 'SEND.SUCCESS_SENT');\r\n this.variablesService.currentWallet.send_data = {address: null, amount: null, comment: null, mixin: null, fee: null, hide: null};\r\n this.sendForm.reset({address: null, amount: null, comment: null, mixin: 0, fee: this.variablesService.default_fee, hide: false});\r\n }\r\n });\r\n }\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n toggleOptions() {\r\n this.additionalOptions = !this.additionalOptions;\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.variablesService.currentWallet.send_data = {\r\n address: this.sendForm.get('address').value,\r\n amount: this.sendForm.get('amount').value,\r\n comment: this.sendForm.get('comment').value,\r\n mixin: this.sendForm.get('mixin').value,\r\n fee: this.sendForm.get('fee').value,\r\n hide: this.sendForm.get('hide').value\r\n };\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n

{{ 'SETTINGS.TITLE' | translate }}

\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.language | translate}}\\r\\n \\r\\n \\r\\n {{item.language | translate}}\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n {{item.name | translate}}\\r\\n \\r\\n \\r\\n {{item.name | translate}}\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n {{ 'SETTINGS.MASTER_PASSWORD.TITLE' | translate }}\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n {{ 'SETTINGS.FORM_ERRORS.PASS_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'ERRORS.WRONG_PASSWORD' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n {{ 'SETTINGS.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n \\r\\n\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
{{ 'SETTINGS.LAST_BUILD' | translate : {value: currentBuild} }}
\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".head {\\n justify-content: flex-end; }\\n\\n.settings-title {\\n font-size: 1.7rem; }\\n\\n.theme-selection {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.theme-selection .radio-block {\\n display: flex;\\n align-items: center;\\n justify-content: flex-start;\\n font-size: 1.3rem;\\n line-height: 2.7rem; }\\n\\n.lock-selection {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n margin: 2.4rem 0;\\n width: 50%; }\\n\\n.lock-selection .lock-selection-title {\\n display: flex;\\n font-size: 1.5rem;\\n line-height: 2.7rem;\\n margin-bottom: 1rem; }\\n\\n.scale-selection {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n padding: 0 0 4rem;\\n width: 50%;\\n height: 0.5rem; }\\n\\n.scale-selection .button-block {\\n position: relative;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 0 auto;\\n margin: 0 0.2rem;\\n padding: 0;\\n height: 0.5rem; }\\n\\n.scale-selection .button-block .label {\\n position: absolute;\\n bottom: -1rem;\\n left: 50%;\\n transform: translate(-50%, 100%);\\n font-size: 1rem;\\n white-space: nowrap; }\\n\\n.master-password {\\n width: 50%; }\\n\\n.master-password .master-password-title {\\n display: flex;\\n font-size: 1.5rem;\\n line-height: 2.7rem;\\n margin-bottom: 1rem; }\\n\\n.master-password button {\\n margin: 2.5rem auto;\\n width: 100%;\\n max-width: 15rem; }\\n\\n.last-build {\\n font-size: 1rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2V0dGluZ3MvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHNldHRpbmdzXFxzZXR0aW5ncy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLHlCQUF5QixFQUFBOztBQUczQjtFQUNFLGlCQUFpQixFQUFBOztBQUduQjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsdUJBQXVCO0VBQ3ZCLGdCQUFnQjtFQUNoQixVQUFVLEVBQUE7O0FBTFo7SUFRSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDJCQUEyQjtJQUMzQixpQkFBaUI7SUFDakIsbUJBQW1CLEVBQUE7O0FBSXZCO0VBQ0UsYUFBYTtFQUNiLHNCQUFzQjtFQUN0Qix1QkFBdUI7RUFDdkIsZ0JBQWdCO0VBQ2hCLFVBQVUsRUFBQTs7QUFMWjtJQVFJLGFBQWE7SUFDYixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLG1CQUFtQixFQUFBOztBQUl2QjtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsOEJBQThCO0VBQzlCLGlCQUFpQjtFQUNqQixVQUFVO0VBQ1YsY0FBYyxFQUFBOztBQU5oQjtJQVNJLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixjQUFjO0lBQ2QsZ0JBQWdCO0lBQ2hCLFVBQVU7SUFDVixjQUFjLEVBQUE7O0FBaEJsQjtNQW1CTSxrQkFBa0I7TUFDbEIsYUFBYTtNQUNiLFNBQVM7TUFDVCxnQ0FBZ0M7TUFDaEMsZUFBZTtNQUNmLG1CQUFtQixFQUFBOztBQUt6QjtFQUNFLFVBQVUsRUFBQTs7QUFEWjtJQUlJLGFBQWE7SUFDYixpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLG1CQUFtQixFQUFBOztBQVB2QjtJQVdJLG1CQUFtQjtJQUNuQixXQUFXO0lBQ1gsZ0JBQWdCLEVBQUE7O0FBSXBCO0VBQ0UsZUFBZSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvc2V0dGluZ3Mvc2V0dGluZ3MuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuaGVhZCB7XHJcbiAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxufVxyXG5cclxuLnNldHRpbmdzLXRpdGxlIHtcclxuICBmb250LXNpemU6IDEuN3JlbTtcclxufVxyXG5cclxuLnRoZW1lLXNlbGVjdGlvbiB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gIGFsaWduLWl0ZW1zOiBmbGV4LXN0YXJ0O1xyXG4gIG1hcmdpbjogMi40cmVtIDA7XHJcbiAgd2lkdGg6IDUwJTtcclxuXHJcbiAgLnJhZGlvLWJsb2NrIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LXN0YXJ0O1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmxvY2stc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luOiAyLjRyZW0gMDtcclxuICB3aWR0aDogNTAlO1xyXG5cclxuICAubG9jay1zZWxlY3Rpb24tdGl0bGUge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgfVxyXG59XHJcblxyXG4uc2NhbGUtc2VsZWN0aW9uIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIHBhZGRpbmc6IDAgMCA0cmVtO1xyXG4gIHdpZHRoOiA1MCU7XHJcbiAgaGVpZ2h0OiAwLjVyZW07XHJcblxyXG4gIC5idXR0b24tYmxvY2sge1xyXG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZsZXg6IDEgMCBhdXRvO1xyXG4gICAgbWFyZ2luOiAwIDAuMnJlbTtcclxuICAgIHBhZGRpbmc6IDA7XHJcbiAgICBoZWlnaHQ6IDAuNXJlbTtcclxuXHJcbiAgICAubGFiZWwge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIGJvdHRvbTogLTFyZW07XHJcbiAgICAgIGxlZnQ6IDUwJTtcclxuICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgMTAwJSk7XHJcbiAgICAgIGZvbnQtc2l6ZTogMXJlbTtcclxuICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi5tYXN0ZXItcGFzc3dvcmQge1xyXG4gIHdpZHRoOiA1MCU7XHJcblxyXG4gIC5tYXN0ZXItcGFzc3dvcmQtdGl0bGUge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgIG1hcmdpbi1ib3R0b206IDFyZW07XHJcbiAgfVxyXG5cclxuICBidXR0b24ge1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gYXV0bztcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgbWF4LXdpZHRoOiAxNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5sYXN0LWJ1aWxkIHtcclxuICBmb250LXNpemU6IDFyZW07XHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnInit, Renderer2} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {FormControl, FormGroup, Validators} from '@angular/forms';\r\nimport {Location} from '@angular/common';\r\nimport { TranslateService } from '@ngx-translate/core';\r\n\r\n@Component({\r\n selector: 'app-settings',\r\n templateUrl: './settings.component.html',\r\n styleUrls: ['./settings.component.scss']\r\n})\r\nexport class SettingsComponent implements OnInit {\r\n\r\n theme: string;\r\n scale: number;\r\n changeForm: any;\r\n languagesOptions = [\r\n {\r\n name: 'en',\r\n language: 'SETTINGS.LANGUAGE.EN'\r\n },\r\n {\r\n name: 'fr',\r\n language: 'SETTINGS.LANGUAGE.FR'\r\n },\r\n {\r\n name: 'de',\r\n language: 'SETTINGS.LANGUAGE.DE'\r\n },\r\n {\r\n name: 'it',\r\n language: 'SETTINGS.LANGUAGE.IT'\r\n },\r\n {\r\n name: 'pt',\r\n language: 'SETTINGS.LANGUAGE.PT'\r\n }\r\n ];\r\n appLockOptions = [\r\n {\r\n id: 5,\r\n name: 'SETTINGS.APP_LOCK.TIME1'\r\n },\r\n {\r\n id: 15,\r\n name: 'SETTINGS.APP_LOCK.TIME2'\r\n },\r\n {\r\n id: 60,\r\n name: 'SETTINGS.APP_LOCK.TIME3'\r\n },\r\n {\r\n id: 0,\r\n name: 'SETTINGS.APP_LOCK.TIME4'\r\n }\r\n ];\r\n appScaleOptions = [\r\n {\r\n id: 7.5,\r\n name: 'SETTINGS.SCALE.75'\r\n },\r\n {\r\n id: 10,\r\n name: 'SETTINGS.SCALE.100'\r\n },\r\n {\r\n id: 12.5,\r\n name: 'SETTINGS.SCALE.125'\r\n },\r\n {\r\n id: 15,\r\n name: 'SETTINGS.SCALE.150'\r\n }\r\n ];\r\n appLogOptions = [\r\n {\r\n id: -1\r\n },\r\n {\r\n id: 0\r\n },\r\n {\r\n id: 1\r\n },\r\n {\r\n id: 2\r\n },\r\n {\r\n id: 3\r\n },\r\n {\r\n id: 4\r\n }\r\n ];\r\n\r\n currentBuild = '';\r\n appPass: any;\r\n\r\n constructor(\r\n private renderer: Renderer2,\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private location: Location,\r\n public translate: TranslateService,\r\n private ngZone: NgZone\r\n ) {\r\n this.theme = this.variablesService.settings.theme;\r\n this.scale = this.variablesService.settings.scale;\r\n this.changeForm = new FormGroup({\r\n password: new FormControl(''),\r\n new_password: new FormControl('', Validators.pattern(this.variablesService.pattern)),\r\n new_confirmation: new FormControl('')\r\n }, [(g: FormGroup) => {\r\n return g.get('new_password').value === g.get('new_confirmation').value ? null : {'confirm_mismatch': true};\r\n }, (g: FormGroup) => {\r\n if (this.variablesService.appPass) {\r\n return g.get('password').value === this.variablesService.appPass ? null : {'pass_mismatch': true};\r\n }\r\n return null;\r\n }]);\r\n }\r\n\r\n ngOnInit() {\r\n this.backend.getVersion((version) => {\r\n this.ngZone.run(() => {\r\n this.currentBuild = version;\r\n });\r\n });\r\n }\r\n\r\n setTheme(theme) {\r\n this.renderer.removeClass(document.body, 'theme-' + this.theme);\r\n this.theme = theme;\r\n this.variablesService.settings.theme = this.theme;\r\n this.renderer.addClass(document.body, 'theme-' + this.theme);\r\n this.backend.storeAppData();\r\n }\r\n\r\n setScale(scale) {\r\n this.scale = scale;\r\n this.variablesService.settings.scale = this.scale;\r\n this.renderer.setStyle(document.documentElement, 'font-size', this.scale + 'px');\r\n this.backend.storeAppData();\r\n }\r\n\r\n onSubmitChangePass() {\r\n if (this.changeForm.valid) {\r\n this.variablesService.appPass = this.changeForm.get('new_password').value;\r\n if (this.variablesService.appPass) {\r\n this.backend.setMasterPassword({pass: this.variablesService.appPass}, (status, data) => {\r\n if (status) {\r\n this.backend.storeSecureAppData({pass: this.variablesService.appPass});\r\n this.variablesService.appLogin = true;\r\n this.variablesService.dataIsLoaded = true;\r\n this.variablesService.startCountdown();\r\n } else {\r\n console.log(data['error_code']);\r\n }\r\n });\r\n } else {\r\n this.backend.dropSecureAppData();\r\n }\r\n this.changeForm.reset();\r\n }\r\n }\r\n\r\n onLockChange() {\r\n if (this.variablesService.appLogin) {\r\n this.variablesService.restartCountdown();\r\n }\r\n this.backend.storeAppData();\r\n }\r\n\r\n onLogChange() {\r\n this.backend.setLogLevel(this.variablesService.settings.appLog);\r\n this.backend.storeAppData();\r\n }\r\n\r\n onLanguageChange() {\r\n this.translate.use(this.variablesService.settings.language);\r\n this.backend.storeAppData();\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n

{{ 'SIDEBAR.TITLE' | translate }}

\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.OFFLINE' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.SYNCING' | translate }} {{ variablesService.height_app }}{{ 'SIDEBAR.SYNCHRONIZATION.SLASH' | translate }}{{ variablesService.height_max }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ONLINE' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.LOADING' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.ERROR' | translate }}\\r\\n \\r\\n \\r\\n {{ 'SIDEBAR.SYNCHRONIZATION.COMPLETE' | translate }}\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
{{ variablesService.sync.progress_value_text }}%
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.STANDARD' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT' | translate }}\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.CRITICAL' | translate }}\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.IMPORTANT_HINT' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{ 'SIDEBAR.UPDATE.TIME' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n justify-content: space-between;\\n flex: 0 0 25rem;\\n padding: 0 3rem;\\n max-width: 25rem; }\\n\\n.animated {\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n margin-right: 1.2rem; }\\n\\n.animated::ng-deep svg {\\n width: 2rem;\\n height: 2rem; }\\n\\n.animated::ng-deep svg path, .animated::ng-deep svg circle, .animated::ng-deep svg polygon {\\n fill: #4db1ff; }\\n\\n.sidebar-accounts {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto; }\\n\\n.sidebar-accounts .sidebar-accounts-header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n flex: 0 0 auto;\\n height: 8rem;\\n font-weight: 400; }\\n\\n.sidebar-accounts .sidebar-accounts-header h3 {\\n font-size: 1.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-header button {\\n background: transparent;\\n border: none;\\n outline: none; }\\n\\n.sidebar-accounts .sidebar-accounts-list {\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto;\\n margin: 0 -3rem;\\n overflow-y: overlay; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account {\\n display: flex;\\n flex-direction: column;\\n flex-shrink: 0;\\n cursor: pointer;\\n padding: 2rem 3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance {\\n line-height: 2.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance .title {\\n font-size: 1.5rem;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-title-balance .balance {\\n font-size: 1.8rem;\\n font-weight: 600;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias {\\n font-size: 1.3rem;\\n line-height: 3.4rem;\\n margin-bottom: 0.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .name {\\n display: flex;\\n align-items: center;\\n flex-shrink: 1;\\n line-height: 1.6rem;\\n padding-right: 1rem;\\n overflow: hidden; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .name span {\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .price {\\n flex-shrink: 0; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .icon {\\n margin-left: 0.5rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-alias .icon.comment {\\n -webkit-mask: url('alert.svg') no-repeat center;\\n mask: url('alert.svg') no-repeat center; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-staking {\\n line-height: 2.9rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-staking .text {\\n font-size: 1.3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages {\\n line-height: 2.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages .text {\\n font-size: 1.3rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-messages .indicator {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 1rem;\\n font-size: 1rem;\\n min-width: 2.4rem;\\n height: 1.6rem;\\n padding: 0 0.5rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\\n flex-direction: column;\\n height: 5.6rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .status {\\n align-self: flex-start;\\n font-size: 1.3rem;\\n line-height: 2.6rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container {\\n display: flex;\\n margin: 0.4rem 0;\\n height: 0.7rem;\\n width: 100%; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-bar {\\n flex: 1 0 auto; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-bar .fill {\\n height: 100%; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization .progress-bar-container .progress-percent {\\n flex: 0 0 auto;\\n font-size: 1.3rem;\\n line-height: 0.7rem;\\n padding-left: 0.7rem; }\\n\\n.sidebar-accounts .sidebar-accounts-list .sidebar-account:focus {\\n outline: none; }\\n\\n.sidebar-accounts:after {\\n content: '';\\n position: absolute;\\n bottom: 0;\\n left: -3rem;\\n width: calc(100% + 6rem);\\n height: 5rem; }\\n\\n.sidebar-settings {\\n flex: 0 0 auto;\\n padding-bottom: 1rem; }\\n\\n.sidebar-settings .wrap-button {\\n margin: 0 -3rem; }\\n\\n.sidebar-settings .wrap-button button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n font-weight: 400;\\n line-height: 3rem;\\n outline: none;\\n padding: 0 3rem;\\n width: 100%; }\\n\\n.sidebar-settings .wrap-button button.disabled {\\n cursor: url('not-allowed.svg'), not-allowed; }\\n\\n.sidebar-settings .wrap-button button .icon {\\n margin-right: 1.2rem;\\n width: 2rem;\\n height: 2rem; }\\n\\n.sidebar-settings .wrap-button button .icon.contacts {\\n -webkit-mask: url('contacts.svg') no-repeat center;\\n mask: url('contacts.svg') no-repeat center; }\\n\\n.sidebar-settings .wrap-button button .icon.settings {\\n -webkit-mask: url('settings.svg') no-repeat center;\\n mask: url('settings.svg') no-repeat center; }\\n\\n.sidebar-settings .wrap-button button .icon.logout {\\n -webkit-mask: url('logout.svg') no-repeat center;\\n mask: url('logout.svg') no-repeat center; }\\n\\n.sidebar-synchronization-status {\\n display: flex;\\n align-items: center;\\n justify-content: flex-start;\\n flex: 0 0 7rem;\\n font-size: 1.3rem; }\\n\\n.sidebar-synchronization-status .status-container {\\n position: relative;\\n flex-grow: 1;\\n text-align: left; }\\n\\n.sidebar-synchronization-status .status-container .offline, .sidebar-synchronization-status .status-container .online {\\n position: relative;\\n display: block;\\n line-height: 1.2rem;\\n padding-left: 2.2rem; }\\n\\n.sidebar-synchronization-status .status-container .offline:before, .sidebar-synchronization-status .status-container .online:before {\\n content: '';\\n position: absolute;\\n top: 0;\\n left: 0;\\n border-radius: 50%;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-synchronization-status .status-container .syncing, .sidebar-synchronization-status .status-container .loading {\\n line-height: 5rem; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container {\\n position: absolute;\\n bottom: 0;\\n left: 0;\\n height: 0.7rem;\\n width: 100%; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing {\\n display: flex; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\\n flex: 1 0 auto; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\\n height: 100%; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-percent {\\n flex: 0 0 auto;\\n font-size: 1.3rem;\\n line-height: 0.7rem;\\n padding-left: 0.7rem; }\\n\\n.sidebar-synchronization-status .status-container .progress-bar-container .loading {\\n -webkit-animation: move 5s linear infinite;\\n animation: move 5s linear infinite;\\n background-image: -webkit-gradient(linear, 0 0, 100% 100%, color-stop(0.125, rgba(0, 0, 0, 0.15)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.1)), color-stop(0.375, rgba(0, 0, 0, 0.1)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.15)), color-stop(0.625, rgba(0, 0, 0, 0.15)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.1)), color-stop(0.875, rgba(0, 0, 0, 0.1)), color-stop(0.875, transparent), to(transparent)), -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.125, rgba(0, 0, 0, 0.3)), color-stop(0.125, transparent), color-stop(0.25, transparent), color-stop(0.25, rgba(0, 0, 0, 0.25)), color-stop(0.375, rgba(0, 0, 0, 0.25)), color-stop(0.375, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(0, 0, 0, 0.3)), color-stop(0.625, rgba(0, 0, 0, 0.3)), color-stop(0.625, transparent), color-stop(0.75, transparent), color-stop(0.75, rgba(0, 0, 0, 0.25)), color-stop(0.875, rgba(0, 0, 0, 0.25)), color-stop(0.875, transparent), to(transparent));\\n background-size: 7rem 7rem;\\n height: 100%; }\\n\\n.sidebar-synchronization-status .update-container {\\n display: flex;\\n flex-grow: 1;\\n margin-left: 1rem;\\n text-align: right; }\\n\\n.sidebar-synchronization-status .update-container .update-text {\\n flex: 1 1 auto;\\n font-size: 1.2rem;\\n line-height: 1.8rem;\\n text-align: left; }\\n\\n.sidebar-synchronization-status .update-container .update-text.time {\\n font-size: 1.1rem; }\\n\\n.sidebar-synchronization-status .update-container .icon {\\n flex: 1 0 auto;\\n margin: 0.3rem 0 0 0.6rem;\\n width: 1.2rem;\\n height: 1.2rem; }\\n\\n.sidebar-synchronization-status .update-container .icon.update {\\n -webkit-mask: url('update.svg') no-repeat center;\\n mask: url('update.svg') no-repeat center; }\\n\\n.sidebar-synchronization-status .update-container .icon.time {\\n -webkit-mask: url('time.svg') no-repeat center;\\n mask: url('time.svg') no-repeat center; }\\n\\n@-webkit-keyframes move {\\n 0% {\\n background-position: 100% -7rem; }\\n 100% {\\n background-position: 100% 7rem; } }\\n\\n@keyframes move {\\n 0% {\\n background-position: 100% -7rem; }\\n 100% {\\n background-position: 100% 7rem; } }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc2lkZWJhci9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc2lkZWJhclxcc2lkZWJhci5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsOEJBQThCO0VBQzlCLGVBQWU7RUFDZixlQUFlO0VBQ2YsZ0JBQWdCLEVBQUE7O0FBR2xCO0VBQ0UsYUFBYTtFQUNiLHVCQUF1QjtFQUN2QixtQkFBbUI7RUFDbkIsb0JBQW9CLEVBQUE7O0FBSnRCO0lBUUksV0FBVztJQUNYLFlBQVksRUFBQTs7QUFUaEI7TUFZTSxhQUFhLEVBQUE7O0FBS25CO0VBQ0Usa0JBQWtCO0VBQ2xCLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsY0FBYyxFQUFBOztBQUpoQjtJQU9JLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsOEJBQThCO0lBQzlCLGNBQWM7SUFDZCxZQUFZO0lBQ1osZ0JBQWdCLEVBQUE7O0FBWnBCO01BZU0saUJBQWlCLEVBQUE7O0FBZnZCO01BbUJNLHVCQUF1QjtNQUN2QixZQUFZO01BQ1osYUFBYSxFQUFBOztBQXJCbkI7SUEwQkksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixjQUFjO0lBQ2QsZUFBZTtJQUNmLG1CQUFtQixFQUFBOztBQTlCdkI7TUFpQ00sYUFBYTtNQUNiLHNCQUFzQjtNQUN0QixjQUFjO01BQ2QsZUFBZTtNQUNmLGtCQUFrQixFQUFBOztBQXJDeEI7UUF3Q1EsYUFBYTtRQUNiLG1CQUFtQjtRQUNuQiw4QkFBOEIsRUFBQTs7QUExQ3RDO1VBNkNVLG1CQUFtQixFQUFBOztBQTdDN0I7WUFnRFksaUJBQWlCO1lBQ2pCLHVCQUF1QjtZQUN2QixnQkFBZ0I7WUFDaEIsbUJBQW1CLEVBQUE7O0FBbkQvQjtZQXVEWSxpQkFBaUI7WUFDakIsZ0JBQWdCO1lBQ2hCLG1CQUFtQixF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QixZQUFZLEVBQUE7O0FBckZwQjtJQTJGSSxhQUFhO0lBQ2IsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQixpQkFBaUIsRUFBQTs7QUE5RnJCO01BaUdNLGNBQWM7TUFDZCxpQkFBaUI7TUFDakIsbUJBQW1CO01BQ25CLGdCQUFnQixFQUFBOztBQXBHdEI7UUF1R1EsaUJBQWlCLEVBQUE7O0FBdkd6QjtNQTRHTSxjQUFjO01BQ2QseUJBQXlCO01BQ3pCLGFBQWE7TUFDYixjQUFjLEVBQUE7O0FBL0dwQjtRQWtIUSxnREFBeUQ7Z0JBQXpELHdDQUF5RCxFQUFBOztBQWxIakU7UUFzSFEsOENBQXVEO2dCQUF2RCxzQ0FBdUQsRUFBQTs7QUFNL0Q7RUFDRTtJQUNFLCtCQUErQixFQUFBO0VBRWpDO0lBQ0UsOEJBQThCLEVBQUEsRUFBQTs7QUFMbEM7RUFDRTtJQUNFLCtCQUErQixFQUFBO0VBRWpDO0lBQ0UsOEJBQThCLEVBQUEsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3NpZGViYXIvc2lkZWJhci5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIjpob3N0IHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGZsZXg6IDAgMCAyNXJlbTtcclxuICBwYWRkaW5nOiAwIDNyZW07XHJcbiAgbWF4LXdpZHRoOiAyNXJlbTtcclxufVxyXG5cclxuLmFuaW1hdGVkIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgbWFyZ2luLXJpZ2h0OiAxLjJyZW07XHJcblxyXG4gICY6Om5nLWRlZXAgc3ZnIHtcclxuXHJcbiAgICB3aWR0aDogMnJlbTtcclxuICAgIGhlaWdodDogMnJlbTtcclxuICBcclxuICAgIHBhdGgsIGNpcmNsZSwgcG9seWdvbiB7XHJcbiAgICAgIGZpbGw6ICM0ZGIxZmY7XHJcbiAgICB9XHJcbiAgfSBcclxufVxyXG5cclxuLnNpZGViYXItYWNjb3VudHMge1xyXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgZmxleDogMSAxIGF1dG87XHJcblxyXG4gIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgIGZsZXg6IDAgMCBhdXRvO1xyXG4gICAgaGVpZ2h0OiA4cmVtO1xyXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuXHJcbiAgICBoMyB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS43cmVtO1xyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXI6IG5vbmU7XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuc2lkZWJhci1hY2NvdW50cy1saXN0IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgZmxleDogMSAxIGF1dG87XHJcbiAgICBtYXJnaW46IDAgLTNyZW07XHJcbiAgICBvdmVyZmxvdy15OiBvdmVybGF5O1xyXG5cclxuICAgIC5zaWRlYmFyLWFjY291bnQge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICBmbGV4LXNocmluazogMDtcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICBwYWRkaW5nOiAycmVtIDNyZW07XHJcblxyXG4gICAgICAuc2lkZWJhci1hY2NvdW50LXJvdyB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuXHJcbiAgICAgICAgJi5hY2NvdW50LXRpdGxlLWJhbGFuY2Uge1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAgICAgICAudGl0bGUge1xyXG4gICAgICAgICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLmJhbGFuY2Uge1xyXG4gICAgICAgICAgICBmb250LXNpemU6IDEuOHJlbTtcclxuICAgICAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgICAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWNjb3VudC1hbGlhcyB7XHJcbiAgICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAzLjRyZW07XHJcbiAgICAgICAgICBtYXJnaW4tYm90dG9tOiAwLjdyZW07XHJcblxyXG4gICAgICAgICAgLm5hbWUge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgICAgICBmbGV4LXNocmluazogMTtcclxuICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNnJlbTtcclxuICAgICAgICAgICAgcGFkZGluZy1yaWdodDogMXJlbTtcclxuICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuXHJcbiAgICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xyXG4gICAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5wcmljZSB7XHJcbiAgICAgICAgICAgIGZsZXgtc2hyaW5rOiAwO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuICAgICAgICAgICAgbWFyZ2luLWxlZnQ6IDAuNXJlbTtcclxuICAgICAgICAgICAgd2lkdGg6IDEuMnJlbTtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxLjJyZW07XHJcblxyXG4gICAgICAgICAgICAmLmNvbW1lbnQge1xyXG4gICAgICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvYWxlcnQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjY291bnQtc3Rha2luZyB7XHJcbiAgICAgICAgICBsaW5lLWhlaWdodDogMi45cmVtO1xyXG5cclxuICAgICAgICAgIC50ZXh0IHtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjY291bnQtbWVzc2FnZXMge1xyXG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAgICAgICAudGV4dCB7XHJcbiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pbmRpY2F0b3Ige1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMXJlbTtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAxcmVtO1xyXG4gICAgICAgICAgICBtaW4td2lkdGg6IDIuNHJlbTtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxLjZyZW07XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDAgMC41cmVtO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XHJcbiAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICAgICAgaGVpZ2h0OiA1LjZyZW07XHJcblxyXG4gICAgICAgICAgLnN0YXR1cyB7XHJcbiAgICAgICAgICAgIGFsaWduLXNlbGY6IGZsZXgtc3RhcnQ7XHJcbiAgICAgICAgICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogMi42cmVtO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuICAgICAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICAgICAgbWFyZ2luOiAwLjRyZW0gMDtcclxuICAgICAgICAgICAgaGVpZ2h0OiAwLjdyZW07XHJcbiAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICAgICAgICAgLnByb2dyZXNzLWJhciB7XHJcbiAgICAgICAgICAgICAgZmxleDogMSAwIGF1dG87XHJcblxyXG4gICAgICAgICAgICAgIC5maWxsIHtcclxuICAgICAgICAgICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5wcm9ncmVzcy1wZXJjZW50IHtcclxuICAgICAgICAgICAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgICAgICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICAgICAgICBsaW5lLWhlaWdodDogMC43cmVtO1xyXG4gICAgICAgICAgICAgIHBhZGRpbmctbGVmdDogMC43cmVtO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAmOmZvY3VzIHtcclxuICAgICAgICBvdXRsaW5lOiBub25lO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmOmFmdGVyIHtcclxuICAgIGNvbnRlbnQ6ICcnO1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgYm90dG9tOiAwO1xyXG4gICAgbGVmdDogLTNyZW07XHJcbiAgICB3aWR0aDogY2FsYygxMDAlICsgNnJlbSk7XHJcbiAgICBoZWlnaHQ6IDVyZW07XHJcbiAgfVxyXG59XHJcblxyXG4uc2lkZWJhci1zZXR0aW5ncyB7XHJcbiAgZmxleDogMCAwIGF1dG87XHJcbiAgcGFkZGluZy1ib3R0b206IDFyZW07XHJcblxyXG4gIC53cmFwLWJ1dHRvbiB7XHJcbiAgICBtYXJnaW46IDAgLTNyZW07XHJcblxyXG4gICAgYnV0dG9uIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgICAgIGJvcmRlcjogbm9uZTtcclxuICAgICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgICAgbGluZS1oZWlnaHQ6IDNyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDAgM3JlbTtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICAmLmRpc2FibGVkIHtcclxuICAgICAgICBjdXJzb3I6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvbm90LWFsbG93ZWQuc3ZnKSwgbm90LWFsbG93ZWQ7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDEuMnJlbTtcclxuICAgICAgICB3aWR0aDogMnJlbTtcclxuICAgICAgICBoZWlnaHQ6IDJyZW07XHJcblxyXG4gICAgICAgICYuY29udGFjdHMge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9jb250YWN0cy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnNldHRpbmdzIHtcclxuICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvc2V0dGluZ3Muc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5sb2dvdXQge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9sb2dvdXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICBmbGV4OiAwIDAgN3JlbTtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuXHJcbiAgLnN0YXR1cy1jb250YWluZXIge1xyXG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICAub2ZmbGluZSwgLm9ubGluZSB7XHJcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgZGlzcGxheTogYmxvY2s7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAxLjJyZW07XHJcbiAgICAgIHBhZGRpbmctbGVmdDogMi4ycmVtO1xyXG5cclxuICAgICAgJjpiZWZvcmUge1xyXG4gICAgICAgIGNvbnRlbnQ6ICcnO1xyXG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICB0b3A6IDA7XHJcbiAgICAgICAgbGVmdDogMDtcclxuICAgICAgICBib3JkZXItcmFkaXVzOiA1MCU7XHJcbiAgICAgICAgd2lkdGg6IDEuMnJlbTtcclxuICAgICAgICBoZWlnaHQ6IDEuMnJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5zeW5jaW5nLCAubG9hZGluZyB7XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiA1cmVtO1xyXG4gICAgfVxyXG5cclxuICAgIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDA7XHJcbiAgICAgIGxlZnQ6IDA7XHJcbiAgICAgIGhlaWdodDogMC43cmVtO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICAgIC5zeW5jaW5nIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG5cclxuICAgICAgICAucHJvZ3Jlc3MtYmFyIHtcclxuICAgICAgICAgIGZsZXg6IDEgMCBhdXRvO1xyXG5cclxuICAgICAgICAgIC5maWxsIHtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnByb2dyZXNzLXBlcmNlbnQge1xyXG4gICAgICAgICAgZmxleDogMCAwIGF1dG87XHJcbiAgICAgICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgICAgIGxpbmUtaGVpZ2h0OiAwLjdyZW07XHJcbiAgICAgICAgICBwYWRkaW5nLWxlZnQ6IDAuN3JlbTtcclxuICAgICAgICB9ICAgICAgIFxyXG4gICAgICB9XHJcblxyXG4gICAgICAubG9hZGluZyB7XHJcbiAgICAgICAgYW5pbWF0aW9uOiBtb3ZlIDVzIGxpbmVhciBpbmZpbml0ZTtcclxuICAgICAgICBiYWNrZ3JvdW5kLWltYWdlOlxyXG4gICAgICAgICAgLXdlYmtpdC1ncmFkaWVudChcclxuICAgICAgICAgICAgICBsaW5lYXIsIDAgMCwgMTAwJSAxMDAlLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjEyNSwgcmdiYSgwLCAwLCAwLCAuMTUpKSwgY29sb3Itc3RvcCguMTI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguMjUwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjI1MCwgcmdiYSgwLCAwLCAwLCAuMTApKSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC4zNzUsIHJnYmEoMCwgMCwgMCwgLjEwKSksIGNvbG9yLXN0b3AoLjM3NSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjUwMCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC41MDAsIHJnYmEoMCwgMCwgMCwgLjE1KSksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguNjI1LCByZ2JhKDAsIDAsIDAsIC4xNSkpLCBjb2xvci1zdG9wKC42MjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC43NTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguNzUwLCByZ2JhKDAsIDAsIDAsIC4xMCkpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjg3NSwgcmdiYSgwLCAwLCAwLCAuMTApKSwgY29sb3Itc3RvcCguODc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgdG8odHJhbnNwYXJlbnQpXHJcbiAgICAgICAgICApLFxyXG4gICAgICAgICAgLXdlYmtpdC1ncmFkaWVudChcclxuICAgICAgICAgICAgICBsaW5lYXIsIDAgMTAwJSwgMTAwJSAwLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjEyNSwgcmdiYSgwLCAwLCAwLCAuMzApKSwgY29sb3Itc3RvcCguMTI1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguMjUwLCB0cmFuc3BhcmVudCksIGNvbG9yLXN0b3AoLjI1MCwgcmdiYSgwLCAwLCAwLCAuMjUpKSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC4zNzUsIHJnYmEoMCwgMCwgMCwgLjI1KSksIGNvbG9yLXN0b3AoLjM3NSwgdHJhbnNwYXJlbnQpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjUwMCwgdHJhbnNwYXJlbnQpLCBjb2xvci1zdG9wKC41MDAsIHJnYmEoMCwgMCwgMCwgLjMwKSksXHJcbiAgICAgICAgICAgICAgY29sb3Itc3RvcCguNjI1LCByZ2JhKDAsIDAsIDAsIC4zMCkpLCBjb2xvci1zdG9wKC42MjUsIHRyYW5zcGFyZW50KSxcclxuICAgICAgICAgICAgICBjb2xvci1zdG9wKC43NTAsIHRyYW5zcGFyZW50KSwgY29sb3Itc3RvcCguNzUwLCByZ2JhKDAsIDAsIDAsIC4yNSkpLFxyXG4gICAgICAgICAgICAgIGNvbG9yLXN0b3AoLjg3NSwgcmdiYSgwLCAwLCAwLCAuMjUpKSwgY29sb3Itc3RvcCguODc1LCB0cmFuc3BhcmVudCksXHJcbiAgICAgICAgICAgICAgdG8odHJhbnNwYXJlbnQpXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgIGJhY2tncm91bmQtc2l6ZTogN3JlbSA3cmVtO1xyXG4gICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnVwZGF0ZS1jb250YWluZXIge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZ3JvdzogMTtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG4gICAgdGV4dC1hbGlnbjogcmlnaHQ7XHJcblxyXG4gICAgLnVwZGF0ZS10ZXh0IHtcclxuICAgICAgZmxleDogMSAxIGF1dG87XHJcbiAgICAgIGZvbnQtc2l6ZTogMS4ycmVtO1xyXG4gICAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgICB0ZXh0LWFsaWduOiBsZWZ0O1xyXG5cclxuICAgICAgJi50aW1lIHtcclxuICAgICAgICBmb250LXNpemU6IDEuMXJlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgZmxleDogMSAwIGF1dG87XHJcbiAgICAgIG1hcmdpbjogMC4zcmVtIDAgMCAwLjZyZW07XHJcbiAgICAgIHdpZHRoOiAxLjJyZW07XHJcbiAgICAgIGhlaWdodDogMS4ycmVtO1xyXG5cclxuICAgICAgJi51cGRhdGUge1xyXG4gICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvdXBkYXRlLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi50aW1lIHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3RpbWUuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5Aa2V5ZnJhbWVzIG1vdmUge1xyXG4gIDAlIHtcclxuICAgIGJhY2tncm91bmQtcG9zaXRpb246IDEwMCUgLTdyZW07XHJcbiAgfVxyXG4gIDEwMCUge1xyXG4gICAgYmFja2dyb3VuZC1wb3NpdGlvbjogMTAwJSA3cmVtO1xyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {ActivatedRoute, NavigationStart, Router} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport { ModalService } from '../_helpers/services/modal.service';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-sidebar',\r\n templateUrl: './sidebar.component.html',\r\n styleUrls: ['./sidebar.component.scss']\r\n})\r\nexport class SidebarComponent implements OnInit, OnDestroy {\r\n walletSubRouting;\r\n\r\n walletActive: number;\r\n\r\n contacts = icons.contacts;\r\n settings = icons.settings;\r\n exit = icons.exit;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n public variablesService: VariablesService,\r\n private backend: BackendService,\r\n private modal: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n if (this.router.url.indexOf('/wallet/') !== -1) {\r\n const localPathArr = this.router.url.split('/');\r\n if (localPathArr.length >= 3) {\r\n this.walletActive = parseInt(localPathArr[2], 10);\r\n }\r\n } else if (this.router.url.indexOf('/details') !== -1) {\r\n this.walletActive = this.variablesService.currentWallet.wallet_id;\r\n } else {\r\n this.walletActive = null;\r\n }\r\n\r\n this.walletSubRouting = this.router.events.subscribe((event) => {\r\n if (event instanceof NavigationStart) {\r\n if (event.url.indexOf('/wallet/') !== -1) {\r\n const localPathArr = event.url.split('/');\r\n if (localPathArr.length >= 3) {\r\n this.walletActive = parseInt(localPathArr[2], 10);\r\n }\r\n } else if (event.url.indexOf('/details') !== -1) {\r\n this.walletActive = this.variablesService.currentWallet.wallet_id;\r\n } else {\r\n this.walletActive = null;\r\n }\r\n }\r\n });\r\n }\r\n\r\n contactsRoute() {\r\n if (this.variablesService.appPass) {\r\n this.router.navigate(['/contacts']);\r\n } else {\r\n this.modal.prepareModal(\r\n 'error',\r\n 'CONTACTS.FORM_ERRORS.SET_MASTER_PASSWORD'\r\n );\r\n }\r\n }\r\n\r\n getUpdate() {\r\n this.backend.openUrlInBrowser('zano.org/downloads.html');\r\n }\r\n\r\n logOut() {\r\n this.variablesService.stopCountdown();\r\n this.variablesService.appLogin = false;\r\n this.variablesService.appPass = '';\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/login'], {queryParams: {type: 'auth'}});\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.walletSubRouting.unsubscribe();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE' | translate }}\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_PENDING' | translate }}\\r\\n {{pending.total | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_TOTAL' | translate }}\\r\\n {{total | intToMoney}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n
\\r\\n {{selectedDate.date | date : 'MMM. EEEE, dd, yyyy'}}\\r\\n {{selectedDate.amount}} {{variablesService.defaultCurrency}}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ 'STAKING.TITLE_PERIOD' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n {{ 'STAKING.TITLE_GROUP' | translate }}\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.chart-header {\\n display: flex;\\n flex: 0 0 auto; }\\n\\n.chart-header .general {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n justify-content: center;\\n flex-grow: 1;\\n font-size: 1.3rem;\\n margin: -0.5rem 0; }\\n\\n.chart-header .general > div {\\n display: flex;\\n align-items: center;\\n margin: 0.5rem 0;\\n height: 2rem; }\\n\\n.chart-header .general > div .label {\\n display: inline-block;\\n width: 9rem; }\\n\\n.chart-header .selected {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-end;\\n justify-content: center;\\n flex-grow: 1;\\n font-size: 1.8rem; }\\n\\n.chart-header .selected span {\\n line-height: 2.9rem; }\\n\\n.chart {\\n position: relative;\\n display: flex;\\n align-items: center;\\n flex: 1 1 auto;\\n min-height: 40rem; }\\n\\n.chart > div {\\n position: absolute;\\n width: 100%;\\n height: 100%; }\\n\\n.chart-options {\\n display: flex;\\n align-items: center;\\n height: 2.4rem;\\n flex: 0 0 auto; }\\n\\n.chart-options .title {\\n font-size: 1.3rem;\\n padding: 0 1rem; }\\n\\n.chart-options .title:first-child {\\n padding-left: 0; }\\n\\n.chart-options .options {\\n display: flex;\\n justify-content: space-between;\\n flex-grow: 1;\\n height: 100%; }\\n\\n.chart-options .options button {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 1 auto;\\n cursor: pointer;\\n font-size: 1.3rem;\\n margin: 0 0.1rem;\\n padding: 0;\\n height: 100%; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvc3Rha2luZy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFwcFxcc3Rha2luZ1xcc3Rha2luZy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsYUFBYTtFQUNiLGNBQWMsRUFBQTs7QUFGaEI7SUFLSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLHVCQUF1QjtJQUN2Qix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGlCQUFpQjtJQUNqQixpQkFBaUIsRUFBQTs7QUFYckI7TUFjTSxhQUFhO01BQ2IsbUJBQW1CO01BQ25CLGdCQUFnQjtNQUNoQixZQUFZLEVBQUE7O0FBakJsQjtRQW9CUSxxQkFBcUI7UUFDckIsV0FBVyxFQUFBOztBQXJCbkI7SUEyQkksYUFBYTtJQUNiLHNCQUFzQjtJQUN0QixxQkFBcUI7SUFDckIsdUJBQXVCO0lBQ3ZCLFlBQVk7SUFDWixpQkFBaUIsRUFBQTs7QUFoQ3JCO01BbUNNLG1CQUFtQixFQUFBOztBQUt6QjtFQUNFLGtCQUFrQjtFQUNsQixhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLGNBQWM7RUFDZCxpQkFBaUIsRUFBQTs7QUFMbkI7SUFRSSxrQkFBa0I7SUFDbEIsV0FBVztJQUNYLFlBQVksRUFBQTs7QUFJaEI7RUFDRSxhQUFhO0VBQ2IsbUJBQW1CO0VBQ25CLGNBQWM7RUFDZCxjQUFjLEVBQUE7O0FBSmhCO0lBT0ksaUJBQWlCO0lBQ2pCLGVBQWUsRUFBQTs7QUFSbkI7TUFXTSxlQUFlLEVBQUE7O0FBWHJCO0lBZ0JJLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsWUFBWTtJQUNaLFlBQVksRUFBQTs7QUFuQmhCO01Bc0JNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGNBQWM7TUFDZCxlQUFlO01BQ2YsaUJBQWlCO01BQ2pCLGdCQUFnQjtNQUNoQixVQUFVO01BQ1YsWUFBWSxFQUFBIiwiZmlsZSI6InNyYy9hcHAvc3Rha2luZy9zdGFraW5nLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmNoYXJ0LWhlYWRlciB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuXHJcbiAgLmdlbmVyYWwge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcclxuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW46IC0wLjVyZW0gMDtcclxuXHJcbiAgICA+IGRpdiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIG1hcmdpbjogMC41cmVtIDA7XHJcbiAgICAgIGhlaWdodDogMnJlbTtcclxuXHJcbiAgICAgIC5sYWJlbCB7XHJcbiAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xyXG4gICAgICAgIHdpZHRoOiA5cmVtO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuc2VsZWN0ZWQge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgIGZsZXgtZ3JvdzogMTtcclxuICAgIGZvbnQtc2l6ZTogMS44cmVtO1xyXG5cclxuICAgIHNwYW4ge1xyXG4gICAgICBsaW5lLWhlaWdodDogMi45cmVtO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmNoYXJ0IHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGZsZXg6IDEgMSBhdXRvO1xyXG4gIG1pbi1oZWlnaHQ6IDQwcmVtO1xyXG5cclxuICA+IGRpdiB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICB9XHJcbn1cclxuXHJcbi5jaGFydC1vcHRpb25zIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgaGVpZ2h0OiAyLjRyZW07XHJcbiAgZmxleDogMCAwIGF1dG87XHJcblxyXG4gIC50aXRsZSB7XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuXHJcbiAgICAmOmZpcnN0LWNoaWxke1xyXG4gICAgICBwYWRkaW5nLWxlZnQ6IDA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAub3B0aW9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleC1ncm93OiAxO1xyXG4gICAgaGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBmbGV4OiAxIDEgYXV0bztcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICBmb250LXNpemU6IDEuM3JlbTtcclxuICAgICAgbWFyZ2luOiAwIDAuMXJlbTtcclxuICAgICAgcGFkZGluZzogMDtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0= */\"","import {Component, NgZone, OnInit, OnDestroy} from '@angular/core';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Chart} from 'angular-highcharts';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {ActivatedRoute} from '@angular/router';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {BigNumber} from 'bignumber.js';\r\n\r\n@Component({\r\n selector: 'app-staking',\r\n templateUrl: './staking.component.html',\r\n styleUrls: ['./staking.component.scss']\r\n})\r\nexport class StakingComponent implements OnInit, OnDestroy {\r\n\r\n parentRouting;\r\n heightAppEvent;\r\n refreshStackingEvent;\r\n\r\n periods = [\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.WEEK1'),\r\n key: '1 week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.WEEK2'),\r\n key: '2 week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH1'),\r\n key: '1 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH3'),\r\n key: '3 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.MONTH6'),\r\n key: '6 month',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.YEAR'),\r\n key: '1 year',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.PERIOD.ALL'),\r\n key: 'All',\r\n active: true\r\n }\r\n ];\r\n\r\n groups = [\r\n {\r\n title: this.translate.instant('STAKING.GROUP.DAY'),\r\n key: 'day',\r\n active: true\r\n },\r\n {\r\n title: this.translate.instant('STAKING.GROUP.WEEK'),\r\n key: 'week',\r\n active: false\r\n },\r\n {\r\n title: this.translate.instant('STAKING.GROUP.MONTH'),\r\n key: 'month',\r\n active: false\r\n }\r\n ];\r\n\r\n selectedDate = {\r\n date: null,\r\n amount: null\r\n };\r\n\r\n originalData = [];\r\n\r\n chart: Chart;\r\n\r\n total = new BigNumber(0);\r\n pending = {\r\n list: [],\r\n total: new BigNumber(0)\r\n };\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private variablesService: VariablesService,\r\n private backend: BackendService,\r\n private ngZone: NgZone,\r\n private intToMoneyPipe: IntToMoneyPipe,\r\n private translate: TranslateService\r\n ) {\r\n }\r\n\r\n static makeGroupTime(key, date) {\r\n if (key === 'day') {\r\n return date.setHours(0, 0, 0, 0);\r\n } else if (key === 'week') {\r\n return new Date(date.setDate(date.getDate() - date.getDay())).setHours(0, 0, 0, 0);\r\n } else {\r\n return new Date(date.setDate(1)).setHours(0, 0, 0, 0);\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.parentRouting = this.route.parent.params.subscribe(() => {\r\n this.getMiningHistory();\r\n });\r\n this.heightAppEvent = this.variablesService.getHeightAppEvent.subscribe((newHeight: number) => {\r\n if (!this.pending.total.isZero()) {\r\n const pendingCount = this.pending.list.length;\r\n for (let i = pendingCount - 1; i >= 0; i--) {\r\n if (newHeight - this.pending.list[i].h >= 10) {\r\n this.pending.list.splice(i, 1);\r\n }\r\n }\r\n if (pendingCount !== this.pending.list.length) {\r\n this.pending.total = new BigNumber(0);\r\n for (let i = 0; i < this.pending.list.length; i++) {\r\n this.pending.total = this.pending.total.plus(this.pending.list[i].a);\r\n }\r\n }\r\n }\r\n });\r\n this.refreshStackingEvent = this.variablesService.getRefreshStackingEvent.subscribe((wallet_id: number) => {\r\n if (this.variablesService.currentWallet.wallet_id === wallet_id) {\r\n this.getMiningHistory();\r\n }\r\n });\r\n }\r\n\r\n\r\n drawChart(data) {\r\n this.chart = new Chart({\r\n title: {text: ''},\r\n credits: {enabled: false},\r\n exporting: {enabled: false},\r\n legend: {enabled: false},\r\n chart: {\r\n type: 'line',\r\n backgroundColor: 'transparent',\r\n height: null,\r\n zoomType: null,\r\n events: {\r\n load: () => {\r\n this.changePeriod();\r\n }\r\n }\r\n },\r\n\r\n yAxis: {\r\n min: 0,\r\n tickAmount: 5,\r\n title: {\r\n text: ''\r\n },\r\n gridLineColor: '#2b3644',\r\n gridLineWidth: 2,\r\n lineColor: '#2b3644',\r\n lineWidth: 2,\r\n tickWidth: 2,\r\n tickLength: 120,\r\n tickColor: '#2b3644',\r\n labels: {\r\n y: -8,\r\n align: 'left',\r\n x: -120,\r\n style: {\r\n 'color': '#e0e0e0',\r\n 'fontSize': '13px'\r\n },\r\n format: '{value} ' + this.variablesService.defaultCurrency\r\n },\r\n showLastLabel: false,\r\n },\r\n\r\n xAxis: {\r\n type: 'datetime',\r\n gridLineColor: '#2b3644',\r\n lineColor: '#2b3644',\r\n lineWidth: 2,\r\n tickWidth: 2,\r\n tickLength: 10,\r\n tickColor: '#2b3644',\r\n labels: {\r\n style: {\r\n 'color': '#e0e0e0',\r\n 'fontSize': '13px'\r\n }\r\n },\r\n minPadding: 0,\r\n maxPadding: 0,\r\n minRange: 86400000,\r\n // tickInterval: 86400000,\r\n minTickInterval: 3600000,\r\n },\r\n\r\n tooltip: {\r\n enabled: false\r\n },\r\n\r\n plotOptions: {\r\n area: {\r\n fillColor: {\r\n linearGradient: {\r\n x1: 0,\r\n y1: 0,\r\n x2: 0,\r\n y2: 1\r\n },\r\n stops: [\r\n [0, 'rgba(124,181,236,0.2)'],\r\n [1, 'rgba(124,181,236,0)']\r\n ]\r\n },\r\n marker: {\r\n enabled: false,\r\n radius: 2\r\n },\r\n lineWidth: 2,\r\n threshold: null\r\n },\r\n\r\n series: {\r\n point: {\r\n events: {\r\n mouseOver: (obj) => {\r\n this.selectedDate.date = obj.target['x'];\r\n this.selectedDate.amount = obj.target['y'];\r\n }\r\n }\r\n },\r\n events: {\r\n mouseOut: () => {\r\n this.selectedDate.date = null;\r\n this.selectedDate.amount = null;\r\n }\r\n }\r\n }\r\n },\r\n series: [\r\n {\r\n type: 'area',\r\n data: data\r\n }\r\n ]\r\n });\r\n }\r\n\r\n\r\n getMiningHistory() {\r\n if (this.variablesService.currentWallet.loaded) {\r\n this.backend.getMiningHistory(this.variablesService.currentWallet.wallet_id, (status, data) => {\r\n this.total = new BigNumber(0);\r\n this.pending.list = [];\r\n this.pending.total = new BigNumber(0);\r\n this.originalData = [];\r\n if (data.mined_entries) {\r\n data.mined_entries.forEach((item, key) => {\r\n if (item.t.toString().length === 10) {\r\n data.mined_entries[key].t = (new Date(item.t * 1000)).setUTCMilliseconds(0);\r\n }\r\n });\r\n data.mined_entries.forEach((item) => {\r\n this.total = this.total.plus(item.a);\r\n if (this.variablesService.height_app - item.h < 10) {\r\n this.pending.list.push(item);\r\n this.pending.total = this.pending.total.plus(item.a);\r\n }\r\n this.originalData.push([parseInt(item.t, 10), parseFloat(this.intToMoneyPipe.transform(item.a))]);\r\n });\r\n this.originalData = this.originalData.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n }\r\n this.ngZone.run(() => {\r\n this.drawChart([]);\r\n });\r\n });\r\n }\r\n }\r\n\r\n changePeriod(period?) {\r\n if (period) {\r\n this.periods.forEach((p) => {\r\n p.active = false;\r\n });\r\n period.active = true;\r\n } else {\r\n period = this.periods.find((p) => p.active);\r\n }\r\n\r\n const d = new Date();\r\n let min = null;\r\n const newData = [];\r\n\r\n const group = this.groups.find((g) => g.active);\r\n\r\n if (period.key === '1 week') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate() - 7, 0, 0, 0, 0);\r\n } else if (period.key === '2 week') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth(), d.getDate() - 14, 0, 0, 0, 0);\r\n } else if (period.key === '1 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 1, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '3 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 3, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '6 month') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear(), d.getMonth() - 6, d.getDate(), 0, 0, 0, 0);\r\n } else if (period.key === '1 year') {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n min = Date.UTC(d.getFullYear() - 1, d.getMonth(), d.getDate(), 0, 0, 0, 0);\r\n } else {\r\n this.originalData.forEach((item) => {\r\n const time = StakingComponent.makeGroupTime(group.key, new Date(item[0]));\r\n const find = newData.find(itemNew => itemNew[0] === time);\r\n if (find) {\r\n find[1] = new BigNumber(find[1]).plus(item[1]).toNumber();\r\n } else {\r\n newData.push([time, item[1]]);\r\n }\r\n });\r\n this.chart.ref.series[0].setData(newData, true);\r\n }\r\n\r\n this.chart.ref.xAxis[0].setExtremes(min, null);\r\n }\r\n\r\n changeGroup(group) {\r\n this.groups.forEach((g) => {\r\n g.active = false;\r\n });\r\n group.active = true;\r\n this.changePeriod();\r\n }\r\n\r\n ngOnDestroy() {\r\n this.parentRouting.unsubscribe();\r\n this.heightAppEvent.unsubscribe();\r\n this.refreshStackingEvent.unsubscribe();\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{ wallet.name }}\\r\\n {{ 'BREADCRUMBS.TRANSFER_ALIAS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
0 && (transferAddressAlias || !transferAddressValid || (transferAddressValid && !permissionSend) || notEnoughMoney)\\\">\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.WRONG_ADDRESS' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.ALIAS_EXISTS' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'TRANSFER_ALIAS.FORM_ERRORS.NO_MONEY' | translate }}\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
{{ \\\"TRANSFER_ALIAS.COST\\\" | translate : {value: variablesService.default_fee, currency: variablesService.defaultCurrency} }}
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".form-transfer {\\n margin: 2.4rem 0; }\\n .form-transfer .alias-name {\\n width: 50%; }\\n .form-transfer .alias-cost {\\n font-size: 1.3rem;\\n margin-top: 2rem; }\\n .form-transfer .wrap-buttons {\\n display: flex;\\n justify-content: space-between;\\n margin: 2.5rem -0.7rem; }\\n .form-transfer .wrap-buttons button {\\n margin: 0 0.7rem;\\n width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHJhbnNmZXItYWxpYXMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHRyYW5zZmVyLWFsaWFzXFx0cmFuc2Zlci1hbGlhcy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGdCQUFnQixFQUFBO0VBRGxCO0lBSUksVUFBVSxFQUFBO0VBSmQ7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCLEVBQUE7RUFUcEI7SUFhSSxhQUFhO0lBQ2IsOEJBQThCO0lBQzlCLHNCQUFzQixFQUFBO0VBZjFCO01Ba0JNLGdCQUFnQjtNQUNoQixZQUFZLEVBQUEiLCJmaWxlIjoic3JjL2FwcC90cmFuc2Zlci1hbGlhcy90cmFuc2Zlci1hbGlhcy5jb21wb25lbnQuc2NzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb3JtLXRyYW5zZmVyIHtcclxuICBtYXJnaW46IDIuNHJlbSAwO1xyXG5cclxuICAuYWxpYXMtbmFtZSB7XHJcbiAgICB3aWR0aDogNTAlO1xyXG4gIH1cclxuXHJcbiAgLmFsaWFzLWNvc3Qge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBtYXJnaW4tdG9wOiAycmVtO1xyXG4gIH1cclxuXHJcbiAgLndyYXAtYnV0dG9ucyB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgbWFyZ2luOiAyLjVyZW0gLTAuN3JlbTtcclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBtYXJnaW46IDAgMC43cmVtO1xyXG4gICAgICB3aWR0aDogMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\"","import {Component, NgZone, OnInit} from '@angular/core';\r\nimport {Location} from '@angular/common';\r\nimport {Router} from '@angular/router';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {ModalService} from '../_helpers/services/modal.service';\r\nimport {Wallet} from '../_helpers/models/wallet.model';\r\n\r\n@Component({\r\n selector: 'app-transfer-alias',\r\n templateUrl: './transfer-alias.component.html',\r\n styleUrls: ['./transfer-alias.component.scss']\r\n})\r\nexport class TransferAliasComponent implements OnInit {\r\n\r\n wallet: Wallet;\r\n alias: any;\r\n transferAddress = '';\r\n transferAddressValid: boolean;\r\n transferAddressAlias: boolean;\r\n permissionSend: boolean;\r\n notEnoughMoney: boolean;\r\n requestProcessing = false;\r\n\r\n constructor(\r\n private location: Location,\r\n private router: Router,\r\n private backend: BackendService,\r\n private variablesService: VariablesService,\r\n private modalService: ModalService,\r\n private ngZone: NgZone\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.wallet = this.variablesService.currentWallet;\r\n const alias = this.backend.getWalletAlias(this.wallet.address);\r\n this.alias = {\r\n name: alias.name,\r\n address: alias.address,\r\n comment: alias.comment,\r\n tracking_key: alias.tracking_key\r\n };\r\n this.notEnoughMoney = this.wallet.unlocked_balance.isLessThan(this.variablesService.default_fee_big);\r\n }\r\n\r\n changeAddress() {\r\n this.backend.validateAddress(this.transferAddress, status => {\r\n this.transferAddressValid = status;\r\n if (status) {\r\n this.backend.getPoolInfo((statusPool, dataPool) => {\r\n if (dataPool.hasOwnProperty('aliases_que') && dataPool.aliases_que.length) {\r\n this.setStatus(!dataPool.aliases_que.some((el) => el.address === this.transferAddress));\r\n } else {\r\n this.setStatus(status);\r\n }\r\n });\r\n } else {\r\n this.setStatus(false);\r\n }\r\n });\r\n }\r\n\r\n setStatus(statusSet) {\r\n this.permissionSend = statusSet;\r\n if (statusSet) {\r\n this.backend.getAliasByAddress(this.transferAddress, (status) => {\r\n this.ngZone.run(() => {\r\n if (status) {\r\n this.transferAddressAlias = true;\r\n this.permissionSend = false;\r\n } else {\r\n this.transferAddressAlias = false;\r\n }\r\n });\r\n });\r\n } else {\r\n this.ngZone.run(() => {\r\n this.transferAddressAlias = false;\r\n });\r\n }\r\n }\r\n\r\n transferAlias() {\r\n if (this.requestProcessing || !this.permissionSend || !this.transferAddressValid || this.notEnoughMoney) {\r\n return;\r\n }\r\n this.requestProcessing = true;\r\n const newAlias = {\r\n name: this.alias.name,\r\n address: this.transferAddress,\r\n comment: this.alias.comment,\r\n tracking_key: this.alias.tracking_key\r\n };\r\n this.backend.updateAlias(this.wallet.wallet_id, newAlias, this.variablesService.default_fee, (status, data) => {\r\n if (status && data.hasOwnProperty('success') && data.success) {\r\n this.modalService.prepareModal('info', 'TRANSFER_ALIAS.REQUEST_SEND_REG');\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.wallet.wallet_id]);\r\n });\r\n }\r\n this.requestProcessing = false;\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n @bitmain\\r\\n
\\r\\n \\r\\n \\r\\n {{ 'COMMON.BACK' | translate }}\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
10:39
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
11:44
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
12:15
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
13:13
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\\r\\n
\\r\\n
\\r\\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\"","module.exports = \":host {\\n display: flex;\\n flex-direction: column;\\n width: 100%; }\\n\\n.head {\\n flex: 0 0 auto;\\n box-sizing: content-box;\\n margin: -3rem -3rem 0; }\\n\\n.messages-content {\\n display: flex;\\n flex-direction: column;\\n justify-content: space-between;\\n flex-grow: 1; }\\n\\n.messages-content .messages-list {\\n display: flex;\\n flex-direction: column;\\n font-size: 1.3rem;\\n margin: 1rem -3rem;\\n padding: 0 3rem;\\n overflow-y: overlay; }\\n\\n.messages-content .messages-list div {\\n margin: 0.7rem 0; }\\n\\n.messages-content .messages-list div.date {\\n text-align: center; }\\n\\n.messages-content .messages-list div.my, .messages-content .messages-list div.buddy {\\n position: relative;\\n padding: 1.8rem;\\n max-width: 60%; }\\n\\n.messages-content .messages-list div.buddy {\\n align-self: flex-end; }\\n\\n.messages-content .type-message {\\n display: flex;\\n flex: 0 0 auto;\\n width: 100%;\\n height: 4.2rem; }\\n\\n.messages-content .type-message .input-block {\\n width: 100%; }\\n\\n.messages-content .type-message .input-block > textarea {\\n min-height: 4.2rem; }\\n\\n.messages-content .type-message button {\\n flex: 0 0 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvdHlwaW5nLW1lc3NhZ2UvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHR5cGluZy1tZXNzYWdlXFx0eXBpbmctbWVzc2FnZS5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsV0FBVyxFQUFBOztBQUdiO0VBQ0UsY0FBYztFQUNkLHVCQUF1QjtFQUN2QixxQkFBcUIsRUFBQTs7QUFHdkI7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLDhCQUE4QjtFQUM5QixZQUFZLEVBQUE7O0FBSmQ7SUFPSSxhQUFhO0lBQ2Isc0JBQXNCO0lBQ3RCLGlCQUFpQjtJQUNqQixrQkFBa0I7SUFDbEIsZUFBZTtJQUNmLG1CQUFtQixFQUFBOztBQVp2QjtNQWVNLGdCQUFnQixFQUFBOztBQWZ0QjtRQWtCUSxrQkFBa0IsRUFBQTs7QUFsQjFCO1FBc0JRLGtCQUFrQjtRQUNsQixlQUFlO1FBQ2YsY0FBYyxFQUFBOztBQXhCdEI7UUE0QlEsb0JBQW9CLEVBQUE7O0FBNUI1QjtJQWtDSSxhQUFhO0lBQ2IsY0FBYztJQUNkLFdBQVc7SUFDWCxjQUFjLEVBQUE7O0FBckNsQjtNQXdDTSxXQUFXLEVBQUE7O0FBeENqQjtRQTJDUSxrQkFBa0IsRUFBQTs7QUEzQzFCO01BZ0RNLGVBQWUsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3R5cGluZy1tZXNzYWdlL3R5cGluZy1tZXNzYWdlLmNvbXBvbmVudC5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiOmhvc3Qge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICB3aWR0aDogMTAwJTtcclxufVxyXG5cclxuLmhlYWQge1xyXG4gIGZsZXg6IDAgMCBhdXRvO1xyXG4gIGJveC1zaXppbmc6IGNvbnRlbnQtYm94O1xyXG4gIG1hcmdpbjogLTNyZW0gLTNyZW0gMDtcclxufVxyXG5cclxuLm1lc3NhZ2VzLWNvbnRlbnQge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgZmxleC1ncm93OiAxO1xyXG5cclxuICAubWVzc2FnZXMtbGlzdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbWFyZ2luOiAxcmVtIC0zcmVtO1xyXG4gICAgcGFkZGluZzogMCAzcmVtO1xyXG4gICAgb3ZlcmZsb3cteTogb3ZlcmxheTtcclxuXHJcbiAgICBkaXYge1xyXG4gICAgICBtYXJnaW46IDAuN3JlbSAwO1xyXG5cclxuICAgICAgJi5kYXRlIHtcclxuICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYubXksICYuYnVkZHkge1xyXG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICBwYWRkaW5nOiAxLjhyZW07XHJcbiAgICAgICAgbWF4LXdpZHRoOiA2MCU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuYnVkZHkge1xyXG4gICAgICAgIGFsaWduLXNlbGY6IGZsZXgtZW5kO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudHlwZS1tZXNzYWdlIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBmbGV4OiAwIDAgYXV0bztcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiA0LjJyZW07XHJcblxyXG4gICAgLmlucHV0LWJsb2NrIHtcclxuICAgICAgd2lkdGg6IDEwMCU7XHJcblxyXG4gICAgICA+IHRleHRhcmVhIHtcclxuICAgICAgICBtaW4taGVpZ2h0OiA0LjJyZW07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBidXR0b24ge1xyXG4gICAgICBmbGV4OiAwIDAgMTVyZW07XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4iXX0= */\"","import { Component, OnInit } from '@angular/core';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\n@Component({\r\n selector: 'app-typing-message',\r\n templateUrl: './typing-message.component.html',\r\n styleUrls: ['./typing-message.component.scss']\r\n})\r\nexport class TypingMessageComponent implements OnInit {\r\n\r\n messagesId: number;\r\n private subMessages: any;\r\n\r\n constructor(private route: ActivatedRoute) {\r\n this.route.params.subscribe( params => console.log(params) );\r\n }\r\n\r\n ngOnInit() {\r\n\r\n }\r\n\r\n}\r\n","module.exports = \"
\\r\\n\\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.name}}\\r\\n {{ 'BREADCRUMBS.WALLET_DETAILS' | translate }}\\r\\n
\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.NAME_REQUIRED' | translate }}\\r\\n
\\r\\n
\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.NAME_DUPLICATE' | translate }}\\r\\n
\\r\\n
\\r\\n
= variablesService.maxWalletNameLength\\\">\\r\\n {{ 'WALLET_DETAILS.FORM_ERRORS.MAX_LENGTH' | translate }}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n
\\r\\n
{{ 'WALLET_DETAILS.SEED_PHRASE_HINT' | translate }}
\\r\\n
\\r\\n \\r\\n
{{(index + 1) + '. ' + word}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n\\r\\n
\\r\\n\"","module.exports = \".form-details {\\n margin-top: 1.8rem; }\\n .form-details .input-block:first-child {\\n width: 50%; }\\n .form-details .seed-phrase {\\n display: flex;\\n font-size: 1.4rem;\\n line-height: 1.5rem;\\n padding: 1.4rem;\\n width: 100%;\\n height: 8.8rem; }\\n .form-details .seed-phrase .seed-phrase-hint {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n cursor: pointer;\\n width: 100%;\\n height: 100%; }\\n .form-details .seed-phrase .seed-phrase-content {\\n display: flex;\\n flex-direction: column;\\n flex-wrap: wrap;\\n width: 100%;\\n height: 100%; }\\n .form-details .wallet-buttons {\\n display: flex;\\n align-items: center;\\n justify-content: space-between; }\\n .form-details .wallet-buttons button {\\n margin: 2.9rem 0;\\n width: 100%;\\n max-width: 15rem; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0LWRldGFpbHMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhcHBcXHdhbGxldC1kZXRhaWxzXFx3YWxsZXQtZGV0YWlscy5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQixFQUFBO0VBRHBCO0lBTU0sVUFBVSxFQUFBO0VBTmhCO0lBV0ksYUFBYTtJQUNiLGlCQUFpQjtJQUNqQixtQkFBbUI7SUFDbkIsZUFBZTtJQUNmLFdBQVc7SUFDWCxjQUFjLEVBQUE7RUFoQmxCO01BbUJNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGVBQWU7TUFDZixXQUFXO01BQ1gsWUFBWSxFQUFBO0VBeEJsQjtNQTRCTSxhQUFhO01BQ2Isc0JBQXNCO01BQ3RCLGVBQWU7TUFDZixXQUFXO01BQ1gsWUFBWSxFQUFBO0VBaENsQjtJQXFDSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLDhCQUE4QixFQUFBO0VBdkNsQztNQTBDTSxnQkFBZ0I7TUFDaEIsV0FBVztNQUNYLGdCQUFnQixFQUFBIiwiZmlsZSI6InNyYy9hcHAvd2FsbGV0LWRldGFpbHMvd2FsbGV0LWRldGFpbHMuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuZm9ybS1kZXRhaWxzIHtcclxuICBtYXJnaW4tdG9wOiAxLjhyZW07XHJcblxyXG4gIC5pbnB1dC1ibG9jayB7XHJcblxyXG4gICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgIHdpZHRoOiA1MCU7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuc2VlZC1waHJhc2Uge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuNXJlbTtcclxuICAgIHBhZGRpbmc6IDEuNHJlbTtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgaGVpZ2h0OiA4LjhyZW07XHJcblxyXG4gICAgLnNlZWQtcGhyYXNlLWhpbnQge1xyXG4gICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG5cclxuICAgIC5zZWVkLXBocmFzZS1jb250ZW50IHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgZmxleC13cmFwOiB3cmFwO1xyXG4gICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLndhbGxldC1idXR0b25zIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICAgIG1hcmdpbjogMi45cmVtIDA7XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtYXgtd2lkdGg6IDE1cmVtO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbn1cclxuIl19 */\"","import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';\r\nimport {FormGroup, FormControl, Validators} from '@angular/forms';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {Router} from '@angular/router';\r\nimport {Location} from '@angular/common';\r\n\r\n@Component({\r\n selector: 'app-wallet-details',\r\n templateUrl: './wallet-details.component.html',\r\n styleUrls: ['./wallet-details.component.scss']\r\n})\r\nexport class WalletDetailsComponent implements OnInit, OnDestroy {\r\n seedPhrase = '';\r\n showSeed = false;\r\n\r\n detailsForm = new FormGroup({\r\n name: new FormControl('', [Validators.required, (g: FormControl) => {\r\n for (let i = 0; i < this.variablesService.wallets.length; i++) {\r\n if (g.value === this.variablesService.wallets[i].name) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n return {'same': true};\r\n } else {\r\n return {'duplicate': true};\r\n }\r\n }\r\n }\r\n return null;\r\n }]),\r\n path: new FormControl('')\r\n });\r\n\r\n constructor(\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private location: Location\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.showSeed = false;\r\n this.detailsForm.get('name').setValue(this.variablesService.currentWallet.name);\r\n this.detailsForm.get('path').setValue(this.variablesService.currentWallet.path);\r\n this.backend.getSmartWalletInfo(this.variablesService.currentWallet.wallet_id, (status, data) => {\r\n if (data.hasOwnProperty('restore_key')) {\r\n this.ngZone.run(() => {\r\n this.seedPhrase = data['restore_key'].trim();\r\n });\r\n }\r\n });\r\n }\r\n\r\n showSeedPhrase() {\r\n this.showSeed = true;\r\n }\r\n\r\n onSubmitEdit() {\r\n if (this.detailsForm.value) {\r\n this.variablesService.currentWallet.name = this.detailsForm.get('name').value;\r\n this.ngZone.run(() => {\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n });\r\n }\r\n }\r\n\r\n closeWallet() {\r\n this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {\r\n for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n this.variablesService.wallets.splice(i, 1);\r\n }\r\n }\r\n this.ngZone.run(() => {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.currentWallet = this.variablesService.wallets[0];\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n } else {\r\n this.router.navigate(['/']);\r\n }\r\n });\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n });\r\n }\r\n\r\n back() {\r\n this.location.back();\r\n }\r\n\r\n ngOnDestroy() {}\r\n\r\n}\r\n","module.exports = \"
\\r\\n
\\r\\n

{{variablesService.currentWallet.name}}

\\r\\n \\r\\n
\\r\\n {{variablesService.currentWallet.alias['name']}}\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.address}}\\r\\n \\r\\n
\\r\\n
\\r\\n {{variablesService.currentWallet.balance | intToMoney : '3'}} {{variablesService.defaultCurrency}}\\r\\n $ {{variablesService.currentWallet.getMoneyEquivalent(variablesService.moneyEquivalent) | intToMoney | number : '1.2-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{ tab.title | translate }}\\r\\n {{variablesService.currentWallet.new_contracts}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n\\r\\n\"","module.exports = \":host {\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n padding: 0 3rem 3rem;\\n min-width: 95rem;\\n width: 100%;\\n height: 100%; }\\n\\n.header {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n flex: 0 0 auto;\\n height: 8rem; }\\n\\n.header > div {\\n display: flex;\\n align-items: center; }\\n\\n.header > div :not(:last-child) {\\n margin-right: 3.2rem; }\\n\\n.header h3 {\\n font-size: 1.7rem;\\n font-weight: 600;\\n text-overflow: ellipsis;\\n overflow: hidden;\\n white-space: nowrap;\\n max-width: 50rem;\\n line-height: 2.7rem; }\\n\\n.header button {\\n display: flex;\\n align-items: center;\\n background: transparent;\\n border: none;\\n cursor: pointer;\\n font-weight: 400;\\n outline: none;\\n padding: 0; }\\n\\n.header button .icon {\\n margin-right: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.header button .icon.account {\\n height: 1.6rem;\\n -webkit-mask: url('account.svg') no-repeat center;\\n mask: url('account.svg') no-repeat center; }\\n\\n.header button .icon.lock {\\n -webkit-mask: url('lock.svg') no-repeat center;\\n mask: url('lock.svg') no-repeat center; }\\n\\n.header button .icon.details {\\n -webkit-mask: url('details-settings.svg') no-repeat center;\\n mask: url('details-settings.svg') no-repeat center;\\n margin-right: 0;\\n height: 1.8rem; }\\n\\n.header button .icon.close-wallet {\\n -webkit-mask: url('close-wallet.svg') no-repeat center;\\n mask: url('close-wallet.svg') no-repeat center;\\n margin-right: 0; }\\n\\n.header .alias {\\n display: flex;\\n align-items: center;\\n font-size: 1.3rem; }\\n\\n.header .alias .icon {\\n cursor: pointer;\\n margin-right: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.header .alias .icon.edit {\\n -webkit-mask: url('details.svg') no-repeat center;\\n mask: url('details.svg') no-repeat center; }\\n\\n.header .alias .icon.transfer {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.address {\\n display: flex;\\n align-items: center;\\n flex: 0 0 auto;\\n font-size: 1.4rem;\\n line-height: 1.7rem; }\\n\\n.address .icon {\\n cursor: pointer;\\n margin-left: 1.2rem;\\n width: 1.7rem;\\n height: 1.7rem; }\\n\\n.address .icon.copy {\\n width: 1.8rem;\\n -webkit-mask: url('copy.svg') no-repeat center;\\n mask: url('copy.svg') no-repeat center; }\\n\\n.address .icon.copy:hover {\\n opacity: 0.75; }\\n\\n.address .icon.copied {\\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\\n mask: url('complete-testwallet.svg') no-repeat center; }\\n\\n.balance {\\n display: flex;\\n align-items: flex-end;\\n justify-content: flex-start;\\n flex: 0 0 auto;\\n margin: 2.6rem 0; }\\n\\n.balance :first-child {\\n font-size: 3.3rem;\\n font-weight: 600;\\n line-height: 2.4rem;\\n margin-right: 3.5rem; }\\n\\n.balance :last-child {\\n font-size: 1.8rem;\\n font-weight: 600;\\n line-height: 1.3rem; }\\n\\n.tabs {\\n display: flex;\\n flex-direction: column;\\n flex: 1 1 auto; }\\n\\n.tabs .tabs-header {\\n display: flex;\\n justify-content: space-between;\\n flex: 0 0 auto; }\\n\\n.tabs .tabs-header .tab {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex: 1 0 auto;\\n cursor: pointer;\\n padding: 0 1rem;\\n height: 5rem; }\\n\\n.tabs .tabs-header .tab .animated {\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n margin-right: 1.3rem; }\\n\\n.tabs .tabs-header .tab .animated ::ng-deep svg {\\n width: 2rem;\\n height: 2rem; }\\n\\n.tabs .tabs-header .tab .animated ::ng-deep svg path, .tabs .tabs-header .tab .animated ::ng-deep svg circle, .tabs .tabs-header .tab .animated ::ng-deep svg polygon {\\n fill: #4db1ff; }\\n\\n.tabs .tabs-header .tab .icon {\\n margin-right: 1.3rem;\\n width: 2rem;\\n height: 2rem; }\\n\\n.tabs .tabs-header .tab .icon.send {\\n -webkit-mask: url('send.svg') no-repeat center;\\n mask: url('send.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.receive {\\n -webkit-mask: url('receive.svg') no-repeat center;\\n mask: url('receive.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.history {\\n -webkit-mask: url('history.svg') no-repeat center;\\n mask: url('history.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.contracts {\\n -webkit-mask: url('contracts.svg') no-repeat center;\\n mask: url('contracts.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.messages {\\n -webkit-mask: url('message.svg') no-repeat center;\\n mask: url('message.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .icon.staking {\\n -webkit-mask: url('staking.svg') no-repeat center;\\n mask: url('staking.svg') no-repeat center; }\\n\\n.tabs .tabs-header .tab .indicator {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n border-radius: 1rem;\\n font-size: 1rem;\\n font-weight: 600;\\n margin-left: 1.3rem;\\n padding: 0 0.5rem;\\n min-width: 1.6rem;\\n height: 1.6rem; }\\n\\n.tabs .tabs-header .tab.disabled {\\n cursor: url('not-allowed.svg'), not-allowed; }\\n\\n.tabs .tabs-header .tab:not(:last-child) {\\n margin-right: 0.3rem; }\\n\\n.tabs .tabs-content {\\n display: flex;\\n padding: 3rem;\\n flex: 1 1 auto;\\n overflow-x: hidden;\\n overflow-y: overlay; }\\n\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9hcHAvd2FsbGV0L0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXBwXFx3YWxsZXRcXHdhbGxldC5jb21wb25lbnQuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFLGtCQUFrQjtFQUNsQixhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLG9CQUFvQjtFQUNwQixnQkFBZ0I7RUFDaEIsV0FBVztFQUNYLFlBQVksRUFBQTs7QUFHZDtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsOEJBQThCO0VBQzlCLGNBQWM7RUFDZCxZQUFZLEVBQUE7O0FBTGQ7SUFRSSxhQUFhO0lBQ2IsbUJBQW1CLEVBQUE7O0FBVHZCO01BWU0sb0JBQW9CLEVBQUE7O0FBWjFCO0lBaUJJLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsdUJBQXVCO0lBQ3ZCLGdCQUFnQjtJQUNoQixtQkFBbUI7SUFDbkIsZ0JBQWdCO0lBQ2hCLG1CQUFtQixFQUFBOztBQXZCdkI7SUEyQkksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQix1QkFBdUI7SUFDdkIsWUFBWTtJQUNaLGVBQWU7SUFDZixnQkFBZ0I7SUFDaEIsYUFBYTtJQUNiLFVBQVUsRUFBQTs7QUFsQ2Q7TUFxQ00sb0JBQW9CO01BQ3BCLGFBQWE7TUFDYixjQUFjLEVBQUE7O0FBdkNwQjtRQTBDUSxjQUFjO1FBQ2QsaURBQTBEO2dCQUExRCx5Q0FBMEQsRUFBQTs7QUEzQ2xFO1FBK0NRLDhDQUF1RDtnQkFBdkQsc0NBQXVELEVBQUE7O0FBL0MvRDtRQW1EUSwwREFBbUU7Z0JBQW5FLGtEQUFtRTtRQUNuRSxlQUFlO1FBQ2YsY0FBYyxFQUFBOztBQXJEdEI7UUF5RFEsc0RBQStEO2dCQUEvRCw4Q0FBK0Q7UUFDL0QsZUFBZSxFQUFBOztBQTFEdkI7SUFnRUksYUFBYTtJQUNiLG1CQUFtQjtJQUNuQixpQkFBaUIsRUFBQTs7QUFsRXJCO01BcUVNLGVBQWU7TUFDZixvQkFBb0I7TUFDcEIsYUFBYTtNQUNiLGNBQWMsRUFBQTs7QUF4RXBCO1FBMkVRLGlEQUEwRDtnQkFBMUQseUNBQTBELEVBQUE7O0FBM0VsRTtRQStFUSw4Q0FBdUQ7Z0JBQXZELHNDQUF1RCxFQUFBOztBQU0vRDtFQUNFLGFBQWE7RUFDYixtQkFBbUI7RUFDbkIsY0FBYztFQUNkLGlCQUFpQjtFQUNqQixtQkFBbUIsRUFBQTs7QUFMckI7SUFRSSxlQUFlO0lBQ2YsbUJBQW1CO0lBQ25CLGFBQWE7SUFDYixjQUFjLEVBQUE7O0FBWGxCO01BY00sYUFBYTtNQUNiLDhDQUF1RDtjQUF2RCxzQ0FBdUQsRUFBQTs7QUFmN0Q7UUFrQlEsYUFBYSxFQUFBOztBQWxCckI7TUF1Qk0sNkRBQXNFO2NBQXRFLHFEQUFzRSxFQUFBOztBQUs1RTtFQUNFLGFBQWE7RUFDYixxQkFBcUI7RUFDckIsMkJBQTJCO0VBQzNCLGNBQWM7RUFDZCxnQkFBZ0IsRUFBQTs7QUFMbEI7SUFRSSxpQkFBaUI7SUFDakIsZ0JBQWdCO0lBQ2hCLG1CQUFtQjtJQUNuQixvQkFBb0IsRUFBQTs7QUFYeEI7SUFlSSxpQkFBaUI7SUFDakIsZ0JBQWdCO0lBQ2hCLG1CQUFtQixFQUFBOztBQUl2QjtFQUNFLGFBQWE7RUFDYixzQkFBc0I7RUFDdEIsY0FBYyxFQUFBOztBQUhoQjtJQU1JLGFBQWE7SUFDYiw4QkFBOEI7SUFDOUIsY0FBYyxFQUFBOztBQVJsQjtNQVdNLGFBQWE7TUFDYixtQkFBbUI7TUFDbkIsdUJBQXVCO01BQ3ZCLGNBQWM7TUFDZCxlQUFlO01BQ2YsZUFBZTtNQUNmLFlBQVksRUFBQTs7QUFqQmxCO1FBb0JRLGFBQWE7UUFDYix1QkFBdUI7UUFDdkIsbUJBQW1CO1FBQ25CLG9CQUFvQixFQUFBOztBQXZCNUI7UUE0QlEsV0FBVztRQUNYLFlBQVksRUFBQTs7QUE3QnBCO1VBZ0NVLGFBQWEsRUFBQTs7QUFoQ3ZCO1FBcUNRLG9CQUFvQjtRQUNwQixXQUFXO1FBQ1gsWUFBWSxFQUFBOztBQXZDcEI7VUEwQ1UsOENBQXVEO2tCQUF2RCxzQ0FBdUQsRUFBQTs7QUExQ2pFO1VBOENVLGlEQUEwRDtrQkFBMUQseUNBQTBELEVBQUE7O0FBOUNwRTtVQWtEVSxpREFBMEQ7a0JBQTFELHlDQUEwRCxFQUFBOztBQWxEcEU7VUFzRFUsbURBQTREO2tCQUE1RCwyQ0FBNEQsRUFBQTs7QUF0RHRFO1VBMERVLGlEQUEwRDtrQkFBMUQseUNBQTBELEVBQUE7O0FBMURwRTtVQThEVSxpREFBMEQ7a0JBQTFELHlDQUEwRCxFQUFBOztBQTlEcEU7UUFtRVEsYUFBYTtRQUNiLG1CQUFtQjtRQUNuQix1QkFBdUI7UUFDdkIsbUJBQW1CO1FBQ25CLGVBQWU7UUFDZixnQkFBZ0I7UUFDaEIsbUJBQW1CO1FBQ25CLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsY0FBYyxFQUFBOztBQTVFdEI7UUFnRlEsMkNBQTRELEVBQUE7O0FBaEZwRTtRQW9GUSxvQkFBb0IsRUFBQTs7QUFwRjVCO0lBMEZJLGFBQWE7SUFDYixhQUFhO0lBQ2IsY0FBYztJQUNkLGtCQUFrQjtJQUNsQixtQkFBbUIsRUFBQSIsImZpbGUiOiJzcmMvYXBwL3dhbGxldC93YWxsZXQuY29tcG9uZW50LnNjc3MiLCJzb3VyY2VzQ29udGVudCI6WyI6aG9zdCB7XHJcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICBwYWRkaW5nOiAwIDNyZW0gM3JlbTtcclxuICBtaW4td2lkdGg6IDk1cmVtO1xyXG4gIHdpZHRoOiAxMDAlO1xyXG4gIGhlaWdodDogMTAwJTtcclxufVxyXG5cclxuLmhlYWRlciB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuICBoZWlnaHQ6IDhyZW07XHJcblxyXG4gID4gZGl2IHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG5cclxuICAgIDpub3QoOmxhc3QtY2hpbGQpIHtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAzLjJyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBoMyB7XHJcbiAgICBmb250LXNpemU6IDEuN3JlbTtcclxuICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcclxuICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xyXG4gICAgbWF4LXdpZHRoOiA1MHJlbTtcclxuICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcbiAgfVxyXG5cclxuICBidXR0b24ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlcjogbm9uZTtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICBvdXRsaW5lOiBub25lO1xyXG4gICAgcGFkZGluZzogMDtcclxuXHJcbiAgICAuaWNvbiB7XHJcbiAgICAgIG1hcmdpbi1yaWdodDogMS4ycmVtO1xyXG4gICAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuN3JlbTtcclxuXHJcbiAgICAgICYuYWNjb3VudCB7XHJcbiAgICAgICAgaGVpZ2h0OiAxLjZyZW07XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9hY2NvdW50LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi5sb2NrIHtcclxuICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2xvY2suc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmRldGFpbHMge1xyXG4gICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvZGV0YWlscy1zZXR0aW5ncy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAwO1xyXG4gICAgICAgIGhlaWdodDogMS44cmVtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAmLmNsb3NlLXdhbGxldCB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9jbG9zZS13YWxsZXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLmFsaWFzIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIG1hcmdpbi1yaWdodDogMS4ycmVtO1xyXG4gICAgICB3aWR0aDogMS43cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuN3JlbTtcclxuXHJcbiAgICAgICYuZWRpdCB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9kZXRhaWxzLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG5cclxuICAgICAgJi50cmFuc2ZlciB7XHJcbiAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZW5kLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmFkZHJlc3Mge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuICBmb250LXNpemU6IDEuNHJlbTtcclxuICBsaW5lLWhlaWdodDogMS43cmVtO1xyXG5cclxuICAuaWNvbiB7XHJcbiAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICBtYXJnaW4tbGVmdDogMS4ycmVtO1xyXG4gICAgd2lkdGg6IDEuN3JlbTtcclxuICAgIGhlaWdodDogMS43cmVtO1xyXG5cclxuICAgICYuY29weSB7XHJcbiAgICAgIHdpZHRoOiAxLjhyZW07XHJcbiAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvY29weS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcblxyXG4gICAgICAmOmhvdmVyIHtcclxuICAgICAgICBvcGFjaXR5OiAwLjc1O1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJi5jb3BpZWQge1xyXG4gICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmJhbGFuY2Uge1xyXG4gIGRpc3BsYXk6IGZsZXg7XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtZW5kO1xyXG4gIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICBmbGV4OiAwIDAgYXV0bztcclxuICBtYXJnaW46IDIuNnJlbSAwO1xyXG5cclxuICA6Zmlyc3QtY2hpbGQge1xyXG4gICAgZm9udC1zaXplOiAzLjNyZW07XHJcbiAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuNHJlbTtcclxuICAgIG1hcmdpbi1yaWdodDogMy41cmVtO1xyXG4gIH1cclxuXHJcbiAgOmxhc3QtY2hpbGQge1xyXG4gICAgZm9udC1zaXplOiAxLjhyZW07XHJcbiAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuM3JlbTtcclxuICB9XHJcbn1cclxuXHJcbi50YWJzIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgZmxleDogMSAxIGF1dG87XHJcblxyXG4gIC50YWJzLWhlYWRlciB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleDogMCAwIGF1dG87XHJcblxyXG4gICAgLnRhYiB7XHJcbiAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xyXG4gICAgICBmbGV4OiAxIDAgYXV0bztcclxuICAgICAgY3Vyc29yOiBwb2ludGVyO1xyXG4gICAgICBwYWRkaW5nOiAwIDFyZW07XHJcbiAgICAgIGhlaWdodDogNXJlbTtcclxuXHJcbiAgICAgIC5hbmltYXRlZCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgIG1hcmdpbi1yaWdodDogMS4zcmVtO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICAuYW5pbWF0ZWQgOjpuZy1kZWVwIHN2ZyB7XHJcbiAgICAgIFxyXG4gICAgICAgIHdpZHRoOiAycmVtO1xyXG4gICAgICAgIGhlaWdodDogMnJlbTtcclxuICAgICAgXHJcbiAgICAgICAgcGF0aCwgY2lyY2xlLCBwb2x5Z29uIHtcclxuICAgICAgICAgIGZpbGw6ICM0ZGIxZmY7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbiB7XHJcbiAgICAgICAgbWFyZ2luLXJpZ2h0OiAxLjNyZW07XHJcbiAgICAgICAgd2lkdGg6IDJyZW07XHJcbiAgICAgICAgaGVpZ2h0OiAycmVtO1xyXG5cclxuICAgICAgICAmLnNlbmQge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zZW5kLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYucmVjZWl2ZSB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL3JlY2VpdmUuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5oaXN0b3J5IHtcclxuICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvaGlzdG9yeS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmNvbnRyYWN0cyB7XHJcbiAgICAgICAgICBtYXNrOiB1cmwoLi4vLi4vYXNzZXRzL2ljb25zL2NvbnRyYWN0cy5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLm1lc3NhZ2VzIHtcclxuICAgICAgICAgIG1hc2s6IHVybCguLi8uLi9hc3NldHMvaWNvbnMvbWVzc2FnZS5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnN0YWtpbmcge1xyXG4gICAgICAgICAgbWFzazogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9zdGFraW5nLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pbmRpY2F0b3Ige1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcclxuICAgICAgICBib3JkZXItcmFkaXVzOiAxcmVtO1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMXJlbTtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICAgIG1hcmdpbi1sZWZ0OiAxLjNyZW07XHJcbiAgICAgICAgcGFkZGluZzogMCAwLjVyZW07XHJcbiAgICAgICAgbWluLXdpZHRoOiAxLjZyZW07XHJcbiAgICAgICAgaGVpZ2h0OiAxLjZyZW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuZGlzYWJsZWQge1xyXG4gICAgICAgIGN1cnNvcjogdXJsKC4uLy4uL2Fzc2V0cy9pY29ucy9ub3QtYWxsb3dlZC5zdmcpLCBub3QtYWxsb3dlZDtcclxuICAgICAgfVxyXG5cclxuICAgICAgJjpub3QoOmxhc3QtY2hpbGQpIHtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDAuM3JlbTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRhYnMtY29udGVudCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgcGFkZGluZzogM3JlbTtcclxuICAgIGZsZXg6IDEgMSBhdXRvO1xyXG4gICAgb3ZlcmZsb3cteDogaGlkZGVuO1xyXG4gICAgb3ZlcmZsb3cteTogb3ZlcmxheTtcclxuICB9XHJcbn1cclxuIl19 */\"","import {Component, OnInit, OnDestroy, NgZone, ViewChild, ElementRef} from '@angular/core';\r\nimport {ActivatedRoute, Router, RoutesRecognized} from '@angular/router';\r\nimport {VariablesService} from '../_helpers/services/variables.service';\r\nimport {BackendService} from '../_helpers/services/backend.service';\r\nimport {TranslateService} from '@ngx-translate/core';\r\nimport {IntToMoneyPipe} from '../_helpers/pipes/int-to-money.pipe';\r\nimport {Subscription} from 'rxjs';\r\n\r\nimport icons from '../../assets/icons/icons.json';\r\n\r\n@Component({\r\n selector: 'app-wallet',\r\n templateUrl: './wallet.component.html',\r\n styleUrls: ['./wallet.component.scss']\r\n})\r\nexport class WalletComponent implements OnInit, OnDestroy {\r\n subRouting1;\r\n subRouting2;\r\n queryRouting;\r\n walletID;\r\n copyAnimation = false;\r\n copyAnimationTimeout;\r\n balanceTooltip;\r\n isModalDialogVisible = false;\r\n\r\n @ViewChild('scrolledContent') private scrolledContent: ElementRef;\r\n\r\n tabs = [\r\n {\r\n title: 'WALLET.TABS.HISTORY',\r\n icon: 'history',\r\n link: '/history',\r\n indicator: false,\r\n active: true,\r\n animated: icons.history,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.SEND',\r\n icon: 'send',\r\n link: '/send',\r\n indicator: false,\r\n active: false,\r\n animated: icons.send,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.RECEIVE',\r\n icon: 'receive',\r\n link: '/receive',\r\n indicator: false,\r\n active: false,\r\n animated: icons.receive,\r\n itemHovered: false\r\n },\r\n {\r\n title: 'WALLET.TABS.CONTRACTS',\r\n icon: 'contracts',\r\n link: '/contracts',\r\n indicator: 1,\r\n active: false,\r\n animated: icons.contracts,\r\n itemHovered: false\r\n },\r\n /*{\r\n title: 'WALLET.TABS.MESSAGES',\r\n icon: 'messages',\r\n link: '/messages',\r\n indicator: 32,\r\n active: false,\r\n animated: icons.messages,\r\n itemHovered: false\r\n },*/\r\n {\r\n title: 'WALLET.TABS.STAKING',\r\n icon: 'staking',\r\n link: '/staking',\r\n indicator: false,\r\n active: false,\r\n animated: icons.staking,\r\n itemHovered: false\r\n }\r\n ];\r\n aliasSubscription: Subscription;\r\n\r\n constructor(\r\n private route: ActivatedRoute,\r\n private router: Router,\r\n private backend: BackendService,\r\n public variablesService: VariablesService,\r\n private ngZone: NgZone,\r\n private translate: TranslateService,\r\n private intToMoneyPipe: IntToMoneyPipe\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.subRouting1 = this.route.params.subscribe(params => {\r\n this.walletID = +params['id'];\r\n this.variablesService.setCurrentWallet(this.walletID);\r\n this.scrolledContent.nativeElement.scrollTop = 0;\r\n clearTimeout(this.copyAnimationTimeout);\r\n this.copyAnimation = false;\r\n });\r\n this.subRouting2 = this.router.events.subscribe(val => {\r\n if (val instanceof RoutesRecognized) {\r\n if ( val.state.root.firstChild && val.state.root.firstChild.firstChild ) {\r\n for (let i = 0; i < this.tabs.length; i++) {\r\n this.tabs[i].active = (this.tabs[i].link === '/' + val.state.root.firstChild.firstChild.url[0].path);\r\n }\r\n }\r\n }\r\n });\r\n this.queryRouting = this.route.queryParams.subscribe(params => {\r\n if (params.send) {\r\n this.tabs.forEach((tab, index) => {\r\n if (tab.link === '/send') {\r\n this.changeTab(index);\r\n }\r\n });\r\n }\r\n });\r\n if (this.variablesService.currentWallet.alias.hasOwnProperty('name')) {\r\n this.variablesService.currentWallet.wakeAlias = false;\r\n }\r\n this.aliasSubscription = this.variablesService.getAliasChangedEvent.subscribe(() => {\r\n if (this.variablesService.currentWallet.alias.hasOwnProperty('name')) {\r\n this.variablesService.currentWallet.wakeAlias = false;\r\n }\r\n });\r\n }\r\n\r\n changeTab(index) {\r\n if ((this.tabs[index].link === '/send' || this.tabs[index].link === '/contracts' || this.tabs[index].link === '/staking') && (this.variablesService.daemon_state !== 2 || !this.variablesService.currentWallet.loaded)) {\r\n return;\r\n }\r\n this.tabs.forEach((tab) => {\r\n tab.active = false;\r\n });\r\n this.tabs[index].active = true;\r\n this.ngZone.run( () => {\r\n this.scrolledContent.nativeElement.scrollTop = 0;\r\n this.router.navigate(['wallet/' + this.walletID + this.tabs[index].link]);\r\n });\r\n }\r\n\r\n itemHovered(index, state: boolean) {\r\n this.tabs[index].itemHovered = state;\r\n }\r\n\r\n copyAddress() {\r\n this.backend.setClipboard(this.variablesService.currentWallet.address);\r\n this.copyAnimation = true;\r\n this.copyAnimationTimeout = window.setTimeout(() => {\r\n this.copyAnimation = false;\r\n }, 2000);\r\n }\r\n\r\n getTooltip() {\r\n this.balanceTooltip = document.createElement('div');\r\n const available = document.createElement('span');\r\n available.setAttribute('class', 'available');\r\n available.innerHTML = this.translate.instant('WALLET.AVAILABLE_BALANCE', {available: this.intToMoneyPipe.transform(this.variablesService.currentWallet.unlocked_balance), currency: this.variablesService.defaultCurrency});\r\n this.balanceTooltip.appendChild(available);\r\n const locked = document.createElement('span');\r\n locked.setAttribute('class', 'locked');\r\n locked.innerHTML = this.translate.instant('WALLET.LOCKED_BALANCE', {locked: this.intToMoneyPipe.transform(this.variablesService.currentWallet.balance.minus(this.variablesService.currentWallet.unlocked_balance)), currency: this.variablesService.defaultCurrency});\r\n this.balanceTooltip.appendChild(locked);\r\n const link = document.createElement('span');\r\n link.setAttribute('class', 'link');\r\n link.innerHTML = this.translate.instant('WALLET.LOCKED_BALANCE_LINK');\r\n link.addEventListener('click', () => {\r\n this.openInBrowser('docs.zano.org/docs/locked-balance');\r\n });\r\n this.balanceTooltip.appendChild(link);\r\n return this.balanceTooltip;\r\n }\r\n\r\n onHideTooltip() {\r\n this.balanceTooltip = null;\r\n }\r\n\r\n openInBrowser(link) {\r\n this.backend.openUrlInBrowser(link);\r\n }\r\n\r\n showDialog() {\r\n this.isModalDialogVisible = true;\r\n }\r\n\r\n confirmed(confirmed: boolean) {\r\n if (confirmed) {\r\n this.closeWallet();\r\n }\r\n this.isModalDialogVisible = false;\r\n }\r\n\r\n closeWallet() {\r\n this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {\r\n for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {\r\n if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {\r\n this.variablesService.wallets.splice(i, 1);\r\n }\r\n }\r\n this.ngZone.run(() => {\r\n if (this.variablesService.wallets.length) {\r\n this.variablesService.currentWallet = this.variablesService.wallets[0];\r\n this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);\r\n } else {\r\n this.router.navigate(['/']);\r\n }\r\n });\r\n if (this.variablesService.appPass) {\r\n this.backend.storeSecureAppData();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.subRouting1.unsubscribe();\r\n this.subRouting2.unsubscribe();\r\n this.queryRouting.unsubscribe();\r\n this.aliasSubscription.unsubscribe();\r\n clearTimeout(this.copyAnimationTimeout);\r\n }\r\n\r\n}\r\n","// This file can be replaced during build by using the `fileReplacements` array.\r\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\r\n// The list of file replacements can be found in `angular.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n\r\n/*\r\n * For easier debugging in development mode, you can import the following file\r\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\r\n *\r\n * This import should be commented out in production mode because it will have a negative impact\r\n * on performance if an error is thrown.\r\n */\r\n// import 'zone.js/dist/zone-error'; // Included with Angular CLI.\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\n\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from './environments/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule)\r\n .catch(err => console.error(err));\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/src/gui/qt-daemon/html/polyfills.js b/src/gui/qt-daemon/html/polyfills.js index 4a42665e..d2cdbb98 100644 --- a/src/gui/qt-daemon/html/polyfills.js +++ b/src/gui/qt-daemon/html/polyfills.js @@ -649,7 +649,7 @@ module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { /*! no static exports found */ /***/ (function(module, exports) { -var core = module.exports = { version: '2.6.9' }; +var core = module.exports = { version: '2.6.10' }; if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef @@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__); /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -__webpack_require__(/*! D:\Projects\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts"); -module.exports = __webpack_require__(/*! D:\Projects\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js"); +__webpack_require__(/*! C:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts"); +module.exports = __webpack_require__(/*! C:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js"); /***/ }) diff --git a/src/gui/qt-daemon/html/polyfills.js.map b/src/gui/qt-daemon/html/polyfills.js.map index e19645c8..e3cce2ae 100644 --- a/src/gui/qt-daemon/html/polyfills.js.map +++ b/src/gui/qt-daemon/html/polyfills.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js","webpack:///./node_modules/core-js/es7/reflect.js","webpack:///./node_modules/core-js/modules/_a-function.js","webpack:///./node_modules/core-js/modules/_an-instance.js","webpack:///./node_modules/core-js/modules/_an-object.js","webpack:///./node_modules/core-js/modules/_array-from-iterable.js","webpack:///./node_modules/core-js/modules/_array-includes.js","webpack:///./node_modules/core-js/modules/_array-methods.js","webpack:///./node_modules/core-js/modules/_array-species-constructor.js","webpack:///./node_modules/core-js/modules/_array-species-create.js","webpack:///./node_modules/core-js/modules/_classof.js","webpack:///./node_modules/core-js/modules/_cof.js","webpack:///./node_modules/core-js/modules/_collection-strong.js","webpack:///./node_modules/core-js/modules/_collection-weak.js","webpack:///./node_modules/core-js/modules/_collection.js","webpack:///./node_modules/core-js/modules/_core.js","webpack:///./node_modules/core-js/modules/_ctx.js","webpack:///./node_modules/core-js/modules/_defined.js","webpack:///./node_modules/core-js/modules/_descriptors.js","webpack:///./node_modules/core-js/modules/_dom-create.js","webpack:///./node_modules/core-js/modules/_enum-bug-keys.js","webpack:///./node_modules/core-js/modules/_export.js","webpack:///./node_modules/core-js/modules/_fails.js","webpack:///./node_modules/core-js/modules/_for-of.js","webpack:///./node_modules/core-js/modules/_function-to-string.js","webpack:///./node_modules/core-js/modules/_global.js","webpack:///./node_modules/core-js/modules/_has.js","webpack:///./node_modules/core-js/modules/_hide.js","webpack:///./node_modules/core-js/modules/_html.js","webpack:///./node_modules/core-js/modules/_ie8-dom-define.js","webpack:///./node_modules/core-js/modules/_inherit-if-required.js","webpack:///./node_modules/core-js/modules/_iobject.js","webpack:///./node_modules/core-js/modules/_is-array-iter.js","webpack:///./node_modules/core-js/modules/_is-array.js","webpack:///./node_modules/core-js/modules/_is-object.js","webpack:///./node_modules/core-js/modules/_iter-call.js","webpack:///./node_modules/core-js/modules/_iter-create.js","webpack:///./node_modules/core-js/modules/_iter-define.js","webpack:///./node_modules/core-js/modules/_iter-detect.js","webpack:///./node_modules/core-js/modules/_iter-step.js","webpack:///./node_modules/core-js/modules/_iterators.js","webpack:///./node_modules/core-js/modules/_library.js","webpack:///./node_modules/core-js/modules/_meta.js","webpack:///./node_modules/core-js/modules/_metadata.js","webpack:///./node_modules/core-js/modules/_object-assign.js","webpack:///./node_modules/core-js/modules/_object-create.js","webpack:///./node_modules/core-js/modules/_object-dp.js","webpack:///./node_modules/core-js/modules/_object-dps.js","webpack:///./node_modules/core-js/modules/_object-gopd.js","webpack:///./node_modules/core-js/modules/_object-gops.js","webpack:///./node_modules/core-js/modules/_object-gpo.js","webpack:///./node_modules/core-js/modules/_object-keys-internal.js","webpack:///./node_modules/core-js/modules/_object-keys.js","webpack:///./node_modules/core-js/modules/_object-pie.js","webpack:///./node_modules/core-js/modules/_property-desc.js","webpack:///./node_modules/core-js/modules/_redefine-all.js","webpack:///./node_modules/core-js/modules/_redefine.js","webpack:///./node_modules/core-js/modules/_set-proto.js","webpack:///./node_modules/core-js/modules/_set-species.js","webpack:///./node_modules/core-js/modules/_set-to-string-tag.js","webpack:///./node_modules/core-js/modules/_shared-key.js","webpack:///./node_modules/core-js/modules/_shared.js","webpack:///./node_modules/core-js/modules/_to-absolute-index.js","webpack:///./node_modules/core-js/modules/_to-integer.js","webpack:///./node_modules/core-js/modules/_to-iobject.js","webpack:///./node_modules/core-js/modules/_to-length.js","webpack:///./node_modules/core-js/modules/_to-object.js","webpack:///./node_modules/core-js/modules/_to-primitive.js","webpack:///./node_modules/core-js/modules/_uid.js","webpack:///./node_modules/core-js/modules/_validate-collection.js","webpack:///./node_modules/core-js/modules/_wks.js","webpack:///./node_modules/core-js/modules/core.get-iterator-method.js","webpack:///./node_modules/core-js/modules/es6.map.js","webpack:///./node_modules/core-js/modules/es6.set.js","webpack:///./node_modules/core-js/modules/es6.weak-map.js","webpack:///./node_modules/core-js/modules/es7.reflect.define-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.delete-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-metadata-keys.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-own-metadata-keys.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-own-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.has-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.has-own-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.metadata.js","webpack:///./node_modules/zone.js/dist/zone.js","webpack:///./src/polyfills.ts"],"names":[],"mappings":"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A;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,yCAAyC;AACzC,qBAAqB;AACrB,0BAA0B;AAC1B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;;;;;;;;;;;;AC/Ia;AACb,kBAAkB,mBAAO,CAAC,wEAAiB;AAC3C,cAAc,mBAAO,CAAC,wDAAS;AAC/B,eAAe,mBAAO,CAAC,kEAAc;AACrC,eAAe,mBAAO,CAAC,kEAAc;AACrC,iBAAiB,mBAAO,CAAC,sEAAgB;AACzC,YAAY,mBAAO,CAAC,4DAAW;AAC/B,wBAAwB,mBAAO,CAAC,0EAAkB;AAClD,WAAW,mBAAO,CAAC,sDAAQ;AAC3B,eAAe,mBAAO,CAAC,sFAAwB;AAC/C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qBAAqB;AACrB,qBAAqB;AACrB,0BAA0B;AAC1B;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;;;;;;;;;;;;ACpFa;AACb,aAAa,mBAAO,CAAC,4DAAW;AAChC,cAAc,mBAAO,CAAC,4DAAW;AACjC,eAAe,mBAAO,CAAC,gE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AgB,mBAAmB;AACnC;AACA;AACA,kCAAkC,2BAA2B;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;;;;;;;;;;;ACpEA,eAAe,mBAAO,CAAC,sDAAQ;AAC/B;;AAEA;AACA;AACA,iCAAiC,qBAAqB;AACtD;AACA,iCAAiC,SAAS,EAAE;AAC5C,CAAC,YAAY;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,SAAS,qBAAqB;AAC3D,iCAAiC,aAAa;AAC9C;AACA,GAAG,YAAY;AACf;AACA;;;;;;;;;;;;ACrBA;AACA,UAAU;AACV;;;;;;;;;;;;ACFA;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA,WAAW,mBAAO,CAAC,sDAAQ;AAC3B,eAAe,mBAAO,CAAC,kEAAc;AACrC,UAAU,mBAAO,CAAC,sDAAQ;AAC1B,cAAc,mBAAO,CAAC,kEAAc;AACpC;AACA;AACA;AACA;AACA,cAAc,mBAAO,CAAC,0DAAU;AAChC,iDAAiD;AACjD,CAAC;AACD;AACA,qBAAqB;AACrB;AACA,SAAS;AACT,GAAG,EAAE;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACpDA,UAAU,mBAAO,CAAC,4DAAW;AAC7B,cAAc,mBAAO,CAAC,4DAAW;AACjC,aAAa,mBAAO,CAAC,4DAAW;AAChC,iDAAiD,mBAAO,CAAC,sEAAgB;;AAEzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D,gBAAgB,EAAE;AAC5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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AAO,CAAC,gEAAa;AACpC,eAAe,mBAAO,CAAC,kEAAc;AACrC;AACA;;AAEA,cAAc;AACd;AACA;AACA,CAAC,EAAE;;;;;;;;;;;;ACRH,gBAAgB,mBAAO,CAAC,gEAAa;AACrC,eAAe,mBAAO,CAAC,kEAAc;AACrC,gBAAgB,mBAAO,CAAC,oEAAe;AACvC;AACA;;AAEA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,EAAE;;;;;;;;;;;;ACdH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,KAA4D;AAC7D,CAAC,SACW;AACZ,CAAC,qBAAqB;;AAEtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,kBAAkB;AACzD,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,0BAA0B;AACrD;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,iEAAiE,+CAA+C,EAAE;AAClH;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT,4DAA4D,0CAA0C;AACtG;AACA;AACA;AACA,gCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B,EAAE;AACnE;AACA;AACA;AACA,wCAAwC,6DAA6D,EAAE;AACvG,uCAAuC,WAAW,EAAE;AACpD;AACA,kCAAkC,aAAa,EAAE;AACjD,oCAAoC,WAAW,EAAE;AACjD,gCAAgC,aAAa,EAAE;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,6BAA6B;AAC7B;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4HAA4H,wBAAwB,oCAAoC;AACxL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gFAAgF,sEAAsE;AACtJ;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,oDAAoD;AAC5F;AACA;AACA;AACA;AACA;AACA,2BAA2B,mCAAmC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,qEAAqE,gBAAgB;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,sCAAsC,MAAI;AAC1C;AACA;AACA,sCAAsC,MAAI;AAC1C;AACA;AACA,mFAAmF,kBAAkB;AACrG;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,QAAQ,gBAAgB;AACnD;AACA;AACA;AACA;AACA,yBAAyB,0BAA0B;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA,mFAAmF,kBAAkB;AACrG;AACA;AACA;AACA;AACA,2BAA2B,QAAQ,gBAAgB;AACnD;AACA;AACA;AACA;AACA,yBAAyB,0BAA0B;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uGAAuG;AACvG;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,mCAAmC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA,iBAAiB;AACjB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,mBAAmB,oBAAoB;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,yBAAyB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD,EAAE;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA,iBAAiB;AACjB;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gEAAgE;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,EAAE;AACR;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA,8CAA8C;AAC9C;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA8C,oCAAoC;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sBAAsB;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sBAAsB;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,0BAA0B;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C,sBAAsB;AAChE,qCAAqC,iBAAiB;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,8BAA8B;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,0BAA0B;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,iBAAiB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,wBAAwB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,wBAAwB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0FAA0F;AAC1F;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,6DAA6D;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sDAAsD,0BAA0B,EAAE;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD,6BAA6B,EAAE;AACpF;AACA;AACA;AACA;AACA,8CAA8C,kDAAkD,EAAE;AAClG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAiD,sDAAsD;AACvG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,0FAA0F;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,mBAAmB,uBAAuB;AAC1C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD,+BAA+B,EAAE;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qEAAqE,gBAAgB;AACrF;AACA,mBAAmB,uBAAuB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,0BAA0B;AAC7C;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA,yCAAyC,6BAA6B;AACtE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA,mBAAmB,4BAA4B;AAC/C;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB,SAAS;AACT;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C,sBAAsB;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mFAAmF;AACnF;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA;AACA;AACA,mFAAmF;AACnF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ,qFAAqF;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kEAAkE,0CAA0C;AAC5G;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,CAAC;;;;;;;;;;;;;ACjxGD;AAAA;AAAA;AAAA;;;;;;;;;;;;;;GAcG;AAEH;;GAEG;AAEH,mEAAmE;AACnE,+BAA+B;AAC/B,+BAA+B;AAC/B,iCAAiC;AACjC,kCAAkC;AAClC,oCAAoC;AACpC,+BAA+B;AAC/B,6BAA6B;AAC7B,+BAA+B;AAC/B,6BAA6B;AAC7B,8BAA8B;AAC9B,+BAA+B;AAC/B,4BAA4B;AAC5B,iCAAiC;AACjC,4BAA4B;AAE5B;;;;IAII;AACJ,8BAA8B;AAE9B,+EAA+E;AAC/E,oEAAoE;AAEpE,gEAAgE;AAChE,gCAAgC;AAEhC;;;;IAII;AACJ,8EAA8E;AAE9E;;;GAGG;AAEF,sGAAsG;AACtG,iGAAiG;AACjG,sHAAsH;AAEtH;;;EAGE;AACH,4DAA4D;AAE5D;;GAEG;AACwB,CAAE,6BAA6B;AAG1D;;GAEG","file":"polyfills.js","sourcesContent":["/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport 'core-js/es7/reflect';\n","require('../modules/es7.reflect.define-metadata');\nrequire('../modules/es7.reflect.delete-metadata');\nrequire('../modules/es7.reflect.get-metadata');\nrequire('../modules/es7.reflect.get-metadata-keys');\nrequire('../modules/es7.reflect.get-own-metadata');\nrequire('../modules/es7.reflect.get-own-metadata-keys');\nrequire('../modules/es7.reflect.has-metadata');\nrequire('../modules/es7.reflect.has-own-metadata');\nrequire('../modules/es7.reflect.metadata');\nmodule.exports = require('../modules/_core').Reflect;\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","var forOf = require('./_for-of');\n\nmodule.exports = function (iter, ITERATOR) {\n var result = [];\n forOf(iter, false, result.push, result, ITERATOR);\n return result;\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","'use strict';\nvar dP = require('./_object-dp').f;\nvar create = require('./_object-create');\nvar redefineAll = require('./_redefine-all');\nvar ctx = require('./_ctx');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar $iterDefine = require('./_iter-define');\nvar step = require('./_iter-step');\nvar setSpecies = require('./_set-species');\nvar DESCRIPTORS = require('./_descriptors');\nvar fastKey = require('./_meta').fastKey;\nvar validate = require('./_validate-collection');\nvar SIZE = DESCRIPTORS ? '_s' : 'size';\n\nvar getEntry = function (that, key) {\n // fast case\n var index = fastKey(key);\n var entry;\n if (index !== 'F') return that._i[index];\n // frozen object case\n for (entry = that._f; entry; entry = entry.n) {\n if (entry.k == key) return entry;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = create(null); // index\n that._f = undefined; // first entry\n that._l = undefined; // last entry\n that[SIZE] = 0; // size\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.1.3.1 Map.prototype.clear()\n // 23.2.3.2 Set.prototype.clear()\n clear: function clear() {\n for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {\n entry.r = true;\n if (entry.p) entry.p = entry.p.n = undefined;\n delete data[entry.i];\n }\n that._f = that._l = undefined;\n that[SIZE] = 0;\n },\n // 23.1.3.3 Map.prototype.delete(key)\n // 23.2.3.4 Set.prototype.delete(value)\n 'delete': function (key) {\n var that = validate(this, NAME);\n var entry = getEntry(that, key);\n if (entry) {\n var next = entry.n;\n var prev = entry.p;\n delete that._i[entry.i];\n entry.r = true;\n if (prev) prev.n = next;\n if (next) next.p = prev;\n if (that._f == entry) that._f = next;\n if (that._l == entry) that._l = prev;\n that[SIZE]--;\n } return !!entry;\n },\n // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)\n // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)\n forEach: function forEach(callbackfn /* , that = undefined */) {\n validate(this, NAME);\n var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);\n var entry;\n while (entry = entry ? entry.n : this._f) {\n f(entry.v, entry.k, this);\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n }\n },\n // 23.1.3.7 Map.prototype.has(key)\n // 23.2.3.7 Set.prototype.has(value)\n has: function has(key) {\n return !!getEntry(validate(this, NAME), key);\n }\n });\n if (DESCRIPTORS) dP(C.prototype, 'size', {\n get: function () {\n return validate(this, NAME)[SIZE];\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var entry = getEntry(that, key);\n var prev, index;\n // change existing entry\n if (entry) {\n entry.v = value;\n // create new entry\n } else {\n that._l = entry = {\n i: index = fastKey(key, true), // <- index\n k: key, // <- key\n v: value, // <- value\n p: prev = that._l, // <- previous entry\n n: undefined, // <- next entry\n r: false // <- removed\n };\n if (!that._f) that._f = entry;\n if (prev) prev.n = entry;\n that[SIZE]++;\n // add to index\n if (index !== 'F') that._i[index] = entry;\n } return that;\n },\n getEntry: getEntry,\n setStrong: function (C, NAME, IS_MAP) {\n // add .keys, .values, .entries, [@@iterator]\n // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11\n $iterDefine(C, NAME, function (iterated, kind) {\n this._t = validate(iterated, NAME); // target\n this._k = kind; // kind\n this._l = undefined; // previous\n }, function () {\n var that = this;\n var kind = that._k;\n var entry = that._l;\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n // get next entry\n if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {\n // or finish the iteration\n that._t = undefined;\n return step(1);\n }\n // return step by kind\n if (kind == 'keys') return step(0, entry.k);\n if (kind == 'values') return step(0, entry.v);\n return step(0, [entry.k, entry.v]);\n }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);\n\n // add [@@species], 23.1.2.2, 23.2.2.2\n setSpecies(NAME);\n }\n};\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","var core = module.exports = { version: '2.6.9' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","module.exports = require('./_shared')('native-function-to-string', Function.toString);\n","// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = $native || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","module.exports = {};\n","module.exports = false;\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","var Map = require('./es6.map');\nvar $export = require('./_export');\nvar shared = require('./_shared')('metadata');\nvar store = shared.store || (shared.store = new (require('./es6.weak-map'))());\n\nvar getOrCreateMetadataMap = function (target, targetKey, create) {\n var targetMetadata = store.get(target);\n if (!targetMetadata) {\n if (!create) return undefined;\n store.set(target, targetMetadata = new Map());\n }\n var keyMetadata = targetMetadata.get(targetKey);\n if (!keyMetadata) {\n if (!create) return undefined;\n targetMetadata.set(targetKey, keyMetadata = new Map());\n } return keyMetadata;\n};\nvar ordinaryHasOwnMetadata = function (MetadataKey, O, P) {\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? false : metadataMap.has(MetadataKey);\n};\nvar ordinaryGetOwnMetadata = function (MetadataKey, O, P) {\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? undefined : metadataMap.get(MetadataKey);\n};\nvar ordinaryDefineOwnMetadata = function (MetadataKey, MetadataValue, O, P) {\n getOrCreateMetadataMap(O, P, true).set(MetadataKey, MetadataValue);\n};\nvar ordinaryOwnMetadataKeys = function (target, targetKey) {\n var metadataMap = getOrCreateMetadataMap(target, targetKey, false);\n var keys = [];\n if (metadataMap) metadataMap.forEach(function (_, key) { keys.push(key); });\n return keys;\n};\nvar toMetaKey = function (it) {\n return it === undefined || typeof it == 'symbol' ? it : String(it);\n};\nvar exp = function (O) {\n $export($export.S, 'Reflect', O);\n};\n\nmodule.exports = {\n store: store,\n map: getOrCreateMetadataMap,\n has: ordinaryHasOwnMetadata,\n get: ordinaryGetOwnMetadata,\n set: ordinaryDefineOwnMetadata,\n keys: ordinaryOwnMetadataKeys,\n key: toMetaKey,\n exp: exp\n};\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar DESCRIPTORS = require('./_descriptors');\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) {\n key = keys[j++];\n if (!DESCRIPTORS || isEnum.call(S, key)) T[key] = S[key];\n }\n } return T;\n} : $assign;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","exports.f = Object.getOwnPropertySymbols;\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","exports.f = {}.propertyIsEnumerable;\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar $toString = require('./_function-to-string');\nvar TO_STRING = 'toString';\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var core = require('./_core');\nvar global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\n\n(module.exports = function (key, value) {\n return store[key] || (store[key] = value !== undefined ? value : {});\n})('versions', []).push({\n version: core.version,\n mode: require('./_library') ? 'pure' : 'global',\n copyright: '© 2019 Denis Pushkarev (zloirock.ru)'\n});\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar MAP = 'Map';\n\n// 23.1 Map Objects\nmodule.exports = require('./_collection')(MAP, function (get) {\n return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.1.3.6 Map.prototype.get(key)\n get: function get(key) {\n var entry = strong.getEntry(validate(this, MAP), key);\n return entry && entry.v;\n },\n // 23.1.3.9 Map.prototype.set(key, value)\n set: function set(key, value) {\n return strong.def(validate(this, MAP), key === 0 ? 0 : key, value);\n }\n}, strong, true);\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar SET = 'Set';\n\n// 23.2 Set Objects\nmodule.exports = require('./_collection')(SET, function (get) {\n return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.2.3.1 Set.prototype.add(value)\n add: function add(value) {\n return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);\n }\n}, strong);\n","'use strict';\nvar global = require('./_global');\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar validate = require('./_validate-collection');\nvar NATIVE_WEAK_MAP = require('./_validate-collection');\nvar IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (NATIVE_WEAK_MAP && IS_IE11) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar toMetaKey = metadata.key;\nvar ordinaryDefineOwnMetadata = metadata.set;\n\nmetadata.exp({ defineMetadata: function defineMetadata(metadataKey, metadataValue, target, targetKey) {\n ordinaryDefineOwnMetadata(metadataKey, metadataValue, anObject(target), toMetaKey(targetKey));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar toMetaKey = metadata.key;\nvar getOrCreateMetadataMap = metadata.map;\nvar store = metadata.store;\n\nmetadata.exp({ deleteMetadata: function deleteMetadata(metadataKey, target /* , targetKey */) {\n var targetKey = arguments.length < 3 ? undefined : toMetaKey(arguments[2]);\n var metadataMap = getOrCreateMetadataMap(anObject(target), targetKey, false);\n if (metadataMap === undefined || !metadataMap['delete'](metadataKey)) return false;\n if (metadataMap.size) return true;\n var targetMetadata = store.get(target);\n targetMetadata['delete'](targetKey);\n return !!targetMetadata.size || store['delete'](target);\n} });\n","var Set = require('./es6.set');\nvar from = require('./_array-from-iterable');\nvar metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryOwnMetadataKeys = metadata.keys;\nvar toMetaKey = metadata.key;\n\nvar ordinaryMetadataKeys = function (O, P) {\n var oKeys = ordinaryOwnMetadataKeys(O, P);\n var parent = getPrototypeOf(O);\n if (parent === null) return oKeys;\n var pKeys = ordinaryMetadataKeys(parent, P);\n return pKeys.length ? oKeys.length ? from(new Set(oKeys.concat(pKeys))) : pKeys : oKeys;\n};\n\nmetadata.exp({ getMetadataKeys: function getMetadataKeys(target /* , targetKey */) {\n return ordinaryMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar ordinaryGetOwnMetadata = metadata.get;\nvar toMetaKey = metadata.key;\n\nvar ordinaryGetMetadata = function (MetadataKey, O, P) {\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if (hasOwn) return ordinaryGetOwnMetadata(MetadataKey, O, P);\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryGetMetadata(MetadataKey, parent, P) : undefined;\n};\n\nmetadata.exp({ getMetadata: function getMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryGetMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryOwnMetadataKeys = metadata.keys;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ getOwnMetadataKeys: function getOwnMetadataKeys(target /* , targetKey */) {\n return ordinaryOwnMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryGetOwnMetadata = metadata.get;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ getOwnMetadata: function getOwnMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryGetOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar toMetaKey = metadata.key;\n\nvar ordinaryHasMetadata = function (MetadataKey, O, P) {\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if (hasOwn) return true;\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryHasMetadata(MetadataKey, parent, P) : false;\n};\n\nmetadata.exp({ hasMetadata: function hasMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryHasMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ hasOwnMetadata: function hasOwnMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryHasOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var $metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar toMetaKey = $metadata.key;\nvar ordinaryDefineOwnMetadata = $metadata.set;\n\n$metadata.exp({ metadata: function metadata(metadataKey, metadataValue) {\n return function decorator(target, targetKey) {\n ordinaryDefineOwnMetadata(\n metadataKey, metadataValue,\n (targetKey !== undefined ? anObject : aFunction)(target),\n toMetaKey(targetKey)\n );\n };\n} });\n","/**\n* @license\n* Copyright Google Inc. All Rights Reserved.\n*\n* Use of this source code is governed by an MIT-style license that can be\n* found in the LICENSE file at https://angular.io/license\n*/\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(factory());\n}(this, (function () { 'use strict';\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar Zone$1 = (function (global) {\n var performance = global['performance'];\n function mark(name) {\n performance && performance['mark'] && performance['mark'](name);\n }\n function performanceMeasure(name, label) {\n performance && performance['measure'] && performance['measure'](name, label);\n }\n mark('Zone');\n var checkDuplicate = global[('__zone_symbol__forceDuplicateZoneCheck')] === true;\n if (global['Zone']) {\n // if global['Zone'] already exists (maybe zone.js was already loaded or\n // some other lib also registered a global object named Zone), we may need\n // to throw an error, but sometimes user may not want this error.\n // For example,\n // we have two web pages, page1 includes zone.js, page2 doesn't.\n // and the 1st time user load page1 and page2, everything work fine,\n // but when user load page2 again, error occurs because global['Zone'] already exists.\n // so we add a flag to let user choose whether to throw this error or not.\n // By default, if existing Zone is from zone.js, we will not throw the error.\n if (checkDuplicate || typeof global['Zone'].__symbol__ !== 'function') {\n throw new Error('Zone already loaded.');\n }\n else {\n return global['Zone'];\n }\n }\n var Zone = /** @class */ (function () {\n function Zone(parent, zoneSpec) {\n this._parent = parent;\n this._name = zoneSpec ? zoneSpec.name || 'unnamed' : '';\n this._properties = zoneSpec && zoneSpec.properties || {};\n this._zoneDelegate =\n new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec);\n }\n Zone.assertZonePatched = function () {\n if (global['Promise'] !== patches['ZoneAwarePromise']) {\n throw new Error('Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' +\n 'has been overwritten.\\n' +\n 'Most likely cause is that a Promise polyfill has been loaded ' +\n 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' +\n 'If you must load one, do so before loading zone.js.)');\n }\n };\n Object.defineProperty(Zone, \"root\", {\n get: function () {\n var zone = Zone.current;\n while (zone.parent) {\n zone = zone.parent;\n }\n return zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone, \"current\", {\n get: function () {\n return _currentZoneFrame.zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone, \"currentTask\", {\n get: function () {\n return _currentTask;\n },\n enumerable: true,\n configurable: true\n });\n Zone.__load_patch = function (name, fn) {\n if (patches.hasOwnProperty(name)) {\n if (checkDuplicate) {\n throw Error('Already loaded patch: ' + name);\n }\n }\n else if (!global['__Zone_disable_' + name]) {\n var perfName = 'Zone:' + name;\n mark(perfName);\n patches[name] = fn(global, Zone, _api);\n performanceMeasure(perfName, perfName);\n }\n };\n Object.defineProperty(Zone.prototype, \"parent\", {\n get: function () {\n return this._parent;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone.prototype, \"name\", {\n get: function () {\n return this._name;\n },\n enumerable: true,\n configurable: true\n });\n Zone.prototype.get = function (key) {\n var zone = this.getZoneWith(key);\n if (zone)\n return zone._properties[key];\n };\n Zone.prototype.getZoneWith = function (key) {\n var current = this;\n while (current) {\n if (current._properties.hasOwnProperty(key)) {\n return current;\n }\n current = current._parent;\n }\n return null;\n };\n Zone.prototype.fork = function (zoneSpec) {\n if (!zoneSpec)\n throw new Error('ZoneSpec required!');\n return this._zoneDelegate.fork(this, zoneSpec);\n };\n Zone.prototype.wrap = function (callback, source) {\n if (typeof callback !== 'function') {\n throw new Error('Expecting function got: ' + callback);\n }\n var _callback = this._zoneDelegate.intercept(this, callback, source);\n var zone = this;\n return function () {\n return zone.runGuarded(_callback, this, arguments, source);\n };\n };\n Zone.prototype.run = function (callback, applyThis, applyArgs, source) {\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runGuarded = function (callback, applyThis, applyArgs, source) {\n if (applyThis === void 0) { applyThis = null; }\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runTask = function (task, applyThis, applyArgs) {\n if (task.zone != this) {\n throw new Error('A task can only be run in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n }\n // https://github.com/angular/zone.js/issues/778, sometimes eventTask\n // will run in notScheduled(canceled) state, we should not try to\n // run such kind of task but just return\n if (task.state === notScheduled && (task.type === eventTask || task.type === macroTask)) {\n return;\n }\n var reEntryGuard = task.state != running;\n reEntryGuard && task._transitionTo(running, scheduled);\n task.runCount++;\n var previousTask = _currentTask;\n _currentTask = task;\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n if (task.type == macroTask && task.data && !task.data.isPeriodic) {\n task.cancelFn = undefined;\n }\n try {\n return this._zoneDelegate.invokeTask(this, task, applyThis, applyArgs);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n // if the task's state is notScheduled or unknown, then it has already been cancelled\n // we should not reset the state to scheduled\n if (task.state !== notScheduled && task.state !== unknown) {\n if (task.type == eventTask || (task.data && task.data.isPeriodic)) {\n reEntryGuard && task._transitionTo(scheduled, running);\n }\n else {\n task.runCount = 0;\n this._updateTaskCount(task, -1);\n reEntryGuard &&\n task._transitionTo(notScheduled, running, notScheduled);\n }\n }\n _currentZoneFrame = _currentZoneFrame.parent;\n _currentTask = previousTask;\n }\n };\n Zone.prototype.scheduleTask = function (task) {\n if (task.zone && task.zone !== this) {\n // check if the task was rescheduled, the newZone\n // should not be the children of the original zone\n var newZone = this;\n while (newZone) {\n if (newZone === task.zone) {\n throw Error(\"can not reschedule task to \" + this.name + \" which is descendants of the original zone \" + task.zone.name);\n }\n newZone = newZone.parent;\n }\n }\n task._transitionTo(scheduling, notScheduled);\n var zoneDelegates = [];\n task._zoneDelegates = zoneDelegates;\n task._zone = this;\n try {\n task = this._zoneDelegate.scheduleTask(this, task);\n }\n catch (err) {\n // should set task's state to unknown when scheduleTask throw error\n // because the err may from reschedule, so the fromState maybe notScheduled\n task._transitionTo(unknown, scheduling, notScheduled);\n // TODO: @JiaLiPassion, should we check the result from handleError?\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n if (task._zoneDelegates === zoneDelegates) {\n // we have to check because internally the delegate can reschedule the task.\n this._updateTaskCount(task, 1);\n }\n if (task.state == scheduling) {\n task._transitionTo(scheduled, scheduling);\n }\n return task;\n };\n Zone.prototype.scheduleMicroTask = function (source, callback, data, customSchedule) {\n return this.scheduleTask(new ZoneTask(microTask, source, callback, data, customSchedule, undefined));\n };\n Zone.prototype.scheduleMacroTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.scheduleEventTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.cancelTask = function (task) {\n if (task.zone != this)\n throw new Error('A task can only be cancelled in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n task._transitionTo(canceling, scheduled, running);\n try {\n this._zoneDelegate.cancelTask(this, task);\n }\n catch (err) {\n // if error occurs when cancelTask, transit the state to unknown\n task._transitionTo(unknown, canceling);\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n this._updateTaskCount(task, -1);\n task._transitionTo(notScheduled, canceling);\n task.runCount = 0;\n return task;\n };\n Zone.prototype._updateTaskCount = function (task, count) {\n var zoneDelegates = task._zoneDelegates;\n if (count == -1) {\n task._zoneDelegates = null;\n }\n for (var i = 0; i < zoneDelegates.length; i++) {\n zoneDelegates[i]._updateTaskCount(task.type, count);\n }\n };\n Zone.__symbol__ = __symbol__;\n return Zone;\n }());\n var DELEGATE_ZS = {\n name: '',\n onHasTask: function (delegate, _, target, hasTaskState) { return delegate.hasTask(target, hasTaskState); },\n onScheduleTask: function (delegate, _, target, task) {\n return delegate.scheduleTask(target, task);\n },\n onInvokeTask: function (delegate, _, target, task, applyThis, applyArgs) {\n return delegate.invokeTask(target, task, applyThis, applyArgs);\n },\n onCancelTask: function (delegate, _, target, task) { return delegate.cancelTask(target, task); }\n };\n var ZoneDelegate = /** @class */ (function () {\n function ZoneDelegate(zone, parentDelegate, zoneSpec) {\n this._taskCounts = { 'microTask': 0, 'macroTask': 0, 'eventTask': 0 };\n this.zone = zone;\n this._parentDelegate = parentDelegate;\n this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate._forkZS);\n this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate._forkDlgt);\n this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone);\n this._interceptZS =\n zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS);\n this._interceptDlgt =\n zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt);\n this._interceptCurrZone =\n zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone);\n this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS);\n this._invokeDlgt =\n zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt);\n this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone);\n this._handleErrorZS =\n zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS);\n this._handleErrorDlgt =\n zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt);\n this._handleErrorCurrZone =\n zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone);\n this._scheduleTaskZS =\n zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS);\n this._scheduleTaskDlgt = zoneSpec &&\n (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt);\n this._scheduleTaskCurrZone =\n zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone);\n this._invokeTaskZS =\n zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS);\n this._invokeTaskDlgt =\n zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt);\n this._invokeTaskCurrZone =\n zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone);\n this._cancelTaskZS =\n zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS);\n this._cancelTaskDlgt =\n zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt);\n this._cancelTaskCurrZone =\n zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone);\n this._hasTaskZS = null;\n this._hasTaskDlgt = null;\n this._hasTaskDlgtOwner = null;\n this._hasTaskCurrZone = null;\n var zoneSpecHasTask = zoneSpec && zoneSpec.onHasTask;\n var parentHasTask = parentDelegate && parentDelegate._hasTaskZS;\n if (zoneSpecHasTask || parentHasTask) {\n // If we need to report hasTask, than this ZS needs to do ref counting on tasks. In such\n // a case all task related interceptors must go through this ZD. We can't short circuit it.\n this._hasTaskZS = zoneSpecHasTask ? zoneSpec : DELEGATE_ZS;\n this._hasTaskDlgt = parentDelegate;\n this._hasTaskDlgtOwner = this;\n this._hasTaskCurrZone = zone;\n if (!zoneSpec.onScheduleTask) {\n this._scheduleTaskZS = DELEGATE_ZS;\n this._scheduleTaskDlgt = parentDelegate;\n this._scheduleTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onInvokeTask) {\n this._invokeTaskZS = DELEGATE_ZS;\n this._invokeTaskDlgt = parentDelegate;\n this._invokeTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onCancelTask) {\n this._cancelTaskZS = DELEGATE_ZS;\n this._cancelTaskDlgt = parentDelegate;\n this._cancelTaskCurrZone = this.zone;\n }\n }\n }\n ZoneDelegate.prototype.fork = function (targetZone, zoneSpec) {\n return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) :\n new Zone(targetZone, zoneSpec);\n };\n ZoneDelegate.prototype.intercept = function (targetZone, callback, source) {\n return this._interceptZS ?\n this._interceptZS.onIntercept(this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) :\n callback;\n };\n ZoneDelegate.prototype.invoke = function (targetZone, callback, applyThis, applyArgs, source) {\n return this._invokeZS ? this._invokeZS.onInvoke(this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, source) :\n callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.handleError = function (targetZone, error) {\n return this._handleErrorZS ?\n this._handleErrorZS.onHandleError(this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) :\n true;\n };\n ZoneDelegate.prototype.scheduleTask = function (targetZone, task) {\n var returnTask = task;\n if (this._scheduleTaskZS) {\n if (this._hasTaskZS) {\n returnTask._zoneDelegates.push(this._hasTaskDlgtOwner);\n }\n returnTask = this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task);\n if (!returnTask)\n returnTask = task;\n }\n else {\n if (task.scheduleFn) {\n task.scheduleFn(task);\n }\n else if (task.type == microTask) {\n scheduleMicroTask(task);\n }\n else {\n throw new Error('Task is missing scheduleFn.');\n }\n }\n return returnTask;\n };\n ZoneDelegate.prototype.invokeTask = function (targetZone, task, applyThis, applyArgs) {\n return this._invokeTaskZS ? this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, applyArgs) :\n task.callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.cancelTask = function (targetZone, task) {\n var value;\n if (this._cancelTaskZS) {\n value = this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task);\n }\n else {\n if (!task.cancelFn) {\n throw Error('Task is not cancelable');\n }\n value = task.cancelFn(task);\n }\n return value;\n };\n ZoneDelegate.prototype.hasTask = function (targetZone, isEmpty) {\n // hasTask should not throw error so other ZoneDelegate\n // can still trigger hasTask callback\n try {\n this._hasTaskZS &&\n this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty);\n }\n catch (err) {\n this.handleError(targetZone, err);\n }\n };\n ZoneDelegate.prototype._updateTaskCount = function (type, count) {\n var counts = this._taskCounts;\n var prev = counts[type];\n var next = counts[type] = prev + count;\n if (next < 0) {\n throw new Error('More tasks executed then were scheduled.');\n }\n if (prev == 0 || next == 0) {\n var isEmpty = {\n microTask: counts['microTask'] > 0,\n macroTask: counts['macroTask'] > 0,\n eventTask: counts['eventTask'] > 0,\n change: type\n };\n this.hasTask(this.zone, isEmpty);\n }\n };\n return ZoneDelegate;\n }());\n var ZoneTask = /** @class */ (function () {\n function ZoneTask(type, source, callback, options, scheduleFn, cancelFn) {\n this._zone = null;\n this.runCount = 0;\n this._zoneDelegates = null;\n this._state = 'notScheduled';\n this.type = type;\n this.source = source;\n this.data = options;\n this.scheduleFn = scheduleFn;\n this.cancelFn = cancelFn;\n this.callback = callback;\n var self = this;\n // TODO: @JiaLiPassion options should have interface\n if (type === eventTask && options && options.useG) {\n this.invoke = ZoneTask.invokeTask;\n }\n else {\n this.invoke = function () {\n return ZoneTask.invokeTask.call(global, self, this, arguments);\n };\n }\n }\n ZoneTask.invokeTask = function (task, target, args) {\n if (!task) {\n task = this;\n }\n _numberOfNestedTaskFrames++;\n try {\n task.runCount++;\n return task.zone.runTask(task, target, args);\n }\n finally {\n if (_numberOfNestedTaskFrames == 1) {\n drainMicroTaskQueue();\n }\n _numberOfNestedTaskFrames--;\n }\n };\n Object.defineProperty(ZoneTask.prototype, \"zone\", {\n get: function () {\n return this._zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ZoneTask.prototype, \"state\", {\n get: function () {\n return this._state;\n },\n enumerable: true,\n configurable: true\n });\n ZoneTask.prototype.cancelScheduleRequest = function () {\n this._transitionTo(notScheduled, scheduling);\n };\n ZoneTask.prototype._transitionTo = function (toState, fromState1, fromState2) {\n if (this._state === fromState1 || this._state === fromState2) {\n this._state = toState;\n if (toState == notScheduled) {\n this._zoneDelegates = null;\n }\n }\n else {\n throw new Error(this.type + \" '\" + this.source + \"': can not transition to '\" + toState + \"', expecting state '\" + fromState1 + \"'\" + (fromState2 ? ' or \\'' + fromState2 + '\\'' : '') + \", was '\" + this._state + \"'.\");\n }\n };\n ZoneTask.prototype.toString = function () {\n if (this.data && typeof this.data.handleId !== 'undefined') {\n return this.data.handleId.toString();\n }\n else {\n return Object.prototype.toString.call(this);\n }\n };\n // add toJSON method to prevent cyclic error when\n // call JSON.stringify(zoneTask)\n ZoneTask.prototype.toJSON = function () {\n return {\n type: this.type,\n state: this.state,\n source: this.source,\n zone: this.zone.name,\n runCount: this.runCount\n };\n };\n return ZoneTask;\n }());\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n /// MICROTASK QUEUE\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n var symbolSetTimeout = __symbol__('setTimeout');\n var symbolPromise = __symbol__('Promise');\n var symbolThen = __symbol__('then');\n var _microTaskQueue = [];\n var _isDrainingMicrotaskQueue = false;\n var nativeMicroTaskQueuePromise;\n function scheduleMicroTask(task) {\n // if we are not running in any task, and there has not been anything scheduled\n // we must bootstrap the initial task creation by manually scheduling the drain\n if (_numberOfNestedTaskFrames === 0 && _microTaskQueue.length === 0) {\n // We are not running in Task, so we need to kickstart the microtask queue.\n if (!nativeMicroTaskQueuePromise) {\n if (global[symbolPromise]) {\n nativeMicroTaskQueuePromise = global[symbolPromise].resolve(0);\n }\n }\n if (nativeMicroTaskQueuePromise) {\n var nativeThen = nativeMicroTaskQueuePromise[symbolThen];\n if (!nativeThen) {\n // native Promise is not patchable, we need to use `then` directly\n // issue 1078\n nativeThen = nativeMicroTaskQueuePromise['then'];\n }\n nativeThen.call(nativeMicroTaskQueuePromise, drainMicroTaskQueue);\n }\n else {\n global[symbolSetTimeout](drainMicroTaskQueue, 0);\n }\n }\n task && _microTaskQueue.push(task);\n }\n function drainMicroTaskQueue() {\n if (!_isDrainingMicrotaskQueue) {\n _isDrainingMicrotaskQueue = true;\n while (_microTaskQueue.length) {\n var queue = _microTaskQueue;\n _microTaskQueue = [];\n for (var i = 0; i < queue.length; i++) {\n var task = queue[i];\n try {\n task.zone.runTask(task, null, null);\n }\n catch (error) {\n _api.onUnhandledError(error);\n }\n }\n }\n _api.microtaskDrainDone();\n _isDrainingMicrotaskQueue = false;\n }\n }\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n /// BOOTSTRAP\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n var NO_ZONE = { name: 'NO ZONE' };\n var notScheduled = 'notScheduled', scheduling = 'scheduling', scheduled = 'scheduled', running = 'running', canceling = 'canceling', unknown = 'unknown';\n var microTask = 'microTask', macroTask = 'macroTask', eventTask = 'eventTask';\n var patches = {};\n var _api = {\n symbol: __symbol__,\n currentZoneFrame: function () { return _currentZoneFrame; },\n onUnhandledError: noop,\n microtaskDrainDone: noop,\n scheduleMicroTask: scheduleMicroTask,\n showUncaughtError: function () { return !Zone[__symbol__('ignoreConsoleErrorUncaughtError')]; },\n patchEventTarget: function () { return []; },\n patchOnProperties: noop,\n patchMethod: function () { return noop; },\n bindArguments: function () { return []; },\n patchThen: function () { return noop; },\n setNativePromise: function (NativePromise) {\n // sometimes NativePromise.resolve static function\n // is not ready yet, (such as core-js/es6.promise)\n // so we need to check here.\n if (NativePromise && typeof NativePromise.resolve === 'function') {\n nativeMicroTaskQueuePromise = NativePromise.resolve(0);\n }\n },\n };\n var _currentZoneFrame = { parent: null, zone: new Zone(null, null) };\n var _currentTask = null;\n var _numberOfNestedTaskFrames = 0;\n function noop() { }\n function __symbol__(name) {\n return '__zone_symbol__' + name;\n }\n performanceMeasure('Zone', 'Zone');\n return global['Zone'] = Zone;\n})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);\n\nvar __values = (undefined && undefined.__values) || function (o) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\n if (m) return m.call(o);\n return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n};\nZone.__load_patch('ZoneAwarePromise', function (global, Zone, api) {\n var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n var ObjectDefineProperty = Object.defineProperty;\n function readableObjectToString(obj) {\n if (obj && obj.toString === Object.prototype.toString) {\n var className = obj.constructor && obj.constructor.name;\n return (className ? className : '') + ': ' + JSON.stringify(obj);\n }\n return obj ? obj.toString() : Object.prototype.toString.call(obj);\n }\n var __symbol__ = api.symbol;\n var _uncaughtPromiseErrors = [];\n var symbolPromise = __symbol__('Promise');\n var symbolThen = __symbol__('then');\n var creationTrace = '__creationTrace__';\n api.onUnhandledError = function (e) {\n if (api.showUncaughtError()) {\n var rejection = e && e.rejection;\n if (rejection) {\n console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined);\n }\n else {\n console.error(e);\n }\n }\n };\n api.microtaskDrainDone = function () {\n while (_uncaughtPromiseErrors.length) {\n var _loop_1 = function () {\n var uncaughtPromiseError = _uncaughtPromiseErrors.shift();\n try {\n uncaughtPromiseError.zone.runGuarded(function () {\n throw uncaughtPromiseError;\n });\n }\n catch (error) {\n handleUnhandledRejection(error);\n }\n };\n while (_uncaughtPromiseErrors.length) {\n _loop_1();\n }\n }\n };\n var UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler');\n function handleUnhandledRejection(e) {\n api.onUnhandledError(e);\n try {\n var handler = Zone[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];\n if (handler && typeof handler === 'function') {\n handler.call(this, e);\n }\n }\n catch (err) {\n }\n }\n function isThenable(value) {\n return value && value.then;\n }\n function forwardResolution(value) {\n return value;\n }\n function forwardRejection(rejection) {\n return ZoneAwarePromise.reject(rejection);\n }\n var symbolState = __symbol__('state');\n var symbolValue = __symbol__('value');\n var symbolFinally = __symbol__('finally');\n var symbolParentPromiseValue = __symbol__('parentPromiseValue');\n var symbolParentPromiseState = __symbol__('parentPromiseState');\n var source = 'Promise.then';\n var UNRESOLVED = null;\n var RESOLVED = true;\n var REJECTED = false;\n var REJECTED_NO_CATCH = 0;\n function makeResolver(promise, state) {\n return function (v) {\n try {\n resolvePromise(promise, state, v);\n }\n catch (err) {\n resolvePromise(promise, false, err);\n }\n // Do not return value or you will break the Promise spec.\n };\n }\n var once = function () {\n var wasCalled = false;\n return function wrapper(wrappedFunction) {\n return function () {\n if (wasCalled) {\n return;\n }\n wasCalled = true;\n wrappedFunction.apply(null, arguments);\n };\n };\n };\n var TYPE_ERROR = 'Promise resolved with itself';\n var CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace');\n // Promise Resolution\n function resolvePromise(promise, state, value) {\n var onceWrapper = once();\n if (promise === value) {\n throw new TypeError(TYPE_ERROR);\n }\n if (promise[symbolState] === UNRESOLVED) {\n // should only get value.then once based on promise spec.\n var then = null;\n try {\n if (typeof value === 'object' || typeof value === 'function') {\n then = value && value.then;\n }\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n return promise;\n }\n // if (value instanceof ZoneAwarePromise) {\n if (state !== REJECTED && value instanceof ZoneAwarePromise &&\n value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) &&\n value[symbolState] !== UNRESOLVED) {\n clearRejectedNoCatch(value);\n resolvePromise(promise, value[symbolState], value[symbolValue]);\n }\n else if (state !== REJECTED && typeof then === 'function') {\n try {\n then.call(value, onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false)));\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n }\n }\n else {\n promise[symbolState] = state;\n var queue = promise[symbolValue];\n promise[symbolValue] = value;\n if (promise[symbolFinally] === symbolFinally) {\n // the promise is generated by Promise.prototype.finally\n if (state === RESOLVED) {\n // the state is resolved, should ignore the value\n // and use parent promise value\n promise[symbolState] = promise[symbolParentPromiseState];\n promise[symbolValue] = promise[symbolParentPromiseValue];\n }\n }\n // record task information in value when error occurs, so we can\n // do some additional work such as render longStackTrace\n if (state === REJECTED && value instanceof Error) {\n // check if longStackTraceZone is here\n var trace = Zone.currentTask && Zone.currentTask.data &&\n Zone.currentTask.data[creationTrace];\n if (trace) {\n // only keep the long stack trace into error when in longStackTraceZone\n ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, { configurable: true, enumerable: false, writable: true, value: trace });\n }\n }\n for (var i = 0; i < queue.length;) {\n scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);\n }\n if (queue.length == 0 && state == REJECTED) {\n promise[symbolState] = REJECTED_NO_CATCH;\n try {\n // try to print more readable error log\n throw new Error('Uncaught (in promise): ' + readableObjectToString(value) +\n (value && value.stack ? '\\n' + value.stack : ''));\n }\n catch (err) {\n var error_1 = err;\n error_1.rejection = value;\n error_1.promise = promise;\n error_1.zone = Zone.current;\n error_1.task = Zone.currentTask;\n _uncaughtPromiseErrors.push(error_1);\n api.scheduleMicroTask(); // to make sure that it is running\n }\n }\n }\n }\n // Resolving an already resolved promise is a noop.\n return promise;\n }\n var REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler');\n function clearRejectedNoCatch(promise) {\n if (promise[symbolState] === REJECTED_NO_CATCH) {\n // if the promise is rejected no catch status\n // and queue.length > 0, means there is a error handler\n // here to handle the rejected promise, we should trigger\n // windows.rejectionhandled eventHandler or nodejs rejectionHandled\n // eventHandler\n try {\n var handler = Zone[REJECTION_HANDLED_HANDLER];\n if (handler && typeof handler === 'function') {\n handler.call(this, { rejection: promise[symbolValue], promise: promise });\n }\n }\n catch (err) {\n }\n promise[symbolState] = REJECTED;\n for (var i = 0; i < _uncaughtPromiseErrors.length; i++) {\n if (promise === _uncaughtPromiseErrors[i].promise) {\n _uncaughtPromiseErrors.splice(i, 1);\n }\n }\n }\n }\n function scheduleResolveOrReject(promise, zone, chainPromise, onFulfilled, onRejected) {\n clearRejectedNoCatch(promise);\n var promiseState = promise[symbolState];\n var delegate = promiseState ?\n (typeof onFulfilled === 'function') ? onFulfilled : forwardResolution :\n (typeof onRejected === 'function') ? onRejected : forwardRejection;\n zone.scheduleMicroTask(source, function () {\n try {\n var parentPromiseValue = promise[symbolValue];\n var isFinallyPromise = chainPromise && symbolFinally === chainPromise[symbolFinally];\n if (isFinallyPromise) {\n // if the promise is generated from finally call, keep parent promise's state and value\n chainPromise[symbolParentPromiseValue] = parentPromiseValue;\n chainPromise[symbolParentPromiseState] = promiseState;\n }\n // should not pass value to finally callback\n var value = zone.run(delegate, undefined, isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ?\n [] :\n [parentPromiseValue]);\n resolvePromise(chainPromise, true, value);\n }\n catch (error) {\n // if error occurs, should always return this error\n resolvePromise(chainPromise, false, error);\n }\n }, chainPromise);\n }\n var ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }';\n var ZoneAwarePromise = /** @class */ (function () {\n function ZoneAwarePromise(executor) {\n var promise = this;\n if (!(promise instanceof ZoneAwarePromise)) {\n throw new Error('Must be an instanceof Promise.');\n }\n promise[symbolState] = UNRESOLVED;\n promise[symbolValue] = []; // queue;\n try {\n executor && executor(makeResolver(promise, RESOLVED), makeResolver(promise, REJECTED));\n }\n catch (error) {\n resolvePromise(promise, false, error);\n }\n }\n ZoneAwarePromise.toString = function () {\n return ZONE_AWARE_PROMISE_TO_STRING;\n };\n ZoneAwarePromise.resolve = function (value) {\n return resolvePromise(new this(null), RESOLVED, value);\n };\n ZoneAwarePromise.reject = function (error) {\n return resolvePromise(new this(null), REJECTED, error);\n };\n ZoneAwarePromise.race = function (values) {\n var e_1, _a;\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n resolve = res;\n reject = rej;\n });\n function onResolve(value) {\n promise && (promise = null || resolve(value));\n }\n function onReject(error) {\n promise && (promise = null || reject(error));\n }\n try {\n for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {\n var value = values_1_1.value;\n if (!isThenable(value)) {\n value = this.resolve(value);\n }\n value.then(onResolve, onReject);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n return promise;\n };\n ZoneAwarePromise.all = function (values) {\n var e_2, _a;\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n resolve = res;\n reject = rej;\n });\n // Start at 2 to prevent prematurely resolving if .then is called immediately.\n var unresolvedCount = 2;\n var valueIndex = 0;\n var resolvedValues = [];\n var _loop_2 = function (value) {\n if (!isThenable(value)) {\n value = this_1.resolve(value);\n }\n var curValueIndex = valueIndex;\n value.then(function (value) {\n resolvedValues[curValueIndex] = value;\n unresolvedCount--;\n if (unresolvedCount === 0) {\n resolve(resolvedValues);\n }\n }, reject);\n unresolvedCount++;\n valueIndex++;\n };\n var this_1 = this;\n try {\n for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) {\n var value = values_2_1.value;\n _loop_2(value);\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2);\n }\n finally { if (e_2) throw e_2.error; }\n }\n // Make the unresolvedCount zero-based again.\n unresolvedCount -= 2;\n if (unresolvedCount === 0) {\n resolve(resolvedValues);\n }\n return promise;\n };\n ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) {\n var chainPromise = new this.constructor(null);\n var zone = Zone.current;\n if (this[symbolState] == UNRESOLVED) {\n this[symbolValue].push(zone, chainPromise, onFulfilled, onRejected);\n }\n else {\n scheduleResolveOrReject(this, zone, chainPromise, onFulfilled, onRejected);\n }\n return chainPromise;\n };\n ZoneAwarePromise.prototype.catch = function (onRejected) {\n return this.then(null, onRejected);\n };\n ZoneAwarePromise.prototype.finally = function (onFinally) {\n var chainPromise = new this.constructor(null);\n chainPromise[symbolFinally] = symbolFinally;\n var zone = Zone.current;\n if (this[symbolState] == UNRESOLVED) {\n this[symbolValue].push(zone, chainPromise, onFinally, onFinally);\n }\n else {\n scheduleResolveOrReject(this, zone, chainPromise, onFinally, onFinally);\n }\n return chainPromise;\n };\n return ZoneAwarePromise;\n }());\n // Protect against aggressive optimizers dropping seemingly unused properties.\n // E.g. Closure Compiler in advanced mode.\n ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve;\n ZoneAwarePromise['reject'] = ZoneAwarePromise.reject;\n ZoneAwarePromise['race'] = ZoneAwarePromise.race;\n ZoneAwarePromise['all'] = ZoneAwarePromise.all;\n var NativePromise = global[symbolPromise] = global['Promise'];\n var ZONE_AWARE_PROMISE = Zone.__symbol__('ZoneAwarePromise');\n var desc = ObjectGetOwnPropertyDescriptor(global, 'Promise');\n if (!desc || desc.configurable) {\n desc && delete desc.writable;\n desc && delete desc.value;\n if (!desc) {\n desc = { configurable: true, enumerable: true };\n }\n desc.get = function () {\n // if we already set ZoneAwarePromise, use patched one\n // otherwise return native one.\n return global[ZONE_AWARE_PROMISE] ? global[ZONE_AWARE_PROMISE] : global[symbolPromise];\n };\n desc.set = function (NewNativePromise) {\n if (NewNativePromise === ZoneAwarePromise) {\n // if the NewNativePromise is ZoneAwarePromise\n // save to global\n global[ZONE_AWARE_PROMISE] = NewNativePromise;\n }\n else {\n // if the NewNativePromise is not ZoneAwarePromise\n // for example: after load zone.js, some library just\n // set es6-promise to global, if we set it to global\n // directly, assertZonePatched will fail and angular\n // will not loaded, so we just set the NewNativePromise\n // to global[symbolPromise], so the result is just like\n // we load ES6 Promise before zone.js\n global[symbolPromise] = NewNativePromise;\n if (!NewNativePromise.prototype[symbolThen]) {\n patchThen(NewNativePromise);\n }\n api.setNativePromise(NewNativePromise);\n }\n };\n ObjectDefineProperty(global, 'Promise', desc);\n }\n global['Promise'] = ZoneAwarePromise;\n var symbolThenPatched = __symbol__('thenPatched');\n function patchThen(Ctor) {\n var proto = Ctor.prototype;\n var prop = ObjectGetOwnPropertyDescriptor(proto, 'then');\n if (prop && (prop.writable === false || !prop.configurable)) {\n // check Ctor.prototype.then propertyDescriptor is writable or not\n // in meteor env, writable is false, we should ignore such case\n return;\n }\n var originalThen = proto.then;\n // Keep a reference to the original method.\n proto[symbolThen] = originalThen;\n Ctor.prototype.then = function (onResolve, onReject) {\n var _this = this;\n var wrapped = new ZoneAwarePromise(function (resolve, reject) {\n originalThen.call(_this, resolve, reject);\n });\n return wrapped.then(onResolve, onReject);\n };\n Ctor[symbolThenPatched] = true;\n }\n api.patchThen = patchThen;\n if (NativePromise) {\n patchThen(NativePromise);\n }\n // This is not part of public API, but it is useful for tests, so we expose it.\n Promise[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors;\n return ZoneAwarePromise;\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nZone.__load_patch('fetch', function (global, Zone, api) {\n var fetch = global['fetch'];\n var ZoneAwarePromise = global.Promise;\n var symbolThenPatched = api.symbol('thenPatched');\n var fetchTaskScheduling = api.symbol('fetchTaskScheduling');\n var fetchTaskAborting = api.symbol('fetchTaskAborting');\n if (typeof fetch !== 'function') {\n return;\n }\n var OriginalAbortController = global['AbortController'];\n var supportAbort = typeof OriginalAbortController === 'function';\n var abortNative = null;\n if (supportAbort) {\n global['AbortController'] = function () {\n var abortController = new OriginalAbortController();\n var signal = abortController.signal;\n signal.abortController = abortController;\n return abortController;\n };\n abortNative = api.patchMethod(OriginalAbortController.prototype, 'abort', function (delegate) { return function (self, args) {\n if (self.task) {\n return self.task.zone.cancelTask(self.task);\n }\n return delegate.apply(self, args);\n }; });\n }\n var placeholder = function () { };\n global['fetch'] = function () {\n var _this = this;\n var args = Array.prototype.slice.call(arguments);\n var options = args.length > 1 ? args[1] : null;\n var signal = options && options.signal;\n return new Promise(function (res, rej) {\n var task = Zone.current.scheduleMacroTask('fetch', placeholder, args, function () {\n var fetchPromise;\n var zone = Zone.current;\n try {\n zone[fetchTaskScheduling] = true;\n fetchPromise = fetch.apply(_this, args);\n }\n catch (error) {\n rej(error);\n return;\n }\n finally {\n zone[fetchTaskScheduling] = false;\n }\n if (!(fetchPromise instanceof ZoneAwarePromise)) {\n var ctor = fetchPromise.constructor;\n if (!ctor[symbolThenPatched]) {\n api.patchThen(ctor);\n }\n }\n fetchPromise.then(function (resource) {\n if (task.state !== 'notScheduled') {\n task.invoke();\n }\n res(resource);\n }, function (error) {\n if (task.state !== 'notScheduled') {\n task.invoke();\n }\n rej(error);\n });\n }, function () {\n if (!supportAbort) {\n rej('No AbortController supported, can not cancel fetch');\n return;\n }\n if (signal && signal.abortController && !signal.aborted &&\n typeof signal.abortController.abort === 'function' && abortNative) {\n try {\n Zone.current[fetchTaskAborting] = true;\n abortNative.call(signal.abortController);\n }\n finally {\n Zone.current[fetchTaskAborting] = false;\n }\n }\n else {\n rej('cancel fetch need a AbortController.signal');\n }\n });\n if (signal && signal.abortController) {\n signal.abortController.task = task;\n }\n });\n };\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * Suppress closure compiler errors about unknown 'Zone' variable\n * @fileoverview\n * @suppress {undefinedVars,globalThis,missingRequire}\n */\n// issue #989, to reduce bundle size, use short name\n/** Object.getOwnPropertyDescriptor */\nvar ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n/** Object.defineProperty */\nvar ObjectDefineProperty = Object.defineProperty;\n/** Object.getPrototypeOf */\nvar ObjectGetPrototypeOf = Object.getPrototypeOf;\n/** Object.create */\nvar ObjectCreate = Object.create;\n/** Array.prototype.slice */\nvar ArraySlice = Array.prototype.slice;\n/** addEventListener string const */\nvar ADD_EVENT_LISTENER_STR = 'addEventListener';\n/** removeEventListener string const */\nvar REMOVE_EVENT_LISTENER_STR = 'removeEventListener';\n/** zoneSymbol addEventListener */\nvar ZONE_SYMBOL_ADD_EVENT_LISTENER = Zone.__symbol__(ADD_EVENT_LISTENER_STR);\n/** zoneSymbol removeEventListener */\nvar ZONE_SYMBOL_REMOVE_EVENT_LISTENER = Zone.__symbol__(REMOVE_EVENT_LISTENER_STR);\n/** true string const */\nvar TRUE_STR = 'true';\n/** false string const */\nvar FALSE_STR = 'false';\n/** __zone_symbol__ string const */\nvar ZONE_SYMBOL_PREFIX = '__zone_symbol__';\nfunction wrapWithCurrentZone(callback, source) {\n return Zone.current.wrap(callback, source);\n}\nfunction scheduleMacroTaskWithCurrentZone(source, callback, data, customSchedule, customCancel) {\n return Zone.current.scheduleMacroTask(source, callback, data, customSchedule, customCancel);\n}\nvar zoneSymbol = Zone.__symbol__;\nvar isWindowExists = typeof window !== 'undefined';\nvar internalWindow = isWindowExists ? window : undefined;\nvar _global = isWindowExists && internalWindow || typeof self === 'object' && self || global;\nvar REMOVE_ATTRIBUTE = 'removeAttribute';\nvar NULL_ON_PROP_VALUE = [null];\nfunction bindArguments(args, source) {\n for (var i = args.length - 1; i >= 0; i--) {\n if (typeof args[i] === 'function') {\n args[i] = wrapWithCurrentZone(args[i], source + '_' + i);\n }\n }\n return args;\n}\nfunction patchPrototype(prototype, fnNames) {\n var source = prototype.constructor['name'];\n var _loop_1 = function (i) {\n var name_1 = fnNames[i];\n var delegate = prototype[name_1];\n if (delegate) {\n var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, name_1);\n if (!isPropertyWritable(prototypeDesc)) {\n return \"continue\";\n }\n prototype[name_1] = (function (delegate) {\n var patched = function () {\n return delegate.apply(this, bindArguments(arguments, source + '.' + name_1));\n };\n attachOriginToPatched(patched, delegate);\n return patched;\n })(delegate);\n }\n };\n for (var i = 0; i < fnNames.length; i++) {\n _loop_1(i);\n }\n}\nfunction isPropertyWritable(propertyDesc) {\n if (!propertyDesc) {\n return true;\n }\n if (propertyDesc.writable === false) {\n return false;\n }\n return !(typeof propertyDesc.get === 'function' && typeof propertyDesc.set === 'undefined');\n}\nvar isWebWorker = (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope);\n// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify\n// this code.\nvar isNode = (!('nw' in _global) && typeof _global.process !== 'undefined' &&\n {}.toString.call(_global.process) === '[object process]');\nvar isBrowser = !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']);\n// we are in electron of nw, so we are both browser and nodejs\n// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify\n// this code.\nvar isMix = typeof _global.process !== 'undefined' &&\n {}.toString.call(_global.process) === '[object process]' && !isWebWorker &&\n !!(isWindowExists && internalWindow['HTMLElement']);\nvar zoneSymbolEventNames = {};\nvar wrapFn = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n var eventNameSymbol = zoneSymbolEventNames[event.type];\n if (!eventNameSymbol) {\n eventNameSymbol = zoneSymbolEventNames[event.type] = zoneSymbol('ON_PROPERTY' + event.type);\n }\n var target = this || event.target || _global;\n var listener = target[eventNameSymbol];\n var result;\n if (isBrowser && target === internalWindow && event.type === 'error') {\n // window.onerror have different signiture\n // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror\n // and onerror callback will prevent default when callback return true\n var errorEvent = event;\n result = listener &&\n listener.call(this, errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error);\n if (result === true) {\n event.preventDefault();\n }\n }\n else {\n result = listener && listener.apply(this, arguments);\n if (result != undefined && !result) {\n event.preventDefault();\n }\n }\n return result;\n};\nfunction patchProperty(obj, prop, prototype) {\n var desc = ObjectGetOwnPropertyDescriptor(obj, prop);\n if (!desc && prototype) {\n // when patch window object, use prototype to check prop exist or not\n var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, prop);\n if (prototypeDesc) {\n desc = { enumerable: true, configurable: true };\n }\n }\n // if the descriptor not exists or is not configurable\n // just return\n if (!desc || !desc.configurable) {\n return;\n }\n var onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched');\n if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) {\n return;\n }\n // A property descriptor cannot have getter/setter and be writable\n // deleting the writable and value properties avoids this error:\n //\n // TypeError: property descriptors must not specify a value or be writable when a\n // getter or setter has been specified\n delete desc.writable;\n delete desc.value;\n var originalDescGet = desc.get;\n var originalDescSet = desc.set;\n // substr(2) cuz 'onclick' -> 'click', etc\n var eventName = prop.substr(2);\n var eventNameSymbol = zoneSymbolEventNames[eventName];\n if (!eventNameSymbol) {\n eventNameSymbol = zoneSymbolEventNames[eventName] = zoneSymbol('ON_PROPERTY' + eventName);\n }\n desc.set = function (newValue) {\n // in some of windows's onproperty callback, this is undefined\n // so we need to check it\n var target = this;\n if (!target && obj === _global) {\n target = _global;\n }\n if (!target) {\n return;\n }\n var previousValue = target[eventNameSymbol];\n if (previousValue) {\n target.removeEventListener(eventName, wrapFn);\n }\n // issue #978, when onload handler was added before loading zone.js\n // we should remove it with originalDescSet\n if (originalDescSet) {\n originalDescSet.apply(target, NULL_ON_PROP_VALUE);\n }\n if (typeof newValue === 'function') {\n target[eventNameSymbol] = newValue;\n target.addEventListener(eventName, wrapFn, false);\n }\n else {\n target[eventNameSymbol] = null;\n }\n };\n // The getter would return undefined for unassigned properties but the default value of an\n // unassigned property is null\n desc.get = function () {\n // in some of windows's onproperty callback, this is undefined\n // so we need to check it\n var target = this;\n if (!target && obj === _global) {\n target = _global;\n }\n if (!target) {\n return null;\n }\n var listener = target[eventNameSymbol];\n if (listener) {\n return listener;\n }\n else if (originalDescGet) {\n // result will be null when use inline event attribute,\n // such as \n // because the onclick function is internal raw uncompiled handler\n // the onclick will be evaluated when first time event was triggered or\n // the property is accessed, https://github.com/angular/zone.js/issues/525\n // so we should use original native get to retrieve the handler\n var value = originalDescGet && originalDescGet.call(this);\n if (value) {\n desc.set.call(this, value);\n if (typeof target[REMOVE_ATTRIBUTE] === 'function') {\n target.removeAttribute(prop);\n }\n return value;\n }\n }\n return null;\n };\n ObjectDefineProperty(obj, prop, desc);\n obj[onPropPatchedSymbol] = true;\n}\nfunction patchOnProperties(obj, properties, prototype) {\n if (properties) {\n for (var i = 0; i < properties.length; i++) {\n patchProperty(obj, 'on' + properties[i], prototype);\n }\n }\n else {\n var onProperties = [];\n for (var prop in obj) {\n if (prop.substr(0, 2) == 'on') {\n onProperties.push(prop);\n }\n }\n for (var j = 0; j < onProperties.length; j++) {\n patchProperty(obj, onProperties[j], prototype);\n }\n }\n}\nvar originalInstanceKey = zoneSymbol('originalInstance');\n// wrap some native API on `window`\nfunction patchClass(className) {\n var OriginalClass = _global[className];\n if (!OriginalClass)\n return;\n // keep original class in global\n _global[zoneSymbol(className)] = OriginalClass;\n _global[className] = function () {\n var a = bindArguments(arguments, className);\n switch (a.length) {\n case 0:\n this[originalInstanceKey] = new OriginalClass();\n break;\n case 1:\n this[originalInstanceKey] = new OriginalClass(a[0]);\n break;\n case 2:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1]);\n break;\n case 3:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]);\n break;\n case 4:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]);\n break;\n default:\n throw new Error('Arg list too long.');\n }\n };\n // attach original delegate to patched function\n attachOriginToPatched(_global[className], OriginalClass);\n var instance = new OriginalClass(function () { });\n var prop;\n for (prop in instance) {\n // https://bugs.webkit.org/show_bug.cgi?id=44721\n if (className === 'XMLHttpRequest' && prop === 'responseBlob')\n continue;\n (function (prop) {\n if (typeof instance[prop] === 'function') {\n _global[className].prototype[prop] = function () {\n return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments);\n };\n }\n else {\n ObjectDefineProperty(_global[className].prototype, prop, {\n set: function (fn) {\n if (typeof fn === 'function') {\n this[originalInstanceKey][prop] = wrapWithCurrentZone(fn, className + '.' + prop);\n // keep callback in wrapped function so we can\n // use it in Function.prototype.toString to return\n // the native one.\n attachOriginToPatched(this[originalInstanceKey][prop], fn);\n }\n else {\n this[originalInstanceKey][prop] = fn;\n }\n },\n get: function () {\n return this[originalInstanceKey][prop];\n }\n });\n }\n }(prop));\n }\n for (prop in OriginalClass) {\n if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) {\n _global[className][prop] = OriginalClass[prop];\n }\n }\n}\nfunction copySymbolProperties(src, dest) {\n if (typeof Object.getOwnPropertySymbols !== 'function') {\n return;\n }\n var symbols = Object.getOwnPropertySymbols(src);\n symbols.forEach(function (symbol) {\n var desc = Object.getOwnPropertyDescriptor(src, symbol);\n Object.defineProperty(dest, symbol, {\n get: function () {\n return src[symbol];\n },\n set: function (value) {\n if (desc && (!desc.writable || typeof desc.set !== 'function')) {\n // if src[symbol] is not writable or not have a setter, just return\n return;\n }\n src[symbol] = value;\n },\n enumerable: desc ? desc.enumerable : true,\n configurable: desc ? desc.configurable : true\n });\n });\n}\nvar shouldCopySymbolProperties = false;\n\nfunction patchMethod(target, name, patchFn) {\n var proto = target;\n while (proto && !proto.hasOwnProperty(name)) {\n proto = ObjectGetPrototypeOf(proto);\n }\n if (!proto && target[name]) {\n // somehow we did not find it, but we can see it. This happens on IE for Window properties.\n proto = target;\n }\n var delegateName = zoneSymbol(name);\n var delegate = null;\n if (proto && !(delegate = proto[delegateName])) {\n delegate = proto[delegateName] = proto[name];\n // check whether proto[name] is writable\n // some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob\n var desc = proto && ObjectGetOwnPropertyDescriptor(proto, name);\n if (isPropertyWritable(desc)) {\n var patchDelegate_1 = patchFn(delegate, delegateName, name);\n proto[name] = function () {\n return patchDelegate_1(this, arguments);\n };\n attachOriginToPatched(proto[name], delegate);\n if (shouldCopySymbolProperties) {\n copySymbolProperties(delegate, proto[name]);\n }\n }\n }\n return delegate;\n}\n// TODO: @JiaLiPassion, support cancel task later if necessary\nfunction patchMacroTask(obj, funcName, metaCreator) {\n var setNative = null;\n function scheduleTask(task) {\n var data = task.data;\n data.args[data.cbIdx] = function () {\n task.invoke.apply(this, arguments);\n };\n setNative.apply(data.target, data.args);\n return task;\n }\n setNative = patchMethod(obj, funcName, function (delegate) { return function (self, args) {\n var meta = metaCreator(self, args);\n if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') {\n return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask);\n }\n else {\n // cause an error by calling it directly.\n return delegate.apply(self, args);\n }\n }; });\n}\n\nfunction attachOriginToPatched(patched, original) {\n patched[zoneSymbol('OriginalDelegate')] = original;\n}\nvar isDetectedIEOrEdge = false;\nvar ieOrEdge = false;\nfunction isIE() {\n try {\n var ua = internalWindow.navigator.userAgent;\n if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1) {\n return true;\n }\n }\n catch (error) {\n }\n return false;\n}\nfunction isIEOrEdge() {\n if (isDetectedIEOrEdge) {\n return ieOrEdge;\n }\n isDetectedIEOrEdge = true;\n try {\n var ua = internalWindow.navigator.userAgent;\n if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) {\n ieOrEdge = true;\n }\n return ieOrEdge;\n }\n catch (error) {\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// override Function.prototype.toString to make zone.js patched function\n// look like native function\nZone.__load_patch('toString', function (global) {\n // patch Func.prototype.toString to let them look like native\n var originalFunctionToString = Function.prototype.toString;\n var ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate');\n var PROMISE_SYMBOL = zoneSymbol('Promise');\n var ERROR_SYMBOL = zoneSymbol('Error');\n var newFunctionToString = function toString() {\n if (typeof this === 'function') {\n var originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL];\n if (originalDelegate) {\n if (typeof originalDelegate === 'function') {\n return originalFunctionToString.apply(this[ORIGINAL_DELEGATE_SYMBOL], arguments);\n }\n else {\n return Object.prototype.toString.call(originalDelegate);\n }\n }\n if (this === Promise) {\n var nativePromise = global[PROMISE_SYMBOL];\n if (nativePromise) {\n return originalFunctionToString.apply(nativePromise, arguments);\n }\n }\n if (this === Error) {\n var nativeError = global[ERROR_SYMBOL];\n if (nativeError) {\n return originalFunctionToString.apply(nativeError, arguments);\n }\n }\n }\n return originalFunctionToString.apply(this, arguments);\n };\n newFunctionToString[ORIGINAL_DELEGATE_SYMBOL] = originalFunctionToString;\n Function.prototype.toString = newFunctionToString;\n // patch Object.prototype.toString to let them look like native\n var originalObjectToString = Object.prototype.toString;\n var PROMISE_OBJECT_TO_STRING = '[object Promise]';\n Object.prototype.toString = function () {\n if (this instanceof Promise) {\n return PROMISE_OBJECT_TO_STRING;\n }\n return originalObjectToString.apply(this, arguments);\n };\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nvar passiveSupported = false;\nif (typeof window !== 'undefined') {\n try {\n var options = Object.defineProperty({}, 'passive', {\n get: function () {\n passiveSupported = true;\n }\n });\n window.addEventListener('test', options, options);\n window.removeEventListener('test', options, options);\n }\n catch (err) {\n passiveSupported = false;\n }\n}\n// an identifier to tell ZoneTask do not create a new invoke closure\nvar OPTIMIZED_ZONE_EVENT_TASK_DATA = {\n useG: true\n};\nvar zoneSymbolEventNames$1 = {};\nvar globalSources = {};\nvar EVENT_NAME_SYMBOL_REGX = /^__zone_symbol__(\\w+)(true|false)$/;\nvar IMMEDIATE_PROPAGATION_SYMBOL = ('__zone_symbol__propagationStopped');\nfunction patchEventTarget(_global, apis, patchOptions) {\n var ADD_EVENT_LISTENER = (patchOptions && patchOptions.add) || ADD_EVENT_LISTENER_STR;\n var REMOVE_EVENT_LISTENER = (patchOptions && patchOptions.rm) || REMOVE_EVENT_LISTENER_STR;\n var LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.listeners) || 'eventListeners';\n var REMOVE_ALL_LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.rmAll) || 'removeAllListeners';\n var zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER);\n var ADD_EVENT_LISTENER_SOURCE = '.' + ADD_EVENT_LISTENER + ':';\n var PREPEND_EVENT_LISTENER = 'prependListener';\n var PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':';\n var invokeTask = function (task, target, event) {\n // for better performance, check isRemoved which is set\n // by removeEventListener\n if (task.isRemoved) {\n return;\n }\n var delegate = task.callback;\n if (typeof delegate === 'object' && delegate.handleEvent) {\n // create the bind version of handleEvent when invoke\n task.callback = function (event) { return delegate.handleEvent(event); };\n task.originalDelegate = delegate;\n }\n // invoke static task.invoke\n task.invoke(task, target, [event]);\n var options = task.options;\n if (options && typeof options === 'object' && options.once) {\n // if options.once is true, after invoke once remove listener here\n // only browser need to do this, nodejs eventEmitter will cal removeListener\n // inside EventEmitter.once\n var delegate_1 = task.originalDelegate ? task.originalDelegate : task.callback;\n target[REMOVE_EVENT_LISTENER].call(target, event.type, delegate_1, options);\n }\n };\n // global shared zoneAwareCallback to handle all event callback with capture = false\n var globalZoneAwareCallback = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n // event.target is needed for Samsung TV and SourceBuffer\n // || global is needed https://github.com/angular/zone.js/issues/190\n var target = this || event.target || _global;\n var tasks = target[zoneSymbolEventNames$1[event.type][FALSE_STR]];\n if (tasks) {\n // invoke all tasks which attached to current target with given event.type and capture = false\n // for performance concern, if task.length === 1, just invoke\n if (tasks.length === 1) {\n invokeTask(tasks[0], target, event);\n }\n else {\n // https://github.com/angular/zone.js/issues/836\n // copy the tasks array before invoke, to avoid\n // the callback will remove itself or other listener\n var copyTasks = tasks.slice();\n for (var i = 0; i < copyTasks.length; i++) {\n if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) {\n break;\n }\n invokeTask(copyTasks[i], target, event);\n }\n }\n }\n };\n // global shared zoneAwareCallback to handle all event callback with capture = true\n var globalZoneAwareCaptureCallback = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n // event.target is needed for Samsung TV and SourceBuffer\n // || global is needed https://github.com/angular/zone.js/issues/190\n var target = this || event.target || _global;\n var tasks = target[zoneSymbolEventNames$1[event.type][TRUE_STR]];\n if (tasks) {\n // invoke all tasks which attached to current target with given event.type and capture = false\n // for performance concern, if task.length === 1, just invoke\n if (tasks.length === 1) {\n invokeTask(tasks[0], target, event);\n }\n else {\n // https://github.com/angular/zone.js/issues/836\n // copy the tasks array before invoke, to avoid\n // the callback will remove itself or other listener\n var copyTasks = tasks.slice();\n for (var i = 0; i < copyTasks.length; i++) {\n if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) {\n break;\n }\n invokeTask(copyTasks[i], target, event);\n }\n }\n }\n };\n function patchEventTargetMethods(obj, patchOptions) {\n if (!obj) {\n return false;\n }\n var useGlobalCallback = true;\n if (patchOptions && patchOptions.useG !== undefined) {\n useGlobalCallback = patchOptions.useG;\n }\n var validateHandler = patchOptions && patchOptions.vh;\n var checkDuplicate = true;\n if (patchOptions && patchOptions.chkDup !== undefined) {\n checkDuplicate = patchOptions.chkDup;\n }\n var returnTarget = false;\n if (patchOptions && patchOptions.rt !== undefined) {\n returnTarget = patchOptions.rt;\n }\n var proto = obj;\n while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) {\n proto = ObjectGetPrototypeOf(proto);\n }\n if (!proto && obj[ADD_EVENT_LISTENER]) {\n // somehow we did not find it, but we can see it. This happens on IE for Window properties.\n proto = obj;\n }\n if (!proto) {\n return false;\n }\n if (proto[zoneSymbolAddEventListener]) {\n return false;\n }\n var eventNameToString = patchOptions && patchOptions.eventNameToString;\n // a shared global taskData to pass data for scheduleEventTask\n // so we do not need to create a new object just for pass some data\n var taskData = {};\n var nativeAddEventListener = proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER];\n var nativeRemoveEventListener = proto[zoneSymbol(REMOVE_EVENT_LISTENER)] =\n proto[REMOVE_EVENT_LISTENER];\n var nativeListeners = proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] =\n proto[LISTENERS_EVENT_LISTENER];\n var nativeRemoveAllListeners = proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] =\n proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER];\n var nativePrependEventListener;\n if (patchOptions && patchOptions.prepend) {\n nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] =\n proto[patchOptions.prepend];\n }\n function checkIsPassive(task) {\n if (!passiveSupported && typeof taskData.options !== 'boolean' &&\n typeof taskData.options !== 'undefined' && taskData.options !== null) {\n // options is a non-null non-undefined object\n // passive is not supported\n // don't pass options as object\n // just pass capture as a boolean\n task.options = !!taskData.options.capture;\n taskData.options = task.options;\n }\n }\n var customScheduleGlobal = function (task) {\n // if there is already a task for the eventName + capture,\n // just return, because we use the shared globalZoneAwareCallback here.\n if (taskData.isExisting) {\n return;\n }\n checkIsPassive(task);\n return nativeAddEventListener.call(taskData.target, taskData.eventName, taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, taskData.options);\n };\n var customCancelGlobal = function (task) {\n // if task is not marked as isRemoved, this call is directly\n // from Zone.prototype.cancelTask, we should remove the task\n // from tasksList of target first\n if (!task.isRemoved) {\n var symbolEventNames = zoneSymbolEventNames$1[task.eventName];\n var symbolEventName = void 0;\n if (symbolEventNames) {\n symbolEventName = symbolEventNames[task.capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = symbolEventName && task.target[symbolEventName];\n if (existingTasks) {\n for (var i = 0; i < existingTasks.length; i++) {\n var existingTask = existingTasks[i];\n if (existingTask === task) {\n existingTasks.splice(i, 1);\n // set isRemoved to data for faster invokeTask check\n task.isRemoved = true;\n if (existingTasks.length === 0) {\n // all tasks for the eventName + capture have gone,\n // remove globalZoneAwareCallback and remove the task cache from target\n task.allRemoved = true;\n task.target[symbolEventName] = null;\n }\n break;\n }\n }\n }\n }\n // if all tasks for the eventName + capture have gone,\n // we will really remove the global event callback,\n // if not, return\n if (!task.allRemoved) {\n return;\n }\n return nativeRemoveEventListener.call(task.target, task.eventName, task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, task.options);\n };\n var customScheduleNonGlobal = function (task) {\n checkIsPassive(task);\n return nativeAddEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);\n };\n var customSchedulePrepend = function (task) {\n return nativePrependEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);\n };\n var customCancelNonGlobal = function (task) {\n return nativeRemoveEventListener.call(task.target, task.eventName, task.invoke, task.options);\n };\n var customSchedule = useGlobalCallback ? customScheduleGlobal : customScheduleNonGlobal;\n var customCancel = useGlobalCallback ? customCancelGlobal : customCancelNonGlobal;\n var compareTaskCallbackVsDelegate = function (task, delegate) {\n var typeOfDelegate = typeof delegate;\n return (typeOfDelegate === 'function' && task.callback === delegate) ||\n (typeOfDelegate === 'object' && task.originalDelegate === delegate);\n };\n var compare = (patchOptions && patchOptions.diff) ? patchOptions.diff : compareTaskCallbackVsDelegate;\n var blackListedEvents = Zone[Zone.__symbol__('BLACK_LISTED_EVENTS')];\n var makeAddListener = function (nativeListener, addSource, customScheduleFn, customCancelFn, returnTarget, prepend) {\n if (returnTarget === void 0) { returnTarget = false; }\n if (prepend === void 0) { prepend = false; }\n return function () {\n var target = this || _global;\n var eventName = arguments[0];\n var delegate = arguments[1];\n if (!delegate) {\n return nativeListener.apply(this, arguments);\n }\n if (isNode && eventName === 'uncaughtException') {\n // don't patch uncaughtException of nodejs to prevent endless loop\n return nativeListener.apply(this, arguments);\n }\n // don't create the bind delegate function for handleEvent\n // case here to improve addEventListener performance\n // we will create the bind delegate when invoke\n var isHandleEvent = false;\n if (typeof delegate !== 'function') {\n if (!delegate.handleEvent) {\n return nativeListener.apply(this, arguments);\n }\n isHandleEvent = true;\n }\n if (validateHandler && !validateHandler(nativeListener, delegate, target, arguments)) {\n return;\n }\n var options = arguments[2];\n if (blackListedEvents) {\n // check black list\n for (var i = 0; i < blackListedEvents.length; i++) {\n if (eventName === blackListedEvents[i]) {\n return nativeListener.apply(this, arguments);\n }\n }\n }\n var capture;\n var once = false;\n if (options === undefined) {\n capture = false;\n }\n else if (options === true) {\n capture = true;\n }\n else if (options === false) {\n capture = false;\n }\n else {\n capture = options ? !!options.capture : false;\n once = options ? !!options.once : false;\n }\n var zone = Zone.current;\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n var symbolEventName;\n if (!symbolEventNames) {\n // the code is duplicate, but I just want to get some better performance\n var falseEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + FALSE_STR;\n var trueEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + TRUE_STR;\n var symbol = ZONE_SYMBOL_PREFIX + falseEventName;\n var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;\n zoneSymbolEventNames$1[eventName] = {};\n zoneSymbolEventNames$1[eventName][FALSE_STR] = symbol;\n zoneSymbolEventNames$1[eventName][TRUE_STR] = symbolCapture;\n symbolEventName = capture ? symbolCapture : symbol;\n }\n else {\n symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = target[symbolEventName];\n var isExisting = false;\n if (existingTasks) {\n // already have task registered\n isExisting = true;\n if (checkDuplicate) {\n for (var i = 0; i < existingTasks.length; i++) {\n if (compare(existingTasks[i], delegate)) {\n // same callback, same capture, same event name, just return\n return;\n }\n }\n }\n }\n else {\n existingTasks = target[symbolEventName] = [];\n }\n var source;\n var constructorName = target.constructor['name'];\n var targetSource = globalSources[constructorName];\n if (targetSource) {\n source = targetSource[eventName];\n }\n if (!source) {\n source = constructorName + addSource +\n (eventNameToString ? eventNameToString(eventName) : eventName);\n }\n // do not create a new object as task.data to pass those things\n // just use the global shared one\n taskData.options = options;\n if (once) {\n // if addEventListener with once options, we don't pass it to\n // native addEventListener, instead we keep the once setting\n // and handle ourselves.\n taskData.options.once = false;\n }\n taskData.target = target;\n taskData.capture = capture;\n taskData.eventName = eventName;\n taskData.isExisting = isExisting;\n var data = useGlobalCallback ? OPTIMIZED_ZONE_EVENT_TASK_DATA : undefined;\n // keep taskData into data to allow onScheduleEventTask to access the task information\n if (data) {\n data.taskData = taskData;\n }\n var task = zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn);\n // should clear taskData.target to avoid memory leak\n // issue, https://github.com/angular/angular/issues/20442\n taskData.target = null;\n // need to clear up taskData because it is a global object\n if (data) {\n data.taskData = null;\n }\n // have to save those information to task in case\n // application may call task.zone.cancelTask() directly\n if (once) {\n options.once = true;\n }\n if (!(!passiveSupported && typeof task.options === 'boolean')) {\n // if not support passive, and we pass an option object\n // to addEventListener, we should save the options to task\n task.options = options;\n }\n task.target = target;\n task.capture = capture;\n task.eventName = eventName;\n if (isHandleEvent) {\n // save original delegate for compare to check duplicate\n task.originalDelegate = delegate;\n }\n if (!prepend) {\n existingTasks.push(task);\n }\n else {\n existingTasks.unshift(task);\n }\n if (returnTarget) {\n return target;\n }\n };\n };\n proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener, ADD_EVENT_LISTENER_SOURCE, customSchedule, customCancel, returnTarget);\n if (nativePrependEventListener) {\n proto[PREPEND_EVENT_LISTENER] = makeAddListener(nativePrependEventListener, PREPEND_EVENT_LISTENER_SOURCE, customSchedulePrepend, customCancel, returnTarget, true);\n }\n proto[REMOVE_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n var options = arguments[2];\n var capture;\n if (options === undefined) {\n capture = false;\n }\n else if (options === true) {\n capture = true;\n }\n else if (options === false) {\n capture = false;\n }\n else {\n capture = options ? !!options.capture : false;\n }\n var delegate = arguments[1];\n if (!delegate) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n if (validateHandler &&\n !validateHandler(nativeRemoveEventListener, delegate, target, arguments)) {\n return;\n }\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n var symbolEventName;\n if (symbolEventNames) {\n symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = symbolEventName && target[symbolEventName];\n if (existingTasks) {\n for (var i = 0; i < existingTasks.length; i++) {\n var existingTask = existingTasks[i];\n if (compare(existingTask, delegate)) {\n existingTasks.splice(i, 1);\n // set isRemoved to data for faster invokeTask check\n existingTask.isRemoved = true;\n if (existingTasks.length === 0) {\n // all tasks for the eventName + capture have gone,\n // remove globalZoneAwareCallback and remove the task cache from target\n existingTask.allRemoved = true;\n target[symbolEventName] = null;\n }\n existingTask.zone.cancelTask(existingTask);\n if (returnTarget) {\n return target;\n }\n return;\n }\n }\n }\n // issue 930, didn't find the event name or callback\n // from zone kept existingTasks, the callback maybe\n // added outside of zone, we need to call native removeEventListener\n // to try to remove it.\n return nativeRemoveEventListener.apply(this, arguments);\n };\n proto[LISTENERS_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n var listeners = [];\n var tasks = findEventTasks(target, eventNameToString ? eventNameToString(eventName) : eventName);\n for (var i = 0; i < tasks.length; i++) {\n var task = tasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n listeners.push(delegate);\n }\n return listeners;\n };\n proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n if (!eventName) {\n var keys = Object.keys(target);\n for (var i = 0; i < keys.length; i++) {\n var prop = keys[i];\n var match = EVENT_NAME_SYMBOL_REGX.exec(prop);\n var evtName = match && match[1];\n // in nodejs EventEmitter, removeListener event is\n // used for monitoring the removeListener call,\n // so just keep removeListener eventListener until\n // all other eventListeners are removed\n if (evtName && evtName !== 'removeListener') {\n this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);\n }\n }\n // remove removeListener listener finally\n this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');\n }\n else {\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n if (symbolEventNames) {\n var symbolEventName = symbolEventNames[FALSE_STR];\n var symbolCaptureEventName = symbolEventNames[TRUE_STR];\n var tasks = target[symbolEventName];\n var captureTasks = target[symbolCaptureEventName];\n if (tasks) {\n var removeTasks = tasks.slice();\n for (var i = 0; i < removeTasks.length; i++) {\n var task = removeTasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);\n }\n }\n if (captureTasks) {\n var removeTasks = captureTasks.slice();\n for (var i = 0; i < removeTasks.length; i++) {\n var task = removeTasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);\n }\n }\n }\n }\n if (returnTarget) {\n return this;\n }\n };\n // for native toString patch\n attachOriginToPatched(proto[ADD_EVENT_LISTENER], nativeAddEventListener);\n attachOriginToPatched(proto[REMOVE_EVENT_LISTENER], nativeRemoveEventListener);\n if (nativeRemoveAllListeners) {\n attachOriginToPatched(proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER], nativeRemoveAllListeners);\n }\n if (nativeListeners) {\n attachOriginToPatched(proto[LISTENERS_EVENT_LISTENER], nativeListeners);\n }\n return true;\n }\n var results = [];\n for (var i = 0; i < apis.length; i++) {\n results[i] = patchEventTargetMethods(apis[i], patchOptions);\n }\n return results;\n}\nfunction findEventTasks(target, eventName) {\n var foundTasks = [];\n for (var prop in target) {\n var match = EVENT_NAME_SYMBOL_REGX.exec(prop);\n var evtName = match && match[1];\n if (evtName && (!eventName || evtName === eventName)) {\n var tasks = target[prop];\n if (tasks) {\n for (var i = 0; i < tasks.length; i++) {\n foundTasks.push(tasks[i]);\n }\n }\n }\n }\n return foundTasks;\n}\nfunction patchEventPrototype(global, api) {\n var Event = global['Event'];\n if (Event && Event.prototype) {\n api.patchMethod(Event.prototype, 'stopImmediatePropagation', function (delegate) { return function (self, args) {\n self[IMMEDIATE_PROPAGATION_SYMBOL] = true;\n // we need to call the native stopImmediatePropagation\n // in case in some hybrid application, some part of\n // application will be controlled by zone, some are not\n delegate && delegate.apply(self, args);\n }; });\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nvar taskSymbol = zoneSymbol('zoneTask');\nfunction patchTimer(window, setName, cancelName, nameSuffix) {\n var setNative = null;\n var clearNative = null;\n setName += nameSuffix;\n cancelName += nameSuffix;\n var tasksByHandleId = {};\n function scheduleTask(task) {\n var data = task.data;\n function timer() {\n try {\n task.invoke.apply(this, arguments);\n }\n finally {\n // issue-934, task will be cancelled\n // even it is a periodic task such as\n // setInterval\n if (!(task.data && task.data.isPeriodic)) {\n if (typeof data.handleId === 'number') {\n // in non-nodejs env, we remove timerId\n // from local cache\n delete tasksByHandleId[data.handleId];\n }\n else if (data.handleId) {\n // Node returns complex objects as handleIds\n // we remove task reference from timer object\n data.handleId[taskSymbol] = null;\n }\n }\n }\n }\n data.args[0] = timer;\n data.handleId = setNative.apply(window, data.args);\n return task;\n }\n function clearTask(task) {\n return clearNative(task.data.handleId);\n }\n setNative =\n patchMethod(window, setName, function (delegate) { return function (self, args) {\n if (typeof args[0] === 'function') {\n var options = {\n isPeriodic: nameSuffix === 'Interval',\n delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 :\n undefined,\n args: args\n };\n var task = scheduleMacroTaskWithCurrentZone(setName, args[0], options, scheduleTask, clearTask);\n if (!task) {\n return task;\n }\n // Node.js must additionally support the ref and unref functions.\n var handle = task.data.handleId;\n if (typeof handle === 'number') {\n // for non nodejs env, we save handleId: task\n // mapping in local cache for clearTimeout\n tasksByHandleId[handle] = task;\n }\n else if (handle) {\n // for nodejs env, we save task\n // reference in timerId Object for clearTimeout\n handle[taskSymbol] = task;\n }\n // check whether handle is null, because some polyfill or browser\n // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame\n if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' &&\n typeof handle.unref === 'function') {\n task.ref = handle.ref.bind(handle);\n task.unref = handle.unref.bind(handle);\n }\n if (typeof handle === 'number' || handle) {\n return handle;\n }\n return task;\n }\n else {\n // cause an error by calling it directly.\n return delegate.apply(window, args);\n }\n }; });\n clearNative =\n patchMethod(window, cancelName, function (delegate) { return function (self, args) {\n var id = args[0];\n var task;\n if (typeof id === 'number') {\n // non nodejs env.\n task = tasksByHandleId[id];\n }\n else {\n // nodejs env.\n task = id && id[taskSymbol];\n // other environments.\n if (!task) {\n task = id;\n }\n }\n if (task && typeof task.type === 'string') {\n if (task.state !== 'notScheduled' &&\n (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) {\n if (typeof id === 'number') {\n delete tasksByHandleId[id];\n }\n else if (id) {\n id[taskSymbol] = null;\n }\n // Do not cancel already canceled functions\n task.zone.cancelTask(task);\n }\n }\n else {\n // cause an error by calling it directly.\n delegate.apply(window, args);\n }\n }; });\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/*\n * This is necessary for Chrome and Chrome mobile, to enable\n * things like redefining `createdCallback` on an element.\n */\nvar _defineProperty = Object[zoneSymbol('defineProperty')] = Object.defineProperty;\nvar _getOwnPropertyDescriptor = Object[zoneSymbol('getOwnPropertyDescriptor')] =\n Object.getOwnPropertyDescriptor;\nvar _create = Object.create;\nvar unconfigurablesKey = zoneSymbol('unconfigurables');\nfunction propertyPatch() {\n Object.defineProperty = function (obj, prop, desc) {\n if (isUnconfigurable(obj, prop)) {\n throw new TypeError('Cannot assign to read only property \\'' + prop + '\\' of ' + obj);\n }\n var originalConfigurableFlag = desc.configurable;\n if (prop !== 'prototype') {\n desc = rewriteDescriptor(obj, prop, desc);\n }\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n };\n Object.defineProperties = function (obj, props) {\n Object.keys(props).forEach(function (prop) {\n Object.defineProperty(obj, prop, props[prop]);\n });\n return obj;\n };\n Object.create = function (obj, proto) {\n if (typeof proto === 'object' && !Object.isFrozen(proto)) {\n Object.keys(proto).forEach(function (prop) {\n proto[prop] = rewriteDescriptor(obj, prop, proto[prop]);\n });\n }\n return _create(obj, proto);\n };\n Object.getOwnPropertyDescriptor = function (obj, prop) {\n var desc = _getOwnPropertyDescriptor(obj, prop);\n if (desc && isUnconfigurable(obj, prop)) {\n desc.configurable = false;\n }\n return desc;\n };\n}\nfunction _redefineProperty(obj, prop, desc) {\n var originalConfigurableFlag = desc.configurable;\n desc = rewriteDescriptor(obj, prop, desc);\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n}\nfunction isUnconfigurable(obj, prop) {\n return obj && obj[unconfigurablesKey] && obj[unconfigurablesKey][prop];\n}\nfunction rewriteDescriptor(obj, prop, desc) {\n // issue-927, if the desc is frozen, don't try to change the desc\n if (!Object.isFrozen(desc)) {\n desc.configurable = true;\n }\n if (!desc.configurable) {\n // issue-927, if the obj is frozen, don't try to set the desc to obj\n if (!obj[unconfigurablesKey] && !Object.isFrozen(obj)) {\n _defineProperty(obj, unconfigurablesKey, { writable: true, value: {} });\n }\n if (obj[unconfigurablesKey]) {\n obj[unconfigurablesKey][prop] = true;\n }\n }\n return desc;\n}\nfunction _tryDefineProperty(obj, prop, desc, originalConfigurableFlag) {\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n if (desc.configurable) {\n // In case of errors, when the configurable flag was likely set by rewriteDescriptor(), let's\n // retry with the original flag value\n if (typeof originalConfigurableFlag == 'undefined') {\n delete desc.configurable;\n }\n else {\n desc.configurable = originalConfigurableFlag;\n }\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n var descJson = null;\n try {\n descJson = JSON.stringify(desc);\n }\n catch (error) {\n descJson = desc.toString();\n }\n console.log(\"Attempting to configure '\" + prop + \"' with descriptor '\" + descJson + \"' on object '\" + obj + \"' and got error, giving up: \" + error);\n }\n }\n else {\n throw error;\n }\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// we have to patch the instance since the proto is non-configurable\nfunction apply(api, _global) {\n var WS = _global.WebSocket;\n // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener\n // On older Chrome, no need since EventTarget was already patched\n if (!_global.EventTarget) {\n patchEventTarget(_global, [WS.prototype]);\n }\n _global.WebSocket = function (x, y) {\n var socket = arguments.length > 1 ? new WS(x, y) : new WS(x);\n var proxySocket;\n var proxySocketProto;\n // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance\n var onmessageDesc = ObjectGetOwnPropertyDescriptor(socket, 'onmessage');\n if (onmessageDesc && onmessageDesc.configurable === false) {\n proxySocket = ObjectCreate(socket);\n // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'\n // but proxySocket not, so we will keep socket as prototype and pass it to\n // patchOnProperties method\n proxySocketProto = socket;\n [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function (propName) {\n proxySocket[propName] = function () {\n var args = ArraySlice.call(arguments);\n if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {\n var eventName = args.length > 0 ? args[0] : undefined;\n if (eventName) {\n var propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);\n socket[propertySymbol] = proxySocket[propertySymbol];\n }\n }\n return socket[propName].apply(socket, args);\n };\n });\n }\n else {\n // we can patch the real socket\n proxySocket = socket;\n }\n patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);\n return proxySocket;\n };\n var globalWebSocket = _global['WebSocket'];\n for (var prop in WS) {\n globalWebSocket[prop] = WS[prop];\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {globalThis}\n */\nvar globalEventHandlersEventNames = [\n 'abort',\n 'animationcancel',\n 'animationend',\n 'animationiteration',\n 'auxclick',\n 'beforeinput',\n 'blur',\n 'cancel',\n 'canplay',\n 'canplaythrough',\n 'change',\n 'compositionstart',\n 'compositionupdate',\n 'compositionend',\n 'cuechange',\n 'click',\n 'close',\n 'contextmenu',\n 'curechange',\n 'dblclick',\n 'drag',\n 'dragend',\n 'dragenter',\n 'dragexit',\n 'dragleave',\n 'dragover',\n 'drop',\n 'durationchange',\n 'emptied',\n 'ended',\n 'error',\n 'focus',\n 'focusin',\n 'focusout',\n 'gotpointercapture',\n 'input',\n 'invalid',\n 'keydown',\n 'keypress',\n 'keyup',\n 'load',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'lostpointercapture',\n 'mousedown',\n 'mouseenter',\n 'mouseleave',\n 'mousemove',\n 'mouseout',\n 'mouseover',\n 'mouseup',\n 'mousewheel',\n 'orientationchange',\n 'pause',\n 'play',\n 'playing',\n 'pointercancel',\n 'pointerdown',\n 'pointerenter',\n 'pointerleave',\n 'pointerlockchange',\n 'mozpointerlockchange',\n 'webkitpointerlockerchange',\n 'pointerlockerror',\n 'mozpointerlockerror',\n 'webkitpointerlockerror',\n 'pointermove',\n 'pointout',\n 'pointerover',\n 'pointerup',\n 'progress',\n 'ratechange',\n 'reset',\n 'resize',\n 'scroll',\n 'seeked',\n 'seeking',\n 'select',\n 'selectionchange',\n 'selectstart',\n 'show',\n 'sort',\n 'stalled',\n 'submit',\n 'suspend',\n 'timeupdate',\n 'volumechange',\n 'touchcancel',\n 'touchmove',\n 'touchstart',\n 'touchend',\n 'transitioncancel',\n 'transitionend',\n 'waiting',\n 'wheel'\n];\nvar documentEventNames = [\n 'afterscriptexecute', 'beforescriptexecute', 'DOMContentLoaded', 'freeze', 'fullscreenchange',\n 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange', 'fullscreenerror',\n 'mozfullscreenerror', 'webkitfullscreenerror', 'msfullscreenerror', 'readystatechange',\n 'visibilitychange', 'resume'\n];\nvar windowEventNames = [\n 'absolutedeviceorientation',\n 'afterinput',\n 'afterprint',\n 'appinstalled',\n 'beforeinstallprompt',\n 'beforeprint',\n 'beforeunload',\n 'devicelight',\n 'devicemotion',\n 'deviceorientation',\n 'deviceorientationabsolute',\n 'deviceproximity',\n 'hashchange',\n 'languagechange',\n 'message',\n 'mozbeforepaint',\n 'offline',\n 'online',\n 'paint',\n 'pageshow',\n 'pagehide',\n 'popstate',\n 'rejectionhandled',\n 'storage',\n 'unhandledrejection',\n 'unload',\n 'userproximity',\n 'vrdisplyconnected',\n 'vrdisplaydisconnected',\n 'vrdisplaypresentchange'\n];\nvar htmlElementEventNames = [\n 'beforecopy', 'beforecut', 'beforepaste', 'copy', 'cut', 'paste', 'dragstart', 'loadend',\n 'animationstart', 'search', 'transitionrun', 'transitionstart', 'webkitanimationend',\n 'webkitanimationiteration', 'webkitanimationstart', 'webkittransitionend'\n];\nvar mediaElementEventNames = ['encrypted', 'waitingforkey', 'msneedkey', 'mozinterruptbegin', 'mozinterruptend'];\nvar ieElementEventNames = [\n 'activate',\n 'afterupdate',\n 'ariarequest',\n 'beforeactivate',\n 'beforedeactivate',\n 'beforeeditfocus',\n 'beforeupdate',\n 'cellchange',\n 'controlselect',\n 'dataavailable',\n 'datasetchanged',\n 'datasetcomplete',\n 'errorupdate',\n 'filterchange',\n 'layoutcomplete',\n 'losecapture',\n 'move',\n 'moveend',\n 'movestart',\n 'propertychange',\n 'resizeend',\n 'resizestart',\n 'rowenter',\n 'rowexit',\n 'rowsdelete',\n 'rowsinserted',\n 'command',\n 'compassneedscalibration',\n 'deactivate',\n 'help',\n 'mscontentzoom',\n 'msmanipulationstatechanged',\n 'msgesturechange',\n 'msgesturedoubletap',\n 'msgestureend',\n 'msgesturehold',\n 'msgesturestart',\n 'msgesturetap',\n 'msgotpointercapture',\n 'msinertiastart',\n 'mslostpointercapture',\n 'mspointercancel',\n 'mspointerdown',\n 'mspointerenter',\n 'mspointerhover',\n 'mspointerleave',\n 'mspointermove',\n 'mspointerout',\n 'mspointerover',\n 'mspointerup',\n 'pointerout',\n 'mssitemodejumplistitemremoved',\n 'msthumbnailclick',\n 'stop',\n 'storagecommit'\n];\nvar webglEventNames = ['webglcontextrestored', 'webglcontextlost', 'webglcontextcreationerror'];\nvar formEventNames = ['autocomplete', 'autocompleteerror'];\nvar detailEventNames = ['toggle'];\nvar frameEventNames = ['load'];\nvar frameSetEventNames = ['blur', 'error', 'focus', 'load', 'resize', 'scroll', 'messageerror'];\nvar marqueeEventNames = ['bounce', 'finish', 'start'];\nvar XMLHttpRequestEventNames = [\n 'loadstart', 'progress', 'abort', 'error', 'load', 'progress', 'timeout', 'loadend',\n 'readystatechange'\n];\nvar IDBIndexEventNames = ['upgradeneeded', 'complete', 'abort', 'success', 'error', 'blocked', 'versionchange', 'close'];\nvar websocketEventNames = ['close', 'error', 'open', 'message'];\nvar workerEventNames = ['error', 'message'];\nvar eventNames = globalEventHandlersEventNames.concat(webglEventNames, formEventNames, detailEventNames, documentEventNames, windowEventNames, htmlElementEventNames, ieElementEventNames);\nfunction filterProperties(target, onProperties, ignoreProperties) {\n if (!ignoreProperties || ignoreProperties.length === 0) {\n return onProperties;\n }\n var tip = ignoreProperties.filter(function (ip) { return ip.target === target; });\n if (!tip || tip.length === 0) {\n return onProperties;\n }\n var targetIgnoreProperties = tip[0].ignoreProperties;\n return onProperties.filter(function (op) { return targetIgnoreProperties.indexOf(op) === -1; });\n}\nfunction patchFilteredProperties(target, onProperties, ignoreProperties, prototype) {\n // check whether target is available, sometimes target will be undefined\n // because different browser or some 3rd party plugin.\n if (!target) {\n return;\n }\n var filteredProperties = filterProperties(target, onProperties, ignoreProperties);\n patchOnProperties(target, filteredProperties, prototype);\n}\nfunction propertyDescriptorPatch(api, _global) {\n if (isNode && !isMix) {\n return;\n }\n var supportsWebSocket = typeof WebSocket !== 'undefined';\n if (canPatchViaPropertyDescriptor()) {\n var ignoreProperties = _global['__Zone_ignore_on_properties'];\n // for browsers that we can patch the descriptor: Chrome & Firefox\n if (isBrowser) {\n var internalWindow = window;\n var ignoreErrorProperties = isIE ? [{ target: internalWindow, ignoreProperties: ['error'] }] : [];\n // in IE/Edge, onProp not exist in window object, but in WindowPrototype\n // so we need to pass WindowPrototype to check onProp exist or not\n patchFilteredProperties(internalWindow, eventNames.concat(['messageerror']), ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties, ObjectGetPrototypeOf(internalWindow));\n patchFilteredProperties(Document.prototype, eventNames, ignoreProperties);\n if (typeof internalWindow['SVGElement'] !== 'undefined') {\n patchFilteredProperties(internalWindow['SVGElement'].prototype, eventNames, ignoreProperties);\n }\n patchFilteredProperties(Element.prototype, eventNames, ignoreProperties);\n patchFilteredProperties(HTMLElement.prototype, eventNames, ignoreProperties);\n patchFilteredProperties(HTMLMediaElement.prototype, mediaElementEventNames, ignoreProperties);\n patchFilteredProperties(HTMLFrameSetElement.prototype, windowEventNames.concat(frameSetEventNames), ignoreProperties);\n patchFilteredProperties(HTMLBodyElement.prototype, windowEventNames.concat(frameSetEventNames), ignoreProperties);\n patchFilteredProperties(HTMLFrameElement.prototype, frameEventNames, ignoreProperties);\n patchFilteredProperties(HTMLIFrameElement.prototype, frameEventNames, ignoreProperties);\n var HTMLMarqueeElement_1 = internalWindow['HTMLMarqueeElement'];\n if (HTMLMarqueeElement_1) {\n patchFilteredProperties(HTMLMarqueeElement_1.prototype, marqueeEventNames, ignoreProperties);\n }\n var Worker_1 = internalWindow['Worker'];\n if (Worker_1) {\n patchFilteredProperties(Worker_1.prototype, workerEventNames, ignoreProperties);\n }\n }\n patchFilteredProperties(XMLHttpRequest.prototype, XMLHttpRequestEventNames, ignoreProperties);\n var XMLHttpRequestEventTarget_1 = _global['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget_1) {\n patchFilteredProperties(XMLHttpRequestEventTarget_1 && XMLHttpRequestEventTarget_1.prototype, XMLHttpRequestEventNames, ignoreProperties);\n }\n if (typeof IDBIndex !== 'undefined') {\n patchFilteredProperties(IDBIndex.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBRequest.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBOpenDBRequest.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBDatabase.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBTransaction.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBCursor.prototype, IDBIndexEventNames, ignoreProperties);\n }\n if (supportsWebSocket) {\n patchFilteredProperties(WebSocket.prototype, websocketEventNames, ignoreProperties);\n }\n }\n else {\n // Safari, Android browsers (Jelly Bean)\n patchViaCapturingAllTheEvents();\n patchClass('XMLHttpRequest');\n if (supportsWebSocket) {\n apply(api, _global);\n }\n }\n}\nfunction canPatchViaPropertyDescriptor() {\n if ((isBrowser || isMix) && !ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') &&\n typeof Element !== 'undefined') {\n // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364\n // IDL interface attributes are not configurable\n var desc = ObjectGetOwnPropertyDescriptor(Element.prototype, 'onclick');\n if (desc && !desc.configurable)\n return false;\n }\n var ON_READY_STATE_CHANGE = 'onreadystatechange';\n var XMLHttpRequestPrototype = XMLHttpRequest.prototype;\n var xhrDesc = ObjectGetOwnPropertyDescriptor(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE);\n // add enumerable and configurable here because in opera\n // by default XMLHttpRequest.prototype.onreadystatechange is undefined\n // without adding enumerable and configurable will cause onreadystatechange\n // non-configurable\n // and if XMLHttpRequest.prototype.onreadystatechange is undefined,\n // we should set a real desc instead a fake one\n if (xhrDesc) {\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {\n enumerable: true,\n configurable: true,\n get: function () {\n return true;\n }\n });\n var req = new XMLHttpRequest();\n var result = !!req.onreadystatechange;\n // restore original desc\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, xhrDesc || {});\n return result;\n }\n else {\n var SYMBOL_FAKE_ONREADYSTATECHANGE_1 = zoneSymbol('fake');\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {\n enumerable: true,\n configurable: true,\n get: function () {\n return this[SYMBOL_FAKE_ONREADYSTATECHANGE_1];\n },\n set: function (value) {\n this[SYMBOL_FAKE_ONREADYSTATECHANGE_1] = value;\n }\n });\n var req = new XMLHttpRequest();\n var detectFunc = function () { };\n req.onreadystatechange = detectFunc;\n var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;\n req.onreadystatechange = null;\n return result;\n }\n}\nvar unboundKey = zoneSymbol('unbound');\n// Whenever any eventListener fires, we check the eventListener target and all parents\n// for `onwhatever` properties and replace them with zone-bound functions\n// - Chrome (for now)\nfunction patchViaCapturingAllTheEvents() {\n var _loop_1 = function (i) {\n var property = eventNames[i];\n var onproperty = 'on' + property;\n self.addEventListener(property, function (event) {\n var elt = event.target, bound, source;\n if (elt) {\n source = elt.constructor['name'] + '.' + onproperty;\n }\n else {\n source = 'unknown.' + onproperty;\n }\n while (elt) {\n if (elt[onproperty] && !elt[onproperty][unboundKey]) {\n bound = wrapWithCurrentZone(elt[onproperty], source);\n bound[unboundKey] = elt[onproperty];\n elt[onproperty] = bound;\n }\n elt = elt.parentElement;\n }\n }, true);\n };\n for (var i = 0; i < eventNames.length; i++) {\n _loop_1(i);\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction eventTargetPatch(_global, api) {\n var WTF_ISSUE_555 = 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video';\n var NO_EVENT_TARGET = 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket'\n .split(',');\n var EVENT_TARGET = 'EventTarget';\n var apis = [];\n var isWtf = _global['wtf'];\n var WTF_ISSUE_555_ARRAY = WTF_ISSUE_555.split(',');\n if (isWtf) {\n // Workaround for: https://github.com/google/tracing-framework/issues/555\n apis = WTF_ISSUE_555_ARRAY.map(function (v) { return 'HTML' + v + 'Element'; }).concat(NO_EVENT_TARGET);\n }\n else if (_global[EVENT_TARGET]) {\n apis.push(EVENT_TARGET);\n }\n else {\n // Note: EventTarget is not available in all browsers,\n // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget\n apis = NO_EVENT_TARGET;\n }\n var isDisableIECheck = _global['__Zone_disable_IE_check'] || false;\n var isEnableCrossContextCheck = _global['__Zone_enable_cross_context_check'] || false;\n var ieOrEdge = isIEOrEdge();\n var ADD_EVENT_LISTENER_SOURCE = '.addEventListener:';\n var FUNCTION_WRAPPER = '[object FunctionWrapper]';\n var BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';\n // predefine all __zone_symbol__ + eventName + true/false string\n for (var i = 0; i < eventNames.length; i++) {\n var eventName = eventNames[i];\n var falseEventName = eventName + FALSE_STR;\n var trueEventName = eventName + TRUE_STR;\n var symbol = ZONE_SYMBOL_PREFIX + falseEventName;\n var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;\n zoneSymbolEventNames$1[eventName] = {};\n zoneSymbolEventNames$1[eventName][FALSE_STR] = symbol;\n zoneSymbolEventNames$1[eventName][TRUE_STR] = symbolCapture;\n }\n // predefine all task.source string\n for (var i = 0; i < WTF_ISSUE_555.length; i++) {\n var target = WTF_ISSUE_555_ARRAY[i];\n var targets = globalSources[target] = {};\n for (var j = 0; j < eventNames.length; j++) {\n var eventName = eventNames[j];\n targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName;\n }\n }\n var checkIEAndCrossContext = function (nativeDelegate, delegate, target, args) {\n if (!isDisableIECheck && ieOrEdge) {\n if (isEnableCrossContextCheck) {\n try {\n var testString = delegate.toString();\n if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n catch (error) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n else {\n var testString = delegate.toString();\n if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n }\n else if (isEnableCrossContextCheck) {\n try {\n delegate.toString();\n }\n catch (error) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n return true;\n };\n var apiTypes = [];\n for (var i = 0; i < apis.length; i++) {\n var type = _global[apis[i]];\n apiTypes.push(type && type.prototype);\n }\n // vh is validateHandler to check event handler\n // is valid or not(for security check)\n patchEventTarget(_global, apiTypes, { vh: checkIEAndCrossContext });\n api.patchEventTarget = patchEventTarget;\n return true;\n}\nfunction patchEvent(global, api) {\n patchEventPrototype(global, api);\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction patchCallbacks(target, targetName, method, callbacks) {\n var symbol = Zone.__symbol__(method);\n if (target[symbol]) {\n return;\n }\n var nativeDelegate = target[symbol] = target[method];\n target[method] = function (name, opts, options) {\n if (opts && opts.prototype) {\n callbacks.forEach(function (callback) {\n var source = targetName + \".\" + method + \"::\" + callback;\n var prototype = opts.prototype;\n if (prototype.hasOwnProperty(callback)) {\n var descriptor = ObjectGetOwnPropertyDescriptor(prototype, callback);\n if (descriptor && descriptor.value) {\n descriptor.value = wrapWithCurrentZone(descriptor.value, source);\n _redefineProperty(opts.prototype, callback, descriptor);\n }\n else if (prototype[callback]) {\n prototype[callback] = wrapWithCurrentZone(prototype[callback], source);\n }\n }\n else if (prototype[callback]) {\n prototype[callback] = wrapWithCurrentZone(prototype[callback], source);\n }\n });\n }\n return nativeDelegate.call(target, name, opts, options);\n };\n attachOriginToPatched(target[method], nativeDelegate);\n}\nfunction registerElementPatch(_global) {\n if ((!isBrowser && !isMix) || !('registerElement' in _global.document)) {\n return;\n }\n var callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];\n patchCallbacks(document, 'Document', 'registerElement', callbacks);\n}\nfunction patchCustomElements(_global) {\n if ((!isBrowser && !isMix) || !('customElements' in _global)) {\n return;\n }\n var callbacks = ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback'];\n patchCallbacks(_global.customElements, 'customElements', 'define', callbacks);\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nZone.__load_patch('util', function (global, Zone, api) {\n api.patchOnProperties = patchOnProperties;\n api.patchMethod = patchMethod;\n api.bindArguments = bindArguments;\n});\nZone.__load_patch('timers', function (global) {\n var set = 'set';\n var clear = 'clear';\n patchTimer(global, set, clear, 'Timeout');\n patchTimer(global, set, clear, 'Interval');\n patchTimer(global, set, clear, 'Immediate');\n});\nZone.__load_patch('requestAnimationFrame', function (global) {\n patchTimer(global, 'request', 'cancel', 'AnimationFrame');\n patchTimer(global, 'mozRequest', 'mozCancel', 'AnimationFrame');\n patchTimer(global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');\n});\nZone.__load_patch('blocking', function (global, Zone) {\n var blockingMethods = ['alert', 'prompt', 'confirm'];\n for (var i = 0; i < blockingMethods.length; i++) {\n var name_1 = blockingMethods[i];\n patchMethod(global, name_1, function (delegate, symbol, name) {\n return function (s, args) {\n return Zone.current.run(delegate, global, args, name);\n };\n });\n }\n});\nZone.__load_patch('EventTarget', function (global, Zone, api) {\n // load blackListEvents from global\n var SYMBOL_BLACK_LISTED_EVENTS = Zone.__symbol__('BLACK_LISTED_EVENTS');\n if (global[SYMBOL_BLACK_LISTED_EVENTS]) {\n Zone[SYMBOL_BLACK_LISTED_EVENTS] = global[SYMBOL_BLACK_LISTED_EVENTS];\n }\n patchEvent(global, api);\n eventTargetPatch(global, api);\n // patch XMLHttpRequestEventTarget's addEventListener/removeEventListener\n var XMLHttpRequestEventTarget = global['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {\n api.patchEventTarget(global, [XMLHttpRequestEventTarget.prototype]);\n }\n patchClass('MutationObserver');\n patchClass('WebKitMutationObserver');\n patchClass('IntersectionObserver');\n patchClass('FileReader');\n});\nZone.__load_patch('on_property', function (global, Zone, api) {\n propertyDescriptorPatch(api, global);\n propertyPatch();\n});\nZone.__load_patch('customElements', function (global, Zone, api) {\n registerElementPatch(global);\n patchCustomElements(global);\n});\nZone.__load_patch('canvas', function (global) {\n var HTMLCanvasElement = global['HTMLCanvasElement'];\n if (typeof HTMLCanvasElement !== 'undefined' && HTMLCanvasElement.prototype &&\n HTMLCanvasElement.prototype.toBlob) {\n patchMacroTask(HTMLCanvasElement.prototype, 'toBlob', function (self, args) {\n return { name: 'HTMLCanvasElement.toBlob', target: self, cbIdx: 0, args: args };\n });\n }\n});\nZone.__load_patch('XHR', function (global, Zone) {\n // Treat XMLHttpRequest as a macrotask.\n patchXHR(global);\n var XHR_TASK = zoneSymbol('xhrTask');\n var XHR_SYNC = zoneSymbol('xhrSync');\n var XHR_LISTENER = zoneSymbol('xhrListener');\n var XHR_SCHEDULED = zoneSymbol('xhrScheduled');\n var XHR_URL = zoneSymbol('xhrURL');\n var XHR_ERROR_BEFORE_SCHEDULED = zoneSymbol('xhrErrorBeforeScheduled');\n function patchXHR(window) {\n var XMLHttpRequestPrototype = XMLHttpRequest.prototype;\n function findPendingTask(target) {\n return target[XHR_TASK];\n }\n var oriAddListener = XMLHttpRequestPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n var oriRemoveListener = XMLHttpRequestPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n if (!oriAddListener) {\n var XMLHttpRequestEventTarget_1 = window['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget_1) {\n var XMLHttpRequestEventTargetPrototype = XMLHttpRequestEventTarget_1.prototype;\n oriAddListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n oriRemoveListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n }\n }\n var READY_STATE_CHANGE = 'readystatechange';\n var SCHEDULED = 'scheduled';\n function scheduleTask(task) {\n var data = task.data;\n var target = data.target;\n target[XHR_SCHEDULED] = false;\n target[XHR_ERROR_BEFORE_SCHEDULED] = false;\n // remove existing event listener\n var listener = target[XHR_LISTENER];\n if (!oriAddListener) {\n oriAddListener = target[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n oriRemoveListener = target[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n }\n if (listener) {\n oriRemoveListener.call(target, READY_STATE_CHANGE, listener);\n }\n var newListener = target[XHR_LISTENER] = function () {\n if (target.readyState === target.DONE) {\n // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with\n // readyState=4 multiple times, so we need to check task state here\n if (!data.aborted && target[XHR_SCHEDULED] && task.state === SCHEDULED) {\n // check whether the xhr has registered onload listener\n // if that is the case, the task should invoke after all\n // onload listeners finish.\n var loadTasks = target['__zone_symbol__loadfalse'];\n if (loadTasks && loadTasks.length > 0) {\n var oriInvoke_1 = task.invoke;\n task.invoke = function () {\n // need to load the tasks again, because in other\n // load listener, they may remove themselves\n var loadTasks = target['__zone_symbol__loadfalse'];\n for (var i = 0; i < loadTasks.length; i++) {\n if (loadTasks[i] === task) {\n loadTasks.splice(i, 1);\n }\n }\n if (!data.aborted && task.state === SCHEDULED) {\n oriInvoke_1.call(task);\n }\n };\n loadTasks.push(task);\n }\n else {\n task.invoke();\n }\n }\n else if (!data.aborted && target[XHR_SCHEDULED] === false) {\n // error occurs when xhr.send()\n target[XHR_ERROR_BEFORE_SCHEDULED] = true;\n }\n }\n };\n oriAddListener.call(target, READY_STATE_CHANGE, newListener);\n var storedTask = target[XHR_TASK];\n if (!storedTask) {\n target[XHR_TASK] = task;\n }\n sendNative.apply(target, data.args);\n target[XHR_SCHEDULED] = true;\n return task;\n }\n function placeholderCallback() { }\n function clearTask(task) {\n var data = task.data;\n // Note - ideally, we would call data.target.removeEventListener here, but it's too late\n // to prevent it from firing. So instead, we store info for the event listener.\n data.aborted = true;\n return abortNative.apply(data.target, data.args);\n }\n var openNative = patchMethod(XMLHttpRequestPrototype, 'open', function () { return function (self, args) {\n self[XHR_SYNC] = args[2] == false;\n self[XHR_URL] = args[1];\n return openNative.apply(self, args);\n }; });\n var XMLHTTPREQUEST_SOURCE = 'XMLHttpRequest.send';\n var fetchTaskAborting = zoneSymbol('fetchTaskAborting');\n var fetchTaskScheduling = zoneSymbol('fetchTaskScheduling');\n var sendNative = patchMethod(XMLHttpRequestPrototype, 'send', function () { return function (self, args) {\n if (Zone.current[fetchTaskScheduling] === true) {\n // a fetch is scheduling, so we are using xhr to polyfill fetch\n // and because we already schedule macroTask for fetch, we should\n // not schedule a macroTask for xhr again\n return sendNative.apply(self, args);\n }\n if (self[XHR_SYNC]) {\n // if the XHR is sync there is no task to schedule, just execute the code.\n return sendNative.apply(self, args);\n }\n else {\n var options = { target: self, url: self[XHR_URL], isPeriodic: false, args: args, aborted: false };\n var task = scheduleMacroTaskWithCurrentZone(XMLHTTPREQUEST_SOURCE, placeholderCallback, options, scheduleTask, clearTask);\n if (self && self[XHR_ERROR_BEFORE_SCHEDULED] === true && !options.aborted &&\n task.state === SCHEDULED) {\n // xhr request throw error when send\n // we should invoke task instead of leaving a scheduled\n // pending macroTask\n task.invoke();\n }\n }\n }; });\n var abortNative = patchMethod(XMLHttpRequestPrototype, 'abort', function () { return function (self, args) {\n var task = findPendingTask(self);\n if (task && typeof task.type == 'string') {\n // If the XHR has already completed, do nothing.\n // If the XHR has already been aborted, do nothing.\n // Fix #569, call abort multiple times before done will cause\n // macroTask task count be negative number\n if (task.cancelFn == null || (task.data && task.data.aborted)) {\n return;\n }\n task.zone.cancelTask(task);\n }\n else if (Zone.current[fetchTaskAborting] === true) {\n // the abort is called from fetch polyfill, we need to call native abort of XHR.\n return abortNative.apply(self, args);\n }\n // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no\n // task\n // to cancel. Do nothing.\n }; });\n }\n});\nZone.__load_patch('geolocation', function (global) {\n /// GEO_LOCATION\n if (global['navigator'] && global['navigator'].geolocation) {\n patchPrototype(global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);\n }\n});\nZone.__load_patch('PromiseRejectionEvent', function (global, Zone) {\n // handle unhandled promise rejection\n function findPromiseRejectionHandler(evtName) {\n return function (e) {\n var eventTasks = findEventTasks(global, evtName);\n eventTasks.forEach(function (eventTask) {\n // windows has added unhandledrejection event listener\n // trigger the event listener\n var PromiseRejectionEvent = global['PromiseRejectionEvent'];\n if (PromiseRejectionEvent) {\n var evt = new PromiseRejectionEvent(evtName, { promise: e.promise, reason: e.rejection });\n eventTask.invoke(evt);\n }\n });\n };\n }\n if (global['PromiseRejectionEvent']) {\n Zone[zoneSymbol('unhandledPromiseRejectionHandler')] =\n findPromiseRejectionHandler('unhandledrejection');\n Zone[zoneSymbol('rejectionHandledHandler')] =\n findPromiseRejectionHandler('rejectionhandled');\n }\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n})));\n","/**\r\n * This file includes polyfills needed by Angular and is loaded before the app.\r\n * You can add your own extra polyfills to this file.\r\n *\r\n * This file is divided into 2 sections:\r\n * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\r\n * 2. Application imports. Files imported after ZoneJS that should be loaded before your main\r\n * file.\r\n *\r\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\r\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\r\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\r\n *\r\n * Learn more in https://angular.io/guide/browser-support\r\n */\r\n\r\n/***************************************************************************************************\r\n * BROWSER POLYFILLS\r\n */\r\n\r\n/** IE9, IE10 and IE11 requires all of the following polyfills. **/\r\n// import 'core-js/es6/symbol';\r\n// import 'core-js/es6/object';\r\n// import 'core-js/es6/function';\r\n// import 'core-js/es6/parse-int';\r\n// import 'core-js/es6/parse-float';\r\n// import 'core-js/es6/number';\r\n// import 'core-js/es6/math';\r\n// import 'core-js/es6/string';\r\n// import 'core-js/es6/date';\r\n// import 'core-js/es6/array';\r\n// import 'core-js/es6/regexp';\r\n// import 'core-js/es6/map';\r\n// import 'core-js/es6/weak-map';\r\n// import 'core-js/es6/set';\r\n\r\n/**\r\n * If the application will be indexed by Google Search, the following is required.\r\n * Googlebot uses a renderer based on Chrome 41.\r\n * https://developers.google.com/search/docs/guides/rendering\r\n **/\r\n// import 'core-js/es6/array';\r\n\r\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\r\n// import 'classlist.js'; // Run `npm install --save classlist.js`.\r\n\r\n/** IE10 and IE11 requires the following for the Reflect API. */\r\n// import 'core-js/es6/reflect';\r\n\r\n/**\r\n * Web Animations `@angular/platform-browser/animations`\r\n * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.\r\n * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).\r\n **/\r\n// import 'web-animations-js'; // Run `npm install --save web-animations-js`.\r\n\r\n/**\r\n * By default, zone.js will patch all possible macroTask and DomEvents\r\n * user can disable parts of macroTask/DomEvents patch by setting following flags\r\n */\r\n\r\n // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame\r\n // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick\r\n // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames\r\n\r\n /*\r\n * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js\r\n * with the following flag, it will bypass `zone.js` patch for IE/Edge\r\n */\r\n// (window as any).__Zone_enable_cross_context_check = true;\r\n\r\n/***************************************************************************************************\r\n * Zone JS is required by default for Angular itself.\r\n */\r\nimport 'zone.js/dist/zone'; // Included with Angular CLI.\r\n\r\n\r\n/***************************************************************************************************\r\n * APPLICATION IMPORTS\r\n */\r\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js","webpack:///./node_modules/core-js/es7/reflect.js","webpack:///./node_modules/core-js/modules/_a-function.js","webpack:///./node_modules/core-js/modules/_an-instance.js","webpack:///./node_modules/core-js/modules/_an-object.js","webpack:///./node_modules/core-js/modules/_array-from-iterable.js","webpack:///./node_modules/core-js/modules/_array-includes.js","webpack:///./node_modules/core-js/modules/_array-methods.js","webpack:///./node_modules/core-js/modules/_array-species-constructor.js","webpack:///./node_modules/core-js/modules/_array-species-create.js","webpack:///./node_modules/core-js/modules/_classof.js","webpack:///./node_modules/core-js/modules/_cof.js","webpack:///./node_modules/core-js/modules/_collection-strong.js","webpack:///./node_modules/core-js/modules/_collection-weak.js","webpack:///./node_modules/core-js/modules/_collection.js","webpack:///./node_modules/core-js/modules/_core.js","webpack:///./node_modules/core-js/modules/_ctx.js","webpack:///./node_modules/core-js/modules/_defined.js","webpack:///./node_modules/core-js/modules/_descriptors.js","webpack:///./node_modules/core-js/modules/_dom-create.js","webpack:///./node_modules/core-js/modules/_enum-bug-keys.js","webpack:///./node_modules/core-js/modules/_export.js","webpack:///./node_modules/core-js/modules/_fails.js","webpack:///./node_modules/core-js/modules/_for-of.js","webpack:///./node_modules/core-js/modules/_function-to-string.js","webpack:///./node_modules/core-js/modules/_global.js","webpack:///./node_modules/core-js/modules/_has.js","webpack:///./node_modules/core-js/modules/_hide.js","webpack:///./node_modules/core-js/modules/_html.js","webpack:///./node_modules/core-js/modules/_ie8-dom-define.js","webpack:///./node_modules/core-js/modules/_inherit-if-required.js","webpack:///./node_modules/core-js/modules/_iobject.js","webpack:///./node_modules/core-js/modules/_is-array-iter.js","webpack:///./node_modules/core-js/modules/_is-array.js","webpack:///./node_modules/core-js/modules/_is-object.js","webpack:///./node_modules/core-js/modules/_iter-call.js","webpack:///./node_modules/core-js/modules/_iter-create.js","webpack:///./node_modules/core-js/modules/_iter-define.js","webpack:///./node_modules/core-js/modules/_iter-detect.js","webpack:///./node_modules/core-js/modules/_iter-step.js","webpack:///./node_modules/core-js/modules/_iterators.js","webpack:///./node_modules/core-js/modules/_library.js","webpack:///./node_modules/core-js/modules/_meta.js","webpack:///./node_modules/core-js/modules/_metadata.js","webpack:///./node_modules/core-js/modules/_object-assign.js","webpack:///./node_modules/core-js/modules/_object-create.js","webpack:///./node_modules/core-js/modules/_object-dp.js","webpack:///./node_modules/core-js/modules/_object-dps.js","webpack:///./node_modules/core-js/modules/_object-gopd.js","webpack:///./node_modules/core-js/modules/_object-gops.js","webpack:///./node_modules/core-js/modules/_object-gpo.js","webpack:///./node_modules/core-js/modules/_object-keys-internal.js","webpack:///./node_modules/core-js/modules/_object-keys.js","webpack:///./node_modules/core-js/modules/_object-pie.js","webpack:///./node_modules/core-js/modules/_property-desc.js","webpack:///./node_modules/core-js/modules/_redefine-all.js","webpack:///./node_modules/core-js/modules/_redefine.js","webpack:///./node_modules/core-js/modules/_set-proto.js","webpack:///./node_modules/core-js/modules/_set-species.js","webpack:///./node_modules/core-js/modules/_set-to-string-tag.js","webpack:///./node_modules/core-js/modules/_shared-key.js","webpack:///./node_modules/core-js/modules/_shared.js","webpack:///./node_modules/core-js/modules/_to-absolute-index.js","webpack:///./node_modules/core-js/modules/_to-integer.js","webpack:///./node_modules/core-js/modules/_to-iobject.js","webpack:///./node_modules/core-js/modules/_to-length.js","webpack:///./node_modules/core-js/modules/_to-object.js","webpack:///./node_modules/core-js/modules/_to-primitive.js","webpack:///./node_modules/core-js/modules/_uid.js","webpack:///./node_modules/core-js/modules/_validate-collection.js","webpack:///./node_modules/core-js/modules/_wks.js","webpack:///./node_modules/core-js/modules/core.get-iterator-method.js","webpack:///./node_modules/core-js/modules/es6.map.js","webpack:///./node_modules/core-js/modules/es6.set.js","webpack:///./node_modules/core-js/modules/es6.weak-map.js","webpack:///./node_modules/core-js/modules/es7.reflect.define-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.delete-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-metadata-keys.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-own-metadata-keys.js","webpack:///./node_modules/core-js/modules/es7.reflect.get-own-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.has-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.has-own-metadata.js","webpack:///./node_modules/core-js/modules/es7.reflect.metadata.js","webpack:///./node_modules/zone.js/dist/zone.js","webpack:///./src/polyfills.ts"],"names":[],"mappings":"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A;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,yCAAyC;AACzC,qBAAqB;AACrB,0BAA0B;AAC1B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;;;;;;;;;;;;AC/Ia;AACb,kBAAkB,mBAAO,CAAC,wEAAiB;AAC3C,cAAc,mBAAO,CAAC,wDAAS;AAC/B,eAAe,mBAAO,CAAC,kEAAc;AACrC,eAAe,mBAAO,CAAC,kEAAc;AACrC,iBAAiB,mBAAO,CAAC,sEAAgB;AACzC,YAAY,mBAAO,CAAC,4DAAW;AAC/B,wBAAwB,mBAAO,CAAC,0EAAkB;AAClD,WAAW,mBAAO,CAAC,sDAAQ;AAC3B,eAAe,mBAAO,CAAC,sFAAwB;AAC/C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qBAAqB;AACrB,qBAAqB;AACrB,0BAA0B;AAC1B;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;;;;;;;;;;;;ACpFa;AACb,aAAa,mBAAO,CAAC,4DAAW;AAChC,cAAc,mBAAO,CAAC,4DAAW;AACjC,eAAe,mBAAO,CAAC,gE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AgB,mBAAmB;AACnC;AACA;AACA,kCAAkC,2BAA2B;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;;;;;;;;;;;ACpEA,eAAe,mBAAO,CAAC,sDAAQ;AAC/B;;AAEA;AACA;AACA,iCAAiC,qBAAqB;AACtD;AACA,iCAAiC,SAAS,EAAE;AAC5C,CAAC,YAAY;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,SAAS,qBAAqB;AAC3D,iCAAiC,aAAa;AAC9C;AACA,GAAG,YAAY;AACf;AACA;;;;;;;;;;;;ACrBA;AACA,UAAU;AACV;;;;;;;;;;;;ACFA;;;;;;;;;;;;ACAA;;;;;;;;;;;;ACAA,WAAW,mBAAO,CAAC,sDAAQ;AAC3B,eAAe,mBAAO,CAAC,kEAAc;AACrC,UAAU,mBAAO,CAAC,sDAAQ;AAC1B,cAAc,mBAAO,CAAC,kEAAc;AACpC;AACA;AACA;AACA;AACA,cAAc,mBAAO,CAAC,0DAAU;AAChC,iDAAiD;AACjD,CAAC;AACD;AACA,qBAAqB;AACrB;AACA,SAAS;AACT,GAAG,EAAE;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACpDA,UAAU,mBAAO,CAAC,4DAAW;AAC7B,cAAc,mBAAO,CAAC,4DAAW;AACjC,aAAa,mBAAO,CAAC,4DAAW;AAChC,iDAAiD,mBAAO,CAAC,sEAAgB;;AAEzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D,gBAAgB,EAAE;AAC5E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;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AAO,CAAC,gEAAa;AACpC,eAAe,mBAAO,CAAC,kEAAc;AACrC;AACA;;AAEA,cAAc;AACd;AACA;AACA,CAAC,EAAE;;;;;;;;;;;;ACRH,gBAAgB,mBAAO,CAAC,gEAAa;AACrC,eAAe,mBAAO,CAAC,kEAAc;AACrC,gBAAgB,mBAAO,CAAC,oEAAe;AACvC;AACA;;AAEA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,EAAE;;;;;;;;;;;;ACdH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,KAA4D;AAC7D,CAAC,SACW;AACZ,CAAC,qBAAqB;;AAEtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,kBAAkB;AACzD,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,0BAA0B;AACrD;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,iEAAiE,+CAA+C,EAAE;AAClH;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT,4DAA4D,0CAA0C;AACtG;AACA;AACA;AACA,gCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B,EAAE;AACnE;AACA;AACA;AACA,wCAAwC,6DAA6D,EAAE;AACvG,uCAAuC,WAAW,EAAE;AACpD;AACA,kCAAkC,aAAa,EAAE;AACjD,oCAAoC,WAAW,EAAE;AACjD,gCAAgC,aAAa,EAAE;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,6BAA6B;AAC7B;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4HAA4H,wBAAwB,oCAAoC;AACxL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gFAAgF,sEAAsE;AACtJ;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,oDAAoD;AAC5F;AACA;AACA;AACA;AACA;AACA,2BAA2B,mCAAmC;AAC9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,qEAAqE,gBAAgB;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,sCAAsC,MAAI;AAC1C;AACA;AACA,sCAAsC,MAAI;AAC1C;AACA;AACA,mFAAmF,kBAAkB;AACrG;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,QAAQ,gBAAgB;AACnD;AACA;AACA;AACA;AACA,yBAAyB,0BAA0B;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA,mFAAmF,kBAAkB;AACrG;AACA;AACA;AACA;AACA,2BAA2B,QAAQ,gBAAgB;AACnD;AACA;AACA;AACA;AACA,yBAAyB,0BAA0B;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uGAAuG;AACvG;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,mCAAmC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA,iBAAiB;AACjB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,mBAAmB,oBAAoB;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uBAAuB,yBAAyB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kDAAkD,EAAE;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA,iBAAiB;AACjB;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,SAAS;AACT,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gEAAgE;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,EAAE;AACR;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA,8CAA8C;AAC9C;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8CAA8C,oCAAoC;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sBAAsB;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sBAAsB;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,0BAA0B;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C,sBAAsB;AAChE,qCAAqC,iBAAiB;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,8BAA8B;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,0BAA0B;AACjE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,0BAA0B;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,kBAAkB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,iBAAiB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,wBAAwB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,wBAAwB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,kBAAkB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0FAA0F;AAC1F;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0DAA0D;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,6DAA6D;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sDAAsD,0BAA0B,EAAE;AAClF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD,6BAA6B,EAAE;AACpF;AACA;AACA;AACA;AACA,8CAA8C,kDAAkD,EAAE;AAClG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAiD,sDAAsD;AACvG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,0FAA0F;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;AACA,sCAAsC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,mBAAmB,uBAAuB;AAC1C;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD,+BAA+B,EAAE;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qEAAqE,gBAAgB;AACrF;AACA,mBAAmB,uBAAuB;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,0BAA0B;AAC7C;AACA;AACA,uBAAuB,uBAAuB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,iBAAiB;AACpC;AACA;AACA;AACA;AACA;AACA,yCAAyC,6BAA6B;AACtE;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA,mBAAmB,4BAA4B;AAC/C;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,oBAAoB;AACpB,SAAS;AACT;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C,sBAAsB;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mFAAmF;AACnF;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA;AACA;AACA,mFAAmF;AACnF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ,qFAAqF;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU,EAAE;AACZ;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kEAAkE,0CAA0C;AAC5G;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,CAAC;;;;;;;;;;;;;ACjxGD;AAAA;AAAA;AAAA;;;;;;;;;;;;;;GAcG;AAEH;;GAEG;AAEH,mEAAmE;AACnE,+BAA+B;AAC/B,+BAA+B;AAC/B,iCAAiC;AACjC,kCAAkC;AAClC,oCAAoC;AACpC,+BAA+B;AAC/B,6BAA6B;AAC7B,+BAA+B;AAC/B,6BAA6B;AAC7B,8BAA8B;AAC9B,+BAA+B;AAC/B,4BAA4B;AAC5B,iCAAiC;AACjC,4BAA4B;AAE5B;;;;IAII;AACJ,8BAA8B;AAE9B,+EAA+E;AAC/E,oEAAoE;AAEpE,gEAAgE;AAChE,gCAAgC;AAEhC;;;;IAII;AACJ,8EAA8E;AAE9E;;;GAGG;AAEF,sGAAsG;AACtG,iGAAiG;AACjG,sHAAsH;AAEtH;;;EAGE;AACH,4DAA4D;AAE5D;;GAEG;AACwB,CAAE,6BAA6B;AAG1D;;GAEG","file":"polyfills.js","sourcesContent":["/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nimport 'core-js/es7/reflect';\n","require('../modules/es7.reflect.define-metadata');\nrequire('../modules/es7.reflect.delete-metadata');\nrequire('../modules/es7.reflect.get-metadata');\nrequire('../modules/es7.reflect.get-metadata-keys');\nrequire('../modules/es7.reflect.get-own-metadata');\nrequire('../modules/es7.reflect.get-own-metadata-keys');\nrequire('../modules/es7.reflect.has-metadata');\nrequire('../modules/es7.reflect.has-own-metadata');\nrequire('../modules/es7.reflect.metadata');\nmodule.exports = require('../modules/_core').Reflect;\n","module.exports = function (it) {\n if (typeof it != 'function') throw TypeError(it + ' is not a function!');\n return it;\n};\n","module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it) {\n if (!isObject(it)) throw TypeError(it + ' is not an object!');\n return it;\n};\n","var forOf = require('./_for-of');\n\nmodule.exports = function (iter, ITERATOR) {\n var result = [];\n forOf(iter, false, result.push, result, ITERATOR);\n return result;\n};\n","// false -> Array#indexOf\n// true -> Array#includes\nvar toIObject = require('./_to-iobject');\nvar toLength = require('./_to-length');\nvar toAbsoluteIndex = require('./_to-absolute-index');\nmodule.exports = function (IS_INCLUDES) {\n return function ($this, el, fromIndex) {\n var O = toIObject($this);\n var length = toLength(O.length);\n var index = toAbsoluteIndex(fromIndex, length);\n var value;\n // Array#includes uses SameValueZero equality algorithm\n // eslint-disable-next-line no-self-compare\n if (IS_INCLUDES && el != el) while (length > index) {\n value = O[index++];\n // eslint-disable-next-line no-self-compare\n if (value != value) return true;\n // Array#indexOf ignores holes, Array#includes - not\n } else for (;length > index; index++) if (IS_INCLUDES || index in O) {\n if (O[index] === el) return IS_INCLUDES || index || 0;\n } return !IS_INCLUDES && -1;\n };\n};\n","// 0 -> Array#forEach\n// 1 -> Array#map\n// 2 -> Array#filter\n// 3 -> Array#some\n// 4 -> Array#every\n// 5 -> Array#find\n// 6 -> Array#findIndex\nvar ctx = require('./_ctx');\nvar IObject = require('./_iobject');\nvar toObject = require('./_to-object');\nvar toLength = require('./_to-length');\nvar asc = require('./_array-species-create');\nmodule.exports = function (TYPE, $create) {\n var IS_MAP = TYPE == 1;\n var IS_FILTER = TYPE == 2;\n var IS_SOME = TYPE == 3;\n var IS_EVERY = TYPE == 4;\n var IS_FIND_INDEX = TYPE == 6;\n var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;\n var create = $create || asc;\n return function ($this, callbackfn, that) {\n var O = toObject($this);\n var self = IObject(O);\n var f = ctx(callbackfn, that, 3);\n var length = toLength(self.length);\n var index = 0;\n var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;\n var val, res;\n for (;length > index; index++) if (NO_HOLES || index in self) {\n val = self[index];\n res = f(val, index, O);\n if (TYPE) {\n if (IS_MAP) result[index] = res; // map\n else if (res) switch (TYPE) {\n case 3: return true; // some\n case 5: return val; // find\n case 6: return index; // findIndex\n case 2: result.push(val); // filter\n } else if (IS_EVERY) return false; // every\n }\n }\n return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;\n };\n};\n","var isObject = require('./_is-object');\nvar isArray = require('./_is-array');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (original) {\n var C;\n if (isArray(original)) {\n C = original.constructor;\n // cross-realm fallback\n if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;\n if (isObject(C)) {\n C = C[SPECIES];\n if (C === null) C = undefined;\n }\n } return C === undefined ? Array : C;\n};\n","// 9.4.2.3 ArraySpeciesCreate(originalArray, length)\nvar speciesConstructor = require('./_array-species-constructor');\n\nmodule.exports = function (original, length) {\n return new (speciesConstructor(original))(length);\n};\n","// getting tag from 19.1.3.6 Object.prototype.toString()\nvar cof = require('./_cof');\nvar TAG = require('./_wks')('toStringTag');\n// ES3 wrong here\nvar ARG = cof(function () { return arguments; }()) == 'Arguments';\n\n// fallback for IE11 Script Access Denied error\nvar tryGet = function (it, key) {\n try {\n return it[key];\n } catch (e) { /* empty */ }\n};\n\nmodule.exports = function (it) {\n var O, T, B;\n return it === undefined ? 'Undefined' : it === null ? 'Null'\n // @@toStringTag case\n : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T\n // builtinTag case\n : ARG ? cof(O)\n // ES3 arguments fallback\n : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;\n};\n","var toString = {}.toString;\n\nmodule.exports = function (it) {\n return toString.call(it).slice(8, -1);\n};\n","'use strict';\nvar dP = require('./_object-dp').f;\nvar create = require('./_object-create');\nvar redefineAll = require('./_redefine-all');\nvar ctx = require('./_ctx');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar $iterDefine = require('./_iter-define');\nvar step = require('./_iter-step');\nvar setSpecies = require('./_set-species');\nvar DESCRIPTORS = require('./_descriptors');\nvar fastKey = require('./_meta').fastKey;\nvar validate = require('./_validate-collection');\nvar SIZE = DESCRIPTORS ? '_s' : 'size';\n\nvar getEntry = function (that, key) {\n // fast case\n var index = fastKey(key);\n var entry;\n if (index !== 'F') return that._i[index];\n // frozen object case\n for (entry = that._f; entry; entry = entry.n) {\n if (entry.k == key) return entry;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = create(null); // index\n that._f = undefined; // first entry\n that._l = undefined; // last entry\n that[SIZE] = 0; // size\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.1.3.1 Map.prototype.clear()\n // 23.2.3.2 Set.prototype.clear()\n clear: function clear() {\n for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) {\n entry.r = true;\n if (entry.p) entry.p = entry.p.n = undefined;\n delete data[entry.i];\n }\n that._f = that._l = undefined;\n that[SIZE] = 0;\n },\n // 23.1.3.3 Map.prototype.delete(key)\n // 23.2.3.4 Set.prototype.delete(value)\n 'delete': function (key) {\n var that = validate(this, NAME);\n var entry = getEntry(that, key);\n if (entry) {\n var next = entry.n;\n var prev = entry.p;\n delete that._i[entry.i];\n entry.r = true;\n if (prev) prev.n = next;\n if (next) next.p = prev;\n if (that._f == entry) that._f = next;\n if (that._l == entry) that._l = prev;\n that[SIZE]--;\n } return !!entry;\n },\n // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)\n // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)\n forEach: function forEach(callbackfn /* , that = undefined */) {\n validate(this, NAME);\n var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3);\n var entry;\n while (entry = entry ? entry.n : this._f) {\n f(entry.v, entry.k, this);\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n }\n },\n // 23.1.3.7 Map.prototype.has(key)\n // 23.2.3.7 Set.prototype.has(value)\n has: function has(key) {\n return !!getEntry(validate(this, NAME), key);\n }\n });\n if (DESCRIPTORS) dP(C.prototype, 'size', {\n get: function () {\n return validate(this, NAME)[SIZE];\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var entry = getEntry(that, key);\n var prev, index;\n // change existing entry\n if (entry) {\n entry.v = value;\n // create new entry\n } else {\n that._l = entry = {\n i: index = fastKey(key, true), // <- index\n k: key, // <- key\n v: value, // <- value\n p: prev = that._l, // <- previous entry\n n: undefined, // <- next entry\n r: false // <- removed\n };\n if (!that._f) that._f = entry;\n if (prev) prev.n = entry;\n that[SIZE]++;\n // add to index\n if (index !== 'F') that._i[index] = entry;\n } return that;\n },\n getEntry: getEntry,\n setStrong: function (C, NAME, IS_MAP) {\n // add .keys, .values, .entries, [@@iterator]\n // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11\n $iterDefine(C, NAME, function (iterated, kind) {\n this._t = validate(iterated, NAME); // target\n this._k = kind; // kind\n this._l = undefined; // previous\n }, function () {\n var that = this;\n var kind = that._k;\n var entry = that._l;\n // revert to the last existing entry\n while (entry && entry.r) entry = entry.p;\n // get next entry\n if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) {\n // or finish the iteration\n that._t = undefined;\n return step(1);\n }\n // return step by kind\n if (kind == 'keys') return step(0, entry.k);\n if (kind == 'values') return step(0, entry.v);\n return step(0, [entry.k, entry.v]);\n }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);\n\n // add [@@species], 23.1.2.2, 23.2.2.2\n setSpecies(NAME);\n }\n};\n","'use strict';\nvar redefineAll = require('./_redefine-all');\nvar getWeak = require('./_meta').getWeak;\nvar anObject = require('./_an-object');\nvar isObject = require('./_is-object');\nvar anInstance = require('./_an-instance');\nvar forOf = require('./_for-of');\nvar createArrayMethod = require('./_array-methods');\nvar $has = require('./_has');\nvar validate = require('./_validate-collection');\nvar arrayFind = createArrayMethod(5);\nvar arrayFindIndex = createArrayMethod(6);\nvar id = 0;\n\n// fallback for uncaught frozen keys\nvar uncaughtFrozenStore = function (that) {\n return that._l || (that._l = new UncaughtFrozenStore());\n};\nvar UncaughtFrozenStore = function () {\n this.a = [];\n};\nvar findUncaughtFrozen = function (store, key) {\n return arrayFind(store.a, function (it) {\n return it[0] === key;\n });\n};\nUncaughtFrozenStore.prototype = {\n get: function (key) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) return entry[1];\n },\n has: function (key) {\n return !!findUncaughtFrozen(this, key);\n },\n set: function (key, value) {\n var entry = findUncaughtFrozen(this, key);\n if (entry) entry[1] = value;\n else this.a.push([key, value]);\n },\n 'delete': function (key) {\n var index = arrayFindIndex(this.a, function (it) {\n return it[0] === key;\n });\n if (~index) this.a.splice(index, 1);\n return !!~index;\n }\n};\n\nmodule.exports = {\n getConstructor: function (wrapper, NAME, IS_MAP, ADDER) {\n var C = wrapper(function (that, iterable) {\n anInstance(that, C, NAME, '_i');\n that._t = NAME; // collection type\n that._i = id++; // collection id\n that._l = undefined; // leak store for uncaught frozen objects\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n });\n redefineAll(C.prototype, {\n // 23.3.3.2 WeakMap.prototype.delete(key)\n // 23.4.3.3 WeakSet.prototype.delete(value)\n 'delete': function (key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);\n return data && $has(data, this._i) && delete data[this._i];\n },\n // 23.3.3.4 WeakMap.prototype.has(key)\n // 23.4.3.4 WeakSet.prototype.has(value)\n has: function has(key) {\n if (!isObject(key)) return false;\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);\n return data && $has(data, this._i);\n }\n });\n return C;\n },\n def: function (that, key, value) {\n var data = getWeak(anObject(key), true);\n if (data === true) uncaughtFrozenStore(that).set(key, value);\n else data[that._i] = value;\n return that;\n },\n ufstore: uncaughtFrozenStore\n};\n","'use strict';\nvar global = require('./_global');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar redefineAll = require('./_redefine-all');\nvar meta = require('./_meta');\nvar forOf = require('./_for-of');\nvar anInstance = require('./_an-instance');\nvar isObject = require('./_is-object');\nvar fails = require('./_fails');\nvar $iterDetect = require('./_iter-detect');\nvar setToStringTag = require('./_set-to-string-tag');\nvar inheritIfRequired = require('./_inherit-if-required');\n\nmodule.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {\n var Base = global[NAME];\n var C = Base;\n var ADDER = IS_MAP ? 'set' : 'add';\n var proto = C && C.prototype;\n var O = {};\n var fixMethod = function (KEY) {\n var fn = proto[KEY];\n redefine(proto, KEY,\n KEY == 'delete' ? function (a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'has' ? function has(a) {\n return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'get' ? function get(a) {\n return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);\n } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }\n : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }\n );\n };\n if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {\n new C().entries().next();\n }))) {\n // create collection constructor\n C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);\n redefineAll(C.prototype, methods);\n meta.NEED = true;\n } else {\n var instance = new C();\n // early implementations not supports chaining\n var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;\n // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false\n var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });\n // most early implementations doesn't supports iterables, most modern - not close it correctly\n var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new\n // for early implementations -0 and +0 not the same\n var BUGGY_ZERO = !IS_WEAK && fails(function () {\n // V8 ~ Chromium 42- fails only with 5+ elements\n var $instance = new C();\n var index = 5;\n while (index--) $instance[ADDER](index, index);\n return !$instance.has(-0);\n });\n if (!ACCEPT_ITERABLES) {\n C = wrapper(function (target, iterable) {\n anInstance(target, C, NAME);\n var that = inheritIfRequired(new Base(), target, C);\n if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);\n return that;\n });\n C.prototype = proto;\n proto.constructor = C;\n }\n if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {\n fixMethod('delete');\n fixMethod('has');\n IS_MAP && fixMethod('get');\n }\n if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);\n // weak collections should not contains .clear method\n if (IS_WEAK && proto.clear) delete proto.clear;\n }\n\n setToStringTag(C, NAME);\n\n O[NAME] = C;\n $export($export.G + $export.W + $export.F * (C != Base), O);\n\n if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);\n\n return C;\n};\n","var core = module.exports = { version: '2.6.10' };\nif (typeof __e == 'number') __e = core; // eslint-disable-line no-undef\n","// optional / simple context binding\nvar aFunction = require('./_a-function');\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n","// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError(\"Can't call method on \" + it);\n return it;\n};\n","// Thank's IE8 for his funny defineProperty\nmodule.exports = !require('./_fails')(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar document = require('./_global').document;\n// typeof document.createElement is 'object' in old IE\nvar is = isObject(document) && isObject(document.createElement);\nmodule.exports = function (it) {\n return is ? document.createElement(it) : {};\n};\n","// IE 8- don't enum bug keys\nmodule.exports = (\n 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'\n).split(',');\n","var global = require('./_global');\nvar core = require('./_core');\nvar hide = require('./_hide');\nvar redefine = require('./_redefine');\nvar ctx = require('./_ctx');\nvar PROTOTYPE = 'prototype';\n\nvar $export = function (type, name, source) {\n var IS_FORCED = type & $export.F;\n var IS_GLOBAL = type & $export.G;\n var IS_STATIC = type & $export.S;\n var IS_PROTO = type & $export.P;\n var IS_BIND = type & $export.B;\n var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];\n var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});\n var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});\n var key, own, out, exp;\n if (IS_GLOBAL) source = name;\n for (key in source) {\n // contains in native\n own = !IS_FORCED && target && target[key] !== undefined;\n // export native or passed\n out = (own ? target : source)[key];\n // bind timers to global for call from export context\n exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;\n // extend global\n if (target) redefine(target, key, out, type & $export.U);\n // export\n if (exports[key] != out) hide(exports, key, exp);\n if (IS_PROTO && expProto[key] != out) expProto[key] = out;\n }\n};\nglobal.core = core;\n// type bitmap\n$export.F = 1; // forced\n$export.G = 2; // global\n$export.S = 4; // static\n$export.P = 8; // proto\n$export.B = 16; // bind\n$export.W = 32; // wrap\n$export.U = 64; // safe\n$export.R = 128; // real proto method for `library`\nmodule.exports = $export;\n","module.exports = function (exec) {\n try {\n return !!exec();\n } catch (e) {\n return true;\n }\n};\n","var ctx = require('./_ctx');\nvar call = require('./_iter-call');\nvar isArrayIter = require('./_is-array-iter');\nvar anObject = require('./_an-object');\nvar toLength = require('./_to-length');\nvar getIterFn = require('./core.get-iterator-method');\nvar BREAK = {};\nvar RETURN = {};\nvar exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {\n var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable);\n var f = ctx(fn, that, entries ? 2 : 1);\n var index = 0;\n var length, step, iterator, result;\n if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');\n // fast case for arrays with default iterator\n if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {\n result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);\n if (result === BREAK || result === RETURN) return result;\n } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {\n result = call(iterator, f, step.value, entries);\n if (result === BREAK || result === RETURN) return result;\n }\n};\nexports.BREAK = BREAK;\nexports.RETURN = RETURN;\n","module.exports = require('./_shared')('native-function-to-string', Function.toString);\n","// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028\nvar global = module.exports = typeof window != 'undefined' && window.Math == Math\n ? window : typeof self != 'undefined' && self.Math == Math ? self\n // eslint-disable-next-line no-new-func\n : Function('return this')();\nif (typeof __g == 'number') __g = global; // eslint-disable-line no-undef\n","var hasOwnProperty = {}.hasOwnProperty;\nmodule.exports = function (it, key) {\n return hasOwnProperty.call(it, key);\n};\n","var dP = require('./_object-dp');\nvar createDesc = require('./_property-desc');\nmodule.exports = require('./_descriptors') ? function (object, key, value) {\n return dP.f(object, key, createDesc(1, value));\n} : function (object, key, value) {\n object[key] = value;\n return object;\n};\n","var document = require('./_global').document;\nmodule.exports = document && document.documentElement;\n","module.exports = !require('./_descriptors') && !require('./_fails')(function () {\n return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7;\n});\n","var isObject = require('./_is-object');\nvar setPrototypeOf = require('./_set-proto').set;\nmodule.exports = function (that, target, C) {\n var S = target.constructor;\n var P;\n if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {\n setPrototypeOf(that, P);\n } return that;\n};\n","// fallback for non-array-like ES3 and non-enumerable old V8 strings\nvar cof = require('./_cof');\n// eslint-disable-next-line no-prototype-builtins\nmodule.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {\n return cof(it) == 'String' ? it.split('') : Object(it);\n};\n","// check on default Array iterator\nvar Iterators = require('./_iterators');\nvar ITERATOR = require('./_wks')('iterator');\nvar ArrayProto = Array.prototype;\n\nmodule.exports = function (it) {\n return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);\n};\n","// 7.2.2 IsArray(argument)\nvar cof = require('./_cof');\nmodule.exports = Array.isArray || function isArray(arg) {\n return cof(arg) == 'Array';\n};\n","module.exports = function (it) {\n return typeof it === 'object' ? it !== null : typeof it === 'function';\n};\n","// call something on iterator step with safe closing on error\nvar anObject = require('./_an-object');\nmodule.exports = function (iterator, fn, value, entries) {\n try {\n return entries ? fn(anObject(value)[0], value[1]) : fn(value);\n // 7.4.6 IteratorClose(iterator, completion)\n } catch (e) {\n var ret = iterator['return'];\n if (ret !== undefined) anObject(ret.call(iterator));\n throw e;\n }\n};\n","'use strict';\nvar create = require('./_object-create');\nvar descriptor = require('./_property-desc');\nvar setToStringTag = require('./_set-to-string-tag');\nvar IteratorPrototype = {};\n\n// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()\nrequire('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; });\n\nmodule.exports = function (Constructor, NAME, next) {\n Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) });\n setToStringTag(Constructor, NAME + ' Iterator');\n};\n","'use strict';\nvar LIBRARY = require('./_library');\nvar $export = require('./_export');\nvar redefine = require('./_redefine');\nvar hide = require('./_hide');\nvar Iterators = require('./_iterators');\nvar $iterCreate = require('./_iter-create');\nvar setToStringTag = require('./_set-to-string-tag');\nvar getPrototypeOf = require('./_object-gpo');\nvar ITERATOR = require('./_wks')('iterator');\nvar BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`\nvar FF_ITERATOR = '@@iterator';\nvar KEYS = 'keys';\nvar VALUES = 'values';\n\nvar returnThis = function () { return this; };\n\nmodule.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {\n $iterCreate(Constructor, NAME, next);\n var getMethod = function (kind) {\n if (!BUGGY && kind in proto) return proto[kind];\n switch (kind) {\n case KEYS: return function keys() { return new Constructor(this, kind); };\n case VALUES: return function values() { return new Constructor(this, kind); };\n } return function entries() { return new Constructor(this, kind); };\n };\n var TAG = NAME + ' Iterator';\n var DEF_VALUES = DEFAULT == VALUES;\n var VALUES_BUG = false;\n var proto = Base.prototype;\n var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];\n var $default = $native || getMethod(DEFAULT);\n var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;\n var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;\n var methods, key, IteratorPrototype;\n // Fix native\n if ($anyNative) {\n IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));\n if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {\n // Set @@toStringTag to native iterators\n setToStringTag(IteratorPrototype, TAG, true);\n // fix for some old engines\n if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);\n }\n }\n // fix Array#{values, @@iterator}.name in V8 / FF\n if (DEF_VALUES && $native && $native.name !== VALUES) {\n VALUES_BUG = true;\n $default = function values() { return $native.call(this); };\n }\n // Define iterator\n if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {\n hide(proto, ITERATOR, $default);\n }\n // Plug for library\n Iterators[NAME] = $default;\n Iterators[TAG] = returnThis;\n if (DEFAULT) {\n methods = {\n values: DEF_VALUES ? $default : getMethod(VALUES),\n keys: IS_SET ? $default : getMethod(KEYS),\n entries: $entries\n };\n if (FORCED) for (key in methods) {\n if (!(key in proto)) redefine(proto, key, methods[key]);\n } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);\n }\n return methods;\n};\n","var ITERATOR = require('./_wks')('iterator');\nvar SAFE_CLOSING = false;\n\ntry {\n var riter = [7][ITERATOR]();\n riter['return'] = function () { SAFE_CLOSING = true; };\n // eslint-disable-next-line no-throw-literal\n Array.from(riter, function () { throw 2; });\n} catch (e) { /* empty */ }\n\nmodule.exports = function (exec, skipClosing) {\n if (!skipClosing && !SAFE_CLOSING) return false;\n var safe = false;\n try {\n var arr = [7];\n var iter = arr[ITERATOR]();\n iter.next = function () { return { done: safe = true }; };\n arr[ITERATOR] = function () { return iter; };\n exec(arr);\n } catch (e) { /* empty */ }\n return safe;\n};\n","module.exports = function (done, value) {\n return { value: value, done: !!done };\n};\n","module.exports = {};\n","module.exports = false;\n","var META = require('./_uid')('meta');\nvar isObject = require('./_is-object');\nvar has = require('./_has');\nvar setDesc = require('./_object-dp').f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !require('./_fails')(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n","var Map = require('./es6.map');\nvar $export = require('./_export');\nvar shared = require('./_shared')('metadata');\nvar store = shared.store || (shared.store = new (require('./es6.weak-map'))());\n\nvar getOrCreateMetadataMap = function (target, targetKey, create) {\n var targetMetadata = store.get(target);\n if (!targetMetadata) {\n if (!create) return undefined;\n store.set(target, targetMetadata = new Map());\n }\n var keyMetadata = targetMetadata.get(targetKey);\n if (!keyMetadata) {\n if (!create) return undefined;\n targetMetadata.set(targetKey, keyMetadata = new Map());\n } return keyMetadata;\n};\nvar ordinaryHasOwnMetadata = function (MetadataKey, O, P) {\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? false : metadataMap.has(MetadataKey);\n};\nvar ordinaryGetOwnMetadata = function (MetadataKey, O, P) {\n var metadataMap = getOrCreateMetadataMap(O, P, false);\n return metadataMap === undefined ? undefined : metadataMap.get(MetadataKey);\n};\nvar ordinaryDefineOwnMetadata = function (MetadataKey, MetadataValue, O, P) {\n getOrCreateMetadataMap(O, P, true).set(MetadataKey, MetadataValue);\n};\nvar ordinaryOwnMetadataKeys = function (target, targetKey) {\n var metadataMap = getOrCreateMetadataMap(target, targetKey, false);\n var keys = [];\n if (metadataMap) metadataMap.forEach(function (_, key) { keys.push(key); });\n return keys;\n};\nvar toMetaKey = function (it) {\n return it === undefined || typeof it == 'symbol' ? it : String(it);\n};\nvar exp = function (O) {\n $export($export.S, 'Reflect', O);\n};\n\nmodule.exports = {\n store: store,\n map: getOrCreateMetadataMap,\n has: ordinaryHasOwnMetadata,\n get: ordinaryGetOwnMetadata,\n set: ordinaryDefineOwnMetadata,\n keys: ordinaryOwnMetadataKeys,\n key: toMetaKey,\n exp: exp\n};\n","'use strict';\n// 19.1.2.1 Object.assign(target, source, ...)\nvar DESCRIPTORS = require('./_descriptors');\nvar getKeys = require('./_object-keys');\nvar gOPS = require('./_object-gops');\nvar pIE = require('./_object-pie');\nvar toObject = require('./_to-object');\nvar IObject = require('./_iobject');\nvar $assign = Object.assign;\n\n// should work with symbols and should have deterministic property order (V8 bug)\nmodule.exports = !$assign || require('./_fails')(function () {\n var A = {};\n var B = {};\n // eslint-disable-next-line no-undef\n var S = Symbol();\n var K = 'abcdefghijklmnopqrst';\n A[S] = 7;\n K.split('').forEach(function (k) { B[k] = k; });\n return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;\n}) ? function assign(target, source) { // eslint-disable-line no-unused-vars\n var T = toObject(target);\n var aLen = arguments.length;\n var index = 1;\n var getSymbols = gOPS.f;\n var isEnum = pIE.f;\n while (aLen > index) {\n var S = IObject(arguments[index++]);\n var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);\n var length = keys.length;\n var j = 0;\n var key;\n while (length > j) {\n key = keys[j++];\n if (!DESCRIPTORS || isEnum.call(S, key)) T[key] = S[key];\n }\n } return T;\n} : $assign;\n","// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])\nvar anObject = require('./_an-object');\nvar dPs = require('./_object-dps');\nvar enumBugKeys = require('./_enum-bug-keys');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar Empty = function () { /* empty */ };\nvar PROTOTYPE = 'prototype';\n\n// Create object with fake `null` prototype: use iframe Object with cleared prototype\nvar createDict = function () {\n // Thrash, waste and sodomy: IE GC bug\n var iframe = require('./_dom-create')('iframe');\n var i = enumBugKeys.length;\n var lt = '<';\n var gt = '>';\n var iframeDocument;\n iframe.style.display = 'none';\n require('./_html').appendChild(iframe);\n iframe.src = 'javascript:'; // eslint-disable-line no-script-url\n // createDict = iframe.contentWindow.Object;\n // html.removeChild(iframe);\n iframeDocument = iframe.contentWindow.document;\n iframeDocument.open();\n iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);\n iframeDocument.close();\n createDict = iframeDocument.F;\n while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]];\n return createDict();\n};\n\nmodule.exports = Object.create || function create(O, Properties) {\n var result;\n if (O !== null) {\n Empty[PROTOTYPE] = anObject(O);\n result = new Empty();\n Empty[PROTOTYPE] = null;\n // add \"__proto__\" for Object.getPrototypeOf polyfill\n result[IE_PROTO] = O;\n } else result = createDict();\n return Properties === undefined ? result : dPs(result, Properties);\n};\n","var anObject = require('./_an-object');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar toPrimitive = require('./_to-primitive');\nvar dP = Object.defineProperty;\n\nexports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) {\n anObject(O);\n P = toPrimitive(P, true);\n anObject(Attributes);\n if (IE8_DOM_DEFINE) try {\n return dP(O, P, Attributes);\n } catch (e) { /* empty */ }\n if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');\n if ('value' in Attributes) O[P] = Attributes.value;\n return O;\n};\n","var dP = require('./_object-dp');\nvar anObject = require('./_an-object');\nvar getKeys = require('./_object-keys');\n\nmodule.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) {\n anObject(O);\n var keys = getKeys(Properties);\n var length = keys.length;\n var i = 0;\n var P;\n while (length > i) dP.f(O, P = keys[i++], Properties[P]);\n return O;\n};\n","var pIE = require('./_object-pie');\nvar createDesc = require('./_property-desc');\nvar toIObject = require('./_to-iobject');\nvar toPrimitive = require('./_to-primitive');\nvar has = require('./_has');\nvar IE8_DOM_DEFINE = require('./_ie8-dom-define');\nvar gOPD = Object.getOwnPropertyDescriptor;\n\nexports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) {\n O = toIObject(O);\n P = toPrimitive(P, true);\n if (IE8_DOM_DEFINE) try {\n return gOPD(O, P);\n } catch (e) { /* empty */ }\n if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);\n};\n","exports.f = Object.getOwnPropertySymbols;\n","// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)\nvar has = require('./_has');\nvar toObject = require('./_to-object');\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\nvar ObjectProto = Object.prototype;\n\nmodule.exports = Object.getPrototypeOf || function (O) {\n O = toObject(O);\n if (has(O, IE_PROTO)) return O[IE_PROTO];\n if (typeof O.constructor == 'function' && O instanceof O.constructor) {\n return O.constructor.prototype;\n } return O instanceof Object ? ObjectProto : null;\n};\n","var has = require('./_has');\nvar toIObject = require('./_to-iobject');\nvar arrayIndexOf = require('./_array-includes')(false);\nvar IE_PROTO = require('./_shared-key')('IE_PROTO');\n\nmodule.exports = function (object, names) {\n var O = toIObject(object);\n var i = 0;\n var result = [];\n var key;\n for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key);\n // Don't enum bug & hidden keys\n while (names.length > i) if (has(O, key = names[i++])) {\n ~arrayIndexOf(result, key) || result.push(key);\n }\n return result;\n};\n","// 19.1.2.14 / 15.2.3.14 Object.keys(O)\nvar $keys = require('./_object-keys-internal');\nvar enumBugKeys = require('./_enum-bug-keys');\n\nmodule.exports = Object.keys || function keys(O) {\n return $keys(O, enumBugKeys);\n};\n","exports.f = {}.propertyIsEnumerable;\n","module.exports = function (bitmap, value) {\n return {\n enumerable: !(bitmap & 1),\n configurable: !(bitmap & 2),\n writable: !(bitmap & 4),\n value: value\n };\n};\n","var redefine = require('./_redefine');\nmodule.exports = function (target, src, safe) {\n for (var key in src) redefine(target, key, src[key], safe);\n return target;\n};\n","var global = require('./_global');\nvar hide = require('./_hide');\nvar has = require('./_has');\nvar SRC = require('./_uid')('src');\nvar $toString = require('./_function-to-string');\nvar TO_STRING = 'toString';\nvar TPL = ('' + $toString).split(TO_STRING);\n\nrequire('./_core').inspectSource = function (it) {\n return $toString.call(it);\n};\n\n(module.exports = function (O, key, val, safe) {\n var isFunction = typeof val == 'function';\n if (isFunction) has(val, 'name') || hide(val, 'name', key);\n if (O[key] === val) return;\n if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));\n if (O === global) {\n O[key] = val;\n } else if (!safe) {\n delete O[key];\n hide(O, key, val);\n } else if (O[key]) {\n O[key] = val;\n } else {\n hide(O, key, val);\n }\n// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative\n})(Function.prototype, TO_STRING, function toString() {\n return typeof this == 'function' && this[SRC] || $toString.call(this);\n});\n","// Works with __proto__ only. Old v8 can't work with null proto objects.\n/* eslint-disable no-proto */\nvar isObject = require('./_is-object');\nvar anObject = require('./_an-object');\nvar check = function (O, proto) {\n anObject(O);\n if (!isObject(proto) && proto !== null) throw TypeError(proto + \": can't set as prototype!\");\n};\nmodule.exports = {\n set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line\n function (test, buggy, set) {\n try {\n set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2);\n set(test, []);\n buggy = !(test instanceof Array);\n } catch (e) { buggy = true; }\n return function setPrototypeOf(O, proto) {\n check(O, proto);\n if (buggy) O.__proto__ = proto;\n else set(O, proto);\n return O;\n };\n }({}, false) : undefined),\n check: check\n};\n","'use strict';\nvar global = require('./_global');\nvar dP = require('./_object-dp');\nvar DESCRIPTORS = require('./_descriptors');\nvar SPECIES = require('./_wks')('species');\n\nmodule.exports = function (KEY) {\n var C = global[KEY];\n if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {\n configurable: true,\n get: function () { return this; }\n });\n};\n","var def = require('./_object-dp').f;\nvar has = require('./_has');\nvar TAG = require('./_wks')('toStringTag');\n\nmodule.exports = function (it, tag, stat) {\n if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag });\n};\n","var shared = require('./_shared')('keys');\nvar uid = require('./_uid');\nmodule.exports = function (key) {\n return shared[key] || (shared[key] = uid(key));\n};\n","var core = require('./_core');\nvar global = require('./_global');\nvar SHARED = '__core-js_shared__';\nvar store = global[SHARED] || (global[SHARED] = {});\n\n(module.exports = function (key, value) {\n return store[key] || (store[key] = value !== undefined ? value : {});\n})('versions', []).push({\n version: core.version,\n mode: require('./_library') ? 'pure' : 'global',\n copyright: '© 2019 Denis Pushkarev (zloirock.ru)'\n});\n","var toInteger = require('./_to-integer');\nvar max = Math.max;\nvar min = Math.min;\nmodule.exports = function (index, length) {\n index = toInteger(index);\n return index < 0 ? max(index + length, 0) : min(index, length);\n};\n","// 7.1.4 ToInteger\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nmodule.exports = function (it) {\n return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);\n};\n","// to indexed object, toObject with fallback for non-array-like ES3 strings\nvar IObject = require('./_iobject');\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return IObject(defined(it));\n};\n","// 7.1.15 ToLength\nvar toInteger = require('./_to-integer');\nvar min = Math.min;\nmodule.exports = function (it) {\n return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991\n};\n","// 7.1.13 ToObject(argument)\nvar defined = require('./_defined');\nmodule.exports = function (it) {\n return Object(defined(it));\n};\n","// 7.1.1 ToPrimitive(input [, PreferredType])\nvar isObject = require('./_is-object');\n// instead of the ES6 spec version, we didn't implement @@toPrimitive case\n// and the second argument - flag - preferred type is a string\nmodule.exports = function (it, S) {\n if (!isObject(it)) return it;\n var fn, val;\n if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;\n if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;\n throw TypeError(\"Can't convert object to primitive value\");\n};\n","var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n","var isObject = require('./_is-object');\nmodule.exports = function (it, TYPE) {\n if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');\n return it;\n};\n","var store = require('./_shared')('wks');\nvar uid = require('./_uid');\nvar Symbol = require('./_global').Symbol;\nvar USE_SYMBOL = typeof Symbol == 'function';\n\nvar $exports = module.exports = function (name) {\n return store[name] || (store[name] =\n USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));\n};\n\n$exports.store = store;\n","var classof = require('./_classof');\nvar ITERATOR = require('./_wks')('iterator');\nvar Iterators = require('./_iterators');\nmodule.exports = require('./_core').getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it['@@iterator']\n || Iterators[classof(it)];\n};\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar MAP = 'Map';\n\n// 23.1 Map Objects\nmodule.exports = require('./_collection')(MAP, function (get) {\n return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.1.3.6 Map.prototype.get(key)\n get: function get(key) {\n var entry = strong.getEntry(validate(this, MAP), key);\n return entry && entry.v;\n },\n // 23.1.3.9 Map.prototype.set(key, value)\n set: function set(key, value) {\n return strong.def(validate(this, MAP), key === 0 ? 0 : key, value);\n }\n}, strong, true);\n","'use strict';\nvar strong = require('./_collection-strong');\nvar validate = require('./_validate-collection');\nvar SET = 'Set';\n\n// 23.2 Set Objects\nmodule.exports = require('./_collection')(SET, function (get) {\n return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); };\n}, {\n // 23.2.3.1 Set.prototype.add(value)\n add: function add(value) {\n return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value);\n }\n}, strong);\n","'use strict';\nvar global = require('./_global');\nvar each = require('./_array-methods')(0);\nvar redefine = require('./_redefine');\nvar meta = require('./_meta');\nvar assign = require('./_object-assign');\nvar weak = require('./_collection-weak');\nvar isObject = require('./_is-object');\nvar validate = require('./_validate-collection');\nvar NATIVE_WEAK_MAP = require('./_validate-collection');\nvar IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;\nvar WEAK_MAP = 'WeakMap';\nvar getWeak = meta.getWeak;\nvar isExtensible = Object.isExtensible;\nvar uncaughtFrozenStore = weak.ufstore;\nvar InternalMap;\n\nvar wrapper = function (get) {\n return function WeakMap() {\n return get(this, arguments.length > 0 ? arguments[0] : undefined);\n };\n};\n\nvar methods = {\n // 23.3.3.3 WeakMap.prototype.get(key)\n get: function get(key) {\n if (isObject(key)) {\n var data = getWeak(key);\n if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);\n return data ? data[this._i] : undefined;\n }\n },\n // 23.3.3.5 WeakMap.prototype.set(key, value)\n set: function set(key, value) {\n return weak.def(validate(this, WEAK_MAP), key, value);\n }\n};\n\n// 23.3 WeakMap Objects\nvar $WeakMap = module.exports = require('./_collection')(WEAK_MAP, wrapper, methods, weak, true, true);\n\n// IE11 WeakMap frozen keys fix\nif (NATIVE_WEAK_MAP && IS_IE11) {\n InternalMap = weak.getConstructor(wrapper, WEAK_MAP);\n assign(InternalMap.prototype, methods);\n meta.NEED = true;\n each(['delete', 'has', 'get', 'set'], function (key) {\n var proto = $WeakMap.prototype;\n var method = proto[key];\n redefine(proto, key, function (a, b) {\n // store frozen objects on internal weakmap shim\n if (isObject(a) && !isExtensible(a)) {\n if (!this._f) this._f = new InternalMap();\n var result = this._f[key](a, b);\n return key == 'set' ? this : result;\n // store all the rest on native weakmap\n } return method.call(this, a, b);\n });\n });\n}\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar toMetaKey = metadata.key;\nvar ordinaryDefineOwnMetadata = metadata.set;\n\nmetadata.exp({ defineMetadata: function defineMetadata(metadataKey, metadataValue, target, targetKey) {\n ordinaryDefineOwnMetadata(metadataKey, metadataValue, anObject(target), toMetaKey(targetKey));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar toMetaKey = metadata.key;\nvar getOrCreateMetadataMap = metadata.map;\nvar store = metadata.store;\n\nmetadata.exp({ deleteMetadata: function deleteMetadata(metadataKey, target /* , targetKey */) {\n var targetKey = arguments.length < 3 ? undefined : toMetaKey(arguments[2]);\n var metadataMap = getOrCreateMetadataMap(anObject(target), targetKey, false);\n if (metadataMap === undefined || !metadataMap['delete'](metadataKey)) return false;\n if (metadataMap.size) return true;\n var targetMetadata = store.get(target);\n targetMetadata['delete'](targetKey);\n return !!targetMetadata.size || store['delete'](target);\n} });\n","var Set = require('./es6.set');\nvar from = require('./_array-from-iterable');\nvar metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryOwnMetadataKeys = metadata.keys;\nvar toMetaKey = metadata.key;\n\nvar ordinaryMetadataKeys = function (O, P) {\n var oKeys = ordinaryOwnMetadataKeys(O, P);\n var parent = getPrototypeOf(O);\n if (parent === null) return oKeys;\n var pKeys = ordinaryMetadataKeys(parent, P);\n return pKeys.length ? oKeys.length ? from(new Set(oKeys.concat(pKeys))) : pKeys : oKeys;\n};\n\nmetadata.exp({ getMetadataKeys: function getMetadataKeys(target /* , targetKey */) {\n return ordinaryMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar ordinaryGetOwnMetadata = metadata.get;\nvar toMetaKey = metadata.key;\n\nvar ordinaryGetMetadata = function (MetadataKey, O, P) {\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if (hasOwn) return ordinaryGetOwnMetadata(MetadataKey, O, P);\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryGetMetadata(MetadataKey, parent, P) : undefined;\n};\n\nmetadata.exp({ getMetadata: function getMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryGetMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryOwnMetadataKeys = metadata.keys;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ getOwnMetadataKeys: function getOwnMetadataKeys(target /* , targetKey */) {\n return ordinaryOwnMetadataKeys(anObject(target), arguments.length < 2 ? undefined : toMetaKey(arguments[1]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryGetOwnMetadata = metadata.get;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ getOwnMetadata: function getOwnMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryGetOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar getPrototypeOf = require('./_object-gpo');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar toMetaKey = metadata.key;\n\nvar ordinaryHasMetadata = function (MetadataKey, O, P) {\n var hasOwn = ordinaryHasOwnMetadata(MetadataKey, O, P);\n if (hasOwn) return true;\n var parent = getPrototypeOf(O);\n return parent !== null ? ordinaryHasMetadata(MetadataKey, parent, P) : false;\n};\n\nmetadata.exp({ hasMetadata: function hasMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryHasMetadata(metadataKey, anObject(target), arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar ordinaryHasOwnMetadata = metadata.has;\nvar toMetaKey = metadata.key;\n\nmetadata.exp({ hasOwnMetadata: function hasOwnMetadata(metadataKey, target /* , targetKey */) {\n return ordinaryHasOwnMetadata(metadataKey, anObject(target)\n , arguments.length < 3 ? undefined : toMetaKey(arguments[2]));\n} });\n","var $metadata = require('./_metadata');\nvar anObject = require('./_an-object');\nvar aFunction = require('./_a-function');\nvar toMetaKey = $metadata.key;\nvar ordinaryDefineOwnMetadata = $metadata.set;\n\n$metadata.exp({ metadata: function metadata(metadataKey, metadataValue) {\n return function decorator(target, targetKey) {\n ordinaryDefineOwnMetadata(\n metadataKey, metadataValue,\n (targetKey !== undefined ? anObject : aFunction)(target),\n toMetaKey(targetKey)\n );\n };\n} });\n","/**\n* @license\n* Copyright Google Inc. All Rights Reserved.\n*\n* Use of this source code is governed by an MIT-style license that can be\n* found in the LICENSE file at https://angular.io/license\n*/\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(factory());\n}(this, (function () { 'use strict';\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nvar Zone$1 = (function (global) {\n var performance = global['performance'];\n function mark(name) {\n performance && performance['mark'] && performance['mark'](name);\n }\n function performanceMeasure(name, label) {\n performance && performance['measure'] && performance['measure'](name, label);\n }\n mark('Zone');\n var checkDuplicate = global[('__zone_symbol__forceDuplicateZoneCheck')] === true;\n if (global['Zone']) {\n // if global['Zone'] already exists (maybe zone.js was already loaded or\n // some other lib also registered a global object named Zone), we may need\n // to throw an error, but sometimes user may not want this error.\n // For example,\n // we have two web pages, page1 includes zone.js, page2 doesn't.\n // and the 1st time user load page1 and page2, everything work fine,\n // but when user load page2 again, error occurs because global['Zone'] already exists.\n // so we add a flag to let user choose whether to throw this error or not.\n // By default, if existing Zone is from zone.js, we will not throw the error.\n if (checkDuplicate || typeof global['Zone'].__symbol__ !== 'function') {\n throw new Error('Zone already loaded.');\n }\n else {\n return global['Zone'];\n }\n }\n var Zone = /** @class */ (function () {\n function Zone(parent, zoneSpec) {\n this._parent = parent;\n this._name = zoneSpec ? zoneSpec.name || 'unnamed' : '';\n this._properties = zoneSpec && zoneSpec.properties || {};\n this._zoneDelegate =\n new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec);\n }\n Zone.assertZonePatched = function () {\n if (global['Promise'] !== patches['ZoneAwarePromise']) {\n throw new Error('Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' +\n 'has been overwritten.\\n' +\n 'Most likely cause is that a Promise polyfill has been loaded ' +\n 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' +\n 'If you must load one, do so before loading zone.js.)');\n }\n };\n Object.defineProperty(Zone, \"root\", {\n get: function () {\n var zone = Zone.current;\n while (zone.parent) {\n zone = zone.parent;\n }\n return zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone, \"current\", {\n get: function () {\n return _currentZoneFrame.zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone, \"currentTask\", {\n get: function () {\n return _currentTask;\n },\n enumerable: true,\n configurable: true\n });\n Zone.__load_patch = function (name, fn) {\n if (patches.hasOwnProperty(name)) {\n if (checkDuplicate) {\n throw Error('Already loaded patch: ' + name);\n }\n }\n else if (!global['__Zone_disable_' + name]) {\n var perfName = 'Zone:' + name;\n mark(perfName);\n patches[name] = fn(global, Zone, _api);\n performanceMeasure(perfName, perfName);\n }\n };\n Object.defineProperty(Zone.prototype, \"parent\", {\n get: function () {\n return this._parent;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(Zone.prototype, \"name\", {\n get: function () {\n return this._name;\n },\n enumerable: true,\n configurable: true\n });\n Zone.prototype.get = function (key) {\n var zone = this.getZoneWith(key);\n if (zone)\n return zone._properties[key];\n };\n Zone.prototype.getZoneWith = function (key) {\n var current = this;\n while (current) {\n if (current._properties.hasOwnProperty(key)) {\n return current;\n }\n current = current._parent;\n }\n return null;\n };\n Zone.prototype.fork = function (zoneSpec) {\n if (!zoneSpec)\n throw new Error('ZoneSpec required!');\n return this._zoneDelegate.fork(this, zoneSpec);\n };\n Zone.prototype.wrap = function (callback, source) {\n if (typeof callback !== 'function') {\n throw new Error('Expecting function got: ' + callback);\n }\n var _callback = this._zoneDelegate.intercept(this, callback, source);\n var zone = this;\n return function () {\n return zone.runGuarded(_callback, this, arguments, source);\n };\n };\n Zone.prototype.run = function (callback, applyThis, applyArgs, source) {\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runGuarded = function (callback, applyThis, applyArgs, source) {\n if (applyThis === void 0) { applyThis = null; }\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n try {\n return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n _currentZoneFrame = _currentZoneFrame.parent;\n }\n };\n Zone.prototype.runTask = function (task, applyThis, applyArgs) {\n if (task.zone != this) {\n throw new Error('A task can only be run in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n }\n // https://github.com/angular/zone.js/issues/778, sometimes eventTask\n // will run in notScheduled(canceled) state, we should not try to\n // run such kind of task but just return\n if (task.state === notScheduled && (task.type === eventTask || task.type === macroTask)) {\n return;\n }\n var reEntryGuard = task.state != running;\n reEntryGuard && task._transitionTo(running, scheduled);\n task.runCount++;\n var previousTask = _currentTask;\n _currentTask = task;\n _currentZoneFrame = { parent: _currentZoneFrame, zone: this };\n try {\n if (task.type == macroTask && task.data && !task.data.isPeriodic) {\n task.cancelFn = undefined;\n }\n try {\n return this._zoneDelegate.invokeTask(this, task, applyThis, applyArgs);\n }\n catch (error) {\n if (this._zoneDelegate.handleError(this, error)) {\n throw error;\n }\n }\n }\n finally {\n // if the task's state is notScheduled or unknown, then it has already been cancelled\n // we should not reset the state to scheduled\n if (task.state !== notScheduled && task.state !== unknown) {\n if (task.type == eventTask || (task.data && task.data.isPeriodic)) {\n reEntryGuard && task._transitionTo(scheduled, running);\n }\n else {\n task.runCount = 0;\n this._updateTaskCount(task, -1);\n reEntryGuard &&\n task._transitionTo(notScheduled, running, notScheduled);\n }\n }\n _currentZoneFrame = _currentZoneFrame.parent;\n _currentTask = previousTask;\n }\n };\n Zone.prototype.scheduleTask = function (task) {\n if (task.zone && task.zone !== this) {\n // check if the task was rescheduled, the newZone\n // should not be the children of the original zone\n var newZone = this;\n while (newZone) {\n if (newZone === task.zone) {\n throw Error(\"can not reschedule task to \" + this.name + \" which is descendants of the original zone \" + task.zone.name);\n }\n newZone = newZone.parent;\n }\n }\n task._transitionTo(scheduling, notScheduled);\n var zoneDelegates = [];\n task._zoneDelegates = zoneDelegates;\n task._zone = this;\n try {\n task = this._zoneDelegate.scheduleTask(this, task);\n }\n catch (err) {\n // should set task's state to unknown when scheduleTask throw error\n // because the err may from reschedule, so the fromState maybe notScheduled\n task._transitionTo(unknown, scheduling, notScheduled);\n // TODO: @JiaLiPassion, should we check the result from handleError?\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n if (task._zoneDelegates === zoneDelegates) {\n // we have to check because internally the delegate can reschedule the task.\n this._updateTaskCount(task, 1);\n }\n if (task.state == scheduling) {\n task._transitionTo(scheduled, scheduling);\n }\n return task;\n };\n Zone.prototype.scheduleMicroTask = function (source, callback, data, customSchedule) {\n return this.scheduleTask(new ZoneTask(microTask, source, callback, data, customSchedule, undefined));\n };\n Zone.prototype.scheduleMacroTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.scheduleEventTask = function (source, callback, data, customSchedule, customCancel) {\n return this.scheduleTask(new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel));\n };\n Zone.prototype.cancelTask = function (task) {\n if (task.zone != this)\n throw new Error('A task can only be cancelled in the zone of creation! (Creation: ' +\n (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');\n task._transitionTo(canceling, scheduled, running);\n try {\n this._zoneDelegate.cancelTask(this, task);\n }\n catch (err) {\n // if error occurs when cancelTask, transit the state to unknown\n task._transitionTo(unknown, canceling);\n this._zoneDelegate.handleError(this, err);\n throw err;\n }\n this._updateTaskCount(task, -1);\n task._transitionTo(notScheduled, canceling);\n task.runCount = 0;\n return task;\n };\n Zone.prototype._updateTaskCount = function (task, count) {\n var zoneDelegates = task._zoneDelegates;\n if (count == -1) {\n task._zoneDelegates = null;\n }\n for (var i = 0; i < zoneDelegates.length; i++) {\n zoneDelegates[i]._updateTaskCount(task.type, count);\n }\n };\n Zone.__symbol__ = __symbol__;\n return Zone;\n }());\n var DELEGATE_ZS = {\n name: '',\n onHasTask: function (delegate, _, target, hasTaskState) { return delegate.hasTask(target, hasTaskState); },\n onScheduleTask: function (delegate, _, target, task) {\n return delegate.scheduleTask(target, task);\n },\n onInvokeTask: function (delegate, _, target, task, applyThis, applyArgs) {\n return delegate.invokeTask(target, task, applyThis, applyArgs);\n },\n onCancelTask: function (delegate, _, target, task) { return delegate.cancelTask(target, task); }\n };\n var ZoneDelegate = /** @class */ (function () {\n function ZoneDelegate(zone, parentDelegate, zoneSpec) {\n this._taskCounts = { 'microTask': 0, 'macroTask': 0, 'eventTask': 0 };\n this.zone = zone;\n this._parentDelegate = parentDelegate;\n this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate._forkZS);\n this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate._forkDlgt);\n this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone);\n this._interceptZS =\n zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS);\n this._interceptDlgt =\n zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt);\n this._interceptCurrZone =\n zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone);\n this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS);\n this._invokeDlgt =\n zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt);\n this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone);\n this._handleErrorZS =\n zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS);\n this._handleErrorDlgt =\n zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt);\n this._handleErrorCurrZone =\n zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone);\n this._scheduleTaskZS =\n zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS);\n this._scheduleTaskDlgt = zoneSpec &&\n (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt);\n this._scheduleTaskCurrZone =\n zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone);\n this._invokeTaskZS =\n zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS);\n this._invokeTaskDlgt =\n zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt);\n this._invokeTaskCurrZone =\n zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone);\n this._cancelTaskZS =\n zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS);\n this._cancelTaskDlgt =\n zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt);\n this._cancelTaskCurrZone =\n zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone);\n this._hasTaskZS = null;\n this._hasTaskDlgt = null;\n this._hasTaskDlgtOwner = null;\n this._hasTaskCurrZone = null;\n var zoneSpecHasTask = zoneSpec && zoneSpec.onHasTask;\n var parentHasTask = parentDelegate && parentDelegate._hasTaskZS;\n if (zoneSpecHasTask || parentHasTask) {\n // If we need to report hasTask, than this ZS needs to do ref counting on tasks. In such\n // a case all task related interceptors must go through this ZD. We can't short circuit it.\n this._hasTaskZS = zoneSpecHasTask ? zoneSpec : DELEGATE_ZS;\n this._hasTaskDlgt = parentDelegate;\n this._hasTaskDlgtOwner = this;\n this._hasTaskCurrZone = zone;\n if (!zoneSpec.onScheduleTask) {\n this._scheduleTaskZS = DELEGATE_ZS;\n this._scheduleTaskDlgt = parentDelegate;\n this._scheduleTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onInvokeTask) {\n this._invokeTaskZS = DELEGATE_ZS;\n this._invokeTaskDlgt = parentDelegate;\n this._invokeTaskCurrZone = this.zone;\n }\n if (!zoneSpec.onCancelTask) {\n this._cancelTaskZS = DELEGATE_ZS;\n this._cancelTaskDlgt = parentDelegate;\n this._cancelTaskCurrZone = this.zone;\n }\n }\n }\n ZoneDelegate.prototype.fork = function (targetZone, zoneSpec) {\n return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) :\n new Zone(targetZone, zoneSpec);\n };\n ZoneDelegate.prototype.intercept = function (targetZone, callback, source) {\n return this._interceptZS ?\n this._interceptZS.onIntercept(this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) :\n callback;\n };\n ZoneDelegate.prototype.invoke = function (targetZone, callback, applyThis, applyArgs, source) {\n return this._invokeZS ? this._invokeZS.onInvoke(this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, source) :\n callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.handleError = function (targetZone, error) {\n return this._handleErrorZS ?\n this._handleErrorZS.onHandleError(this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) :\n true;\n };\n ZoneDelegate.prototype.scheduleTask = function (targetZone, task) {\n var returnTask = task;\n if (this._scheduleTaskZS) {\n if (this._hasTaskZS) {\n returnTask._zoneDelegates.push(this._hasTaskDlgtOwner);\n }\n returnTask = this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task);\n if (!returnTask)\n returnTask = task;\n }\n else {\n if (task.scheduleFn) {\n task.scheduleFn(task);\n }\n else if (task.type == microTask) {\n scheduleMicroTask(task);\n }\n else {\n throw new Error('Task is missing scheduleFn.');\n }\n }\n return returnTask;\n };\n ZoneDelegate.prototype.invokeTask = function (targetZone, task, applyThis, applyArgs) {\n return this._invokeTaskZS ? this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, applyArgs) :\n task.callback.apply(applyThis, applyArgs);\n };\n ZoneDelegate.prototype.cancelTask = function (targetZone, task) {\n var value;\n if (this._cancelTaskZS) {\n value = this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task);\n }\n else {\n if (!task.cancelFn) {\n throw Error('Task is not cancelable');\n }\n value = task.cancelFn(task);\n }\n return value;\n };\n ZoneDelegate.prototype.hasTask = function (targetZone, isEmpty) {\n // hasTask should not throw error so other ZoneDelegate\n // can still trigger hasTask callback\n try {\n this._hasTaskZS &&\n this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty);\n }\n catch (err) {\n this.handleError(targetZone, err);\n }\n };\n ZoneDelegate.prototype._updateTaskCount = function (type, count) {\n var counts = this._taskCounts;\n var prev = counts[type];\n var next = counts[type] = prev + count;\n if (next < 0) {\n throw new Error('More tasks executed then were scheduled.');\n }\n if (prev == 0 || next == 0) {\n var isEmpty = {\n microTask: counts['microTask'] > 0,\n macroTask: counts['macroTask'] > 0,\n eventTask: counts['eventTask'] > 0,\n change: type\n };\n this.hasTask(this.zone, isEmpty);\n }\n };\n return ZoneDelegate;\n }());\n var ZoneTask = /** @class */ (function () {\n function ZoneTask(type, source, callback, options, scheduleFn, cancelFn) {\n this._zone = null;\n this.runCount = 0;\n this._zoneDelegates = null;\n this._state = 'notScheduled';\n this.type = type;\n this.source = source;\n this.data = options;\n this.scheduleFn = scheduleFn;\n this.cancelFn = cancelFn;\n this.callback = callback;\n var self = this;\n // TODO: @JiaLiPassion options should have interface\n if (type === eventTask && options && options.useG) {\n this.invoke = ZoneTask.invokeTask;\n }\n else {\n this.invoke = function () {\n return ZoneTask.invokeTask.call(global, self, this, arguments);\n };\n }\n }\n ZoneTask.invokeTask = function (task, target, args) {\n if (!task) {\n task = this;\n }\n _numberOfNestedTaskFrames++;\n try {\n task.runCount++;\n return task.zone.runTask(task, target, args);\n }\n finally {\n if (_numberOfNestedTaskFrames == 1) {\n drainMicroTaskQueue();\n }\n _numberOfNestedTaskFrames--;\n }\n };\n Object.defineProperty(ZoneTask.prototype, \"zone\", {\n get: function () {\n return this._zone;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ZoneTask.prototype, \"state\", {\n get: function () {\n return this._state;\n },\n enumerable: true,\n configurable: true\n });\n ZoneTask.prototype.cancelScheduleRequest = function () {\n this._transitionTo(notScheduled, scheduling);\n };\n ZoneTask.prototype._transitionTo = function (toState, fromState1, fromState2) {\n if (this._state === fromState1 || this._state === fromState2) {\n this._state = toState;\n if (toState == notScheduled) {\n this._zoneDelegates = null;\n }\n }\n else {\n throw new Error(this.type + \" '\" + this.source + \"': can not transition to '\" + toState + \"', expecting state '\" + fromState1 + \"'\" + (fromState2 ? ' or \\'' + fromState2 + '\\'' : '') + \", was '\" + this._state + \"'.\");\n }\n };\n ZoneTask.prototype.toString = function () {\n if (this.data && typeof this.data.handleId !== 'undefined') {\n return this.data.handleId.toString();\n }\n else {\n return Object.prototype.toString.call(this);\n }\n };\n // add toJSON method to prevent cyclic error when\n // call JSON.stringify(zoneTask)\n ZoneTask.prototype.toJSON = function () {\n return {\n type: this.type,\n state: this.state,\n source: this.source,\n zone: this.zone.name,\n runCount: this.runCount\n };\n };\n return ZoneTask;\n }());\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n /// MICROTASK QUEUE\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n var symbolSetTimeout = __symbol__('setTimeout');\n var symbolPromise = __symbol__('Promise');\n var symbolThen = __symbol__('then');\n var _microTaskQueue = [];\n var _isDrainingMicrotaskQueue = false;\n var nativeMicroTaskQueuePromise;\n function scheduleMicroTask(task) {\n // if we are not running in any task, and there has not been anything scheduled\n // we must bootstrap the initial task creation by manually scheduling the drain\n if (_numberOfNestedTaskFrames === 0 && _microTaskQueue.length === 0) {\n // We are not running in Task, so we need to kickstart the microtask queue.\n if (!nativeMicroTaskQueuePromise) {\n if (global[symbolPromise]) {\n nativeMicroTaskQueuePromise = global[symbolPromise].resolve(0);\n }\n }\n if (nativeMicroTaskQueuePromise) {\n var nativeThen = nativeMicroTaskQueuePromise[symbolThen];\n if (!nativeThen) {\n // native Promise is not patchable, we need to use `then` directly\n // issue 1078\n nativeThen = nativeMicroTaskQueuePromise['then'];\n }\n nativeThen.call(nativeMicroTaskQueuePromise, drainMicroTaskQueue);\n }\n else {\n global[symbolSetTimeout](drainMicroTaskQueue, 0);\n }\n }\n task && _microTaskQueue.push(task);\n }\n function drainMicroTaskQueue() {\n if (!_isDrainingMicrotaskQueue) {\n _isDrainingMicrotaskQueue = true;\n while (_microTaskQueue.length) {\n var queue = _microTaskQueue;\n _microTaskQueue = [];\n for (var i = 0; i < queue.length; i++) {\n var task = queue[i];\n try {\n task.zone.runTask(task, null, null);\n }\n catch (error) {\n _api.onUnhandledError(error);\n }\n }\n }\n _api.microtaskDrainDone();\n _isDrainingMicrotaskQueue = false;\n }\n }\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n /// BOOTSTRAP\n //////////////////////////////////////////////////////\n //////////////////////////////////////////////////////\n var NO_ZONE = { name: 'NO ZONE' };\n var notScheduled = 'notScheduled', scheduling = 'scheduling', scheduled = 'scheduled', running = 'running', canceling = 'canceling', unknown = 'unknown';\n var microTask = 'microTask', macroTask = 'macroTask', eventTask = 'eventTask';\n var patches = {};\n var _api = {\n symbol: __symbol__,\n currentZoneFrame: function () { return _currentZoneFrame; },\n onUnhandledError: noop,\n microtaskDrainDone: noop,\n scheduleMicroTask: scheduleMicroTask,\n showUncaughtError: function () { return !Zone[__symbol__('ignoreConsoleErrorUncaughtError')]; },\n patchEventTarget: function () { return []; },\n patchOnProperties: noop,\n patchMethod: function () { return noop; },\n bindArguments: function () { return []; },\n patchThen: function () { return noop; },\n setNativePromise: function (NativePromise) {\n // sometimes NativePromise.resolve static function\n // is not ready yet, (such as core-js/es6.promise)\n // so we need to check here.\n if (NativePromise && typeof NativePromise.resolve === 'function') {\n nativeMicroTaskQueuePromise = NativePromise.resolve(0);\n }\n },\n };\n var _currentZoneFrame = { parent: null, zone: new Zone(null, null) };\n var _currentTask = null;\n var _numberOfNestedTaskFrames = 0;\n function noop() { }\n function __symbol__(name) {\n return '__zone_symbol__' + name;\n }\n performanceMeasure('Zone', 'Zone');\n return global['Zone'] = Zone;\n})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);\n\nvar __values = (undefined && undefined.__values) || function (o) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\n if (m) return m.call(o);\n return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n};\nZone.__load_patch('ZoneAwarePromise', function (global, Zone, api) {\n var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n var ObjectDefineProperty = Object.defineProperty;\n function readableObjectToString(obj) {\n if (obj && obj.toString === Object.prototype.toString) {\n var className = obj.constructor && obj.constructor.name;\n return (className ? className : '') + ': ' + JSON.stringify(obj);\n }\n return obj ? obj.toString() : Object.prototype.toString.call(obj);\n }\n var __symbol__ = api.symbol;\n var _uncaughtPromiseErrors = [];\n var symbolPromise = __symbol__('Promise');\n var symbolThen = __symbol__('then');\n var creationTrace = '__creationTrace__';\n api.onUnhandledError = function (e) {\n if (api.showUncaughtError()) {\n var rejection = e && e.rejection;\n if (rejection) {\n console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined);\n }\n else {\n console.error(e);\n }\n }\n };\n api.microtaskDrainDone = function () {\n while (_uncaughtPromiseErrors.length) {\n var _loop_1 = function () {\n var uncaughtPromiseError = _uncaughtPromiseErrors.shift();\n try {\n uncaughtPromiseError.zone.runGuarded(function () {\n throw uncaughtPromiseError;\n });\n }\n catch (error) {\n handleUnhandledRejection(error);\n }\n };\n while (_uncaughtPromiseErrors.length) {\n _loop_1();\n }\n }\n };\n var UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler');\n function handleUnhandledRejection(e) {\n api.onUnhandledError(e);\n try {\n var handler = Zone[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];\n if (handler && typeof handler === 'function') {\n handler.call(this, e);\n }\n }\n catch (err) {\n }\n }\n function isThenable(value) {\n return value && value.then;\n }\n function forwardResolution(value) {\n return value;\n }\n function forwardRejection(rejection) {\n return ZoneAwarePromise.reject(rejection);\n }\n var symbolState = __symbol__('state');\n var symbolValue = __symbol__('value');\n var symbolFinally = __symbol__('finally');\n var symbolParentPromiseValue = __symbol__('parentPromiseValue');\n var symbolParentPromiseState = __symbol__('parentPromiseState');\n var source = 'Promise.then';\n var UNRESOLVED = null;\n var RESOLVED = true;\n var REJECTED = false;\n var REJECTED_NO_CATCH = 0;\n function makeResolver(promise, state) {\n return function (v) {\n try {\n resolvePromise(promise, state, v);\n }\n catch (err) {\n resolvePromise(promise, false, err);\n }\n // Do not return value or you will break the Promise spec.\n };\n }\n var once = function () {\n var wasCalled = false;\n return function wrapper(wrappedFunction) {\n return function () {\n if (wasCalled) {\n return;\n }\n wasCalled = true;\n wrappedFunction.apply(null, arguments);\n };\n };\n };\n var TYPE_ERROR = 'Promise resolved with itself';\n var CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace');\n // Promise Resolution\n function resolvePromise(promise, state, value) {\n var onceWrapper = once();\n if (promise === value) {\n throw new TypeError(TYPE_ERROR);\n }\n if (promise[symbolState] === UNRESOLVED) {\n // should only get value.then once based on promise spec.\n var then = null;\n try {\n if (typeof value === 'object' || typeof value === 'function') {\n then = value && value.then;\n }\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n return promise;\n }\n // if (value instanceof ZoneAwarePromise) {\n if (state !== REJECTED && value instanceof ZoneAwarePromise &&\n value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) &&\n value[symbolState] !== UNRESOLVED) {\n clearRejectedNoCatch(value);\n resolvePromise(promise, value[symbolState], value[symbolValue]);\n }\n else if (state !== REJECTED && typeof then === 'function') {\n try {\n then.call(value, onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false)));\n }\n catch (err) {\n onceWrapper(function () {\n resolvePromise(promise, false, err);\n })();\n }\n }\n else {\n promise[symbolState] = state;\n var queue = promise[symbolValue];\n promise[symbolValue] = value;\n if (promise[symbolFinally] === symbolFinally) {\n // the promise is generated by Promise.prototype.finally\n if (state === RESOLVED) {\n // the state is resolved, should ignore the value\n // and use parent promise value\n promise[symbolState] = promise[symbolParentPromiseState];\n promise[symbolValue] = promise[symbolParentPromiseValue];\n }\n }\n // record task information in value when error occurs, so we can\n // do some additional work such as render longStackTrace\n if (state === REJECTED && value instanceof Error) {\n // check if longStackTraceZone is here\n var trace = Zone.currentTask && Zone.currentTask.data &&\n Zone.currentTask.data[creationTrace];\n if (trace) {\n // only keep the long stack trace into error when in longStackTraceZone\n ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, { configurable: true, enumerable: false, writable: true, value: trace });\n }\n }\n for (var i = 0; i < queue.length;) {\n scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);\n }\n if (queue.length == 0 && state == REJECTED) {\n promise[symbolState] = REJECTED_NO_CATCH;\n try {\n // try to print more readable error log\n throw new Error('Uncaught (in promise): ' + readableObjectToString(value) +\n (value && value.stack ? '\\n' + value.stack : ''));\n }\n catch (err) {\n var error_1 = err;\n error_1.rejection = value;\n error_1.promise = promise;\n error_1.zone = Zone.current;\n error_1.task = Zone.currentTask;\n _uncaughtPromiseErrors.push(error_1);\n api.scheduleMicroTask(); // to make sure that it is running\n }\n }\n }\n }\n // Resolving an already resolved promise is a noop.\n return promise;\n }\n var REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler');\n function clearRejectedNoCatch(promise) {\n if (promise[symbolState] === REJECTED_NO_CATCH) {\n // if the promise is rejected no catch status\n // and queue.length > 0, means there is a error handler\n // here to handle the rejected promise, we should trigger\n // windows.rejectionhandled eventHandler or nodejs rejectionHandled\n // eventHandler\n try {\n var handler = Zone[REJECTION_HANDLED_HANDLER];\n if (handler && typeof handler === 'function') {\n handler.call(this, { rejection: promise[symbolValue], promise: promise });\n }\n }\n catch (err) {\n }\n promise[symbolState] = REJECTED;\n for (var i = 0; i < _uncaughtPromiseErrors.length; i++) {\n if (promise === _uncaughtPromiseErrors[i].promise) {\n _uncaughtPromiseErrors.splice(i, 1);\n }\n }\n }\n }\n function scheduleResolveOrReject(promise, zone, chainPromise, onFulfilled, onRejected) {\n clearRejectedNoCatch(promise);\n var promiseState = promise[symbolState];\n var delegate = promiseState ?\n (typeof onFulfilled === 'function') ? onFulfilled : forwardResolution :\n (typeof onRejected === 'function') ? onRejected : forwardRejection;\n zone.scheduleMicroTask(source, function () {\n try {\n var parentPromiseValue = promise[symbolValue];\n var isFinallyPromise = chainPromise && symbolFinally === chainPromise[symbolFinally];\n if (isFinallyPromise) {\n // if the promise is generated from finally call, keep parent promise's state and value\n chainPromise[symbolParentPromiseValue] = parentPromiseValue;\n chainPromise[symbolParentPromiseState] = promiseState;\n }\n // should not pass value to finally callback\n var value = zone.run(delegate, undefined, isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ?\n [] :\n [parentPromiseValue]);\n resolvePromise(chainPromise, true, value);\n }\n catch (error) {\n // if error occurs, should always return this error\n resolvePromise(chainPromise, false, error);\n }\n }, chainPromise);\n }\n var ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }';\n var ZoneAwarePromise = /** @class */ (function () {\n function ZoneAwarePromise(executor) {\n var promise = this;\n if (!(promise instanceof ZoneAwarePromise)) {\n throw new Error('Must be an instanceof Promise.');\n }\n promise[symbolState] = UNRESOLVED;\n promise[symbolValue] = []; // queue;\n try {\n executor && executor(makeResolver(promise, RESOLVED), makeResolver(promise, REJECTED));\n }\n catch (error) {\n resolvePromise(promise, false, error);\n }\n }\n ZoneAwarePromise.toString = function () {\n return ZONE_AWARE_PROMISE_TO_STRING;\n };\n ZoneAwarePromise.resolve = function (value) {\n return resolvePromise(new this(null), RESOLVED, value);\n };\n ZoneAwarePromise.reject = function (error) {\n return resolvePromise(new this(null), REJECTED, error);\n };\n ZoneAwarePromise.race = function (values) {\n var e_1, _a;\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n resolve = res;\n reject = rej;\n });\n function onResolve(value) {\n promise && (promise = null || resolve(value));\n }\n function onReject(error) {\n promise && (promise = null || reject(error));\n }\n try {\n for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {\n var value = values_1_1.value;\n if (!isThenable(value)) {\n value = this.resolve(value);\n }\n value.then(onResolve, onReject);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n return promise;\n };\n ZoneAwarePromise.all = function (values) {\n var e_2, _a;\n var resolve;\n var reject;\n var promise = new this(function (res, rej) {\n resolve = res;\n reject = rej;\n });\n // Start at 2 to prevent prematurely resolving if .then is called immediately.\n var unresolvedCount = 2;\n var valueIndex = 0;\n var resolvedValues = [];\n var _loop_2 = function (value) {\n if (!isThenable(value)) {\n value = this_1.resolve(value);\n }\n var curValueIndex = valueIndex;\n value.then(function (value) {\n resolvedValues[curValueIndex] = value;\n unresolvedCount--;\n if (unresolvedCount === 0) {\n resolve(resolvedValues);\n }\n }, reject);\n unresolvedCount++;\n valueIndex++;\n };\n var this_1 = this;\n try {\n for (var values_2 = __values(values), values_2_1 = values_2.next(); !values_2_1.done; values_2_1 = values_2.next()) {\n var value = values_2_1.value;\n _loop_2(value);\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (values_2_1 && !values_2_1.done && (_a = values_2.return)) _a.call(values_2);\n }\n finally { if (e_2) throw e_2.error; }\n }\n // Make the unresolvedCount zero-based again.\n unresolvedCount -= 2;\n if (unresolvedCount === 0) {\n resolve(resolvedValues);\n }\n return promise;\n };\n ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) {\n var chainPromise = new this.constructor(null);\n var zone = Zone.current;\n if (this[symbolState] == UNRESOLVED) {\n this[symbolValue].push(zone, chainPromise, onFulfilled, onRejected);\n }\n else {\n scheduleResolveOrReject(this, zone, chainPromise, onFulfilled, onRejected);\n }\n return chainPromise;\n };\n ZoneAwarePromise.prototype.catch = function (onRejected) {\n return this.then(null, onRejected);\n };\n ZoneAwarePromise.prototype.finally = function (onFinally) {\n var chainPromise = new this.constructor(null);\n chainPromise[symbolFinally] = symbolFinally;\n var zone = Zone.current;\n if (this[symbolState] == UNRESOLVED) {\n this[symbolValue].push(zone, chainPromise, onFinally, onFinally);\n }\n else {\n scheduleResolveOrReject(this, zone, chainPromise, onFinally, onFinally);\n }\n return chainPromise;\n };\n return ZoneAwarePromise;\n }());\n // Protect against aggressive optimizers dropping seemingly unused properties.\n // E.g. Closure Compiler in advanced mode.\n ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve;\n ZoneAwarePromise['reject'] = ZoneAwarePromise.reject;\n ZoneAwarePromise['race'] = ZoneAwarePromise.race;\n ZoneAwarePromise['all'] = ZoneAwarePromise.all;\n var NativePromise = global[symbolPromise] = global['Promise'];\n var ZONE_AWARE_PROMISE = Zone.__symbol__('ZoneAwarePromise');\n var desc = ObjectGetOwnPropertyDescriptor(global, 'Promise');\n if (!desc || desc.configurable) {\n desc && delete desc.writable;\n desc && delete desc.value;\n if (!desc) {\n desc = { configurable: true, enumerable: true };\n }\n desc.get = function () {\n // if we already set ZoneAwarePromise, use patched one\n // otherwise return native one.\n return global[ZONE_AWARE_PROMISE] ? global[ZONE_AWARE_PROMISE] : global[symbolPromise];\n };\n desc.set = function (NewNativePromise) {\n if (NewNativePromise === ZoneAwarePromise) {\n // if the NewNativePromise is ZoneAwarePromise\n // save to global\n global[ZONE_AWARE_PROMISE] = NewNativePromise;\n }\n else {\n // if the NewNativePromise is not ZoneAwarePromise\n // for example: after load zone.js, some library just\n // set es6-promise to global, if we set it to global\n // directly, assertZonePatched will fail and angular\n // will not loaded, so we just set the NewNativePromise\n // to global[symbolPromise], so the result is just like\n // we load ES6 Promise before zone.js\n global[symbolPromise] = NewNativePromise;\n if (!NewNativePromise.prototype[symbolThen]) {\n patchThen(NewNativePromise);\n }\n api.setNativePromise(NewNativePromise);\n }\n };\n ObjectDefineProperty(global, 'Promise', desc);\n }\n global['Promise'] = ZoneAwarePromise;\n var symbolThenPatched = __symbol__('thenPatched');\n function patchThen(Ctor) {\n var proto = Ctor.prototype;\n var prop = ObjectGetOwnPropertyDescriptor(proto, 'then');\n if (prop && (prop.writable === false || !prop.configurable)) {\n // check Ctor.prototype.then propertyDescriptor is writable or not\n // in meteor env, writable is false, we should ignore such case\n return;\n }\n var originalThen = proto.then;\n // Keep a reference to the original method.\n proto[symbolThen] = originalThen;\n Ctor.prototype.then = function (onResolve, onReject) {\n var _this = this;\n var wrapped = new ZoneAwarePromise(function (resolve, reject) {\n originalThen.call(_this, resolve, reject);\n });\n return wrapped.then(onResolve, onReject);\n };\n Ctor[symbolThenPatched] = true;\n }\n api.patchThen = patchThen;\n if (NativePromise) {\n patchThen(NativePromise);\n }\n // This is not part of public API, but it is useful for tests, so we expose it.\n Promise[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors;\n return ZoneAwarePromise;\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nZone.__load_patch('fetch', function (global, Zone, api) {\n var fetch = global['fetch'];\n var ZoneAwarePromise = global.Promise;\n var symbolThenPatched = api.symbol('thenPatched');\n var fetchTaskScheduling = api.symbol('fetchTaskScheduling');\n var fetchTaskAborting = api.symbol('fetchTaskAborting');\n if (typeof fetch !== 'function') {\n return;\n }\n var OriginalAbortController = global['AbortController'];\n var supportAbort = typeof OriginalAbortController === 'function';\n var abortNative = null;\n if (supportAbort) {\n global['AbortController'] = function () {\n var abortController = new OriginalAbortController();\n var signal = abortController.signal;\n signal.abortController = abortController;\n return abortController;\n };\n abortNative = api.patchMethod(OriginalAbortController.prototype, 'abort', function (delegate) { return function (self, args) {\n if (self.task) {\n return self.task.zone.cancelTask(self.task);\n }\n return delegate.apply(self, args);\n }; });\n }\n var placeholder = function () { };\n global['fetch'] = function () {\n var _this = this;\n var args = Array.prototype.slice.call(arguments);\n var options = args.length > 1 ? args[1] : null;\n var signal = options && options.signal;\n return new Promise(function (res, rej) {\n var task = Zone.current.scheduleMacroTask('fetch', placeholder, args, function () {\n var fetchPromise;\n var zone = Zone.current;\n try {\n zone[fetchTaskScheduling] = true;\n fetchPromise = fetch.apply(_this, args);\n }\n catch (error) {\n rej(error);\n return;\n }\n finally {\n zone[fetchTaskScheduling] = false;\n }\n if (!(fetchPromise instanceof ZoneAwarePromise)) {\n var ctor = fetchPromise.constructor;\n if (!ctor[symbolThenPatched]) {\n api.patchThen(ctor);\n }\n }\n fetchPromise.then(function (resource) {\n if (task.state !== 'notScheduled') {\n task.invoke();\n }\n res(resource);\n }, function (error) {\n if (task.state !== 'notScheduled') {\n task.invoke();\n }\n rej(error);\n });\n }, function () {\n if (!supportAbort) {\n rej('No AbortController supported, can not cancel fetch');\n return;\n }\n if (signal && signal.abortController && !signal.aborted &&\n typeof signal.abortController.abort === 'function' && abortNative) {\n try {\n Zone.current[fetchTaskAborting] = true;\n abortNative.call(signal.abortController);\n }\n finally {\n Zone.current[fetchTaskAborting] = false;\n }\n }\n else {\n rej('cancel fetch need a AbortController.signal');\n }\n });\n if (signal && signal.abortController) {\n signal.abortController.task = task;\n }\n });\n };\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * Suppress closure compiler errors about unknown 'Zone' variable\n * @fileoverview\n * @suppress {undefinedVars,globalThis,missingRequire}\n */\n// issue #989, to reduce bundle size, use short name\n/** Object.getOwnPropertyDescriptor */\nvar ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\n/** Object.defineProperty */\nvar ObjectDefineProperty = Object.defineProperty;\n/** Object.getPrototypeOf */\nvar ObjectGetPrototypeOf = Object.getPrototypeOf;\n/** Object.create */\nvar ObjectCreate = Object.create;\n/** Array.prototype.slice */\nvar ArraySlice = Array.prototype.slice;\n/** addEventListener string const */\nvar ADD_EVENT_LISTENER_STR = 'addEventListener';\n/** removeEventListener string const */\nvar REMOVE_EVENT_LISTENER_STR = 'removeEventListener';\n/** zoneSymbol addEventListener */\nvar ZONE_SYMBOL_ADD_EVENT_LISTENER = Zone.__symbol__(ADD_EVENT_LISTENER_STR);\n/** zoneSymbol removeEventListener */\nvar ZONE_SYMBOL_REMOVE_EVENT_LISTENER = Zone.__symbol__(REMOVE_EVENT_LISTENER_STR);\n/** true string const */\nvar TRUE_STR = 'true';\n/** false string const */\nvar FALSE_STR = 'false';\n/** __zone_symbol__ string const */\nvar ZONE_SYMBOL_PREFIX = '__zone_symbol__';\nfunction wrapWithCurrentZone(callback, source) {\n return Zone.current.wrap(callback, source);\n}\nfunction scheduleMacroTaskWithCurrentZone(source, callback, data, customSchedule, customCancel) {\n return Zone.current.scheduleMacroTask(source, callback, data, customSchedule, customCancel);\n}\nvar zoneSymbol = Zone.__symbol__;\nvar isWindowExists = typeof window !== 'undefined';\nvar internalWindow = isWindowExists ? window : undefined;\nvar _global = isWindowExists && internalWindow || typeof self === 'object' && self || global;\nvar REMOVE_ATTRIBUTE = 'removeAttribute';\nvar NULL_ON_PROP_VALUE = [null];\nfunction bindArguments(args, source) {\n for (var i = args.length - 1; i >= 0; i--) {\n if (typeof args[i] === 'function') {\n args[i] = wrapWithCurrentZone(args[i], source + '_' + i);\n }\n }\n return args;\n}\nfunction patchPrototype(prototype, fnNames) {\n var source = prototype.constructor['name'];\n var _loop_1 = function (i) {\n var name_1 = fnNames[i];\n var delegate = prototype[name_1];\n if (delegate) {\n var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, name_1);\n if (!isPropertyWritable(prototypeDesc)) {\n return \"continue\";\n }\n prototype[name_1] = (function (delegate) {\n var patched = function () {\n return delegate.apply(this, bindArguments(arguments, source + '.' + name_1));\n };\n attachOriginToPatched(patched, delegate);\n return patched;\n })(delegate);\n }\n };\n for (var i = 0; i < fnNames.length; i++) {\n _loop_1(i);\n }\n}\nfunction isPropertyWritable(propertyDesc) {\n if (!propertyDesc) {\n return true;\n }\n if (propertyDesc.writable === false) {\n return false;\n }\n return !(typeof propertyDesc.get === 'function' && typeof propertyDesc.set === 'undefined');\n}\nvar isWebWorker = (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope);\n// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify\n// this code.\nvar isNode = (!('nw' in _global) && typeof _global.process !== 'undefined' &&\n {}.toString.call(_global.process) === '[object process]');\nvar isBrowser = !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']);\n// we are in electron of nw, so we are both browser and nodejs\n// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify\n// this code.\nvar isMix = typeof _global.process !== 'undefined' &&\n {}.toString.call(_global.process) === '[object process]' && !isWebWorker &&\n !!(isWindowExists && internalWindow['HTMLElement']);\nvar zoneSymbolEventNames = {};\nvar wrapFn = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n var eventNameSymbol = zoneSymbolEventNames[event.type];\n if (!eventNameSymbol) {\n eventNameSymbol = zoneSymbolEventNames[event.type] = zoneSymbol('ON_PROPERTY' + event.type);\n }\n var target = this || event.target || _global;\n var listener = target[eventNameSymbol];\n var result;\n if (isBrowser && target === internalWindow && event.type === 'error') {\n // window.onerror have different signiture\n // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror\n // and onerror callback will prevent default when callback return true\n var errorEvent = event;\n result = listener &&\n listener.call(this, errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error);\n if (result === true) {\n event.preventDefault();\n }\n }\n else {\n result = listener && listener.apply(this, arguments);\n if (result != undefined && !result) {\n event.preventDefault();\n }\n }\n return result;\n};\nfunction patchProperty(obj, prop, prototype) {\n var desc = ObjectGetOwnPropertyDescriptor(obj, prop);\n if (!desc && prototype) {\n // when patch window object, use prototype to check prop exist or not\n var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, prop);\n if (prototypeDesc) {\n desc = { enumerable: true, configurable: true };\n }\n }\n // if the descriptor not exists or is not configurable\n // just return\n if (!desc || !desc.configurable) {\n return;\n }\n var onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched');\n if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) {\n return;\n }\n // A property descriptor cannot have getter/setter and be writable\n // deleting the writable and value properties avoids this error:\n //\n // TypeError: property descriptors must not specify a value or be writable when a\n // getter or setter has been specified\n delete desc.writable;\n delete desc.value;\n var originalDescGet = desc.get;\n var originalDescSet = desc.set;\n // substr(2) cuz 'onclick' -> 'click', etc\n var eventName = prop.substr(2);\n var eventNameSymbol = zoneSymbolEventNames[eventName];\n if (!eventNameSymbol) {\n eventNameSymbol = zoneSymbolEventNames[eventName] = zoneSymbol('ON_PROPERTY' + eventName);\n }\n desc.set = function (newValue) {\n // in some of windows's onproperty callback, this is undefined\n // so we need to check it\n var target = this;\n if (!target && obj === _global) {\n target = _global;\n }\n if (!target) {\n return;\n }\n var previousValue = target[eventNameSymbol];\n if (previousValue) {\n target.removeEventListener(eventName, wrapFn);\n }\n // issue #978, when onload handler was added before loading zone.js\n // we should remove it with originalDescSet\n if (originalDescSet) {\n originalDescSet.apply(target, NULL_ON_PROP_VALUE);\n }\n if (typeof newValue === 'function') {\n target[eventNameSymbol] = newValue;\n target.addEventListener(eventName, wrapFn, false);\n }\n else {\n target[eventNameSymbol] = null;\n }\n };\n // The getter would return undefined for unassigned properties but the default value of an\n // unassigned property is null\n desc.get = function () {\n // in some of windows's onproperty callback, this is undefined\n // so we need to check it\n var target = this;\n if (!target && obj === _global) {\n target = _global;\n }\n if (!target) {\n return null;\n }\n var listener = target[eventNameSymbol];\n if (listener) {\n return listener;\n }\n else if (originalDescGet) {\n // result will be null when use inline event attribute,\n // such as \n // because the onclick function is internal raw uncompiled handler\n // the onclick will be evaluated when first time event was triggered or\n // the property is accessed, https://github.com/angular/zone.js/issues/525\n // so we should use original native get to retrieve the handler\n var value = originalDescGet && originalDescGet.call(this);\n if (value) {\n desc.set.call(this, value);\n if (typeof target[REMOVE_ATTRIBUTE] === 'function') {\n target.removeAttribute(prop);\n }\n return value;\n }\n }\n return null;\n };\n ObjectDefineProperty(obj, prop, desc);\n obj[onPropPatchedSymbol] = true;\n}\nfunction patchOnProperties(obj, properties, prototype) {\n if (properties) {\n for (var i = 0; i < properties.length; i++) {\n patchProperty(obj, 'on' + properties[i], prototype);\n }\n }\n else {\n var onProperties = [];\n for (var prop in obj) {\n if (prop.substr(0, 2) == 'on') {\n onProperties.push(prop);\n }\n }\n for (var j = 0; j < onProperties.length; j++) {\n patchProperty(obj, onProperties[j], prototype);\n }\n }\n}\nvar originalInstanceKey = zoneSymbol('originalInstance');\n// wrap some native API on `window`\nfunction patchClass(className) {\n var OriginalClass = _global[className];\n if (!OriginalClass)\n return;\n // keep original class in global\n _global[zoneSymbol(className)] = OriginalClass;\n _global[className] = function () {\n var a = bindArguments(arguments, className);\n switch (a.length) {\n case 0:\n this[originalInstanceKey] = new OriginalClass();\n break;\n case 1:\n this[originalInstanceKey] = new OriginalClass(a[0]);\n break;\n case 2:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1]);\n break;\n case 3:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]);\n break;\n case 4:\n this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]);\n break;\n default:\n throw new Error('Arg list too long.');\n }\n };\n // attach original delegate to patched function\n attachOriginToPatched(_global[className], OriginalClass);\n var instance = new OriginalClass(function () { });\n var prop;\n for (prop in instance) {\n // https://bugs.webkit.org/show_bug.cgi?id=44721\n if (className === 'XMLHttpRequest' && prop === 'responseBlob')\n continue;\n (function (prop) {\n if (typeof instance[prop] === 'function') {\n _global[className].prototype[prop] = function () {\n return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments);\n };\n }\n else {\n ObjectDefineProperty(_global[className].prototype, prop, {\n set: function (fn) {\n if (typeof fn === 'function') {\n this[originalInstanceKey][prop] = wrapWithCurrentZone(fn, className + '.' + prop);\n // keep callback in wrapped function so we can\n // use it in Function.prototype.toString to return\n // the native one.\n attachOriginToPatched(this[originalInstanceKey][prop], fn);\n }\n else {\n this[originalInstanceKey][prop] = fn;\n }\n },\n get: function () {\n return this[originalInstanceKey][prop];\n }\n });\n }\n }(prop));\n }\n for (prop in OriginalClass) {\n if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) {\n _global[className][prop] = OriginalClass[prop];\n }\n }\n}\nfunction copySymbolProperties(src, dest) {\n if (typeof Object.getOwnPropertySymbols !== 'function') {\n return;\n }\n var symbols = Object.getOwnPropertySymbols(src);\n symbols.forEach(function (symbol) {\n var desc = Object.getOwnPropertyDescriptor(src, symbol);\n Object.defineProperty(dest, symbol, {\n get: function () {\n return src[symbol];\n },\n set: function (value) {\n if (desc && (!desc.writable || typeof desc.set !== 'function')) {\n // if src[symbol] is not writable or not have a setter, just return\n return;\n }\n src[symbol] = value;\n },\n enumerable: desc ? desc.enumerable : true,\n configurable: desc ? desc.configurable : true\n });\n });\n}\nvar shouldCopySymbolProperties = false;\n\nfunction patchMethod(target, name, patchFn) {\n var proto = target;\n while (proto && !proto.hasOwnProperty(name)) {\n proto = ObjectGetPrototypeOf(proto);\n }\n if (!proto && target[name]) {\n // somehow we did not find it, but we can see it. This happens on IE for Window properties.\n proto = target;\n }\n var delegateName = zoneSymbol(name);\n var delegate = null;\n if (proto && !(delegate = proto[delegateName])) {\n delegate = proto[delegateName] = proto[name];\n // check whether proto[name] is writable\n // some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob\n var desc = proto && ObjectGetOwnPropertyDescriptor(proto, name);\n if (isPropertyWritable(desc)) {\n var patchDelegate_1 = patchFn(delegate, delegateName, name);\n proto[name] = function () {\n return patchDelegate_1(this, arguments);\n };\n attachOriginToPatched(proto[name], delegate);\n if (shouldCopySymbolProperties) {\n copySymbolProperties(delegate, proto[name]);\n }\n }\n }\n return delegate;\n}\n// TODO: @JiaLiPassion, support cancel task later if necessary\nfunction patchMacroTask(obj, funcName, metaCreator) {\n var setNative = null;\n function scheduleTask(task) {\n var data = task.data;\n data.args[data.cbIdx] = function () {\n task.invoke.apply(this, arguments);\n };\n setNative.apply(data.target, data.args);\n return task;\n }\n setNative = patchMethod(obj, funcName, function (delegate) { return function (self, args) {\n var meta = metaCreator(self, args);\n if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') {\n return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask);\n }\n else {\n // cause an error by calling it directly.\n return delegate.apply(self, args);\n }\n }; });\n}\n\nfunction attachOriginToPatched(patched, original) {\n patched[zoneSymbol('OriginalDelegate')] = original;\n}\nvar isDetectedIEOrEdge = false;\nvar ieOrEdge = false;\nfunction isIE() {\n try {\n var ua = internalWindow.navigator.userAgent;\n if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1) {\n return true;\n }\n }\n catch (error) {\n }\n return false;\n}\nfunction isIEOrEdge() {\n if (isDetectedIEOrEdge) {\n return ieOrEdge;\n }\n isDetectedIEOrEdge = true;\n try {\n var ua = internalWindow.navigator.userAgent;\n if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) {\n ieOrEdge = true;\n }\n return ieOrEdge;\n }\n catch (error) {\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// override Function.prototype.toString to make zone.js patched function\n// look like native function\nZone.__load_patch('toString', function (global) {\n // patch Func.prototype.toString to let them look like native\n var originalFunctionToString = Function.prototype.toString;\n var ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate');\n var PROMISE_SYMBOL = zoneSymbol('Promise');\n var ERROR_SYMBOL = zoneSymbol('Error');\n var newFunctionToString = function toString() {\n if (typeof this === 'function') {\n var originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL];\n if (originalDelegate) {\n if (typeof originalDelegate === 'function') {\n return originalFunctionToString.apply(this[ORIGINAL_DELEGATE_SYMBOL], arguments);\n }\n else {\n return Object.prototype.toString.call(originalDelegate);\n }\n }\n if (this === Promise) {\n var nativePromise = global[PROMISE_SYMBOL];\n if (nativePromise) {\n return originalFunctionToString.apply(nativePromise, arguments);\n }\n }\n if (this === Error) {\n var nativeError = global[ERROR_SYMBOL];\n if (nativeError) {\n return originalFunctionToString.apply(nativeError, arguments);\n }\n }\n }\n return originalFunctionToString.apply(this, arguments);\n };\n newFunctionToString[ORIGINAL_DELEGATE_SYMBOL] = originalFunctionToString;\n Function.prototype.toString = newFunctionToString;\n // patch Object.prototype.toString to let them look like native\n var originalObjectToString = Object.prototype.toString;\n var PROMISE_OBJECT_TO_STRING = '[object Promise]';\n Object.prototype.toString = function () {\n if (this instanceof Promise) {\n return PROMISE_OBJECT_TO_STRING;\n }\n return originalObjectToString.apply(this, arguments);\n };\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nvar passiveSupported = false;\nif (typeof window !== 'undefined') {\n try {\n var options = Object.defineProperty({}, 'passive', {\n get: function () {\n passiveSupported = true;\n }\n });\n window.addEventListener('test', options, options);\n window.removeEventListener('test', options, options);\n }\n catch (err) {\n passiveSupported = false;\n }\n}\n// an identifier to tell ZoneTask do not create a new invoke closure\nvar OPTIMIZED_ZONE_EVENT_TASK_DATA = {\n useG: true\n};\nvar zoneSymbolEventNames$1 = {};\nvar globalSources = {};\nvar EVENT_NAME_SYMBOL_REGX = /^__zone_symbol__(\\w+)(true|false)$/;\nvar IMMEDIATE_PROPAGATION_SYMBOL = ('__zone_symbol__propagationStopped');\nfunction patchEventTarget(_global, apis, patchOptions) {\n var ADD_EVENT_LISTENER = (patchOptions && patchOptions.add) || ADD_EVENT_LISTENER_STR;\n var REMOVE_EVENT_LISTENER = (patchOptions && patchOptions.rm) || REMOVE_EVENT_LISTENER_STR;\n var LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.listeners) || 'eventListeners';\n var REMOVE_ALL_LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.rmAll) || 'removeAllListeners';\n var zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER);\n var ADD_EVENT_LISTENER_SOURCE = '.' + ADD_EVENT_LISTENER + ':';\n var PREPEND_EVENT_LISTENER = 'prependListener';\n var PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':';\n var invokeTask = function (task, target, event) {\n // for better performance, check isRemoved which is set\n // by removeEventListener\n if (task.isRemoved) {\n return;\n }\n var delegate = task.callback;\n if (typeof delegate === 'object' && delegate.handleEvent) {\n // create the bind version of handleEvent when invoke\n task.callback = function (event) { return delegate.handleEvent(event); };\n task.originalDelegate = delegate;\n }\n // invoke static task.invoke\n task.invoke(task, target, [event]);\n var options = task.options;\n if (options && typeof options === 'object' && options.once) {\n // if options.once is true, after invoke once remove listener here\n // only browser need to do this, nodejs eventEmitter will cal removeListener\n // inside EventEmitter.once\n var delegate_1 = task.originalDelegate ? task.originalDelegate : task.callback;\n target[REMOVE_EVENT_LISTENER].call(target, event.type, delegate_1, options);\n }\n };\n // global shared zoneAwareCallback to handle all event callback with capture = false\n var globalZoneAwareCallback = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n // event.target is needed for Samsung TV and SourceBuffer\n // || global is needed https://github.com/angular/zone.js/issues/190\n var target = this || event.target || _global;\n var tasks = target[zoneSymbolEventNames$1[event.type][FALSE_STR]];\n if (tasks) {\n // invoke all tasks which attached to current target with given event.type and capture = false\n // for performance concern, if task.length === 1, just invoke\n if (tasks.length === 1) {\n invokeTask(tasks[0], target, event);\n }\n else {\n // https://github.com/angular/zone.js/issues/836\n // copy the tasks array before invoke, to avoid\n // the callback will remove itself or other listener\n var copyTasks = tasks.slice();\n for (var i = 0; i < copyTasks.length; i++) {\n if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) {\n break;\n }\n invokeTask(copyTasks[i], target, event);\n }\n }\n }\n };\n // global shared zoneAwareCallback to handle all event callback with capture = true\n var globalZoneAwareCaptureCallback = function (event) {\n // https://github.com/angular/zone.js/issues/911, in IE, sometimes\n // event will be undefined, so we need to use window.event\n event = event || _global.event;\n if (!event) {\n return;\n }\n // event.target is needed for Samsung TV and SourceBuffer\n // || global is needed https://github.com/angular/zone.js/issues/190\n var target = this || event.target || _global;\n var tasks = target[zoneSymbolEventNames$1[event.type][TRUE_STR]];\n if (tasks) {\n // invoke all tasks which attached to current target with given event.type and capture = false\n // for performance concern, if task.length === 1, just invoke\n if (tasks.length === 1) {\n invokeTask(tasks[0], target, event);\n }\n else {\n // https://github.com/angular/zone.js/issues/836\n // copy the tasks array before invoke, to avoid\n // the callback will remove itself or other listener\n var copyTasks = tasks.slice();\n for (var i = 0; i < copyTasks.length; i++) {\n if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) {\n break;\n }\n invokeTask(copyTasks[i], target, event);\n }\n }\n }\n };\n function patchEventTargetMethods(obj, patchOptions) {\n if (!obj) {\n return false;\n }\n var useGlobalCallback = true;\n if (patchOptions && patchOptions.useG !== undefined) {\n useGlobalCallback = patchOptions.useG;\n }\n var validateHandler = patchOptions && patchOptions.vh;\n var checkDuplicate = true;\n if (patchOptions && patchOptions.chkDup !== undefined) {\n checkDuplicate = patchOptions.chkDup;\n }\n var returnTarget = false;\n if (patchOptions && patchOptions.rt !== undefined) {\n returnTarget = patchOptions.rt;\n }\n var proto = obj;\n while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) {\n proto = ObjectGetPrototypeOf(proto);\n }\n if (!proto && obj[ADD_EVENT_LISTENER]) {\n // somehow we did not find it, but we can see it. This happens on IE for Window properties.\n proto = obj;\n }\n if (!proto) {\n return false;\n }\n if (proto[zoneSymbolAddEventListener]) {\n return false;\n }\n var eventNameToString = patchOptions && patchOptions.eventNameToString;\n // a shared global taskData to pass data for scheduleEventTask\n // so we do not need to create a new object just for pass some data\n var taskData = {};\n var nativeAddEventListener = proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER];\n var nativeRemoveEventListener = proto[zoneSymbol(REMOVE_EVENT_LISTENER)] =\n proto[REMOVE_EVENT_LISTENER];\n var nativeListeners = proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] =\n proto[LISTENERS_EVENT_LISTENER];\n var nativeRemoveAllListeners = proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] =\n proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER];\n var nativePrependEventListener;\n if (patchOptions && patchOptions.prepend) {\n nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] =\n proto[patchOptions.prepend];\n }\n function checkIsPassive(task) {\n if (!passiveSupported && typeof taskData.options !== 'boolean' &&\n typeof taskData.options !== 'undefined' && taskData.options !== null) {\n // options is a non-null non-undefined object\n // passive is not supported\n // don't pass options as object\n // just pass capture as a boolean\n task.options = !!taskData.options.capture;\n taskData.options = task.options;\n }\n }\n var customScheduleGlobal = function (task) {\n // if there is already a task for the eventName + capture,\n // just return, because we use the shared globalZoneAwareCallback here.\n if (taskData.isExisting) {\n return;\n }\n checkIsPassive(task);\n return nativeAddEventListener.call(taskData.target, taskData.eventName, taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, taskData.options);\n };\n var customCancelGlobal = function (task) {\n // if task is not marked as isRemoved, this call is directly\n // from Zone.prototype.cancelTask, we should remove the task\n // from tasksList of target first\n if (!task.isRemoved) {\n var symbolEventNames = zoneSymbolEventNames$1[task.eventName];\n var symbolEventName = void 0;\n if (symbolEventNames) {\n symbolEventName = symbolEventNames[task.capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = symbolEventName && task.target[symbolEventName];\n if (existingTasks) {\n for (var i = 0; i < existingTasks.length; i++) {\n var existingTask = existingTasks[i];\n if (existingTask === task) {\n existingTasks.splice(i, 1);\n // set isRemoved to data for faster invokeTask check\n task.isRemoved = true;\n if (existingTasks.length === 0) {\n // all tasks for the eventName + capture have gone,\n // remove globalZoneAwareCallback and remove the task cache from target\n task.allRemoved = true;\n task.target[symbolEventName] = null;\n }\n break;\n }\n }\n }\n }\n // if all tasks for the eventName + capture have gone,\n // we will really remove the global event callback,\n // if not, return\n if (!task.allRemoved) {\n return;\n }\n return nativeRemoveEventListener.call(task.target, task.eventName, task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, task.options);\n };\n var customScheduleNonGlobal = function (task) {\n checkIsPassive(task);\n return nativeAddEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);\n };\n var customSchedulePrepend = function (task) {\n return nativePrependEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);\n };\n var customCancelNonGlobal = function (task) {\n return nativeRemoveEventListener.call(task.target, task.eventName, task.invoke, task.options);\n };\n var customSchedule = useGlobalCallback ? customScheduleGlobal : customScheduleNonGlobal;\n var customCancel = useGlobalCallback ? customCancelGlobal : customCancelNonGlobal;\n var compareTaskCallbackVsDelegate = function (task, delegate) {\n var typeOfDelegate = typeof delegate;\n return (typeOfDelegate === 'function' && task.callback === delegate) ||\n (typeOfDelegate === 'object' && task.originalDelegate === delegate);\n };\n var compare = (patchOptions && patchOptions.diff) ? patchOptions.diff : compareTaskCallbackVsDelegate;\n var blackListedEvents = Zone[Zone.__symbol__('BLACK_LISTED_EVENTS')];\n var makeAddListener = function (nativeListener, addSource, customScheduleFn, customCancelFn, returnTarget, prepend) {\n if (returnTarget === void 0) { returnTarget = false; }\n if (prepend === void 0) { prepend = false; }\n return function () {\n var target = this || _global;\n var eventName = arguments[0];\n var delegate = arguments[1];\n if (!delegate) {\n return nativeListener.apply(this, arguments);\n }\n if (isNode && eventName === 'uncaughtException') {\n // don't patch uncaughtException of nodejs to prevent endless loop\n return nativeListener.apply(this, arguments);\n }\n // don't create the bind delegate function for handleEvent\n // case here to improve addEventListener performance\n // we will create the bind delegate when invoke\n var isHandleEvent = false;\n if (typeof delegate !== 'function') {\n if (!delegate.handleEvent) {\n return nativeListener.apply(this, arguments);\n }\n isHandleEvent = true;\n }\n if (validateHandler && !validateHandler(nativeListener, delegate, target, arguments)) {\n return;\n }\n var options = arguments[2];\n if (blackListedEvents) {\n // check black list\n for (var i = 0; i < blackListedEvents.length; i++) {\n if (eventName === blackListedEvents[i]) {\n return nativeListener.apply(this, arguments);\n }\n }\n }\n var capture;\n var once = false;\n if (options === undefined) {\n capture = false;\n }\n else if (options === true) {\n capture = true;\n }\n else if (options === false) {\n capture = false;\n }\n else {\n capture = options ? !!options.capture : false;\n once = options ? !!options.once : false;\n }\n var zone = Zone.current;\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n var symbolEventName;\n if (!symbolEventNames) {\n // the code is duplicate, but I just want to get some better performance\n var falseEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + FALSE_STR;\n var trueEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + TRUE_STR;\n var symbol = ZONE_SYMBOL_PREFIX + falseEventName;\n var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;\n zoneSymbolEventNames$1[eventName] = {};\n zoneSymbolEventNames$1[eventName][FALSE_STR] = symbol;\n zoneSymbolEventNames$1[eventName][TRUE_STR] = symbolCapture;\n symbolEventName = capture ? symbolCapture : symbol;\n }\n else {\n symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = target[symbolEventName];\n var isExisting = false;\n if (existingTasks) {\n // already have task registered\n isExisting = true;\n if (checkDuplicate) {\n for (var i = 0; i < existingTasks.length; i++) {\n if (compare(existingTasks[i], delegate)) {\n // same callback, same capture, same event name, just return\n return;\n }\n }\n }\n }\n else {\n existingTasks = target[symbolEventName] = [];\n }\n var source;\n var constructorName = target.constructor['name'];\n var targetSource = globalSources[constructorName];\n if (targetSource) {\n source = targetSource[eventName];\n }\n if (!source) {\n source = constructorName + addSource +\n (eventNameToString ? eventNameToString(eventName) : eventName);\n }\n // do not create a new object as task.data to pass those things\n // just use the global shared one\n taskData.options = options;\n if (once) {\n // if addEventListener with once options, we don't pass it to\n // native addEventListener, instead we keep the once setting\n // and handle ourselves.\n taskData.options.once = false;\n }\n taskData.target = target;\n taskData.capture = capture;\n taskData.eventName = eventName;\n taskData.isExisting = isExisting;\n var data = useGlobalCallback ? OPTIMIZED_ZONE_EVENT_TASK_DATA : undefined;\n // keep taskData into data to allow onScheduleEventTask to access the task information\n if (data) {\n data.taskData = taskData;\n }\n var task = zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn);\n // should clear taskData.target to avoid memory leak\n // issue, https://github.com/angular/angular/issues/20442\n taskData.target = null;\n // need to clear up taskData because it is a global object\n if (data) {\n data.taskData = null;\n }\n // have to save those information to task in case\n // application may call task.zone.cancelTask() directly\n if (once) {\n options.once = true;\n }\n if (!(!passiveSupported && typeof task.options === 'boolean')) {\n // if not support passive, and we pass an option object\n // to addEventListener, we should save the options to task\n task.options = options;\n }\n task.target = target;\n task.capture = capture;\n task.eventName = eventName;\n if (isHandleEvent) {\n // save original delegate for compare to check duplicate\n task.originalDelegate = delegate;\n }\n if (!prepend) {\n existingTasks.push(task);\n }\n else {\n existingTasks.unshift(task);\n }\n if (returnTarget) {\n return target;\n }\n };\n };\n proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener, ADD_EVENT_LISTENER_SOURCE, customSchedule, customCancel, returnTarget);\n if (nativePrependEventListener) {\n proto[PREPEND_EVENT_LISTENER] = makeAddListener(nativePrependEventListener, PREPEND_EVENT_LISTENER_SOURCE, customSchedulePrepend, customCancel, returnTarget, true);\n }\n proto[REMOVE_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n var options = arguments[2];\n var capture;\n if (options === undefined) {\n capture = false;\n }\n else if (options === true) {\n capture = true;\n }\n else if (options === false) {\n capture = false;\n }\n else {\n capture = options ? !!options.capture : false;\n }\n var delegate = arguments[1];\n if (!delegate) {\n return nativeRemoveEventListener.apply(this, arguments);\n }\n if (validateHandler &&\n !validateHandler(nativeRemoveEventListener, delegate, target, arguments)) {\n return;\n }\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n var symbolEventName;\n if (symbolEventNames) {\n symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];\n }\n var existingTasks = symbolEventName && target[symbolEventName];\n if (existingTasks) {\n for (var i = 0; i < existingTasks.length; i++) {\n var existingTask = existingTasks[i];\n if (compare(existingTask, delegate)) {\n existingTasks.splice(i, 1);\n // set isRemoved to data for faster invokeTask check\n existingTask.isRemoved = true;\n if (existingTasks.length === 0) {\n // all tasks for the eventName + capture have gone,\n // remove globalZoneAwareCallback and remove the task cache from target\n existingTask.allRemoved = true;\n target[symbolEventName] = null;\n }\n existingTask.zone.cancelTask(existingTask);\n if (returnTarget) {\n return target;\n }\n return;\n }\n }\n }\n // issue 930, didn't find the event name or callback\n // from zone kept existingTasks, the callback maybe\n // added outside of zone, we need to call native removeEventListener\n // to try to remove it.\n return nativeRemoveEventListener.apply(this, arguments);\n };\n proto[LISTENERS_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n var listeners = [];\n var tasks = findEventTasks(target, eventNameToString ? eventNameToString(eventName) : eventName);\n for (var i = 0; i < tasks.length; i++) {\n var task = tasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n listeners.push(delegate);\n }\n return listeners;\n };\n proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () {\n var target = this || _global;\n var eventName = arguments[0];\n if (!eventName) {\n var keys = Object.keys(target);\n for (var i = 0; i < keys.length; i++) {\n var prop = keys[i];\n var match = EVENT_NAME_SYMBOL_REGX.exec(prop);\n var evtName = match && match[1];\n // in nodejs EventEmitter, removeListener event is\n // used for monitoring the removeListener call,\n // so just keep removeListener eventListener until\n // all other eventListeners are removed\n if (evtName && evtName !== 'removeListener') {\n this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);\n }\n }\n // remove removeListener listener finally\n this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');\n }\n else {\n var symbolEventNames = zoneSymbolEventNames$1[eventName];\n if (symbolEventNames) {\n var symbolEventName = symbolEventNames[FALSE_STR];\n var symbolCaptureEventName = symbolEventNames[TRUE_STR];\n var tasks = target[symbolEventName];\n var captureTasks = target[symbolCaptureEventName];\n if (tasks) {\n var removeTasks = tasks.slice();\n for (var i = 0; i < removeTasks.length; i++) {\n var task = removeTasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);\n }\n }\n if (captureTasks) {\n var removeTasks = captureTasks.slice();\n for (var i = 0; i < removeTasks.length; i++) {\n var task = removeTasks[i];\n var delegate = task.originalDelegate ? task.originalDelegate : task.callback;\n this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);\n }\n }\n }\n }\n if (returnTarget) {\n return this;\n }\n };\n // for native toString patch\n attachOriginToPatched(proto[ADD_EVENT_LISTENER], nativeAddEventListener);\n attachOriginToPatched(proto[REMOVE_EVENT_LISTENER], nativeRemoveEventListener);\n if (nativeRemoveAllListeners) {\n attachOriginToPatched(proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER], nativeRemoveAllListeners);\n }\n if (nativeListeners) {\n attachOriginToPatched(proto[LISTENERS_EVENT_LISTENER], nativeListeners);\n }\n return true;\n }\n var results = [];\n for (var i = 0; i < apis.length; i++) {\n results[i] = patchEventTargetMethods(apis[i], patchOptions);\n }\n return results;\n}\nfunction findEventTasks(target, eventName) {\n var foundTasks = [];\n for (var prop in target) {\n var match = EVENT_NAME_SYMBOL_REGX.exec(prop);\n var evtName = match && match[1];\n if (evtName && (!eventName || evtName === eventName)) {\n var tasks = target[prop];\n if (tasks) {\n for (var i = 0; i < tasks.length; i++) {\n foundTasks.push(tasks[i]);\n }\n }\n }\n }\n return foundTasks;\n}\nfunction patchEventPrototype(global, api) {\n var Event = global['Event'];\n if (Event && Event.prototype) {\n api.patchMethod(Event.prototype, 'stopImmediatePropagation', function (delegate) { return function (self, args) {\n self[IMMEDIATE_PROPAGATION_SYMBOL] = true;\n // we need to call the native stopImmediatePropagation\n // in case in some hybrid application, some part of\n // application will be controlled by zone, some are not\n delegate && delegate.apply(self, args);\n }; });\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nvar taskSymbol = zoneSymbol('zoneTask');\nfunction patchTimer(window, setName, cancelName, nameSuffix) {\n var setNative = null;\n var clearNative = null;\n setName += nameSuffix;\n cancelName += nameSuffix;\n var tasksByHandleId = {};\n function scheduleTask(task) {\n var data = task.data;\n function timer() {\n try {\n task.invoke.apply(this, arguments);\n }\n finally {\n // issue-934, task will be cancelled\n // even it is a periodic task such as\n // setInterval\n if (!(task.data && task.data.isPeriodic)) {\n if (typeof data.handleId === 'number') {\n // in non-nodejs env, we remove timerId\n // from local cache\n delete tasksByHandleId[data.handleId];\n }\n else if (data.handleId) {\n // Node returns complex objects as handleIds\n // we remove task reference from timer object\n data.handleId[taskSymbol] = null;\n }\n }\n }\n }\n data.args[0] = timer;\n data.handleId = setNative.apply(window, data.args);\n return task;\n }\n function clearTask(task) {\n return clearNative(task.data.handleId);\n }\n setNative =\n patchMethod(window, setName, function (delegate) { return function (self, args) {\n if (typeof args[0] === 'function') {\n var options = {\n isPeriodic: nameSuffix === 'Interval',\n delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 :\n undefined,\n args: args\n };\n var task = scheduleMacroTaskWithCurrentZone(setName, args[0], options, scheduleTask, clearTask);\n if (!task) {\n return task;\n }\n // Node.js must additionally support the ref and unref functions.\n var handle = task.data.handleId;\n if (typeof handle === 'number') {\n // for non nodejs env, we save handleId: task\n // mapping in local cache for clearTimeout\n tasksByHandleId[handle] = task;\n }\n else if (handle) {\n // for nodejs env, we save task\n // reference in timerId Object for clearTimeout\n handle[taskSymbol] = task;\n }\n // check whether handle is null, because some polyfill or browser\n // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame\n if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' &&\n typeof handle.unref === 'function') {\n task.ref = handle.ref.bind(handle);\n task.unref = handle.unref.bind(handle);\n }\n if (typeof handle === 'number' || handle) {\n return handle;\n }\n return task;\n }\n else {\n // cause an error by calling it directly.\n return delegate.apply(window, args);\n }\n }; });\n clearNative =\n patchMethod(window, cancelName, function (delegate) { return function (self, args) {\n var id = args[0];\n var task;\n if (typeof id === 'number') {\n // non nodejs env.\n task = tasksByHandleId[id];\n }\n else {\n // nodejs env.\n task = id && id[taskSymbol];\n // other environments.\n if (!task) {\n task = id;\n }\n }\n if (task && typeof task.type === 'string') {\n if (task.state !== 'notScheduled' &&\n (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) {\n if (typeof id === 'number') {\n delete tasksByHandleId[id];\n }\n else if (id) {\n id[taskSymbol] = null;\n }\n // Do not cancel already canceled functions\n task.zone.cancelTask(task);\n }\n }\n else {\n // cause an error by calling it directly.\n delegate.apply(window, args);\n }\n }; });\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/*\n * This is necessary for Chrome and Chrome mobile, to enable\n * things like redefining `createdCallback` on an element.\n */\nvar _defineProperty = Object[zoneSymbol('defineProperty')] = Object.defineProperty;\nvar _getOwnPropertyDescriptor = Object[zoneSymbol('getOwnPropertyDescriptor')] =\n Object.getOwnPropertyDescriptor;\nvar _create = Object.create;\nvar unconfigurablesKey = zoneSymbol('unconfigurables');\nfunction propertyPatch() {\n Object.defineProperty = function (obj, prop, desc) {\n if (isUnconfigurable(obj, prop)) {\n throw new TypeError('Cannot assign to read only property \\'' + prop + '\\' of ' + obj);\n }\n var originalConfigurableFlag = desc.configurable;\n if (prop !== 'prototype') {\n desc = rewriteDescriptor(obj, prop, desc);\n }\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n };\n Object.defineProperties = function (obj, props) {\n Object.keys(props).forEach(function (prop) {\n Object.defineProperty(obj, prop, props[prop]);\n });\n return obj;\n };\n Object.create = function (obj, proto) {\n if (typeof proto === 'object' && !Object.isFrozen(proto)) {\n Object.keys(proto).forEach(function (prop) {\n proto[prop] = rewriteDescriptor(obj, prop, proto[prop]);\n });\n }\n return _create(obj, proto);\n };\n Object.getOwnPropertyDescriptor = function (obj, prop) {\n var desc = _getOwnPropertyDescriptor(obj, prop);\n if (desc && isUnconfigurable(obj, prop)) {\n desc.configurable = false;\n }\n return desc;\n };\n}\nfunction _redefineProperty(obj, prop, desc) {\n var originalConfigurableFlag = desc.configurable;\n desc = rewriteDescriptor(obj, prop, desc);\n return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);\n}\nfunction isUnconfigurable(obj, prop) {\n return obj && obj[unconfigurablesKey] && obj[unconfigurablesKey][prop];\n}\nfunction rewriteDescriptor(obj, prop, desc) {\n // issue-927, if the desc is frozen, don't try to change the desc\n if (!Object.isFrozen(desc)) {\n desc.configurable = true;\n }\n if (!desc.configurable) {\n // issue-927, if the obj is frozen, don't try to set the desc to obj\n if (!obj[unconfigurablesKey] && !Object.isFrozen(obj)) {\n _defineProperty(obj, unconfigurablesKey, { writable: true, value: {} });\n }\n if (obj[unconfigurablesKey]) {\n obj[unconfigurablesKey][prop] = true;\n }\n }\n return desc;\n}\nfunction _tryDefineProperty(obj, prop, desc, originalConfigurableFlag) {\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n if (desc.configurable) {\n // In case of errors, when the configurable flag was likely set by rewriteDescriptor(), let's\n // retry with the original flag value\n if (typeof originalConfigurableFlag == 'undefined') {\n delete desc.configurable;\n }\n else {\n desc.configurable = originalConfigurableFlag;\n }\n try {\n return _defineProperty(obj, prop, desc);\n }\n catch (error) {\n var descJson = null;\n try {\n descJson = JSON.stringify(desc);\n }\n catch (error) {\n descJson = desc.toString();\n }\n console.log(\"Attempting to configure '\" + prop + \"' with descriptor '\" + descJson + \"' on object '\" + obj + \"' and got error, giving up: \" + error);\n }\n }\n else {\n throw error;\n }\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// we have to patch the instance since the proto is non-configurable\nfunction apply(api, _global) {\n var WS = _global.WebSocket;\n // On Safari window.EventTarget doesn't exist so need to patch WS add/removeEventListener\n // On older Chrome, no need since EventTarget was already patched\n if (!_global.EventTarget) {\n patchEventTarget(_global, [WS.prototype]);\n }\n _global.WebSocket = function (x, y) {\n var socket = arguments.length > 1 ? new WS(x, y) : new WS(x);\n var proxySocket;\n var proxySocketProto;\n // Safari 7.0 has non-configurable own 'onmessage' and friends properties on the socket instance\n var onmessageDesc = ObjectGetOwnPropertyDescriptor(socket, 'onmessage');\n if (onmessageDesc && onmessageDesc.configurable === false) {\n proxySocket = ObjectCreate(socket);\n // socket have own property descriptor 'onopen', 'onmessage', 'onclose', 'onerror'\n // but proxySocket not, so we will keep socket as prototype and pass it to\n // patchOnProperties method\n proxySocketProto = socket;\n [ADD_EVENT_LISTENER_STR, REMOVE_EVENT_LISTENER_STR, 'send', 'close'].forEach(function (propName) {\n proxySocket[propName] = function () {\n var args = ArraySlice.call(arguments);\n if (propName === ADD_EVENT_LISTENER_STR || propName === REMOVE_EVENT_LISTENER_STR) {\n var eventName = args.length > 0 ? args[0] : undefined;\n if (eventName) {\n var propertySymbol = Zone.__symbol__('ON_PROPERTY' + eventName);\n socket[propertySymbol] = proxySocket[propertySymbol];\n }\n }\n return socket[propName].apply(socket, args);\n };\n });\n }\n else {\n // we can patch the real socket\n proxySocket = socket;\n }\n patchOnProperties(proxySocket, ['close', 'error', 'message', 'open'], proxySocketProto);\n return proxySocket;\n };\n var globalWebSocket = _global['WebSocket'];\n for (var prop in WS) {\n globalWebSocket[prop] = WS[prop];\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {globalThis}\n */\nvar globalEventHandlersEventNames = [\n 'abort',\n 'animationcancel',\n 'animationend',\n 'animationiteration',\n 'auxclick',\n 'beforeinput',\n 'blur',\n 'cancel',\n 'canplay',\n 'canplaythrough',\n 'change',\n 'compositionstart',\n 'compositionupdate',\n 'compositionend',\n 'cuechange',\n 'click',\n 'close',\n 'contextmenu',\n 'curechange',\n 'dblclick',\n 'drag',\n 'dragend',\n 'dragenter',\n 'dragexit',\n 'dragleave',\n 'dragover',\n 'drop',\n 'durationchange',\n 'emptied',\n 'ended',\n 'error',\n 'focus',\n 'focusin',\n 'focusout',\n 'gotpointercapture',\n 'input',\n 'invalid',\n 'keydown',\n 'keypress',\n 'keyup',\n 'load',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'lostpointercapture',\n 'mousedown',\n 'mouseenter',\n 'mouseleave',\n 'mousemove',\n 'mouseout',\n 'mouseover',\n 'mouseup',\n 'mousewheel',\n 'orientationchange',\n 'pause',\n 'play',\n 'playing',\n 'pointercancel',\n 'pointerdown',\n 'pointerenter',\n 'pointerleave',\n 'pointerlockchange',\n 'mozpointerlockchange',\n 'webkitpointerlockerchange',\n 'pointerlockerror',\n 'mozpointerlockerror',\n 'webkitpointerlockerror',\n 'pointermove',\n 'pointout',\n 'pointerover',\n 'pointerup',\n 'progress',\n 'ratechange',\n 'reset',\n 'resize',\n 'scroll',\n 'seeked',\n 'seeking',\n 'select',\n 'selectionchange',\n 'selectstart',\n 'show',\n 'sort',\n 'stalled',\n 'submit',\n 'suspend',\n 'timeupdate',\n 'volumechange',\n 'touchcancel',\n 'touchmove',\n 'touchstart',\n 'touchend',\n 'transitioncancel',\n 'transitionend',\n 'waiting',\n 'wheel'\n];\nvar documentEventNames = [\n 'afterscriptexecute', 'beforescriptexecute', 'DOMContentLoaded', 'freeze', 'fullscreenchange',\n 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange', 'fullscreenerror',\n 'mozfullscreenerror', 'webkitfullscreenerror', 'msfullscreenerror', 'readystatechange',\n 'visibilitychange', 'resume'\n];\nvar windowEventNames = [\n 'absolutedeviceorientation',\n 'afterinput',\n 'afterprint',\n 'appinstalled',\n 'beforeinstallprompt',\n 'beforeprint',\n 'beforeunload',\n 'devicelight',\n 'devicemotion',\n 'deviceorientation',\n 'deviceorientationabsolute',\n 'deviceproximity',\n 'hashchange',\n 'languagechange',\n 'message',\n 'mozbeforepaint',\n 'offline',\n 'online',\n 'paint',\n 'pageshow',\n 'pagehide',\n 'popstate',\n 'rejectionhandled',\n 'storage',\n 'unhandledrejection',\n 'unload',\n 'userproximity',\n 'vrdisplyconnected',\n 'vrdisplaydisconnected',\n 'vrdisplaypresentchange'\n];\nvar htmlElementEventNames = [\n 'beforecopy', 'beforecut', 'beforepaste', 'copy', 'cut', 'paste', 'dragstart', 'loadend',\n 'animationstart', 'search', 'transitionrun', 'transitionstart', 'webkitanimationend',\n 'webkitanimationiteration', 'webkitanimationstart', 'webkittransitionend'\n];\nvar mediaElementEventNames = ['encrypted', 'waitingforkey', 'msneedkey', 'mozinterruptbegin', 'mozinterruptend'];\nvar ieElementEventNames = [\n 'activate',\n 'afterupdate',\n 'ariarequest',\n 'beforeactivate',\n 'beforedeactivate',\n 'beforeeditfocus',\n 'beforeupdate',\n 'cellchange',\n 'controlselect',\n 'dataavailable',\n 'datasetchanged',\n 'datasetcomplete',\n 'errorupdate',\n 'filterchange',\n 'layoutcomplete',\n 'losecapture',\n 'move',\n 'moveend',\n 'movestart',\n 'propertychange',\n 'resizeend',\n 'resizestart',\n 'rowenter',\n 'rowexit',\n 'rowsdelete',\n 'rowsinserted',\n 'command',\n 'compassneedscalibration',\n 'deactivate',\n 'help',\n 'mscontentzoom',\n 'msmanipulationstatechanged',\n 'msgesturechange',\n 'msgesturedoubletap',\n 'msgestureend',\n 'msgesturehold',\n 'msgesturestart',\n 'msgesturetap',\n 'msgotpointercapture',\n 'msinertiastart',\n 'mslostpointercapture',\n 'mspointercancel',\n 'mspointerdown',\n 'mspointerenter',\n 'mspointerhover',\n 'mspointerleave',\n 'mspointermove',\n 'mspointerout',\n 'mspointerover',\n 'mspointerup',\n 'pointerout',\n 'mssitemodejumplistitemremoved',\n 'msthumbnailclick',\n 'stop',\n 'storagecommit'\n];\nvar webglEventNames = ['webglcontextrestored', 'webglcontextlost', 'webglcontextcreationerror'];\nvar formEventNames = ['autocomplete', 'autocompleteerror'];\nvar detailEventNames = ['toggle'];\nvar frameEventNames = ['load'];\nvar frameSetEventNames = ['blur', 'error', 'focus', 'load', 'resize', 'scroll', 'messageerror'];\nvar marqueeEventNames = ['bounce', 'finish', 'start'];\nvar XMLHttpRequestEventNames = [\n 'loadstart', 'progress', 'abort', 'error', 'load', 'progress', 'timeout', 'loadend',\n 'readystatechange'\n];\nvar IDBIndexEventNames = ['upgradeneeded', 'complete', 'abort', 'success', 'error', 'blocked', 'versionchange', 'close'];\nvar websocketEventNames = ['close', 'error', 'open', 'message'];\nvar workerEventNames = ['error', 'message'];\nvar eventNames = globalEventHandlersEventNames.concat(webglEventNames, formEventNames, detailEventNames, documentEventNames, windowEventNames, htmlElementEventNames, ieElementEventNames);\nfunction filterProperties(target, onProperties, ignoreProperties) {\n if (!ignoreProperties || ignoreProperties.length === 0) {\n return onProperties;\n }\n var tip = ignoreProperties.filter(function (ip) { return ip.target === target; });\n if (!tip || tip.length === 0) {\n return onProperties;\n }\n var targetIgnoreProperties = tip[0].ignoreProperties;\n return onProperties.filter(function (op) { return targetIgnoreProperties.indexOf(op) === -1; });\n}\nfunction patchFilteredProperties(target, onProperties, ignoreProperties, prototype) {\n // check whether target is available, sometimes target will be undefined\n // because different browser or some 3rd party plugin.\n if (!target) {\n return;\n }\n var filteredProperties = filterProperties(target, onProperties, ignoreProperties);\n patchOnProperties(target, filteredProperties, prototype);\n}\nfunction propertyDescriptorPatch(api, _global) {\n if (isNode && !isMix) {\n return;\n }\n var supportsWebSocket = typeof WebSocket !== 'undefined';\n if (canPatchViaPropertyDescriptor()) {\n var ignoreProperties = _global['__Zone_ignore_on_properties'];\n // for browsers that we can patch the descriptor: Chrome & Firefox\n if (isBrowser) {\n var internalWindow = window;\n var ignoreErrorProperties = isIE ? [{ target: internalWindow, ignoreProperties: ['error'] }] : [];\n // in IE/Edge, onProp not exist in window object, but in WindowPrototype\n // so we need to pass WindowPrototype to check onProp exist or not\n patchFilteredProperties(internalWindow, eventNames.concat(['messageerror']), ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties, ObjectGetPrototypeOf(internalWindow));\n patchFilteredProperties(Document.prototype, eventNames, ignoreProperties);\n if (typeof internalWindow['SVGElement'] !== 'undefined') {\n patchFilteredProperties(internalWindow['SVGElement'].prototype, eventNames, ignoreProperties);\n }\n patchFilteredProperties(Element.prototype, eventNames, ignoreProperties);\n patchFilteredProperties(HTMLElement.prototype, eventNames, ignoreProperties);\n patchFilteredProperties(HTMLMediaElement.prototype, mediaElementEventNames, ignoreProperties);\n patchFilteredProperties(HTMLFrameSetElement.prototype, windowEventNames.concat(frameSetEventNames), ignoreProperties);\n patchFilteredProperties(HTMLBodyElement.prototype, windowEventNames.concat(frameSetEventNames), ignoreProperties);\n patchFilteredProperties(HTMLFrameElement.prototype, frameEventNames, ignoreProperties);\n patchFilteredProperties(HTMLIFrameElement.prototype, frameEventNames, ignoreProperties);\n var HTMLMarqueeElement_1 = internalWindow['HTMLMarqueeElement'];\n if (HTMLMarqueeElement_1) {\n patchFilteredProperties(HTMLMarqueeElement_1.prototype, marqueeEventNames, ignoreProperties);\n }\n var Worker_1 = internalWindow['Worker'];\n if (Worker_1) {\n patchFilteredProperties(Worker_1.prototype, workerEventNames, ignoreProperties);\n }\n }\n patchFilteredProperties(XMLHttpRequest.prototype, XMLHttpRequestEventNames, ignoreProperties);\n var XMLHttpRequestEventTarget_1 = _global['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget_1) {\n patchFilteredProperties(XMLHttpRequestEventTarget_1 && XMLHttpRequestEventTarget_1.prototype, XMLHttpRequestEventNames, ignoreProperties);\n }\n if (typeof IDBIndex !== 'undefined') {\n patchFilteredProperties(IDBIndex.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBRequest.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBOpenDBRequest.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBDatabase.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBTransaction.prototype, IDBIndexEventNames, ignoreProperties);\n patchFilteredProperties(IDBCursor.prototype, IDBIndexEventNames, ignoreProperties);\n }\n if (supportsWebSocket) {\n patchFilteredProperties(WebSocket.prototype, websocketEventNames, ignoreProperties);\n }\n }\n else {\n // Safari, Android browsers (Jelly Bean)\n patchViaCapturingAllTheEvents();\n patchClass('XMLHttpRequest');\n if (supportsWebSocket) {\n apply(api, _global);\n }\n }\n}\nfunction canPatchViaPropertyDescriptor() {\n if ((isBrowser || isMix) && !ObjectGetOwnPropertyDescriptor(HTMLElement.prototype, 'onclick') &&\n typeof Element !== 'undefined') {\n // WebKit https://bugs.webkit.org/show_bug.cgi?id=134364\n // IDL interface attributes are not configurable\n var desc = ObjectGetOwnPropertyDescriptor(Element.prototype, 'onclick');\n if (desc && !desc.configurable)\n return false;\n }\n var ON_READY_STATE_CHANGE = 'onreadystatechange';\n var XMLHttpRequestPrototype = XMLHttpRequest.prototype;\n var xhrDesc = ObjectGetOwnPropertyDescriptor(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE);\n // add enumerable and configurable here because in opera\n // by default XMLHttpRequest.prototype.onreadystatechange is undefined\n // without adding enumerable and configurable will cause onreadystatechange\n // non-configurable\n // and if XMLHttpRequest.prototype.onreadystatechange is undefined,\n // we should set a real desc instead a fake one\n if (xhrDesc) {\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {\n enumerable: true,\n configurable: true,\n get: function () {\n return true;\n }\n });\n var req = new XMLHttpRequest();\n var result = !!req.onreadystatechange;\n // restore original desc\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, xhrDesc || {});\n return result;\n }\n else {\n var SYMBOL_FAKE_ONREADYSTATECHANGE_1 = zoneSymbol('fake');\n ObjectDefineProperty(XMLHttpRequestPrototype, ON_READY_STATE_CHANGE, {\n enumerable: true,\n configurable: true,\n get: function () {\n return this[SYMBOL_FAKE_ONREADYSTATECHANGE_1];\n },\n set: function (value) {\n this[SYMBOL_FAKE_ONREADYSTATECHANGE_1] = value;\n }\n });\n var req = new XMLHttpRequest();\n var detectFunc = function () { };\n req.onreadystatechange = detectFunc;\n var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;\n req.onreadystatechange = null;\n return result;\n }\n}\nvar unboundKey = zoneSymbol('unbound');\n// Whenever any eventListener fires, we check the eventListener target and all parents\n// for `onwhatever` properties and replace them with zone-bound functions\n// - Chrome (for now)\nfunction patchViaCapturingAllTheEvents() {\n var _loop_1 = function (i) {\n var property = eventNames[i];\n var onproperty = 'on' + property;\n self.addEventListener(property, function (event) {\n var elt = event.target, bound, source;\n if (elt) {\n source = elt.constructor['name'] + '.' + onproperty;\n }\n else {\n source = 'unknown.' + onproperty;\n }\n while (elt) {\n if (elt[onproperty] && !elt[onproperty][unboundKey]) {\n bound = wrapWithCurrentZone(elt[onproperty], source);\n bound[unboundKey] = elt[onproperty];\n elt[onproperty] = bound;\n }\n elt = elt.parentElement;\n }\n }, true);\n };\n for (var i = 0; i < eventNames.length; i++) {\n _loop_1(i);\n }\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction eventTargetPatch(_global, api) {\n var WTF_ISSUE_555 = 'Anchor,Area,Audio,BR,Base,BaseFont,Body,Button,Canvas,Content,DList,Directory,Div,Embed,FieldSet,Font,Form,Frame,FrameSet,HR,Head,Heading,Html,IFrame,Image,Input,Keygen,LI,Label,Legend,Link,Map,Marquee,Media,Menu,Meta,Meter,Mod,OList,Object,OptGroup,Option,Output,Paragraph,Pre,Progress,Quote,Script,Select,Source,Span,Style,TableCaption,TableCell,TableCol,Table,TableRow,TableSection,TextArea,Title,Track,UList,Unknown,Video';\n var NO_EVENT_TARGET = 'ApplicationCache,EventSource,FileReader,InputMethodContext,MediaController,MessagePort,Node,Performance,SVGElementInstance,SharedWorker,TextTrack,TextTrackCue,TextTrackList,WebKitNamedFlow,Window,Worker,WorkerGlobalScope,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload,IDBRequest,IDBOpenDBRequest,IDBDatabase,IDBTransaction,IDBCursor,DBIndex,WebSocket'\n .split(',');\n var EVENT_TARGET = 'EventTarget';\n var apis = [];\n var isWtf = _global['wtf'];\n var WTF_ISSUE_555_ARRAY = WTF_ISSUE_555.split(',');\n if (isWtf) {\n // Workaround for: https://github.com/google/tracing-framework/issues/555\n apis = WTF_ISSUE_555_ARRAY.map(function (v) { return 'HTML' + v + 'Element'; }).concat(NO_EVENT_TARGET);\n }\n else if (_global[EVENT_TARGET]) {\n apis.push(EVENT_TARGET);\n }\n else {\n // Note: EventTarget is not available in all browsers,\n // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget\n apis = NO_EVENT_TARGET;\n }\n var isDisableIECheck = _global['__Zone_disable_IE_check'] || false;\n var isEnableCrossContextCheck = _global['__Zone_enable_cross_context_check'] || false;\n var ieOrEdge = isIEOrEdge();\n var ADD_EVENT_LISTENER_SOURCE = '.addEventListener:';\n var FUNCTION_WRAPPER = '[object FunctionWrapper]';\n var BROWSER_TOOLS = 'function __BROWSERTOOLS_CONSOLE_SAFEFUNC() { [native code] }';\n // predefine all __zone_symbol__ + eventName + true/false string\n for (var i = 0; i < eventNames.length; i++) {\n var eventName = eventNames[i];\n var falseEventName = eventName + FALSE_STR;\n var trueEventName = eventName + TRUE_STR;\n var symbol = ZONE_SYMBOL_PREFIX + falseEventName;\n var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;\n zoneSymbolEventNames$1[eventName] = {};\n zoneSymbolEventNames$1[eventName][FALSE_STR] = symbol;\n zoneSymbolEventNames$1[eventName][TRUE_STR] = symbolCapture;\n }\n // predefine all task.source string\n for (var i = 0; i < WTF_ISSUE_555.length; i++) {\n var target = WTF_ISSUE_555_ARRAY[i];\n var targets = globalSources[target] = {};\n for (var j = 0; j < eventNames.length; j++) {\n var eventName = eventNames[j];\n targets[eventName] = target + ADD_EVENT_LISTENER_SOURCE + eventName;\n }\n }\n var checkIEAndCrossContext = function (nativeDelegate, delegate, target, args) {\n if (!isDisableIECheck && ieOrEdge) {\n if (isEnableCrossContextCheck) {\n try {\n var testString = delegate.toString();\n if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n catch (error) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n else {\n var testString = delegate.toString();\n if ((testString === FUNCTION_WRAPPER || testString == BROWSER_TOOLS)) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n }\n else if (isEnableCrossContextCheck) {\n try {\n delegate.toString();\n }\n catch (error) {\n nativeDelegate.apply(target, args);\n return false;\n }\n }\n return true;\n };\n var apiTypes = [];\n for (var i = 0; i < apis.length; i++) {\n var type = _global[apis[i]];\n apiTypes.push(type && type.prototype);\n }\n // vh is validateHandler to check event handler\n // is valid or not(for security check)\n patchEventTarget(_global, apiTypes, { vh: checkIEAndCrossContext });\n api.patchEventTarget = patchEventTarget;\n return true;\n}\nfunction patchEvent(global, api) {\n patchEventPrototype(global, api);\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nfunction patchCallbacks(target, targetName, method, callbacks) {\n var symbol = Zone.__symbol__(method);\n if (target[symbol]) {\n return;\n }\n var nativeDelegate = target[symbol] = target[method];\n target[method] = function (name, opts, options) {\n if (opts && opts.prototype) {\n callbacks.forEach(function (callback) {\n var source = targetName + \".\" + method + \"::\" + callback;\n var prototype = opts.prototype;\n if (prototype.hasOwnProperty(callback)) {\n var descriptor = ObjectGetOwnPropertyDescriptor(prototype, callback);\n if (descriptor && descriptor.value) {\n descriptor.value = wrapWithCurrentZone(descriptor.value, source);\n _redefineProperty(opts.prototype, callback, descriptor);\n }\n else if (prototype[callback]) {\n prototype[callback] = wrapWithCurrentZone(prototype[callback], source);\n }\n }\n else if (prototype[callback]) {\n prototype[callback] = wrapWithCurrentZone(prototype[callback], source);\n }\n });\n }\n return nativeDelegate.call(target, name, opts, options);\n };\n attachOriginToPatched(target[method], nativeDelegate);\n}\nfunction registerElementPatch(_global) {\n if ((!isBrowser && !isMix) || !('registerElement' in _global.document)) {\n return;\n }\n var callbacks = ['createdCallback', 'attachedCallback', 'detachedCallback', 'attributeChangedCallback'];\n patchCallbacks(document, 'Document', 'registerElement', callbacks);\n}\nfunction patchCustomElements(_global) {\n if ((!isBrowser && !isMix) || !('customElements' in _global)) {\n return;\n }\n var callbacks = ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback'];\n patchCallbacks(_global.customElements, 'customElements', 'define', callbacks);\n}\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * @fileoverview\n * @suppress {missingRequire}\n */\nZone.__load_patch('util', function (global, Zone, api) {\n api.patchOnProperties = patchOnProperties;\n api.patchMethod = patchMethod;\n api.bindArguments = bindArguments;\n});\nZone.__load_patch('timers', function (global) {\n var set = 'set';\n var clear = 'clear';\n patchTimer(global, set, clear, 'Timeout');\n patchTimer(global, set, clear, 'Interval');\n patchTimer(global, set, clear, 'Immediate');\n});\nZone.__load_patch('requestAnimationFrame', function (global) {\n patchTimer(global, 'request', 'cancel', 'AnimationFrame');\n patchTimer(global, 'mozRequest', 'mozCancel', 'AnimationFrame');\n patchTimer(global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');\n});\nZone.__load_patch('blocking', function (global, Zone) {\n var blockingMethods = ['alert', 'prompt', 'confirm'];\n for (var i = 0; i < blockingMethods.length; i++) {\n var name_1 = blockingMethods[i];\n patchMethod(global, name_1, function (delegate, symbol, name) {\n return function (s, args) {\n return Zone.current.run(delegate, global, args, name);\n };\n });\n }\n});\nZone.__load_patch('EventTarget', function (global, Zone, api) {\n // load blackListEvents from global\n var SYMBOL_BLACK_LISTED_EVENTS = Zone.__symbol__('BLACK_LISTED_EVENTS');\n if (global[SYMBOL_BLACK_LISTED_EVENTS]) {\n Zone[SYMBOL_BLACK_LISTED_EVENTS] = global[SYMBOL_BLACK_LISTED_EVENTS];\n }\n patchEvent(global, api);\n eventTargetPatch(global, api);\n // patch XMLHttpRequestEventTarget's addEventListener/removeEventListener\n var XMLHttpRequestEventTarget = global['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {\n api.patchEventTarget(global, [XMLHttpRequestEventTarget.prototype]);\n }\n patchClass('MutationObserver');\n patchClass('WebKitMutationObserver');\n patchClass('IntersectionObserver');\n patchClass('FileReader');\n});\nZone.__load_patch('on_property', function (global, Zone, api) {\n propertyDescriptorPatch(api, global);\n propertyPatch();\n});\nZone.__load_patch('customElements', function (global, Zone, api) {\n registerElementPatch(global);\n patchCustomElements(global);\n});\nZone.__load_patch('canvas', function (global) {\n var HTMLCanvasElement = global['HTMLCanvasElement'];\n if (typeof HTMLCanvasElement !== 'undefined' && HTMLCanvasElement.prototype &&\n HTMLCanvasElement.prototype.toBlob) {\n patchMacroTask(HTMLCanvasElement.prototype, 'toBlob', function (self, args) {\n return { name: 'HTMLCanvasElement.toBlob', target: self, cbIdx: 0, args: args };\n });\n }\n});\nZone.__load_patch('XHR', function (global, Zone) {\n // Treat XMLHttpRequest as a macrotask.\n patchXHR(global);\n var XHR_TASK = zoneSymbol('xhrTask');\n var XHR_SYNC = zoneSymbol('xhrSync');\n var XHR_LISTENER = zoneSymbol('xhrListener');\n var XHR_SCHEDULED = zoneSymbol('xhrScheduled');\n var XHR_URL = zoneSymbol('xhrURL');\n var XHR_ERROR_BEFORE_SCHEDULED = zoneSymbol('xhrErrorBeforeScheduled');\n function patchXHR(window) {\n var XMLHttpRequestPrototype = XMLHttpRequest.prototype;\n function findPendingTask(target) {\n return target[XHR_TASK];\n }\n var oriAddListener = XMLHttpRequestPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n var oriRemoveListener = XMLHttpRequestPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n if (!oriAddListener) {\n var XMLHttpRequestEventTarget_1 = window['XMLHttpRequestEventTarget'];\n if (XMLHttpRequestEventTarget_1) {\n var XMLHttpRequestEventTargetPrototype = XMLHttpRequestEventTarget_1.prototype;\n oriAddListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n oriRemoveListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n }\n }\n var READY_STATE_CHANGE = 'readystatechange';\n var SCHEDULED = 'scheduled';\n function scheduleTask(task) {\n var data = task.data;\n var target = data.target;\n target[XHR_SCHEDULED] = false;\n target[XHR_ERROR_BEFORE_SCHEDULED] = false;\n // remove existing event listener\n var listener = target[XHR_LISTENER];\n if (!oriAddListener) {\n oriAddListener = target[ZONE_SYMBOL_ADD_EVENT_LISTENER];\n oriRemoveListener = target[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];\n }\n if (listener) {\n oriRemoveListener.call(target, READY_STATE_CHANGE, listener);\n }\n var newListener = target[XHR_LISTENER] = function () {\n if (target.readyState === target.DONE) {\n // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with\n // readyState=4 multiple times, so we need to check task state here\n if (!data.aborted && target[XHR_SCHEDULED] && task.state === SCHEDULED) {\n // check whether the xhr has registered onload listener\n // if that is the case, the task should invoke after all\n // onload listeners finish.\n var loadTasks = target['__zone_symbol__loadfalse'];\n if (loadTasks && loadTasks.length > 0) {\n var oriInvoke_1 = task.invoke;\n task.invoke = function () {\n // need to load the tasks again, because in other\n // load listener, they may remove themselves\n var loadTasks = target['__zone_symbol__loadfalse'];\n for (var i = 0; i < loadTasks.length; i++) {\n if (loadTasks[i] === task) {\n loadTasks.splice(i, 1);\n }\n }\n if (!data.aborted && task.state === SCHEDULED) {\n oriInvoke_1.call(task);\n }\n };\n loadTasks.push(task);\n }\n else {\n task.invoke();\n }\n }\n else if (!data.aborted && target[XHR_SCHEDULED] === false) {\n // error occurs when xhr.send()\n target[XHR_ERROR_BEFORE_SCHEDULED] = true;\n }\n }\n };\n oriAddListener.call(target, READY_STATE_CHANGE, newListener);\n var storedTask = target[XHR_TASK];\n if (!storedTask) {\n target[XHR_TASK] = task;\n }\n sendNative.apply(target, data.args);\n target[XHR_SCHEDULED] = true;\n return task;\n }\n function placeholderCallback() { }\n function clearTask(task) {\n var data = task.data;\n // Note - ideally, we would call data.target.removeEventListener here, but it's too late\n // to prevent it from firing. So instead, we store info for the event listener.\n data.aborted = true;\n return abortNative.apply(data.target, data.args);\n }\n var openNative = patchMethod(XMLHttpRequestPrototype, 'open', function () { return function (self, args) {\n self[XHR_SYNC] = args[2] == false;\n self[XHR_URL] = args[1];\n return openNative.apply(self, args);\n }; });\n var XMLHTTPREQUEST_SOURCE = 'XMLHttpRequest.send';\n var fetchTaskAborting = zoneSymbol('fetchTaskAborting');\n var fetchTaskScheduling = zoneSymbol('fetchTaskScheduling');\n var sendNative = patchMethod(XMLHttpRequestPrototype, 'send', function () { return function (self, args) {\n if (Zone.current[fetchTaskScheduling] === true) {\n // a fetch is scheduling, so we are using xhr to polyfill fetch\n // and because we already schedule macroTask for fetch, we should\n // not schedule a macroTask for xhr again\n return sendNative.apply(self, args);\n }\n if (self[XHR_SYNC]) {\n // if the XHR is sync there is no task to schedule, just execute the code.\n return sendNative.apply(self, args);\n }\n else {\n var options = { target: self, url: self[XHR_URL], isPeriodic: false, args: args, aborted: false };\n var task = scheduleMacroTaskWithCurrentZone(XMLHTTPREQUEST_SOURCE, placeholderCallback, options, scheduleTask, clearTask);\n if (self && self[XHR_ERROR_BEFORE_SCHEDULED] === true && !options.aborted &&\n task.state === SCHEDULED) {\n // xhr request throw error when send\n // we should invoke task instead of leaving a scheduled\n // pending macroTask\n task.invoke();\n }\n }\n }; });\n var abortNative = patchMethod(XMLHttpRequestPrototype, 'abort', function () { return function (self, args) {\n var task = findPendingTask(self);\n if (task && typeof task.type == 'string') {\n // If the XHR has already completed, do nothing.\n // If the XHR has already been aborted, do nothing.\n // Fix #569, call abort multiple times before done will cause\n // macroTask task count be negative number\n if (task.cancelFn == null || (task.data && task.data.aborted)) {\n return;\n }\n task.zone.cancelTask(task);\n }\n else if (Zone.current[fetchTaskAborting] === true) {\n // the abort is called from fetch polyfill, we need to call native abort of XHR.\n return abortNative.apply(self, args);\n }\n // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no\n // task\n // to cancel. Do nothing.\n }; });\n }\n});\nZone.__load_patch('geolocation', function (global) {\n /// GEO_LOCATION\n if (global['navigator'] && global['navigator'].geolocation) {\n patchPrototype(global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);\n }\n});\nZone.__load_patch('PromiseRejectionEvent', function (global, Zone) {\n // handle unhandled promise rejection\n function findPromiseRejectionHandler(evtName) {\n return function (e) {\n var eventTasks = findEventTasks(global, evtName);\n eventTasks.forEach(function (eventTask) {\n // windows has added unhandledrejection event listener\n // trigger the event listener\n var PromiseRejectionEvent = global['PromiseRejectionEvent'];\n if (PromiseRejectionEvent) {\n var evt = new PromiseRejectionEvent(evtName, { promise: e.promise, reason: e.rejection });\n eventTask.invoke(evt);\n }\n });\n };\n }\n if (global['PromiseRejectionEvent']) {\n Zone[zoneSymbol('unhandledPromiseRejectionHandler')] =\n findPromiseRejectionHandler('unhandledrejection');\n Zone[zoneSymbol('rejectionHandledHandler')] =\n findPromiseRejectionHandler('rejectionhandled');\n }\n});\n\n/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n})));\n","/**\r\n * This file includes polyfills needed by Angular and is loaded before the app.\r\n * You can add your own extra polyfills to this file.\r\n *\r\n * This file is divided into 2 sections:\r\n * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\r\n * 2. Application imports. Files imported after ZoneJS that should be loaded before your main\r\n * file.\r\n *\r\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\r\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\r\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\r\n *\r\n * Learn more in https://angular.io/guide/browser-support\r\n */\r\n\r\n/***************************************************************************************************\r\n * BROWSER POLYFILLS\r\n */\r\n\r\n/** IE9, IE10 and IE11 requires all of the following polyfills. **/\r\n// import 'core-js/es6/symbol';\r\n// import 'core-js/es6/object';\r\n// import 'core-js/es6/function';\r\n// import 'core-js/es6/parse-int';\r\n// import 'core-js/es6/parse-float';\r\n// import 'core-js/es6/number';\r\n// import 'core-js/es6/math';\r\n// import 'core-js/es6/string';\r\n// import 'core-js/es6/date';\r\n// import 'core-js/es6/array';\r\n// import 'core-js/es6/regexp';\r\n// import 'core-js/es6/map';\r\n// import 'core-js/es6/weak-map';\r\n// import 'core-js/es6/set';\r\n\r\n/**\r\n * If the application will be indexed by Google Search, the following is required.\r\n * Googlebot uses a renderer based on Chrome 41.\r\n * https://developers.google.com/search/docs/guides/rendering\r\n **/\r\n// import 'core-js/es6/array';\r\n\r\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\r\n// import 'classlist.js'; // Run `npm install --save classlist.js`.\r\n\r\n/** IE10 and IE11 requires the following for the Reflect API. */\r\n// import 'core-js/es6/reflect';\r\n\r\n/**\r\n * Web Animations `@angular/platform-browser/animations`\r\n * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.\r\n * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).\r\n **/\r\n// import 'web-animations-js'; // Run `npm install --save web-animations-js`.\r\n\r\n/**\r\n * By default, zone.js will patch all possible macroTask and DomEvents\r\n * user can disable parts of macroTask/DomEvents patch by setting following flags\r\n */\r\n\r\n // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame\r\n // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick\r\n // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames\r\n\r\n /*\r\n * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js\r\n * with the following flag, it will bypass `zone.js` patch for IE/Edge\r\n */\r\n// (window as any).__Zone_enable_cross_context_check = true;\r\n\r\n/***************************************************************************************************\r\n * Zone JS is required by default for Angular itself.\r\n */\r\nimport 'zone.js/dist/zone'; // Included with Angular CLI.\r\n\r\n\r\n/***************************************************************************************************\r\n * APPLICATION IMPORTS\r\n */\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/src/gui/qt-daemon/html/styles.js b/src/gui/qt-daemon/html/styles.js index 44e76846..c3a8b17a 100644 --- a/src/gui/qt-daemon/html/styles.js +++ b/src/gui/qt-daemon/html/styles.js @@ -7,7 +7,7 @@ /*! no static exports found */ /***/ (function(module, exports) { -module.exports = [[module.i, "/*\r\n* Implementation of themes\r\n*/\n.ng-select.ng-select-opened>.ng-select-container{background:#fff;border-color:#b3b3b3 #ccc #d9d9d9}\n.ng-select.ng-select-opened>.ng-select-container:hover{box-shadow:none}\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow:hover{border-color:transparent transparent #333}\n.ng-select.ng-select-opened.ng-select-bottom>.ng-select-container{border-bottom-right-radius:0;border-bottom-left-radius:0}\n.ng-select.ng-select-opened.ng-select-top>.ng-select-container{border-top-right-radius:0;border-top-left-radius:0}\n.ng-select.ng-select-focused:not(.ng-select-opened)>.ng-select-container{border-color:#007eff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 0 3px rgba(0,126,255,0.1)}\n.ng-select.ng-select-disabled>.ng-select-container{background-color:#f9f9f9}\n.ng-select .ng-has-value .ng-placeholder{display:none}\n.ng-select .ng-select-container{background-color:#fff;border-radius:4px;border:1px solid #ccc;min-height:36px;align-items:center}\n.ng-select .ng-select-container:hover{box-shadow:0 1px 0 rgba(0,0,0,0.06)}\n.ng-select .ng-select-container .ng-value-container{align-items:center;padding-left:10px}\n[dir=\"rtl\"] .ng-select .ng-select-container .ng-value-container{padding-right:10px;padding-left:0}\n.ng-select .ng-select-container .ng-value-container .ng-placeholder{color:#999}\n.ng-select.ng-select-single .ng-select-container{height:36px}\n.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{top:5px;left:0;padding-left:10px;padding-right:50px}\n[dir=\"rtl\"] .ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{padding-right:10px;padding-left:50px}\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value{background-color:#f9f9f9;border:1px solid #e6e6e6}\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-label{padding:0 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-top:5px;padding-left:7px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-right:7px;padding-left:0}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{font-size:.9em;margin-bottom:5px;background-color:#ebf5ff;border-radius:2px;margin-right:5px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{margin-right:0;margin-left:5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled{background-color:#f9f9f9}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:5px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:0;padding-right:5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-label{display:inline-block;padding:1px 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:inline-block;padding:1px 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon:hover{background-color:#d1e8ff}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-right:1px solid #b8dbff}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-left:1px solid #b8dbff;border-right:none}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:1px solid #b8dbff}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:0;border-right:1px solid #b8dbff}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 0 3px 3px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 3px 3px 0}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{top:5px;padding-bottom:5px;padding-left:3px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-right:3px;padding-left:0}\n.ng-select .ng-clear-wrapper{color:#999}\n.ng-select .ng-clear-wrapper:hover .ng-clear{color:#D0021B}\n.ng-select .ng-spinner-zone{padding:5px 5px 0 0}\n[dir=\"rtl\"] .ng-select .ng-spinner-zone{padding:5px 0 0 5px}\n.ng-select .ng-arrow-wrapper{width:25px;padding-right:5px}\n[dir=\"rtl\"] .ng-select .ng-arrow-wrapper{padding-left:5px;padding-right:0}\n.ng-select .ng-arrow-wrapper:hover .ng-arrow{border-top-color:#666}\n.ng-select .ng-arrow-wrapper .ng-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px}\n.ng-dropdown-panel{background-color:#fff;border:1px solid #ccc;box-shadow:0 1px 0 rgba(0,0,0,0.06);left:0}\n.ng-dropdown-panel.ng-select-bottom{top:100%;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top-color:#e6e6e6;margin-top:-1px}\n.ng-dropdown-panel.ng-select-bottom .ng-dropdown-panel-items .ng-option:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px}\n.ng-dropdown-panel.ng-select-top{bottom:100%;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-color:#e6e6e6;margin-bottom:-1px}\n.ng-dropdown-panel.ng-select-top .ng-dropdown-panel-items .ng-option:first-child{border-top-right-radius:4px;border-top-left-radius:4px}\n.ng-dropdown-panel .ng-dropdown-header{border-bottom:1px solid #ccc;padding:5px 7px}\n.ng-dropdown-panel .ng-dropdown-footer{border-top:1px solid #ccc;padding:5px 7px}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:8px 10px;font-weight:500;color:rgba(0,0,0,0.54);cursor:pointer}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-disabled{cursor:default}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-marked{background-color:#f5faff}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected.ng-option-marked{background-color:#ebf5ff;font-weight:600}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option{background-color:#fff;color:rgba(0,0,0,0.87);padding:8px 10px}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked{color:#333;background-color:#ebf5ff}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected .ng-option-label,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked .ng-option-label{font-weight:600}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked{background-color:#f5faff;color:#333}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-disabled{color:#ccc}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-left:22px}\n[dir=\"rtl\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-right:22px;padding-left:0}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{font-size:80%;font-weight:400;padding-right:5px}\n[dir=\"rtl\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{padding-left:5px;padding-right:0}\n[dir=\"rtl\"] .ng-dropdown-panel{direction:rtl;text-align:right}\nhtml {\n box-sizing: border-box;\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box; }\n*, *:before, *:after {\n box-sizing: inherit;\n -webkit-box-sizing: inherit;\n -moz-box-sizing: inherit;\n margin: 0;\n padding: 0;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n border: 0;\n font-size: 100%;\n font: inherit;\n vertical-align: baseline; }\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, menu, nav, section {\n display: block; }\nbody {\n line-height: 1;\n font-style: normal; }\nol, ul {\n list-style: none; }\nblockquote, q {\n quotes: none; }\nblockquote:before, blockquote:after,\nq:before, q:after {\n content: none; }\ntable {\n border-collapse: collapse;\n border-spacing: 0; }\ntd,\nth {\n padding: 0; }\ninput {\n outline: none; }\ninput:-webkit-autofill {\n -webkit-box-shadow: 0 0 0 1000px white inset; }\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n outline: none; }\nbutton[disabled],\nhtml input[disabled] {\n cursor: default; }\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0; }\ninput {\n line-height: normal; }\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box; }\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none; }\na {\n text-decoration: none; }\na:active, a:hover, a:focus {\n outline: 0; }\ni {\n font-style: italic; }\nb, strong {\n font-weight: 700; }\nimg {\n width: auto;\n max-width: 100%;\n height: auto;\n vertical-align: top;\n border: 0; }\n.hidden {\n display: none !important; }\n.theme-dark .app-content .preloader .loading-bar {\n background-color: #5cda9d; }\n.theme-gray .app-content .preloader .loading-bar {\n background-color: #47cf8d; }\n.theme-white .app-content .preloader .loading-bar {\n background-color: #46c172; }\nbutton {\n border: none;\n font-family: OpenSans, sans-serif;\n font-size: 1.5rem;\n font-weight: 600;\n outline: none;\n padding: 0 1rem;\n height: 4.2rem; }\n.theme-dark button:disabled:not(.transparent-button), .theme-dark button.blue-button_reset {\n background-color: #9cadb7;\n color: #111921; }\n.theme-gray button:disabled:not(.transparent-button), .theme-gray button.blue-button_reset {\n background-color: #79848f;\n color: #1a1a1a; }\n.theme-white button:disabled:not(.transparent-button), .theme-white button.blue-button_reset {\n background-color: #90a4ae;\n color: #fefefe; }\n.theme-dark button:disabled:not(.transparent-button):hover, .theme-dark button.blue-button_reset:hover {\n background-color: #b7d1e0; }\n.theme-gray button:disabled:not(.transparent-button):hover, .theme-gray button.blue-button_reset:hover {\n background-color: #a1aebb; }\n.theme-white button:disabled:not(.transparent-button):hover, .theme-white button.blue-button_reset:hover {\n background-color: #aebec6; }\n.theme-dark button:disabled:not(.transparent-button):focus, .theme-dark button.blue-button_reset:focus {\n background-color: #a7b9c2; }\n.theme-gray button:disabled:not(.transparent-button):focus, .theme-gray button.blue-button_reset:focus {\n background-color: #8a959f; }\n.theme-white button:disabled:not(.transparent-button):focus, .theme-white button.blue-button_reset:focus {\n background-color: #a7b9c2; }\n.theme-dark button.blue-button:not(:disabled) {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray button.blue-button:not(:disabled) {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white button.blue-button:not(:disabled) {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark button.blue-button:not(:disabled):hover {\n background-color: #82d7ff; }\n.theme-gray button.blue-button:not(:disabled):hover {\n background-color: #86d6ff; }\n.theme-white button.blue-button:not(:disabled):hover {\n background-color: #5cb3ff; }\n.theme-dark button.blue-button:not(:disabled):focus {\n background-color: #59b5fd; }\n.theme-gray button.blue-button:not(:disabled):focus {\n background-color: #5fb6fc; }\n.theme-white button.blue-button:not(:disabled):focus {\n background-color: #379ffa; }\n.theme-dark button.green-button:not(:disabled) {\n background-color: #5cda9d;\n color: #111921; }\n.theme-gray button.green-button:not(:disabled) {\n background-color: #47cf8d;\n color: #1a1a1a; }\n.theme-white button.green-button:not(:disabled) {\n background-color: #46c172;\n color: #fefefe; }\n.theme-dark button.green-button:not(:disabled):hover {\n background-color: #8dfcc6; }\n.theme-gray button.green-button:not(:disabled):hover {\n background-color: #7bf6c6; }\n.theme-white button.green-button:not(:disabled):hover {\n background-color: #5ad586; }\n.theme-dark button.green-button:not(:disabled):focus {\n background-color: #62e0b2; }\n.theme-gray button.green-button:not(:disabled):focus {\n background-color: #5cdc9e; }\n.theme-white button.green-button:not(:disabled):focus {\n background-color: #53c77c; }\n.theme-dark button.turquoise-button:not(:disabled) {\n background-color: #4dd0e1;\n color: #111921; }\n.theme-gray button.turquoise-button:not(:disabled) {\n background-color: #3ec5d7;\n color: #1a1a1a; }\n.theme-white button.turquoise-button:not(:disabled) {\n background-color: #26b6c7;\n color: #fefefe; }\n.theme-dark button.turquoise-button:not(:disabled):hover {\n background-color: #87f4f5; }\n.theme-gray button.turquoise-button:not(:disabled):hover {\n background-color: #72edfe; }\n.theme-white button.turquoise-button:not(:disabled):hover {\n background-color: #52cbd9; }\n.theme-dark button.turquoise-button:not(:disabled):focus {\n background-color: #42d5e8; }\n.theme-gray button.turquoise-button:not(:disabled):focus {\n background-color: #50d0e1; }\n.theme-white button.turquoise-button:not(:disabled):focus {\n background-color: #31becf; }\nbutton.transparent-button {\n display: flex;\n align-items: center;\n justify-content: center; }\n.theme-dark button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #2b3644;\n color: #e0e0e0; }\n.theme-gray button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #2f3438;\n color: #e0e0e0; }\n.theme-white button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #ebebeb;\n color: #43454b; }\nbutton.transparent-button .icon {\n margin-right: 1rem;\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\n mask: url('complete-testwallet.svg') no-repeat center;\n width: 1.7rem;\n height: 1.7rem; }\n.theme-dark button.transparent-button .icon {\n background-color: #e0e0e0; }\n.theme-gray button.transparent-button .icon {\n background-color: #e0e0e0; }\n.theme-white button.transparent-button .icon {\n background-color: #43454b; }\n.input-block {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.4rem; }\n.input-block .wrap-label {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n min-height: 2.4rem; }\n.input-block label {\n font-size: 1.3rem;\n line-height: 2.4rem; }\n.theme-dark .input-block label {\n color: #556576; }\n.theme-gray .input-block label {\n color: #565c62; }\n.theme-white .input-block label {\n color: #a0a5ab; }\n.input-block input[type='text'], .input-block input[type='password'], .input-block select {\n border: none;\n font-size: 1.4rem;\n outline: none;\n padding: 0 1rem;\n width: 100%;\n height: 4.2rem; }\n.theme-dark .input-block input[type='text'], .theme-dark .input-block input[type='password'], .theme-dark .input-block select {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block input[type='text'], .theme-gray .input-block input[type='password'], .theme-gray .input-block select {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block input[type='text'], .theme-white .input-block input[type='password'], .theme-white .input-block select {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block.textarea {\n height: auto; }\n.input-block.textarea textarea {\n font-family: OpenSans, sans-serif;\n border: none;\n font-size: 1.4rem;\n outline: none;\n padding: 1rem;\n width: 100%;\n min-width: 100%;\n height: 100%;\n min-height: 7.5rem;\n max-height: 7.5rem;\n overflow: auto;\n resize: none; }\n.theme-dark .input-block.textarea textarea {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block.textarea textarea {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block.textarea textarea {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block .error-block {\n font-size: 1rem;\n line-height: 1.4rem;\n align-self: flex-end;\n text-align: right; }\n.theme-dark .input-block .error-block {\n color: #ff5252; }\n.theme-gray .input-block .error-block {\n color: #ff5252; }\n.theme-white .input-block .error-block {\n color: #ff5252; }\n.theme-dark .error-text {\n color: #ff5252; }\n.theme-gray .error-text {\n color: #ff5252; }\n.theme-white .error-text {\n color: #ff5252; }\ninput[type='radio'].style-radio + label {\n display: flex;\n align-items: center;\n cursor: pointer;\n font-weight: 400;\n padding-left: 2.4rem;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n.theme-dark input[type='radio'].style-radio + label {\n color: #556576; }\n.theme-gray input[type='radio'].style-radio + label {\n color: #565c62; }\n.theme-white input[type='radio'].style-radio + label {\n color: #a0a5ab; }\ninput[type='radio'].style-radio:not(checked) {\n position: absolute;\n opacity: 0; }\ninput[type='radio'].style-radio:not(checked) + label {\n position: relative; }\ninput[type='radio'].style-radio:not(checked) + label:before {\n content: '';\n position: absolute;\n top: 0.7rem;\n left: 0;\n background: transparent;\n border-radius: 50%;\n width: 1.4rem;\n height: 1.4rem; }\n.theme-dark input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #4db1ff; }\n.theme-gray input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #42a5f5; }\n.theme-white input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #2c95f1; }\ninput[type='radio'].style-radio:not(checked) + label:after {\n content: '';\n position: absolute;\n top: 1rem;\n left: 0.3rem;\n border-radius: 50%;\n opacity: 0;\n width: 0.8rem;\n height: 0.8rem; }\n.theme-dark input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #4db1ff; }\n.theme-gray input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #42a5f5; }\n.theme-white input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #2c95f1; }\ninput[type='radio'].style-radio:checked + label:after {\n opacity: 1; }\ninput[type='checkbox'].style-checkbox + label {\n display: flex;\n align-items: center;\n cursor: pointer;\n font-weight: 400;\n padding-left: 3.6rem;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n.theme-dark input[type='checkbox'].style-checkbox + label {\n color: #556576; }\n.theme-gray input[type='checkbox'].style-checkbox + label {\n color: #565c62; }\n.theme-white input[type='checkbox'].style-checkbox + label {\n color: #a0a5ab; }\ninput[type='checkbox'].style-checkbox:not(checked) {\n position: absolute;\n top: 50%;\n left: 1.6rem;\n transform: translateY(-50%);\n visibility: hidden; }\ninput[type='checkbox'].style-checkbox:not(checked) + label {\n position: relative; }\ninput[type='checkbox'].style-checkbox:not(checked) + label:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 1.6rem;\n transform: translateY(-50%);\n background: transparent;\n width: 1.4rem;\n height: 1.4rem; }\n.theme-dark input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #4db1ff; }\n.theme-gray input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #42a5f5; }\n.theme-white input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #2c95f1; }\ninput[type='checkbox'].style-checkbox:checked + label:before {\n background: url('complete-testwallet.svg'); }\n.theme-dark input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #4db1ff; }\n.theme-gray input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #42a5f5; }\n.theme-white input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #2c95f1; }\n.theme-dark .switch {\n background-color: #000000; }\n.theme-gray .switch {\n background-color: #000000; }\n.theme-white .switch {\n background-color: #e0e0e0; }\n.theme-dark .switch .circle.on {\n background-color: #4db1ff; }\n.theme-gray .switch .circle.on {\n background-color: #42a5f5; }\n.theme-white .switch .circle.on {\n background-color: #2c95f1; }\n.theme-dark .switch .circle.off {\n background-color: #556576; }\n.theme-gray .switch .circle.off {\n background-color: #565c62; }\n.theme-white .switch .circle.off {\n background-color: #a0a5ab; }\n.table-tooltip {\n padding: 1rem 2rem; }\n.theme-dark .table-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .table-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .table-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.table-tooltip .tooltip-inner {\n font-size: 1.3rem;\n line-height: 1.8rem;\n white-space: pre-wrap; }\n.table-tooltip.ng-tooltip-top {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n left: calc(50% - 0.5rem);\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top:after {\n border-color: #42505f transparent transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-top:after {\n border-color: #3e464c transparent transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-top:after {\n border-color: #ffffff transparent transparent transparent; }\n.table-tooltip.ng-tooltip-top-left {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top-left:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n left: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top-left:after {\n border-color: #42505f transparent transparent #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-top-left:after {\n border-color: #3e464c transparent transparent #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-top-left:after {\n border-color: #ffffff transparent transparent #ffffff; }\n.table-tooltip.ng-tooltip-top-right {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top-right:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n right: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top-right:after {\n border-color: #42505f #42505f transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-top-right:after {\n border-color: #3e464c #3e464c transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-top-right:after {\n border-color: #ffffff #ffffff transparent transparent; }\n.table-tooltip.ng-tooltip-bottom {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n left: calc(50% - 0.5rem);\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #42505f transparent; }\n.theme-gray .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #3e464c transparent; }\n.theme-white .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #ffffff transparent; }\n.table-tooltip.ng-tooltip-bottom-left {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom-left:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n left: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #42505f #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #3e464c #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #ffffff #ffffff; }\n.table-tooltip.ng-tooltip-bottom-right {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom-right:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n right: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #42505f #42505f transparent; }\n.theme-gray .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #3e464c #3e464c transparent; }\n.theme-white .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #ffffff #ffffff transparent; }\n.table-tooltip.ng-tooltip-left {\n margin-left: -1rem; }\n.table-tooltip.ng-tooltip-left:after {\n content: \"\";\n position: absolute;\n top: calc(50% - 0.5rem);\n right: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #ffffff; }\n.table-tooltip.ng-tooltip-right {\n margin-left: 1rem; }\n.table-tooltip.ng-tooltip-right:before {\n content: \"\";\n position: absolute;\n top: calc(50% - 0.5rem);\n left: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #42505f transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #3e464c transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #ffffff transparent transparent; }\n.table-tooltip-dimensions .tooltip-inner {\n overflow: auto;\n max-width: 20rem;\n max-height: 10rem; }\n.balance-tooltip {\n padding: 1.3rem; }\n.theme-dark .balance-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .balance-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .balance-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.balance-tooltip .tooltip-inner {\n display: flex;\n flex-direction: column;\n font-size: 1.3rem; }\n.balance-tooltip .tooltip-inner .available {\n margin-bottom: 1.7rem; }\n.balance-tooltip .tooltip-inner .available b {\n font-weight: 600; }\n.balance-tooltip .tooltip-inner .locked {\n margin-bottom: 0.7rem; }\n.balance-tooltip .tooltip-inner .locked b {\n font-weight: 600; }\n.balance-tooltip .tooltip-inner .link {\n cursor: pointer; }\n.theme-dark .balance-tooltip .tooltip-inner .link {\n color: #4db1ff; }\n.theme-gray .balance-tooltip .tooltip-inner .link {\n color: #42a5f5; }\n.theme-white .balance-tooltip .tooltip-inner .link {\n color: #2c95f1; }\n.balance-tooltip.ng-tooltip-top {\n margin-top: -1rem; }\n.balance-tooltip.ng-tooltip-bottom {\n margin-top: 1rem; }\n.balance-tooltip.ng-tooltip-left {\n margin-left: -1rem; }\n.balance-tooltip.ng-tooltip-right {\n margin-left: 1rem; }\n.account-tooltip .tooltip-inner {\n word-break: break-word;\n max-width: 18rem; }\n.comment-tooltip .tooltip-inner {\n overflow: auto;\n word-break: break-word;\n max-width: 50rem;\n max-height: 25rem; }\n.update-tooltip {\n padding: 1.5rem; }\n.theme-dark .update-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .update-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .update-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.theme-dark .update-tooltip.important {\n background: #5f2b11;\n color: #e0e0e0; }\n.theme-gray .update-tooltip.important {\n background: #55240d;\n color: #e0e0e0; }\n.theme-white .update-tooltip.important {\n background: #ef6c00;\n color: #ffffff; }\n.theme-dark .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #5f2b11 #5f2b11; }\n.theme-gray .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #55240d #55240d; }\n.theme-white .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #ef6c00 #ef6c00; }\n.theme-dark .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #5f2b11 #5f2b11 transparent; }\n.theme-gray .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #55240d #55240d transparent; }\n.theme-white .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #ef6c00 #ef6c00 transparent; }\n.update-tooltip.critical {\n padding: 2.5rem; }\n.theme-dark .update-tooltip.critical {\n background: #5f1d1d;\n color: #e0e0e0; }\n.theme-gray .update-tooltip.critical {\n background: #4c1919;\n color: #e0e0e0; }\n.theme-white .update-tooltip.critical {\n background: #e53935;\n color: #ffffff; }\n.update-tooltip.critical .tooltip-inner {\n display: flex;\n flex-direction: column;\n align-items: center; }\n.theme-dark .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #5f1d1d #5f1d1d; }\n.theme-gray .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #4c1919 #4c1919; }\n.theme-white .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #e53935 #e53935; }\n.theme-dark .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #5f1d1d #5f1d1d transparent; }\n.theme-gray .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #4c1919 #4c1919 transparent; }\n.theme-white .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #e53935 #e53935 transparent; }\n.update-tooltip .tooltip-inner {\n font-size: 1.3rem;\n line-height: 1.8rem;\n white-space: pre-wrap; }\n.update-tooltip .tooltip-inner .standard-update {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .standard-update {\n color: #4db1ff; }\n.theme-gray .update-tooltip .tooltip-inner .standard-update {\n color: #42a5f5; }\n.theme-white .update-tooltip .tooltip-inner .standard-update {\n color: #2c95f1; }\n.update-tooltip .tooltip-inner .important-update {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .important-update {\n color: #ff6f00; }\n.theme-gray .update-tooltip .tooltip-inner .important-update {\n color: #ff6f00; }\n.theme-white .update-tooltip .tooltip-inner .important-update {\n color: #ffffff; }\n.update-tooltip .tooltip-inner .critical-update {\n font-size: 1.5rem;\n line-height: 2.7rem;\n text-align: center; }\n.update-tooltip .tooltip-inner .wrong-time {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .wrong-time {\n color: #ff6f00; }\n.theme-gray .update-tooltip .tooltip-inner .wrong-time {\n color: #ff6f00; }\n.theme-white .update-tooltip .tooltip-inner .wrong-time {\n color: #ffffff; }\n.update-tooltip .tooltip-inner .icon {\n margin: 1.5rem 0;\n width: 5rem;\n height: 5rem; }\n.theme-dark .update-tooltip .tooltip-inner .icon {\n background-color: #ff5252; }\n.theme-gray .update-tooltip .tooltip-inner .icon {\n background-color: #ff5252; }\n.theme-white .update-tooltip .tooltip-inner .icon {\n background-color: #ffffff; }\n.update-tooltip.ng-tooltip-left-bottom {\n margin-left: -1.5rem; }\n.update-tooltip.ng-tooltip-left-bottom:after {\n content: \"\";\n position: absolute;\n bottom: 0.6rem;\n right: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #42505f #42505f; }\n.theme-gray .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #3e464c #3e464c; }\n.theme-white .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #ffffff #ffffff; }\n.update-tooltip.ng-tooltip-right-bottom {\n margin-left: 1.5rem; }\n.update-tooltip.ng-tooltip-right-bottom:before {\n content: \"\";\n position: absolute;\n bottom: 0.6rem;\n left: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #42505f #42505f transparent; }\n.theme-gray .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #3e464c #3e464c transparent; }\n.theme-white .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #ffffff #ffffff transparent; }\n.ngx-contextmenu .dropdown-menu {\n border: none;\n padding: 0; }\n.theme-dark .ngx-contextmenu .dropdown-menu {\n background-color: #2b3644;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\n.theme-gray .ngx-contextmenu .dropdown-menu {\n background-color: #292d31;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\n.theme-white .ngx-contextmenu .dropdown-menu {\n background-color: #e0e0e0;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5); }\n.ngx-contextmenu li {\n display: block;\n font-family: OpenSans, sans-serif;\n font-size: 1.3rem;\n text-transform: uppercase;\n text-align: center; }\n.ngx-contextmenu a {\n display: block;\n padding: 0.5em 1em; }\n.theme-dark .ngx-contextmenu a {\n color: #e0e0e0; }\n.theme-gray .ngx-contextmenu a {\n color: #e0e0e0; }\n.theme-white .ngx-contextmenu a {\n color: #43454b; }\n.theme-dark .ngx-contextmenu a:hover {\n background-color: #556576;\n color: #e0e0e0; }\n.theme-gray .ngx-contextmenu a:hover {\n background-color: #515960;\n color: #e0e0e0; }\n.theme-white .ngx-contextmenu a:hover {\n background-color: #ffffff;\n color: #43454b; }\n.ng-select.custom-select {\n width: 100%; }\n.ng-select.custom-select.ng-select-single .ng-select-container .ng-value-container .ng-value {\n line-height: 1.8rem; }\n.ng-select.custom-select .ng-select-container {\n border: none;\n border-radius: 0;\n cursor: pointer;\n font-size: 1.4rem;\n outline: none;\n padding: 0 1rem;\n height: 4.2rem; }\n.theme-dark .ng-select.custom-select .ng-select-container {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-select-container {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-select-container {\n background-color: #e6e6e6;\n color: #43454b; }\n.ng-select.custom-select .ng-select-container .ng-value-container {\n padding: 0; }\n.ng-select.custom-select .ng-select-container .ng-value-container .ng-input {\n top: auto; }\n.ng-select.custom-select .ng-dropdown-panel {\n border: none; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel {\n background-color: #171e27; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel {\n background-color: #292d31; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel {\n background-color: #e6e6e6; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n font-size: 1.4rem;\n padding: 1rem; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #e6e6e6;\n color: #43454b; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(58, 69, 85, 0.5);\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(58, 62, 66, 0.5);\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(240, 240, 240, 0.5);\n color: #43454b; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(224, 224, 224, 0.5);\n color: #43454b; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar {\n background-color: transparent;\n cursor: default;\n width: 1rem;\n height: 1rem; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-track {\n background: transparent; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb {\n background-color: #556576;\n background-clip: padding-box;\n border: 0.25rem solid transparent;\n border-radius: 0.5rem; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb:hover {\n background-color: #556576; }\n.theme-dark app-modal-container .modal, .theme-dark app-confirm-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-modal-container .modal, .theme-gray app-confirm-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-modal-container .modal, .theme-white app-confirm-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-modal-container .modal .content .icon.error, .theme-dark app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-gray app-modal-container .modal .content .icon.error, .theme-gray app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-white app-modal-container .modal .content .icon.error, .theme-white app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-dark app-modal-container .modal .content .icon.success, .theme-dark app-confirm-modal .modal .content .icon.success {\n background-color: #5cda9d; }\n.theme-gray app-modal-container .modal .content .icon.success, .theme-gray app-confirm-modal .modal .content .icon.success {\n background-color: #47cf8d; }\n.theme-white app-modal-container .modal .content .icon.success, .theme-white app-confirm-modal .modal .content .icon.success {\n background-color: #46c172; }\n.theme-dark app-modal-container .modal .content .icon.info, .theme-dark app-confirm-modal .modal .content .icon.info {\n background-color: #4db1ff; }\n.theme-gray app-modal-container .modal .content .icon.info, .theme-gray app-confirm-modal .modal .content .icon.info {\n background-color: #42a5f5; }\n.theme-white app-modal-container .modal .content .icon.info, .theme-white app-confirm-modal .modal .content .icon.info {\n background-color: #2c95f1; }\n.theme-dark app-modal-container .modal .action-button, .theme-dark app-confirm-modal .modal .action-button {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-modal-container .modal .action-button, .theme-gray app-confirm-modal .modal .action-button {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-modal-container .modal .action-button, .theme-white app-confirm-modal .modal .action-button {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark app-modal-container .modal .close-button .icon, .theme-dark app-confirm-modal .modal .close-button .icon {\n background-color: #556576; }\n.theme-gray app-modal-container .modal .close-button .icon, .theme-gray app-confirm-modal .modal .close-button .icon {\n background-color: #515960; }\n.theme-white app-modal-container .modal .close-button .icon, .theme-white app-confirm-modal .modal .close-button .icon {\n background-color: #43454b; }\n.theme-dark app-transaction-details .table {\n border-top: 0.2rem solid #2b3644; }\n.theme-gray app-transaction-details .table {\n border-top: 0.2rem solid #2f3438; }\n.theme-white app-transaction-details .table {\n border-top: 0.2rem solid #ebebeb; }\n.theme-dark app-transaction-details .table .row .cell.label {\n color: #556576; }\n.theme-gray app-transaction-details .table .row .cell.label {\n color: #565c62; }\n.theme-white app-transaction-details .table .row .cell.label {\n color: #a0a5ab; }\n.theme-dark app-transaction-details .table .row .cell.value {\n color: #e0e0e0; }\n.theme-gray app-transaction-details .table .row .cell.value {\n color: #e0e0e0; }\n.theme-white app-transaction-details .table .row .cell.value {\n color: #43454b; }\n.theme-dark app-transaction-details .table .row .cell.key-value {\n color: #4db1ff; }\n.theme-gray app-transaction-details .table .row .cell.key-value {\n color: #42a5f5; }\n.theme-white app-transaction-details .table .row .cell.key-value {\n color: #2c95f1; }\n.theme-dark app-progress-container .progress-bar-container {\n color: #e0e0e0; }\n.theme-gray app-progress-container .progress-bar-container {\n color: #e0e0e0; }\n.theme-white app-progress-container .progress-bar-container {\n color: #43454b; }\n.theme-dark app-progress-container .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-progress-container .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-progress-container .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #5cda9d; }\n.theme-gray app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #47cf8d; }\n.theme-white app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #46c172; }\n.theme-dark app-open-wallet-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-open-wallet-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-open-wallet-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-send-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-send-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-send-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-send-modal .modal .title {\n border-bottom: 0.2rem solid #2b3644; }\n.theme-gray app-send-modal .modal .title {\n border-bottom: 0.2rem solid #2f3438; }\n.theme-white app-send-modal .modal .title {\n border-bottom: 0.2rem solid #ebebeb; }\n.theme-dark app-send-modal .modal .action-button {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-send-modal .modal .action-button {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-send-modal .modal .action-button {\n background-color: #2c95f1;\n color: #fefefe; }\napp-main, app-create-wallet, app-open-wallet, app-restore-wallet, app-seed-phrase, app-wallet-details, app-assign-alias, app-edit-alias, app-transfer-alias, app-settings, app-login {\n flex: 1 1 auto;\n padding: 3rem;\n min-width: 85rem; }\napp-main .content, app-create-wallet .content, app-open-wallet .content, app-restore-wallet .content, app-seed-phrase .content, app-wallet-details .content, app-assign-alias .content, app-edit-alias .content, app-transfer-alias .content, app-settings .content, app-login .content {\n position: relative;\n padding: 3rem;\n min-height: 100%; }\n.theme-dark app-main .content, .theme-dark app-create-wallet .content, .theme-dark app-open-wallet .content, .theme-dark app-restore-wallet .content, .theme-dark app-seed-phrase .content, .theme-dark app-wallet-details .content, .theme-dark app-assign-alias .content, .theme-dark app-edit-alias .content, .theme-dark app-transfer-alias .content, .theme-dark app-settings .content, .theme-dark app-login .content {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-main .content, .theme-gray app-create-wallet .content, .theme-gray app-open-wallet .content, .theme-gray app-restore-wallet .content, .theme-gray app-seed-phrase .content, .theme-gray app-wallet-details .content, .theme-gray app-assign-alias .content, .theme-gray app-edit-alias .content, .theme-gray app-transfer-alias .content, .theme-gray app-settings .content, .theme-gray app-login .content {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-main .content, .theme-white app-create-wallet .content, .theme-white app-open-wallet .content, .theme-white app-restore-wallet .content, .theme-white app-seed-phrase .content, .theme-white app-wallet-details .content, .theme-white app-assign-alias .content, .theme-white app-edit-alias .content, .theme-white app-transfer-alias .content, .theme-white app-settings .content, .theme-white app-login .content {\n background-color: rgba(255, 255, 255, 0.5);\n color: #43454b; }\napp-main .content .head, app-create-wallet .content .head, app-open-wallet .content .head, app-restore-wallet .content .head, app-seed-phrase .content .head, app-wallet-details .content .head, app-assign-alias .content .head, app-edit-alias .content .head, app-transfer-alias .content .head, app-settings .content .head, app-login .content .head {\n position: absolute;\n top: 0;\n left: 0; }\n.theme-dark app-main .content .add-wallet .add-wallet-help {\n color: #4db1ff; }\n.theme-gray app-main .content .add-wallet .add-wallet-help {\n color: #42a5f5; }\n.theme-white app-main .content .add-wallet .add-wallet-help {\n color: #2c95f1; }\n.theme-dark app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #4db1ff; }\n.theme-gray app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #42a5f5; }\n.theme-white app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #2c95f1; }\n.theme-dark app-seed-phrase .seed-phrase-content {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray app-seed-phrase .seed-phrase-content {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white app-seed-phrase .seed-phrase-content {\n background-color: #e6e6e6;\n color: #43454b; }\n.theme-dark app-wallet-details .seed-phrase {\n background-color: #171e27; }\n.theme-gray app-wallet-details .seed-phrase {\n background-color: #292d31; }\n.theme-white app-wallet-details .seed-phrase {\n background-color: #e6e6e6; }\napp-settings .content {\n height: 100%;\n overflow-y: auto;\n display: flex;\n justify-content: space-between;\n flex-direction: column; }\n.theme-dark app-settings .content .theme-selection {\n color: #556576; }\n.theme-gray app-settings .content .theme-selection {\n color: #565c62; }\n.theme-white app-settings .content .theme-selection {\n color: #a0a5ab; }\n.theme-dark app-settings .content .scale-selection .button-block {\n background-color: rgba(23, 31, 39, 0.5); }\n.theme-gray app-settings .content .scale-selection .button-block {\n background-color: rgba(28, 30, 33, 0.5); }\n.theme-white app-settings .content .scale-selection .button-block {\n background-color: rgba(224, 224, 224, 0.5); }\n.theme-dark app-settings .content .scale-selection .button-block .label {\n color: #556576; }\n.theme-gray app-settings .content .scale-selection .button-block .label {\n color: #565c62; }\n.theme-white app-settings .content .scale-selection .button-block .label {\n color: #a0a5ab; }\n.theme-dark app-settings .content .scale-selection .button-block.active {\n background-color: #4db1ff; }\n.theme-gray app-settings .content .scale-selection .button-block.active {\n background-color: #42a5f5; }\n.theme-white app-settings .content .scale-selection .button-block.active {\n background-color: #2c95f1; }\n.theme-dark app-settings .content .scale-selection .button-block.active .label {\n color: #4db1ff; }\n.theme-gray app-settings .content .scale-selection .button-block.active .label {\n color: #42a5f5; }\n.theme-white app-settings .content .scale-selection .button-block.active .label {\n color: #2c95f1; }\napp-login {\n min-width: inherit; }\n.theme-dark app-sidebar {\n background-color: #171f27; }\n.theme-gray app-sidebar {\n background-color: #1c1e21; }\n.theme-white app-sidebar {\n background-color: white; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: #1e88e5;\n color: #ffffff; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #91baf1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #000000;\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #000000;\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #91baf1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(240, 240, 240, 0.5); }\n.theme-dark app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, #171f27 100%); }\n.theme-gray app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, #1c1e21 100%); }\n.theme-white app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, white 100%); }\n.theme-dark app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #1f2833; }\n.theme-gray app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #2e3337; }\n.theme-white app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #ebebeb; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button button {\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button button {\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-settings .wrap-button button {\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: rgba(43, 54, 68, 0.5) !important;\n color: #e0e0e0 !important; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: rgba(37, 40, 43, 0.5) !important;\n color: #e0e0e0 !important; }\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: #1e88e5 !important;\n color: #ffffff !important; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #4db1ff !important; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #42a5f5 !important; }\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #ffffff !important; }\n.theme-dark app-sidebar .sidebar-synchronization-status {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-synchronization-status {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-synchronization-status {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #363a3e; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #42a5f5; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-dark app-wallet {\n color: #e0e0e0; }\n.theme-gray app-wallet {\n color: #e0e0e0; }\n.theme-white app-wallet {\n color: #43454b; }\n.theme-dark app-wallet .header button {\n color: #e0e0e0; }\n.theme-gray app-wallet .header button {\n color: #e0e0e0; }\n.theme-white app-wallet .header button {\n color: #43454b; }\n.theme-dark app-wallet .header button .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .header button .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .header button .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .header .alias .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .header .alias .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .header .alias .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .address {\n color: #4db1ff; }\n.theme-gray app-wallet .address {\n color: #42a5f5; }\n.theme-white app-wallet .address {\n color: #2c95f1; }\n.theme-dark app-wallet .address .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .address .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .address .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .tabs .tabs-header .tab {\n background-color: rgba(23, 31, 39, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab {\n background-color: rgba(28, 30, 33, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab {\n background-color: rgba(224, 224, 224, 0.5); }\n.theme-dark app-wallet .tabs .tabs-header .tab .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .tabs .tabs-header .tab .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .tabs .tabs-header .tab .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(43, 54, 68, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(37, 40, 43, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(255, 255, 255, 0.5); }\n.theme-dark app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: #ffffff; }\n.theme-dark app-wallet .tabs .tabs-content {\n background-color: rgba(43, 54, 68, 0.5); }\n.theme-gray app-wallet .tabs .tabs-content {\n background-color: rgba(37, 40, 43, 0.5); }\n.theme-white app-wallet .tabs .tabs-content {\n background-color: rgba(255, 255, 255, 0.5); }\n.theme-dark app-send .form-send .send-select {\n color: #e0e0e0; }\n.theme-gray app-send .form-send .send-select {\n color: #e0e0e0; }\n.theme-white app-send .form-send .send-select {\n color: #43454b; }\n.theme-dark app-send .form-send .send-select .icon {\n background-color: #4db1ff; }\n.theme-gray app-send .form-send .send-select .icon {\n background-color: #42a5f5; }\n.theme-white app-send .form-send .send-select .icon {\n background-color: #2c95f1; }\n.theme-dark app-send .form-send .additional-details {\n border: 0.2rem solid #2b3644; }\n.theme-gray app-send .form-send .additional-details {\n border: 0.2rem solid #2f3438; }\n.theme-white app-send .form-send .additional-details {\n border: 0.2rem solid #ebebeb; }\n.theme-dark app-receive .btn-copy-address {\n background-color: #4db1ff; }\n.theme-gray app-receive .btn-copy-address {\n background-color: #42a5f5; }\n.theme-white app-receive .btn-copy-address {\n background-color: #2c95f1; }\n.theme-dark app-history table tbody tr.locked-transaction {\n color: #556576; }\n.theme-gray app-history table tbody tr.locked-transaction {\n color: #565c62; }\n.theme-white app-history table tbody tr.locked-transaction {\n color: #a0a5ab; }\n.theme-dark app-history table tbody tr:nth-child(4n+1) {\n background-color: #18202a; }\n.theme-gray app-history table tbody tr:nth-child(4n+1) {\n background-color: #25292d; }\n.theme-white app-history table tbody tr:nth-child(4n+1) {\n background-color: #ffffff; }\n.theme-dark app-history table tbody tr:nth-child(4n+2) {\n background-color: #18202a; }\n.theme-gray app-history table tbody tr:nth-child(4n+2) {\n background-color: #25292d; }\n.theme-white app-history table tbody tr:nth-child(4n+2) {\n background-color: #ffffff; }\n.theme-dark app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-gray app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-white app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-dark app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-gray app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-white app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-dark app-history table tbody tr .status .confirmation {\n background-color: #343f4a; }\n.theme-gray app-history table tbody tr .status .confirmation {\n background-color: #363a3e; }\n.theme-white app-history table tbody tr .status .confirmation {\n background-color: #dcdcdc; }\n.theme-dark app-history table tbody tr .status .confirmation .fill {\n background-color: #5cda9d; }\n.theme-gray app-history table tbody tr .status .confirmation .fill {\n background-color: #47cf8d; }\n.theme-white app-history table tbody tr .status .confirmation .fill {\n background-color: #46c172; }\n.theme-dark app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-gray app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-white app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-dark app-history table tbody tr .unlock-transaction {\n background-color: #4db1ff; }\n.theme-gray app-history table tbody tr .unlock-transaction {\n background-color: #42a5f5; }\n.theme-white app-history table tbody tr .unlock-transaction {\n background-color: #2c95f1; }\n.theme-dark app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-gray app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-white app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-dark app-history table tbody tr .status.received .status-transaction {\n background-color: #5cda9d; }\n.theme-gray app-history table tbody tr .status.received .status-transaction {\n background-color: #47cf8d; }\n.theme-white app-history table tbody tr .status.received .status-transaction {\n background-color: #46c172; }\n.theme-dark app-contracts .wrap-table .contract .icon.new, .theme-dark app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-gray app-contracts .wrap-table .contract .icon.new, .theme-gray app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-white app-contracts .wrap-table .contract .icon.new, .theme-white app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-dark app-contracts .wrap-table .contract .icon.purchase, .theme-dark app-contracts .wrap-table .contract .icon.sell {\n background-color: #4db1ff; }\n.theme-gray app-contracts .wrap-table .contract .icon.purchase, .theme-gray app-contracts .wrap-table .contract .icon.sell {\n background-color: #42a5f5; }\n.theme-white app-contracts .wrap-table .contract .icon.purchase, .theme-white app-contracts .wrap-table .contract .icon.sell {\n background-color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .purchase-select {\n color: #e0e0e0; }\n.theme-gray app-purchase .form-purchase .purchase-select {\n color: #e0e0e0; }\n.theme-white app-purchase .form-purchase .purchase-select {\n color: #43454b; }\n.theme-dark app-purchase .form-purchase .purchase-select .icon {\n background-color: #4db1ff; }\n.theme-gray app-purchase .form-purchase .purchase-select .icon {\n background-color: #42a5f5; }\n.theme-white app-purchase .form-purchase .purchase-select .icon {\n background-color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .purchase-states {\n color: #4db1ff; }\n.theme-gray app-purchase .form-purchase .purchase-states {\n color: #42a5f5; }\n.theme-white app-purchase .form-purchase .purchase-states {\n color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #2b3644; }\n.theme-gray app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #2f3438; }\n.theme-white app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #ebebeb; }\n.theme-dark app-purchase .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-purchase .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-purchase .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #5cda9d; }\n.theme-gray app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #47cf8d; }\n.theme-white app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #46c172; }\napp-messages table tbody tr td:first-child span {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n.theme-dark app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-gray app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-white app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-dark app-typing-message .head .interlocutor {\n color: #4db1ff; }\n.theme-gray app-typing-message .head .interlocutor {\n color: #42a5f5; }\n.theme-white app-typing-message .head .interlocutor {\n color: #2c95f1; }\n.theme-dark app-typing-message .messages-content .messages-list div.date {\n color: #556576; }\n.theme-gray app-typing-message .messages-content .messages-list div.date {\n color: #565c62; }\n.theme-white app-typing-message .messages-content .messages-list div.date {\n color: #a0a5ab; }\n.theme-dark app-typing-message .messages-content .messages-list div.my {\n background-color: #2a3544; }\n.theme-gray app-typing-message .messages-content .messages-list div.my {\n background-color: #30363c; }\n.theme-white app-typing-message .messages-content .messages-list div.my {\n background-color: #fff; }\napp-typing-message .messages-content .messages-list div.my:before {\n content: \"\";\n display: block;\n position: absolute;\n top: 0;\n left: -1.1rem;\n border: 1.2rem solid transparent; }\n.theme-dark app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #2a3544; }\n.theme-gray app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #30363c; }\n.theme-white app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #fff; }\n.theme-dark app-typing-message .messages-content .messages-list div.buddy {\n background-color: #18202a; }\n.theme-gray app-typing-message .messages-content .messages-list div.buddy {\n background-color: #25292d; }\n.theme-white app-typing-message .messages-content .messages-list div.buddy {\n background-color: #ededed; }\napp-typing-message .messages-content .messages-list div.buddy:after {\n content: \"\";\n display: block;\n position: absolute;\n right: -1.1rem;\n top: 0;\n border: 1.2rem solid transparent; }\n.theme-dark app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #18202a; }\n.theme-gray app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #25292d; }\n.theme-white app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #ededed; }\n.theme-dark app-staking .chart-header .general .label {\n color: #556576; }\n.theme-gray app-staking .chart-header .general .label {\n color: #565c62; }\n.theme-white app-staking .chart-header .general .label {\n color: #a0a5ab; }\n.theme-dark app-staking .chart-header .general .options {\n color: #e0e0e0; }\n.theme-gray app-staking .chart-header .general .options {\n color: #e0e0e0; }\n.theme-white app-staking .chart-header .general .options {\n color: #43454b; }\napp-staking .chart-header .selected {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n flex-grow: 1;\n font-size: 1.6rem; }\n.theme-dark app-staking .chart-options .title {\n color: #556576; }\n.theme-gray app-staking .chart-options .title {\n color: #565c62; }\n.theme-white app-staking .chart-options .title {\n color: #a0a5ab; }\n.theme-dark app-staking .chart-options .options button {\n color: #e0e0e0;\n background-color: #2b3644; }\n.theme-gray app-staking .chart-options .options button {\n color: #e0e0e0;\n background-color: #292d31; }\n.theme-white app-staking .chart-options .options button {\n color: #43454b;\n background-color: #e0e0e0; }\n.theme-dark app-staking .chart-options .options button.active {\n background-color: #556576; }\n.theme-gray app-staking .chart-options .options button.active {\n background-color: #515960; }\n.theme-white app-staking .chart-options .options button.active {\n background-color: #ffffff; }\n.input-block-alias {\n position: relative; }\n.input-block-alias .alias-dropdown {\n position: absolute;\n top: 6.5rem;\n max-height: 10rem;\n overflow: auto;\n width: 100%; }\n.theme-dark .input-block-alias .alias-dropdown {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block-alias .alias-dropdown {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block-alias .alias-dropdown {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block-alias .alias-dropdown div {\n font-size: 1.4rem;\n padding: 1rem; }\n.theme-dark .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(240, 240, 240, 0.5); }\napp-contacts, app-add-contacts,\napp-contact-send, app-export-import {\n flex: 1 1 auto;\n padding: 3rem;\n min-width: 85rem; }\napp-contacts .content, app-add-contacts .content,\n app-contact-send .content, app-export-import .content {\n position: relative;\n padding: 3rem;\n min-height: 100%; }\n.theme-dark app-contacts .content, .theme-dark app-add-contacts .content, .theme-dark\n app-contact-send .content, .theme-dark app-export-import .content {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-contacts .content, .theme-gray app-add-contacts .content, .theme-gray\n app-contact-send .content, .theme-gray app-export-import .content {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-contacts .content, .theme-white app-add-contacts .content, .theme-white\n app-contact-send .content, .theme-white app-export-import .content {\n background-color: rgba(255, 255, 255, 0.5);\n color: #43454b; }\napp-contacts .content .head, app-add-contacts .content .head,\n app-contact-send .content .head, app-export-import .content .head {\n position: absolute;\n top: 0;\n left: 0; }\n.theme-dark app-contacts table .alias {\n color: #4db1ff; }\n.theme-gray app-contacts table .alias {\n color: #42a5f5; }\n.theme-white app-contacts table .alias {\n color: #2c95f1; }\n.theme-dark app-contacts table button .icon {\n background-color: #4db1ff; }\n.theme-gray app-contacts table button .icon {\n background-color: #42a5f5; }\n.theme-white app-contacts table button .icon {\n background-color: #2c95f1; }\n.theme-dark app-contacts table button span {\n color: #e0e0e0; }\n.theme-gray app-contacts table button span {\n color: #e0e0e0; }\n.theme-white app-contacts table button span {\n color: #43454b; }\n.theme-dark app-contacts .footer {\n color: #4db1ff; }\n.theme-gray app-contacts .footer {\n color: #42a5f5; }\n.theme-white app-contacts .footer {\n color: #2c95f1; }\n.theme-dark app-contacts .footer .import-btn {\n color: #4db1ff; }\n.theme-gray app-contacts .footer .import-btn {\n color: #42a5f5; }\n.theme-white app-contacts .footer .import-btn {\n color: #2c95f1; }\n.theme-dark app-contacts .footer .import-btn .icon {\n background-color: #4db1ff; }\n.theme-gray app-contacts .footer .import-btn .icon {\n background-color: #42a5f5; }\n.theme-white app-contacts .footer .import-btn .icon {\n background-color: #2c95f1; }\n.theme-dark app-contact-send .wallets-selection button {\n color: #4db1ff; }\n.theme-gray app-contact-send .wallets-selection button {\n color: #42a5f5; }\n.theme-white app-contact-send .wallets-selection button {\n color: #2c95f1; }\n.head {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n font-size: 1.3rem;\n padding: 0 3rem;\n width: 100%;\n height: 3rem; }\n.theme-dark .head {\n color: #4db1ff; }\n.theme-gray .head {\n color: #42a5f5; }\n.theme-white .head {\n color: #2c95f1; }\n.head .breadcrumbs > span:not(:last-child), .head .breadcrumbs a:not(:last-child) {\n position: relative;\n cursor: pointer;\n margin-right: 20px;\n outline-style: none; }\n.head .breadcrumbs > span:not(:last-child):after, .head .breadcrumbs a:not(:last-child):after {\n content: \"\";\n display: block;\n position: absolute;\n top: 0.5rem;\n right: -1.5rem;\n width: 0.9rem;\n height: 0.9rem;\n -webkit-mask: url('arrow-right.svg') no-repeat center;\n mask: url('arrow-right.svg') no-repeat center;\n -webkit-mask-size: cover;\n mask-size: cover; }\n.theme-dark .head .breadcrumbs > span:not(:last-child):after, .theme-dark .head .breadcrumbs a:not(:last-child):after {\n background-color: #4db1ff; }\n.theme-gray .head .breadcrumbs > span:not(:last-child):after, .theme-gray .head .breadcrumbs a:not(:last-child):after {\n background-color: #42a5f5; }\n.theme-white .head .breadcrumbs > span:not(:last-child):after, .theme-white .head .breadcrumbs a:not(:last-child):after {\n background-color: #2c95f1; }\n.head .back-btn {\n display: flex;\n align-items: center;\n background-color: transparent;\n color: #4db1ff;\n font-size: inherit;\n font-weight: 400;\n line-height: 1.3rem;\n padding: 0;\n height: auto; }\n.head .back-btn .icon {\n margin-right: 0.7rem;\n -webkit-mask: url('back.svg') no-repeat center;\n mask: url('back.svg') no-repeat center;\n width: 0.9rem;\n height: 0.9rem; }\n.theme-dark .head .back-btn .icon {\n background-color: #4db1ff; }\n.theme-gray .head .back-btn .icon {\n background-color: #42a5f5; }\n.theme-white .head .back-btn .icon {\n background-color: #2c95f1; }\n.scrolled-content::-webkit-scrollbar {\n background-color: transparent;\n cursor: default;\n width: 1rem;\n height: 1rem; }\n.scrolled-content::-webkit-scrollbar-track {\n background: transparent; }\n.scrolled-content::-webkit-scrollbar-thumb {\n background-color: #556576;\n background-clip: padding-box;\n border: 0.25rem solid transparent;\n border-radius: 0.5rem; }\n.scrolled-content::-webkit-scrollbar-thumb:hover {\n background-color: #556576; }\ntable {\n font-size: 1.3rem;\n width: 100%; }\ntable thead {\n text-align: left; }\n.theme-dark table thead {\n color: #556576; }\n.theme-gray table thead {\n color: #565c62; }\n.theme-white table thead {\n color: #a0a5ab; }\ntable thead tr {\n height: 4rem; }\ntable thead tr th {\n padding: 1rem;\n vertical-align: bottom; }\ntable thead tr th:first-child {\n padding-left: 3rem; }\ntable thead tr th:last-child {\n padding-right: 3rem; }\ntable tbody {\n text-align: left; }\n.theme-dark table tbody {\n color: #e0e0e0; }\n.theme-gray table tbody {\n color: #e0e0e0; }\n.theme-white table tbody {\n color: #43454b; }\ntable tbody tr {\n height: 3.5rem; }\n.theme-dark table tbody tr:nth-child(odd) {\n background-color: #18202a; }\n.theme-gray table tbody tr:nth-child(odd) {\n background-color: #25292d; }\n.theme-white table tbody tr:nth-child(odd) {\n background-color: #ffffff; }\ntable tbody tr td {\n line-height: 1.7rem;\n padding: 0 1rem;\n vertical-align: middle;\n white-space: nowrap;\n max-width: 20rem; }\ntable tbody tr td:first-child {\n padding-left: 3rem; }\ntable tbody tr td:last-child {\n padding-right: 3rem; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Light.ttf');\n font-weight: 300; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Regular.ttf');\n font-weight: 400; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-SemiBold.ttf');\n font-weight: 600; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Bold.ttf');\n font-weight: 700; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-ExtraBold.ttf');\n font-weight: 800; }\nhtml {\n font-family: OpenSans, sans-serif;\n font-size: 10px; }\nbody {\n font-family: OpenSans, sans-serif;\n font-size: 1.6rem;\n width: 100vw;\n height: 100vh; }\nbody.theme-dark {\n background: #131921 url('background-dark.png') no-repeat center;\n background-size: cover; }\nbody.theme-gray {\n background: #101417 url('background-gray.png') no-repeat center;\n background-size: cover; }\nbody.theme-white {\n background: #eeeeee url('background-white.png') no-repeat center;\n background-size: cover; }\nbody app-root {\n display: flex;\n width: 100%;\n height: 100%; }\n.update-tooltip .tooltip-inner .icon {\n -webkit-mask: url('update-alert.svg') no-repeat center;\n mask: url('update-alert.svg') no-repeat center; }\n\r\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxiYXNlXFxfbWl4aW5zLnNjc3MiLCJzcmMvc3R5bGVzLnNjc3MiLCJub2RlX21vZHVsZXMvQG5nLXNlbGVjdC9uZy1zZWxlY3QvdGhlbWVzL2RlZmF1bHQudGhlbWUuY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGJhc2VcXF9udWxsLnNjc3MiLCJzcmMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX2Jhc2Uuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxiYXNlXFxfdGhlbWUuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxsYXlvdXRcXF9tYWluLnNjc3MiLCJzcmMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcbGF5b3V0XFxfc2lkZWJhci5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGxheW91dFxcX3dhbGxldC5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGxheW91dFxcX2NvbnRhY3Quc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfaGVhZC5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXG1vZHVsZXNcXF9zY3JvbGwuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfdGFibGUuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcc3R5bGVzLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBOEVBOztDQzVFQztBQ0ZELGlEQUFpRCxlQUFlLENBQUMsaUNBQWlDO0FBQUMsdURBQXVELGVBQWU7QUFBQywyREFBMkQsUUFBUSxDQUFDLHlDQUF5QyxDQUFDLHNCQUFzQjtBQUFDLGlFQUFpRSx5Q0FBeUM7QUFBQyxrRUFBa0UsNEJBQTRCLENBQUMsMkJBQTJCO0FBQUMsK0RBQStELHlCQUF5QixDQUFDLHdCQUF3QjtBQUFDLHlFQUF5RSxvQkFBb0IsQ0FBQywwRUFBMEU7QUFBQyxtREFBbUQsd0JBQXdCO0FBQUMseUNBQXlDLFlBQVk7QUFBQyxnQ0FBZ0MscUJBQXFCLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsZUFBZSxDQUFDLGtCQUFrQjtBQUFDLHNDQUFzQyxtQ0FBbUM7QUFBQyxvREFBb0Qsa0JBQWtCLENBQUMsaUJBQWlCO0FBQUMsZ0VBQWdFLGtCQUFrQixDQUFDLGNBQWM7QUFBQyxvRUFBb0UsVUFBVTtBQUFDLGlEQUFpRCxXQUFXO0FBQUMsK0VBQStFLE9BQU8sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCO0FBQUMsMkZBQTJGLGtCQUFrQixDQUFDLGlCQUFpQjtBQUFDLG9HQUFvRyx3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SUkzQ0kseUJDb0M2QixFQUFBO0FMT2pDO0lJM0NJLHlCQzRGNkIsRUFBQTtBTGpEakM7SUluQ0UseUJDakNnQztJRGtDaEMsY0N4QzJCLEVBQUE7QUwwRTdCO0lJbkNFLHlCQ3VCZ0M7SUR0QmhDLGNDZ0IyQixFQUFBO0FMa0I3QjtJSW5DRSx5QkMrRWdDO0lEOUVoQyxjQ3dFMkIsRUFBQTtBTHRDN0I7SUk1QkkseUJDdkN5QixFQUFBO0FMbUU3QjtJSTVCSSx5QkNpQnlCLEVBQUE7QUxXN0I7SUk1QkkseUJDeUV5QixFQUFBO0FMN0M3QjtJSXJCSSx5QkM3Q3lCLEVBQUE7QUxrRTdCO0lJckJJLHlCQ1d5QixFQUFBO0FMVTdCO0lJckJJLHlCQ21FeUIsRUFBQTtBTDlDN0I7SUliRSx5QkNqRGlDO0lEa0RqQyxjQzlEMkIsRUFBQTtBTDBFN0I7SUliRSx5QkNPaUM7SUROakMsY0NOMkIsRUFBQTtBTGtCN0I7SUliRSx5QkMrRGlDO0lEOURqQyxjQ2tEMkIsRUFBQTtBTHRDN0I7SUlOSSx5QkN2RDBCLEVBQUE7QUw2RDlCO0lJTkkseUJDQzBCLEVBQUE7QUxLOUI7SUlOSSx5QkN5RDBCLEVBQUE7QUxuRDlCO0lJQ0kseUJDN0QwQixFQUFBO0FMNEQ5QjtJSUNJLHlCQ0wwQixFQUFBO0FMSTlCO0lJQ0kseUJDbUQwQixFQUFBO0FMcEQ5QjtJSVNFLHlCQ3BFcUM7SURxRXJDLGNDcEYyQixFQUFBO0FMMEU3QjtJSVNFLHlCQ1pxQztJRGFyQyxjQzVCMkIsRUFBQTtBTGtCN0I7SUlTRSx5QkM0Q3FDO0lEM0NyQyxjQzRCMkIsRUFBQTtBTHRDN0I7SUlnQkkseUJDMUU4QixFQUFBO0FMMERsQztJSWdCSSx5QkNsQjhCLEVBQUE7QUxFbEM7SUlnQkkseUJDc0M4QixFQUFBO0FMdERsQztJSXVCSSx5QkNoRjhCLEVBQUE7QUx5RGxDO0lJdUJJLHlCQ3hCOEIsRUFBQTtBTENsQztJSXVCSSx5QkNnQzhCLEVBQUE7QUQ3SHRDO0lBbUdJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7QUovQnZC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LGNDcnNCb0IsRUFBQTtBTG1CdEI7SUlrckJFLGNDN29Cb0IsRUFBQTtBTHJDdEI7SUl3ckJJLHlCQzV0QjJCO0lENnRCM0IsY0Nwd0JrQixFQUFBO0FMMkV0QjtJSXdyQkkseUJDcHFCMkI7SURxcUIzQixjQzVzQmtCLEVBQUE7QUxtQnRCO0lJd3JCSSx5QkM1bUIyQjtJRDZtQjNCLGNDcHBCa0IsRUFBQTtBRDBwQjFCO0VBR0ksV0FBVyxFQUFBO0FBSGY7SUFTWSxtQkFBbUIsRUFBQTtBQVQvQjtJQWdCTSxZQUFZO0lBQ1osZ0JBQWdCO0lBQ2hCLGVBQWU7SUFDZixpQkFBaUI7SUFDakIsYUFBYTtJQUNiLGVBQWU7SUFDZixjQUFjLEVBQUE7QUpydEJoQjtNSXd0QkkseUJDL3dCeUI7TURneEJ6QixjQ3B5QmtCLEVBQUE7QUwyRXRCO01Jd3RCSSx5QkN2dEJ5QjtNRHd0QnpCLGNDNXVCa0IsRUFBQTtBTG1CdEI7TUl3dEJJLHlCQy9wQnlCO01EZ3FCekIsY0NwckJrQixFQUFBO0FEMHBCMUI7TUE4QlEsVUFBVSxFQUFBO0FBOUJsQjtRQWlDVSxTQUFTLEVBQUE7QUFqQ25CO0lBdUNNLFlBQVksRUFBQTtBSnR1QmQ7TUl5dUJJLHlCQ2h5QnlCLEVBQUE7QUx1RDdCO01JeXVCSSx5QkN4dUJ5QixFQUFBO0FMRDdCO01JeXVCSSx5QkNockJ5QixFQUFBO0FEc29CakM7TUFnRFUsaUJBQWlCO01BQ2pCLGFBQWEsRUFBQTtBSmh2Qm5CO1FJbXZCUSx5QkMxeUJxQjtRRDJ5QnJCLGNDL3pCYyxFQUFBO0FMMkV0QjtRSW12QlEseUJDbHZCcUI7UURtdkJyQixjQ3Z3QmMsRUFBQTtBTG1CdEI7UUltdkJRLHlCQzFyQnFCO1FEMnJCckIsY0Mvc0JjLEVBQUE7QUxyQ3RCO1FJMHZCVSx1Q0NoekI2QjtRRGl6QjdCLGNDdDBCWSxFQUFBO0FMMkV0QjtRSTB2QlUsdUNDeHZCNkI7UUR5dkI3QixjQzl3QlksRUFBQTtBTG1CdEI7UUkwdkJVLDBDQ2hzQmdDO1FEaXNCaEMsY0N0dEJZLEVBQUE7QUxyQ3RCO1FJa3dCVSx1Q0N2ekJnQztRRHd6QmhDLGNDOTBCWSxFQUFBO0FMMkV0QjtRSWt3QlUsdUNDL3ZCZ0M7UURnd0JoQyxjQ3R4QlksRUFBQTtBTG1CdEI7UUlrd0JVLDBDQ3ZzQm1DO1FEd3NCbkMsY0M5dEJZLEVBQUE7QUQwcEIxQjtNQTBFVSw2QkFBNkI7TUFDN0IsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7QUE3RXRCO01BaUZVLHVCQUF1QixFQUFBO0FBakZqQztNQXFGVSx5QkFBeUI7TUFDekIsNEJBQTRCO01BQzVCLGlDQUFpQztNQUNqQyxxQkFBcUIsRUFBQTtBQXhGL0I7TUE0RlUseUJBQXlCLEVBQUE7QUozeEIvQjtFSXV5QkUsc0NDcDBCMEQ7RURxMEIxRCxjQ24zQm9CLEVBQUE7QUwyRXRCO0VJdXlCRSxzQ0M1d0IwRDtFRDZ3QjFELGNDM3pCb0IsRUFBQTtBTG1CdEI7RUl1eUJFLHVDQ3B0QjJEO0VEcXRCM0QsY0Nud0JvQixFQUFBO0FMckN0QjtFSWd6Qk0seUJDcjNCZSxFQUFBO0FMcUVyQjtFSWd6Qk0seUJDN3pCZSxFQUFBO0FMYXJCO0VJZ3pCTSx5QkNyd0JlLEVBQUE7QUwzQ3JCO0VJdXpCTSx5QkM5M0JpQixFQUFBO0FMdUV2QjtFSXV6Qk0seUJDdDBCaUIsRUFBQTtBTGV2QjtFSXV6Qk0seUJDOXdCaUIsRUFBQTtBTHpDdkI7RUk4ekJNLHlCQ3Q0QmdCLEVBQUE7QUx3RXRCO0VJOHpCTSx5QkM5MEJnQixFQUFBO0FMZ0J0QjtFSTh6Qk0seUJDdHhCZ0IsRUFBQTtBTHhDdEI7RUlzMEJJLHlCQzk0QmtCO0VEKzRCbEIsY0NqNUJ5QixFQUFBO0FMMEU3QjtFSXMwQkkseUJDdDFCa0I7RUR1MUJsQixjQ3oxQnlCLEVBQUE7QUxrQjdCO0VJczBCSSx5QkM5eEJrQjtFRCt4QmxCLGNDanlCeUIsRUFBQTtBTHRDN0I7RUlnMUJNLHlCQzUyQm1CLEVBQUE7QUw0QnpCO0VJZzFCTSx5QkNwekJtQixFQUFBO0FMNUJ6QjtFSWcxQk0seUJDNXZCbUIsRUFBQTtBTHBGekI7RUk0MUJFLGdDQ3A1Qm1DLEVBQUE7QUx3RHJDO0VJNDFCRSxnQ0M1MUJtQyxFQUFBO0FMQXJDO0VJNDFCRSxnQ0NweUJtQyxFQUFBO0FMeERyQztFSXMyQlEsY0MvNkJrQixFQUFBO0FMeUUxQjtFSXMyQlEsY0N2M0JrQixFQUFBO0FMaUIxQjtFSXMyQlEsY0MvekJrQixFQUFBO0FMdkMxQjtFSTYyQlEsY0N4N0JjLEVBQUE7QUwyRXRCO0VJNjJCUSxjQ2g0QmMsRUFBQTtBTG1CdEI7RUk2MkJRLGNDeDBCYyxFQUFBO0FMckN0QjtFSW8zQlEsY0M1N0JjLEVBQUE7QUx3RXRCO0VJbzNCUSxjQ3A0QmMsRUFBQTtBTGdCdEI7RUlvM0JRLGNDNTBCYyxFQUFBO0FMeEN0QjtFSWk0QkUsY0M1OEJvQixFQUFBO0FMMkV0QjtFSWk0QkUsY0NwNUJvQixFQUFBO0FMbUJ0QjtFSWk0QkUsY0M1MUJvQixFQUFBO0FMckN0QjtFSXU0QkkseUJDOTZCK0IsRUFBQTtBTHVDbkM7RUl1NEJJLHlCQ3QzQitCLEVBQUE7QUxqQm5DO0VJdTRCSSx5QkM5ekIrQixFQUFBO0FMekVuQztFSTY0Qk0seUJDbjdCaUMsRUFBQTtBTHNDdkM7RUk2NEJNLHlCQzMzQmlDLEVBQUE7QUxsQnZDO0VJNjRCTSx5QkNuMEJpQyxFQUFBO0FMMUV2QztFSXk1QkUsc0NDdDdCMEQ7RUR1N0IxRCxjQ3IrQm9CLEVBQUE7QUwyRXRCO0VJeTVCRSxzQ0M5M0IwRDtFRCszQjFELGNDNzZCb0IsRUFBQTtBTG1CdEI7RUl5NUJFLHVDQ3QwQjJEO0VEdTBCM0QsY0NyM0JvQixFQUFBO0FMckN0QjtFSW02QkUsc0NDaDhCMEQ7RURpOEIxRCxjQy8rQm9CLEVBQUE7QUwyRXRCO0VJbTZCRSxzQ0N4NEIwRDtFRHk0QjFELGNDdjdCb0IsRUFBQTtBTG1CdEI7RUltNkJFLHVDQ2gxQjJEO0VEaTFCM0QsY0MvM0JvQixFQUFBO0FMckN0QjtFSTA2QkksbUNDbCtCaUMsRUFBQTtBTHdEckM7RUkwNkJJLG1DQzE2QmlDLEVBQUE7QUxBckM7RUkwNkJJLG1DQ2wzQmlDLEVBQUE7QUx4RHJDO0VJazdCSSx5QkMxL0JrQjtFRDIvQmxCLGNDNy9CeUIsRUFBQTtBTDBFN0I7RUlrN0JJLHlCQ2w4QmtCO0VEbThCbEIsY0NyOEJ5QixFQUFBO0FMa0I3QjtFSWs3QkkseUJDMTRCa0I7RUQyNEJsQixjQzc0QnlCLEVBQUE7QUN6SGpDO0VBQ0UsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUhsQjtJQU1JLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsZ0JBQWdCLEVBQUE7QU4yRWhCO01NeEVFLHVDREoyQztNQ0szQyxjREpvQixFQUFBO0FMMkV0QjtNTXhFRSx1Q0RvRDJDO01DbkQzQyxjRG9Eb0IsRUFBQTtBTG1CdEI7TU14RUUsMENENEc4QztNQzNHOUMsY0Q0R29CLEVBQUE7QUN4SDFCO01BZ0JNLGtCQUFrQjtNQUNsQixNQUFNO01BQ04sT0FBTyxFQUFBO0FOaUVUO0VNbkRNLGNEckJnQixFQUFBO0FMd0V0QjtFTW5ETSxjRG1DZ0IsRUFBQTtBTGdCdEI7RU1uRE0sY0QyRmdCLEVBQUE7QUx4Q3RCO0VNN0NRLHlCRDNCYyxFQUFBO0FMd0V0QjtFTTdDUSx5QkQ2QmMsRUFBQTtBTGdCdEI7RU03Q1EseUJEcUZjLEVBQUE7QUx4Q3RCO0VNaENFLHlCRHZCMkI7RUN3QjNCLGNENUNvQixFQUFBO0FMMkV0QjtFTWhDRSx5QkRpQzJCO0VDaEMzQixjRFlvQixFQUFBO0FMbUJ0QjtFTWhDRSx5QkR5RjJCO0VDeEYzQixjRG9Fb0IsRUFBQTtBTHJDdEI7RU1yQkUseUJEbEMyQixFQUFBO0FMdUQ3QjtFTXJCRSx5QkRzQjJCLEVBQUE7QUxEN0I7RU1yQkUseUJEOEUyQixFQUFBO0FDekVqQztFQUdJLFlBQVk7RUFDWixnQkFBZ0I7RUFDaEIsYUFBYTtFQUNiLDhCQUE4QjtFQUM5QixzQkFBc0IsRUFBQTtBTlN0QjtJTUpJLGNEckVzQixFQUFBO0FMeUUxQjtJTUpJLGNEYnNCLEVBQUE7QUxpQjFCO0lNSkksY0QyQ3NCLEVBQUE7QUx2QzFCO0lNS00sdUNEakQyQyxFQUFBO0FMNENqRDtJTUtNLHVDRE8yQyxFQUFBO0FMWmpEO0lNS00sMENEK0Q4QyxFQUFBO0FMcEVwRDtJTVdRLGNEcEZrQixFQUFBO0FMeUUxQjtJTVdRLGNENUJrQixFQUFBO0FMaUIxQjtJTVdRLGNENEJrQixFQUFBO0FMdkMxQjtJTWtCUSx5QkQxRmMsRUFBQTtBTHdFdEI7SU1rQlEseUJEbENjLEVBQUE7QUxnQnRCO0lNa0JRLHlCRHNCYyxFQUFBO0FMeEN0QjtJTXdCVSxjRGhHWSxFQUFBO0FMd0V0QjtJTXdCVSxjRHhDWSxFQUFBO0FMZ0J0QjtJTXdCVSxjRGdCWSxFQUFBO0FDUDFCO0VBQ0Usa0JBQWtCLEVBQUE7QU5sQ2hCO0VPaEZBLHlCRkEyQyxFQUFBO0FMZ0YzQztFT2hGQSx5QkZ3RDJDLEVBQUE7QUx3QjNDO0VPaEZBLHVCRmdIOEMsRUFBQTtBTGhDOUM7RU90RU0sY0ZMZ0IsRUFBQTtBTDJFdEI7RU90RU0sY0ZtRGdCLEVBQUE7QUxtQnRCO0VPdEVNLGNGMkdnQixFQUFBO0FMckN0QjtFTy9ETSxjRlRnQixFQUFBO0FMd0V0QjtFTy9ETSxjRitDZ0IsRUFBQTtBTGdCdEI7RU8vRE0sY0Z1R2dCLEVBQUE7QUx4Q3RCO0VPckRNLDZCQUE2QjtFQUM3QixjRnZCZ0IsRUFBQTtBTDJFdEI7RU9yRE0sNkJBQTZCO0VBQzdCLGNGaUNnQixFQUFBO0FMbUJ0QjtFT3JETSw2QkFBNkI7RUFDN0IsY0Z5RmdCLEVBQUE7QUxyQ3RCO0VPNUNVLGNGN0JnQixFQUFBO0FMeUUxQjtFTzVDVSxjRjJCZ0IsRUFBQTtBTGlCMUI7RU81Q1UsY0ZtRmdCLEVBQUE7QUx2QzFCO0VPckNVLHlCRm5DWSxFQUFBO0FMd0V0QjtFT3JDVSx5QkZxQlksRUFBQTtBTGdCdEI7RU9yQ1UseUJGNkVZLEVBQUE7QUx4Q3RCO0VPOUJVLHlCRnRDd0I7RUV1Q3hCLGNGN0NtQixFQUFBO0FMMEU3QjtFTzlCVSx5QkZrQndCO0VFakJ4QixjRldtQixFQUFBO0FMa0I3QjtFTzlCVSx5QkYwRXdCO0VFekV4QixjRm1FbUIsRUFBQTtBTHRDN0I7RU9wQlkseUJGbkJ1QixFQUFBO0FMdUNuQztFT3BCWSx5QkZxQ3VCLEVBQUE7QUxqQm5DO0VPcEJZLHlCRjZGdUIsRUFBQTtBTHpFbkM7RU9kYyx5QkYxRFEsRUFBQTtBTHdFdEI7RU9kYyx5QkZGUSxFQUFBO0FMZ0J0QjtFT2RjLHlCRnNEUSxFQUFBO0FMeEN0QjtFT0xVLGNGcEVnQixFQUFBO0FMeUUxQjtFT0xVLGNGWmdCLEVBQUE7QUxpQjFCO0VPTFUsY0Y0Q2dCLEVBQUE7QUx2QzFCO0VPR1EsdUNGdERxQztFRXVEckMsY0ZyRHFCLEVBQUE7QUxpRDdCO0VPR1EsdUNGRXFDO0VFRHJDLGNGR3FCLEVBQUE7QUxQN0I7RU9HUSx5QkYwRHFDO0VFekRyQyxjRjJEcUIsRUFBQTtBTC9EN0I7RU9ZWSxjRjVEcUIsRUFBQTtBTGdEakM7RU9ZWSxjRkpxQixFQUFBO0FMUmpDO0VPWVksY0ZvRHFCLEVBQUE7QUxoRWpDO0VPbUJZLHlCRmhFNEI7RUVpRTVCLGNGbkVzQixFQUFBO0FMK0NsQztFT21CWSx5QkZSNEI7RUVTNUIsY0ZYc0IsRUFBQTtBTFRsQztFT21CWSx5QkZnRDRCO0VFL0M1QixjRjZDc0IsRUFBQTtBTGpFbEM7RU8yQlkseUJGekV5QjtFRTBFekIsY0Z2R1UsRUFBQTtBTDJFdEI7RU8yQlkseUJGakJ5QjtFRWtCekIsY0YvQ1UsRUFBQTtBTG1CdEI7RU8yQlkseUJGdUN5QjtFRXRDekIsY0ZTVSxFQUFBO0FMckN0QjtFT21DWSxjRm5GcUIsRUFBQTtBTGdEakM7RU9tQ1ksY0YzQnFCLEVBQUE7QUxSakM7RU9tQ1ksY0Y2QnFCLEVBQUE7QUxoRWpDO0VPNENRLHVDRjlGMEMsRUFBQTtBTGtEbEQ7RU80Q1EsdUNGdEMwQyxFQUFBO0FMTmxEO0VPNENRLDBDRmtCNkMsRUFBQTtBTDlEckQ7RU9xREksb0VBQTJGLEVBQUE7QVByRC9GO0VPcURJLG9FQUEyRixFQUFBO0FQckQvRjtFT3FESSxrRUFBMkYsRUFBQTtBUHJEL0Y7RU82REUsbUNGNUl5QixFQUFBO0FMK0UzQjtFTzZERSxtQ0ZwRnlCLEVBQUE7QUx1QjNCO0VPNkRFLG1DRjVCeUIsRUFBQTtBTGpDM0I7RU9xRU0sY0ZoSmdCLEVBQUE7QUwyRXRCO0VPcUVNLGNGeEZnQixFQUFBO0FMbUJ0QjtFT3FFTSxjRmhDZ0IsRUFBQTtBTHJDdEI7RU8yRVEseUJGbkpjLEVBQUE7QUx3RXRCO0VPMkVRLHlCRjNGYyxFQUFBO0FMZ0J0QjtFTzJFUSx5QkZuQ2MsRUFBQTtBTHhDdEI7RU9xRlEsa0RBQTBEO0VBQzFELHlCQUE2QyxFQUFBO0FQdEZyRDtFT3FGUSxrREFBMEQ7RUFDMUQseUJBQTZDLEVBQUE7QVB0RnJEO0VPcUZRLG9DQUEwRDtFQUMxRCx5QkFBNkMsRUFBQTtBUHRGckQ7RU80RlUsb0NBQW1FLEVBQUE7QVA1RjdFO0VPNEZVLG9DQUFtRSxFQUFBO0FQNUY3RTtFTzRGVSxvQ0FBbUUsRUFBQTtBUDVGN0U7RU91R0UsY0ZoTHdCLEVBQUE7QUx5RTFCO0VPdUdFLGNGeEh3QixFQUFBO0FMaUIxQjtFT3VHRSxjRmhFd0IsRUFBQTtBTHZDMUI7RU8rR00seUJGNUxlLEVBQUE7QUw2RXJCO0VPK0dNLHlCRnBJZSxFQUFBO0FMcUJyQjtFTytHTSx5QkY1RWUsRUFBQTtBTG5DckI7RU9zSE0seUJGcE1jLEVBQUE7QUw4RXBCO0VPc0hNLHlCRjVJYyxFQUFBO0FMc0JwQjtFT3NITSx5QkZwRmMsRUFBQTtBTGxDcEI7RU9pSVUseUJGeEt5QixFQUFBO0FMdUNuQztFT2lJVSx5QkZoSHlCLEVBQUE7QUxqQm5DO0VPaUlVLHlCRnhEeUIsRUFBQTtBTHpFbkM7RU91SVkseUJGN0syQixFQUFBO0FMc0N2QztFT3VJWSx5QkZySDJCLEVBQUE7QUxsQnZDO0VPdUlZLHlCRjdEMkIsRUFBQTtBTDFFdkM7RU9nSlEseUJGdEwrQixFQUFBO0FMc0N2QztFT2dKUSx5QkY5SCtCLEVBQUE7QUxsQnZDO0VPZ0pRLHlCRnRFK0IsRUFBQTtBTDFFdkM7RU8ySk0sY0ZuT2dCLEVBQUE7QUx3RXRCO0VPMkpNLGNGM0tnQixFQUFBO0FMZ0J0QjtFTzJKTSxjRm5IZ0IsRUFBQTtBTHhDdEI7RU9rS00sY0Z4T2tCLEVBQUE7QUxzRXhCO0VPa0tNLGNGaExrQixFQUFBO0FMY3hCO0VPa0tNLGNGeEhrQixFQUFBO0FMMUN4QjtFT3lLTSxjRjlPZSxFQUFBO0FMcUVyQjtFT3lLTSxjRnRMZSxFQUFBO0FMYXJCO0VPeUtNLGNGOUhlLEVBQUE7QUwzQ3JCO0VPZ0xNLGNGdFBrQixFQUFBO0FMc0V4QjtFT2dMTSxjRjlMa0IsRUFBQTtBTGN4QjtFT2dMTSxjRnRJa0IsRUFBQTtBTDFDeEI7RU95TFEseUJGalFjLEVBQUE7QUx3RXRCO0VPeUxRLHlCRnpNYyxFQUFBO0FMZ0J0QjtFT3lMUSx5QkZqSmMsRUFBQTtBTHhDdEI7RU9nTVEseUJGdFFnQixFQUFBO0FMc0V4QjtFT2dNUSx5QkY5TWdCLEVBQUE7QUxjeEI7RU9nTVEseUJGdEpnQixFQUFBO0FMMUN4QjtFT3VNUSx5QkY1UWEsRUFBQTtBTHFFckI7RU91TVEseUJGcE5hLEVBQUE7QUxhckI7RU91TVEseUJGNUphLEVBQUE7QUwzQ3JCO0VPOE1RLHlCRnBSZ0IsRUFBQTtBTHNFeEI7RU84TVEseUJGNU5nQixFQUFBO0FMY3hCO0VPOE1RLHlCRnBLZ0IsRUFBQTtBTDFDeEI7RVFoRkEsY0hLc0IsRUFBQTtBTDJFdEI7RVFoRkEsY0g2RHNCLEVBQUE7QUxtQnRCO0VRaEZBLGNIcUhzQixFQUFBO0FMckN0QjtFUXhFSSxjSEhrQixFQUFBO0FMMkV0QjtFUXhFSSxjSHFEa0IsRUFBQTtBTG1CdEI7RVF4RUksY0g2R2tCLEVBQUE7QUxyQ3RCO0VRbEVNLHlCSE5nQixFQUFBO0FMd0V0QjtFUWxFTSx5QkhrRGdCLEVBQUE7QUxnQnRCO0VRbEVNLHlCSDBHZ0IsRUFBQTtBTHhDdEI7RVF4RE0seUJIaEJnQixFQUFBO0FMd0V0QjtFUXhETSx5Qkh3Q2dCLEVBQUE7QUxnQnRCO0VReERNLHlCSGdHZ0IsRUFBQTtBTHhDdEI7RVEvQ0UsY0h6Qm9CLEVBQUE7QUx3RXRCO0VRL0NFLGNIK0JvQixFQUFBO0FMZ0J0QjtFUS9DRSxjSHVGb0IsRUFBQTtBTHhDdEI7RVF6Q0kseUJIL0JrQixFQUFBO0FMd0V0QjtFUXpDSSx5Qkh5QmtCLEVBQUE7QUxnQnRCO0VRekNJLHlCSGlGa0IsRUFBQTtBTHhDdEI7RVE3Qk0sdUNIZjJDLEVBQUE7QUw0Q2pEO0VRN0JNLHVDSHlDMkMsRUFBQTtBTFpqRDtFUTdCTSwwQ0hpRzhDLEVBQUE7QUxwRXBEO0VRdkJRLHlCSGpEYyxFQUFBO0FMd0V0QjtFUXZCUSx5QkhPYyxFQUFBO0FMZ0J0QjtFUXZCUSx5QkgrRGMsRUFBQTtBTHhDdEI7RVFoQlEseUJIN0JnQztFRzhCaEMsY0hoQzBCLEVBQUE7QUwrQ2xDO0VRaEJRLHlCSDJCZ0M7RUcxQmhDLGNId0IwQixFQUFBO0FMVGxDO0VRaEJRLHlCSG1GZ0M7RUdsRmhDLGNIZ0YwQixFQUFBO0FMakVsQztFUVJRLHVDSHBFcUMsRUFBQTtBTDRFN0M7RVFSUSx1Q0hacUMsRUFBQTtBTG9CN0M7RVFSUSwwQ0g0Q3dDLEVBQUE7QUxwQ2hEO0VRRFEsdUNIMUNzQyxFQUFBO0FMMkM5QztFUURRLHVDSGNzQyxFQUFBO0FMYjlDO0VRRFEseUJIc0V3QixFQUFBO0FMckVoQztFUVFJLHVDSHBGeUMsRUFBQTtBTDRFN0M7RVFRSSx1Q0g1QnlDLEVBQUE7QUxvQjdDO0VRUUksMENINEI0QyxFQUFBO0FMcENoRDtFUXFCSSxjSGhHa0IsRUFBQTtBTDJFdEI7RVFxQkksY0h4Q2tCLEVBQUE7QUxtQnRCO0VRcUJJLGNIZ0JrQixFQUFBO0FMckN0QjtFUTJCTSx5QkhuR2dCLEVBQUE7QUx3RXRCO0VRMkJNLHlCSDNDZ0IsRUFBQTtBTGdCdEI7RVEyQk0seUJIYWdCLEVBQUE7QUx4Q3RCO0VRbUNJLDRCSDNGaUMsRUFBQTtBTHdEckM7RVFtQ0ksNEJIbkNpQyxFQUFBO0FMQXJDO0VRbUNJLDRCSHFCaUMsRUFBQTtBTHhEckM7RVE4Q0UseUJIdEhvQixFQUFBO0FMd0V0QjtFUThDRSx5Qkg5RG9CLEVBQUE7QUxnQnRCO0VROENFLHlCSE5vQixFQUFBO0FMeEN0QjtFUThEUSxjSHZJa0IsRUFBQTtBTHlFMUI7RVE4RFEsY0gvRWtCLEVBQUE7QUxpQjFCO0VROERRLGNIdkJrQixFQUFBO0FMdkMxQjtFUXFFUSx5QkgvR3FCLEVBQUE7QUwwQzdCO0VRcUVRLHlCSHZEcUIsRUFBQTtBTGQ3QjtFUXFFUSx5QkhDcUIsRUFBQTtBTHRFN0I7RVE0RVEseUJIdEhxQixFQUFBO0FMMEM3QjtFUTRFUSx5Qkg5RHFCLEVBQUE7QUxkN0I7RVE0RVEseUJITnFCLEVBQUE7QUx0RTdCO0VRbUZRLDZCQUE2QixFQUFBO0FSbkZyQztFUW1GUSw2QkFBNkIsRUFBQTtBUm5GckM7RVFtRlEsNkJBQTZCLEVBQUE7QVJuRnJDO0VRMEZRLDZCQUE2QixFQUFBO0FSMUZyQztFUTBGUSw2QkFBNkIsRUFBQTtBUjFGckM7RVEwRlEsNkJBQTZCLEVBQUE7QVIxRnJDO0VRbUdVLHlCSDFJeUIsRUFBQTtBTHVDbkM7RVFtR1UseUJIbEZ5QixFQUFBO0FMakJuQztFUW1HVSx5QkgxQnlCLEVBQUE7QUx6RW5DO0VReUdZLHlCSC9JMkIsRUFBQTtBTHNDdkM7RVF5R1kseUJIdkYyQixFQUFBO0FMbEJ2QztFUXlHWSx5QkgvQjJCLEVBQUE7QUwxRXZDO0VRa0hRLHlCSHhMZ0IsRUFBQTtBTHNFeEI7RVFrSFEseUJIaElnQixFQUFBO0FMY3hCO0VRa0hRLHlCSHhFZ0IsRUFBQTtBTDFDeEI7RVF5SFEseUJIak1jLEVBQUE7QUx3RXRCO0VReUhRLHlCSHpJYyxFQUFBO0FMZ0J0QjtFUXlIUSx5QkhqRmMsRUFBQTtBTHhDdEI7RVFrSVUseUJIdk1XLEVBQUE7QUxxRXJCO0VRa0lVLHlCSC9JVyxFQUFBO0FMYXJCO0VRa0lVLHlCSHZGVyxFQUFBO0FMM0NyQjtFUTRJVSx5QkhuTmEsRUFBQTtBTHVFdkI7RVE0SVUseUJIM0phLEVBQUE7QUxldkI7RVE0SVUseUJIbkdhLEVBQUE7QUx6Q3ZCO0VRZ0tRLHlCSHJPYSxFQUFBO0FMcUVyQjtFUWdLUSx5Qkg3S2EsRUFBQTtBTGFyQjtFUWdLUSx5QkhySGEsRUFBQTtBTDNDckI7RVF1S1EseUJIL09jLEVBQUE7QUx3RXRCO0VRdUtRLHlCSHZMYyxFQUFBO0FMZ0J0QjtFUXVLUSx5QkgvSGMsRUFBQTtBTHhDdEI7RVFzTEksY0hqUWtCLEVBQUE7QUwyRXRCO0VRc0xJLGNIek1rQixFQUFBO0FMbUJ0QjtFUXNMSSxjSGpKa0IsRUFBQTtBTHJDdEI7RVE0TE0seUJIcFFnQixFQUFBO0FMd0V0QjtFUTRMTSx5Qkg1TWdCLEVBQUE7QUxnQnRCO0VRNExNLHlCSHBKZ0IsRUFBQTtBTHhDdEI7RVFvTUksY0g1UWtCLEVBQUE7QUx3RXRCO0VRb01JLGNIcE5rQixFQUFBO0FMZ0J0QjtFUW9NSSxjSDVKa0IsRUFBQTtBTHhDdEI7RVEyTUksNEJIblFpQyxFQUFBO0FMd0RyQztFUTJNSSw0QkgzTWlDLEVBQUE7QUxBckM7RVEyTUksNEJIbkppQyxFQUFBO0FMeERyQztFUXFOSSx5Qkg1UCtCLEVBQUE7QUx1Q25DO0VRcU5JLHlCSHBNK0IsRUFBQTtBTGpCbkM7RVFxTkkseUJINUkrQixFQUFBO0FMekVuQztFUTJOTSx5QkhqUWlDLEVBQUE7QUxzQ3ZDO0VRMk5NLHlCSHpNaUMsRUFBQTtBTGxCdkM7RVEyTk0seUJIakppQyxFQUFBO0FHd0ozQztFUnBURSxnQkFBZ0I7RUFDaEIsdUJBQXVCO0VBQ3ZCLG1CQUFtQixFQUFBO0FBZ0ZqQjtFUW1QVSx5Qkh4VFcsRUFBQTtBTHFFckI7RVFtUFUseUJIaFFXLEVBQUE7QUxhckI7RVFtUFUseUJIeE1XLEVBQUE7QUwzQ3JCO0VRbVFJLGNIM1VrQixFQUFBO0FMd0V0QjtFUW1RSSxjSG5Sa0IsRUFBQTtBTGdCdEI7RVFtUUksY0gzTmtCLEVBQUE7QUx4Q3RCO0VRaVJRLGNIMVZrQixFQUFBO0FMeUUxQjtFUWlSUSxjSGxTa0IsRUFBQTtBTGlCMUI7RVFpUlEsY0gxT2tCLEVBQUE7QUx2QzFCO0VRd1JRLHlCSGpVeUIsRUFBQTtBTHlDakM7RVF3UlEseUJIelF5QixFQUFBO0FMZmpDO0VRd1JRLHNCSGpOc0IsRUFBQTtBR3FMbEM7RVJ0UUUsV0FEMEQ7RUFFMUQsY0FGNEI7RUFHNUIsa0JBSDRDO0VReVNsQyxNQUFNO0VBQ04sYUFBYTtFQUNiLGdDQUFnQyxFQUFBO0FSaFN4QztJUW1TVSx5Qkg1VXVCLEVBQUE7QUx5Q2pDO0lRbVNVLHlCSHBSdUIsRUFBQTtBTGZqQztJUW1TVSxzQkg1Tm9CLEVBQUE7QUx2RTlCO0VRMlNRLHlCSG5WNEIsRUFBQTtBTHdDcEM7RVEyU1EseUJIM1I0QixFQUFBO0FMaEJwQztFUTJTUSx5QkhuTzRCLEVBQUE7QUdvTHhDO0VSdFFFLFdBRDBEO0VBRTFELGNBRjRCO0VBRzVCLGtCQUg0QztFUTRUbEMsY0FBYztFQUNkLE1BQU07RUFDTixnQ0FBZ0MsRUFBQTtBUm5UeEM7SVFzVFUseUJIOVYwQixFQUFBO0FMd0NwQztJUXNUVSx5Qkh0UzBCLEVBQUE7QUxoQnBDO0lRc1RVLHlCSDlPMEIsRUFBQTtBTHhFcEM7RVF3VU0sY0hqWm9CLEVBQUE7QUx5RTFCO0VRd1VNLGNIelZvQixFQUFBO0FMaUIxQjtFUXdVTSxjSGpTb0IsRUFBQTtBTHZDMUI7RVErVU0sY0gxWmdCLEVBQUE7QUwyRXRCO0VRK1VNLGNIbFdnQixFQUFBO0FMbUJ0QjtFUStVTSxjSDFTZ0IsRUFBQTtBRzBSMUI7RUFzQk0sYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix5QkFBeUI7RUFDekIsWUFBWTtFQUNaLGlCQUFpQixFQUFBO0FSelZuQjtFUWtXSSxjSDNhc0IsRUFBQTtBTHlFMUI7RVFrV0ksY0huWHNCLEVBQUE7QUxpQjFCO0VRa1dJLGNIM1RzQixFQUFBO0FMdkMxQjtFUTJXTSxjSHRiZ0I7RUd1YmhCLHlCSGpaOEIsRUFBQTtBTHFDcEM7RVEyV00sY0g5WGdCO0VHK1hoQix5Qkh6VjhCLEVBQUE7QUxuQnBDO0VRMldNLGNIdFVnQjtFR3VVaEIseUJIalM4QixFQUFBO0FMM0VwQztFUWtYUSx5Qkh0WnVCLEVBQUE7QUxvQy9CO0VRa1hRLHlCSDlWdUIsRUFBQTtBTHBCL0I7RVFrWFEseUJIdFN1QixFQUFBO0FHOFNuQztFQUNFLGtCQUFrQixFQUFBO0FBRHBCO0lBSUksa0JBQWtCO0lBQ2xCLFdBQVc7SUFDWCxpQkFBaUI7SUFDakIsY0FBYztJQUNkLFdBQVcsRUFBQTtBUmxZWDtNUXFZRSx5Qkg1YjJCO01HNmIzQixjSGpkb0IsRUFBQTtBTDJFdEI7TVFxWUUseUJIcFkyQjtNR3FZM0IsY0h6Wm9CLEVBQUE7QUxtQnRCO01RcVlFLHlCSDVVMkI7TUc2VTNCLGNIaldvQixFQUFBO0FHcVYxQjtNQWdCTSxpQkFBaUI7TUFDakIsYUFBYSxFQUFBO0FSM1lmO1FRK1lNLHVDSHJjaUMsRUFBQTtBTHNEdkM7UVErWU0sdUNIN1lpQyxFQUFBO0FMRnZDO1FRK1lNLDBDSHJWb0MsRUFBQTtBSTdJOUM7O0VBRUUsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUpsQjs7SUFPSSxrQkFBa0I7SUFDbEIsYUFBYTtJQUNiLGdCQUFnQixFQUFBO0FUMEVoQjs7TVN2RUUsdUNKTDJDO01JTTNDLGNKTG9CLEVBQUE7QUwyRXRCOztNU3ZFRSx1Q0ptRDJDO01JbEQzQyxjSm1Eb0IsRUFBQTtBTG1CdEI7O01TdkVFLDBDSjJHOEM7TUkxRzlDLGNKMkdvQixFQUFBO0FJeEgxQjs7TUFpQk0sa0JBQWtCO01BQ2xCLE1BQU07TUFDTixPQUFPLEVBQUE7QVRnRVQ7RVNwRE0sY0pwQmdCLEVBQUE7QUx3RXRCO0VTcERNLGNKb0NnQixFQUFBO0FMZ0J0QjtFU3BETSxjSjRGZ0IsRUFBQTtBTHhDdEI7RVMzQ00seUJKN0JnQixFQUFBO0FMd0V0QjtFUzNDTSx5QkoyQmdCLEVBQUE7QUxnQnRCO0VTM0NNLHlCSm1GZ0IsRUFBQTtBTHhDdEI7RVNwQ00sY0p2Q2dCLEVBQUE7QUwyRXRCO0VTcENNLGNKaUJnQixFQUFBO0FMbUJ0QjtFU3BDTSxjSnlFZ0IsRUFBQTtBTHJDdEI7RVMzQkUsY0o3Q29CLEVBQUE7QUx3RXRCO0VTM0JFLGNKV29CLEVBQUE7QUxnQnRCO0VTM0JFLGNKbUVvQixFQUFBO0FMeEN0QjtFU3JCSSxjSm5Ea0IsRUFBQTtBTHdFdEI7RVNyQkksY0pLa0IsRUFBQTtB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QUFHbEI7RUFDRSxxQkFBcUI7RUFDckIsa0NBQWtEO0VBQ2xELGdCQUFnQixFQUFBO0FBSWxCO0VBQ0UsaUNBQWlDO0VBQ2pDLGVBQWUsRUFBQTtBQUdqQjtFQUNFLGlDQUFpQztFQUNqQyxpQkFBaUI7RUFDakIsWUFBWTtFQUNaLGFBQWEsRUFBQTtBQUpmO0lBT0ksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBUjFCO0lBWUksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBYjFCO0lBaUJJLGdFQUE4RTtJQUM5RSxzQkFBc0IsRUFBQTtBQWxCMUI7SUFzQkksYUFBYTtJQUNiLFdBQVc7SUFDWCxZQUFZLEVBQUE7QUFJaEI7RUFLTSxzREFBeUQ7VUFBekQsOENBQXlELEVBQUEiLCJmaWxlIjoic3JjL3N0eWxlcy5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQG1peGluIHRleHQtdHJ1bmNhdGUge1xyXG4gIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxufVxyXG5AbWl4aW4gdGV4dFdyYXAge1xyXG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XHJcbiAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgd29yZC1icmVhazogYnJlYWstYWxsO1xyXG4gIGxpbmUtYnJlYWs6IHN0cmljdDtcclxuICAtd2Via2l0LWh5cGhlbnM6IGF1dG87XHJcbiAgLW1zLWh5cGhlbnM6IGF1dG87XHJcbiAgaHlwaGVuczogYXV0bztcclxufVxyXG5AbWl4aW4gY292ZXJCb3gge1xyXG5cdHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuXHR0b3A6IDA7XHJcblx0bGVmdDogMDtcclxuXHR3aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IDEwMCU7XHJcbn1cclxuQG1peGluIGFicyAoJHRvcDogYXV0bywgJHJpZ2h0OiBhdXRvLCAkYm90dG9tOiBhdXRvLCAkbGVmdDogYXV0bykge1xyXG4gIHRvcDogJHRvcDtcclxuICByaWdodDogJHJpZ2h0O1xyXG4gIGJvdHRvbTogJGJvdHRvbTtcclxuICBsZWZ0OiAkbGVmdDtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbn1cclxuQG1peGluIGNvdmVySW1nIHtcclxuXHRiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0O1xyXG5cdC13ZWJraXQtYmFja2dyb3VuZC1zaXplOiBjb3ZlcjtcclxuXHQtby1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG5cdGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcblx0YmFja2dyb3VuZC1wb3NpdGlvbjogNTAlIDUwJTtcclxufVxyXG5AbWl4aW4gdmFsaW5nQm94IHtcclxuXHRwb3NpdGlvbjogYWJzb2x1dGU7XHJcblx0dG9wOiAgNTAlO1xyXG5cdGxlZnQ6IDUwJTtcclxuXHR0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTtcclxufVxyXG5AbWl4aW4gdW5TZWxlY3Qge1xyXG5cdC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcclxuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcclxuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcclxuICB1c2VyLXNlbGVjdDogbm9uZTtcclxufVxyXG5AbWl4aW4gbWF4MTE5OSB7IC8vIG1ha2V0IDExNzFcclxuICBAbWVkaWEgKG1heC13aWR0aDogMTE5OXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDExNzAgeyAvLyBtYWtldHMgOTkyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExNzBweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXg5OTEgeyAvLyBtYWtldHMgNzYyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDk5MXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDc2MSB7IC8vIG1ha2V0cyA1NzZcclxuICBAbWVkaWEgKG1heC13aWR0aDogNzYxcHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbWF4NTc1IHsgLy8gbWFrZXRzIDQwMFxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA1NzVweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtb2JpbGUge1xyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiAzOTlweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBpY29DZW50ZXIge1xyXG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcclxuICAgIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlciBjZW50ZXI7XHJcbn1cclxuQG1peGluIHBzZXVkbyAoJGRpc3BsYXk6IGJsb2NrLCAkcG9zOiBhYnNvbHV0ZSwgJGNvbnRlbnQ6ICcnKXtcclxuICBjb250ZW50OiAkY29udGVudDtcclxuICBkaXNwbGF5OiAkZGlzcGxheTtcclxuICBwb3NpdGlvbjogJHBvcztcclxufVxyXG5cclxuLypcclxuKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGVtZXNcclxuKi9cclxuQG1peGluIHRoZW1pZnkoJHRoZW1lczogJHRoZW1lcykge1xyXG4gIEBlYWNoICR0aGVtZSwgJG1hcCBpbiAkdGhlbWVzIHtcclxuICAgIC50aGVtZS0jeyR0aGVtZX0gJiB7XHJcbiAgICAgICR0aGVtZS1tYXA6ICgpICFnbG9iYWw7XHJcbiAgICAgIEBlYWNoICRrZXksICRzdWJtYXAgaW4gJG1hcCB7XHJcbiAgICAgICAgJHZhbHVlOiBtYXAtZ2V0KG1hcC1nZXQoJHRoZW1lcywgJHRoZW1lKSwgJyN7JGtleX0nKTtcclxuICAgICAgICAkdGhlbWUtbWFwOiBtYXAtbWVyZ2UoJHRoZW1lLW1hcCwgKCRrZXk6ICR2YWx1ZSkpICFnbG9iYWw7XHJcbiAgICAgIH1cclxuICAgICAgQGNvbnRlbnQ7XHJcbiAgICAgICR0aGVtZS1tYXA6IG51bGwgIWdsb2JhbDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbkBmdW5jdGlvbiB0aGVtZWQoJGtleSkge1xyXG4gIEByZXR1cm4gbWFwLWdldCgkdGhlbWUtbWFwLCAka2V5KTtcclxufVxyXG4iLCIvKlxyXG4qIEltcGxlbWVudGF0aW9uIG9mIHRoZW1lc1xyXG4qL1xuQGltcG9ydCB1cmwofkBuZy1zZWxlY3Qvbmctc2VsZWN0L3RoZW1lcy9kZWZhdWx0LnRoZW1lLmNzcyk7XG5odG1sIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7IH1cblxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xuICBib3gtc2l6aW5nOiBpbmhlcml0O1xuICAtd2Via2l0LWJveC1zaXppbmc6IGluaGVyaXQ7XG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcbiAgbWFyZ2luOiAwO1xuICBwYWRkaW5nOiAwO1xuICAtd2Via2l0LXRvdWNoLWNvbGxvdXQ6IG5vbmU7XG4gIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1vei11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1zLXVzZXItc2VsZWN0OiBub25lO1xuICB1c2VyLXNlbGVjdDogbm9uZTsgfVxuXG5odG1sLCBib2R5LCBkaXYsIHNwYW4sIGFwcGxldCwgb2JqZWN0LCBpZnJhbWUsXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXG5hLCBhYmJyLCBhY3JvbnltLCBhZGRyZXNzLCBiaWcsIGNpdGUsIGNvZGUsXG5kZWwsIGRmbiwgZW0sIGltZywgaW5zLCBrYmQsIHEsIHMsIHNhbXAsXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxuYiwgdSwgaSwgY2VudGVyLFxuZGwsIGR0LCBkZCwgb2wsIHVsLCBsaSxcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxudGFibGUsIGNhcHRpb24sIHRib2R5LCB0Zm9vdCwgdGhlYWQsIHRyLCB0aCwgdGQsXG5hcnRpY2xlLCBhc2lkZSwgY2FudmFzLCBkZXRhaWxzLCBlbWJlZCxcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcbm1lbnUsIG5hdiwgb3V0cHV0LCBydWJ5LCBzZWN0aW9uLCBzdW1tYXJ5LFxudGltZSwgbWFyaywgYXVkaW8sIHZpZGVvIHtcbiAgYm9yZGVyOiAwO1xuICBmb250LXNpemU6IDEwMCU7XG4gIGZvbnQ6IGluaGVyaXQ7XG4gIHZlcnRpY2FsLWFsaWduOiBiYXNlbGluZTsgfVxuXG5hcnRpY2xlLCBhc2lkZSwgZGV0YWlscywgZmlnY2FwdGlvbiwgZmlndXJlLFxuZm9vdGVyLCBoZWFkZXIsIGhncm91cCwgbWVudSwgbmF2LCBzZWN0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7IH1cblxuYm9keSB7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICBmb250LXN0eWxlOiBub3JtYWw7IH1cblxub2wsIHVsIHtcbiAgbGlzdC1zdHlsZTogbm9uZTsgfVxuXG5ibG9ja3F1b3RlLCBxIHtcbiAgcXVvdGVzOiBub25lOyB9XG5cbmJsb2NrcXVvdGU6YmVmb3JlLCBibG9ja3F1b3RlOmFmdGVyLFxucTpiZWZvcmUsIHE6YWZ0ZXIge1xuICBjb250ZW50OiBub25lOyB9XG5cbnRhYmxlIHtcbiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcbiAgYm9yZGVyLXNwYWNpbmc6IDA7IH1cblxudGQsXG50aCB7XG4gIHBhZGRpbmc6IDA7IH1cblxuaW5wdXQge1xuICBvdXRsaW5lOiBub25lOyB9XG4gIGlucHV0Oi13ZWJraXQtYXV0b2ZpbGwge1xuICAgIC13ZWJraXQtYm94LXNoYWRvdzogMCAwIDAgMTAwMHB4IHdoaXRlIGluc2V0OyB9XG5cbmJ1dHRvbixcbmh0bWwgaW5wdXRbdHlwZT1cImJ1dHRvblwiXSxcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcbmlucHV0W3R5cGU9XCJzdWJtaXRcIl0ge1xuICAtd2Via2l0LWFwcGVhcmFuY2U6IGJ1dHRvbjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBvdXRsaW5lOiBub25lOyB9XG5cbmJ1dHRvbltkaXNhYmxlZF0sXG5odG1sIGlucHV0W2Rpc2FibGVkXSB7XG4gIGN1cnNvcjogZGVmYXVsdDsgfVxuXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXG5pbnB1dDo6LW1vei1mb2N1cy1pbm5lciB7XG4gIGJvcmRlcjogMDtcbiAgcGFkZGluZzogMDsgfVxuXG5pbnB1dCB7XG4gIGxpbmUtaGVpZ2h0OiBub3JtYWw7IH1cblxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXSB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDsgfVxuXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXTo6LXdlYmtpdC1zZWFyY2gtZGVjb3JhdGlvbiB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTsgfVxuXG5hIHtcbiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOyB9XG4gIGE6YWN0aXZlLCBhOmhvdmVyLCBhOmZvY3VzIHtcbiAgICBvdXRsaW5lOiAwOyB9XG5cbmkge1xuICBmb250LXN0eWxlOiBpdGFsaWM7IH1cblxuYiwgc3Ryb25nIHtcbiAgZm9udC13ZWlnaHQ6IDcwMDsgfVxuXG5pbWcge1xuICB3aWR0aDogYXV0bztcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IGF1dG87XG4gIHZlcnRpY2FsLWFsaWduOiB0b3A7XG4gIGJvcmRlcjogMDsgfVxuXG4uaGlkZGVuIHtcbiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS1kYXJrIC5hcHAtY29udGVudCAucHJlbG9hZGVyIC5sb2FkaW5nLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG5idXR0b24ge1xuICBib3JkZXI6IG5vbmU7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxLjVyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIG91dGxpbmU6IG5vbmU7XG4gIHBhZGRpbmc6IDAgMXJlbTtcbiAgaGVpZ2h0OiA0LjJyZW07IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0IHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjOWNhZGI3O1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbiksIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzc5ODQ4ZjtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzkwYTRhZTtcbiAgICBjb2xvcjogI2ZlZmVmZTsgfVxuICAudGhlbWUtZGFyayBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNiN2QxZTA7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKTpob3ZlciwgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTFhZWJiOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYWViZWM2OyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldDpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2E3YjljMjsgfVxuICAudGhlbWUtZ3JheSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmZvY3VzLCAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4YTk1OWY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNhN2I5YzI7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmO1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzgyZDdmZjsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4NmQ2ZmY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjYjNmZjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1OWI1ZmQ7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWZiNmZjOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzNzlmZmE7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDtcbiAgICBjb2xvcjogIzExMTkyMTsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkO1xuICAgIGNvbG9yOiAjMWExYTFhOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4ZGZjYzY7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzdiZjZjNjsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVhZDU4NjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjJlMGIyOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1Y2RjOWU7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1M2M3N2M7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGQwZTE7XG4gICAgY29sb3I6ICMxMTE5MjE7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzZWM1ZDc7XG4gICAgY29sb3I6ICMxYTFhMWE7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjZiNmM3O1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjODdmNGY1OyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzJlZGZlOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUyY2JkOTsgfVxuICAudGhlbWUtZGFyayBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyZDVlODsgfVxuICAudGhlbWUtZ3JheSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUwZDBlMTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzMWJlY2Y7IH1cbiAgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOyB9XG4gICAgLnRoZW1lLWRhcmsgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyYjM2NDQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmYzNDM4O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7XG4gICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgIGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAxcmVtO1xuICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgd2lkdGg6IDEuN3JlbTtcbiAgICAgIGhlaWdodDogMS43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQzNDU0YjsgfVxuXG4uaW5wdXQtYmxvY2sge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtOyB9XG4gIC5pbnB1dC1ibG9jayAud3JhcC1sYWJlbCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbiAgICBtaW4taGVpZ2h0OiAyLjRyZW07IH1cbiAgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICBmb250LXNpemU6IDEuM3JlbTtcbiAgICBsaW5lLWhlaWdodDogMi40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBsYWJlbCB7XG4gICAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ndGV4dCddLCAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLmlucHV0LWJsb2NrIHNlbGVjdCB7XG4gICAgYm9yZGVyOiBub25lO1xuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgIG91dGxpbmU6IG5vbmU7XG4gICAgcGFkZGluZzogMCAxcmVtO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogNC4ycmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1ncmF5IC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBpbnB1dFt0eXBlPSd0ZXh0J10sIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC5pbnB1dC1ibG9jay50ZXh0YXJlYSB7XG4gICAgaGVpZ2h0OiBhdXRvOyB9XG4gICAgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgICAgb3V0bGluZTogbm9uZTtcbiAgICAgIHBhZGRpbmc6IDFyZW07XG4gICAgICB3aWR0aDogMTAwJTtcbiAgICAgIG1pbi13aWR0aDogMTAwJTtcbiAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgIG1pbi1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG1heC1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xuICAgICAgcmVzaXplOiBub25lOyB9XG4gICAgICAudGhlbWUtZGFyayAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICBmb250LXNpemU6IDFyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuNHJlbTtcbiAgICBhbGlnbi1zZWxmOiBmbGV4LWVuZDtcbiAgICB0ZXh0LWFsaWduOiByaWdodDsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cbiAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICAgIGNvbG9yOiAjZmY1MjUyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgLmVycm9yLXRleHQge1xuICBjb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbmlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgZm9udC13ZWlnaHQ6IDQwMDtcbiAgcGFkZGluZy1sZWZ0OiAyLjRyZW07XG4gIC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcbiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLWtodG1sLXVzZXItc2VsZWN0OiBub25lO1xuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xuICAtbXMtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIHVzZXItc2VsZWN0OiBub25lOyB9XG4gIC50aGVtZS1kYXJrIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gICAgY29sb3I6ICM1NTY1NzY7IH1cbiAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgb3BhY2l0eTogMDsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDAuN3JlbTtcbiAgICBsZWZ0OiAwO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICB3aWR0aDogMS40cmVtO1xuICAgIGhlaWdodDogMS40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzRkYjFmZjsgfVxuICAgIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YmVmb3JlIHtcbiAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkICM0MmE1ZjU7IH1cbiAgICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzJjOTVmMTsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsOmFmdGVyIHtcbiAgICBjb250ZW50OiAnJztcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAxcmVtO1xuICAgIGxlZnQ6IDAuM3JlbTtcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgb3BhY2l0eTogMDtcbiAgICB3aWR0aDogMC44cmVtO1xuICAgIGhlaWdodDogMC44cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gICAgLnRoZW1lLXdoaXRlIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YWZ0ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOmNoZWNrZWQgKyBsYWJlbDphZnRlciB7XG4gIG9wYWNpdHk6IDE7IH1cblxuaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LXdlaWdodDogNDAwO1xuICBwYWRkaW5nLWxlZnQ6IDMuNnJlbTtcbiAgLXdlYmtpdC10b3VjaC1jb2xsb3V0OiBub25lO1xuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xuICAta2h0bWwtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tb3otdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6bm90KGNoZWNrZWQpIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDUwJTtcbiAgbGVmdDogMS42cmVtO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjsgfVxuICBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiAxLjZyZW07XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIHdpZHRoOiAxLjRyZW07XG4gICAgaGVpZ2h0OiAxLjRyZW07IH1cbiAgICAudGhlbWUtZGFyayBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzQyYTVmNTsgfVxuICAgIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjMmM5NWYxOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zyk7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS13aGl0ZSAuc3dpdGNoIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayAuc3dpdGNoIC5jaXJjbGUub24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vZmYge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTBhNWFiOyB9XG5cbi50YWJsZS10b29sdGlwIHtcbiAgcGFkZGluZzogMXJlbSAycmVtOyB9XG4gIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcCB7XG4gICAgYmFja2dyb3VuZDogIzNlNDY0YztcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAudGFibGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gICAgZm9udC1zaXplOiAxLjNyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3Age1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3A6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAtMXJlbTtcbiAgICAgIGxlZnQ6IDAuN3JlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICByaWdodDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6ICNmZmZmZmYgI2ZmZmZmZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tOmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIGxlZnQ6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b206YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGMgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQ7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLWxlZnQ6YmVmb3JlIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IC0xcmVtO1xuICAgICAgbGVmdDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgI2ZmZmZmZjsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIHJpZ2h0OiAwLjdyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICMzZTQ2NGMgIzNlNDY0YyB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIHJpZ2h0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cbiAgICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBsZWZ0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS1ncmF5IC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQ6YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cblxuLnRhYmxlLXRvb2x0aXAtZGltZW5zaW9ucyAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICBtYXgtd2lkdGg6IDIwcmVtO1xuICBtYXgtaGVpZ2h0OiAxMHJlbTsgfVxuXG4uYmFsYW5jZS10b29sdGlwIHtcbiAgcGFkZGluZzogMS4zcmVtOyB9XG4gIC50aGVtZS1kYXJrIC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICM0MjUwNWY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS1ncmF5IC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZm9udC1zaXplOiAxLjNyZW07IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMC43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgIGN1cnNvcjogcG9pbnRlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmJhbGFuY2UtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAubGluayB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLXRvcCB7XG4gICAgbWFyZ2luLXRvcDogLTFyZW07IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAuYmFsYW5jZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gIC5iYWxhbmNlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cblxuLmFjY291bnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XG4gIG1heC13aWR0aDogMThyZW07IH1cblxuLmNvbW1lbnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICB3b3JkLWJyZWFrOiBicmVhay13b3JkO1xuICBtYXgtd2lkdGg6IDUwcmVtO1xuICBtYXgtaGVpZ2h0OiAyNXJlbTsgfVxuXG4udXBkYXRlLXRvb2x0aXAge1xuICBwYWRkaW5nOiAxLjVyZW07IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICNmZmZmZmY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpO1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQge1xuICAgIGJhY2tncm91bmQ6ICM1ZjJiMTE7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogIzU1MjQwZDtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogI2VmNmMwMDtcbiAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuaW1wb3J0YW50Lm5nLXRvb2x0aXAtbGVmdC1ib3R0b206YWZ0ZXIge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExOyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNTUyNDBkICM1NTI0MGQ7IH1cbiAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjZWY2YzAwICNlZjZjMDA7IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExIHRyYW5zcGFyZW50OyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1yaWdodC1ib3R0b206YmVmb3JlIHtcbiAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1NTI0MGQgIzU1MjQwZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2VmNmMwMCAjZWY2YzAwIHRyYW5zcGFyZW50OyB9XG4gIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgcGFkZGluZzogMi41cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICM1ZjFkMWQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgICBiYWNrZ3JvdW5kOiAjNGMxOTE5O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICNlNTM5MzU7XG4gICAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCAudG9vbHRpcC1pbm5lciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7IH1cbiAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuY3JpdGljYWwubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzRjMTkxOSAjNGMxOTE5OyB9XG4gICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2U1MzkzNSAjZTUzOTM1OyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZCB0cmFuc3BhcmVudDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjNGMxOTE5ICM0YzE5MTkgdHJhbnNwYXJlbnQ7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNlNTM5MzUgI2U1MzkzNSB0cmFuc3BhcmVudDsgfVxuICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIge1xuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgICBjb2xvcjogIzJjOTVmMTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmltcG9ydGFudC11cGRhdGUge1xuICAgICAgICBjb2xvcjogI2ZmNmYwMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmZmZmZmOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5jcml0aWNhbC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xuICAgICAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZjZmMDA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAud3JvbmctdGltZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZmZmZmY7IH1cbiAgICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgbWFyZ2luOiAxLjVyZW0gMDtcbiAgICAgIHdpZHRoOiA1cmVtO1xuICAgICAgaGVpZ2h0OiA1cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xLjVyZW07IH1cbiAgICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAwLjZyZW07XG4gICAgICByaWdodDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmICM0MjUwNWY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjM2U0NjRjICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmOyB9XG4gIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogMC42cmVtO1xuICAgICAgbGVmdDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgIzQyNTA1ZiB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICBib3JkZXI6IG5vbmU7XG4gIHBhZGRpbmc6IDA7IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJiMzY0NDtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgbGkge1xuICBkaXNwbGF5OiBibG9jaztcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xuICBmb250LXNpemU6IDEuM3JlbTtcbiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgYSB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBwYWRkaW5nOiAwLjVlbSAxZW07IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSBhIHtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGE6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuXG4ubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qge1xuICB3aWR0aDogMTAwJTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSB7XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICBoZWlnaHQ6IDQuMnJlbTsgfVxuICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtZ3JheSAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciB7XG4gICAgICBwYWRkaW5nOiAwOyB9XG4gICAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXQge1xuICAgICAgICB0b3A6IGF1dG87IH1cbiAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgYm9yZGVyOiBub25lOyB9XG4gICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3OyB9XG4gICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjsgfVxuICAgIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgZm9udC1zaXplOiAxLjRyZW07XG4gICAgICBwYWRkaW5nOiAxcmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLW1hcmtlZCB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjQwLCAyNDAsIDI0MCwgMC41KTtcbiAgICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXM6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgICAgY3Vyc29yOiBkZWZhdWx0O1xuICAgICAgd2lkdGg6IDFyZW07XG4gICAgICBoZWlnaHQ6IDFyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xuICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICAgIGJhY2tncm91bmQtY2xpcDogcGFkZGluZy1ib3g7XG4gICAgICBib3JkZXI6IDAuMjVyZW0gc29saWQgdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwsIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZyk7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWdyYXkgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3IsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmFjdGlvbi1idXR0b24sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSB7XG4gIGJvcmRlci10b3A6IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmxhYmVsIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHJhbnNhY3Rpb24tZGV0YWlscyAudGFibGUgLnJvdyAuY2VsbC52YWx1ZSB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmtleS12YWx1ZSB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNjNhM2U7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZGFyay5wbmcpO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtb3Blbi13YWxsZXQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKTtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC50aXRsZSB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmYzNDM4OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbmFwcC1tYWluLCBhcHAtY3JlYXRlLXdhbGxldCwgYXBwLW9wZW4td2FsbGV0LCBhcHAtcmVzdG9yZS13YWxsZXQsIGFwcC1zZWVkLXBocmFzZSwgYXBwLXdhbGxldC1kZXRhaWxzLCBhcHAtYXNzaWduLWFsaWFzLCBhcHAtZWRpdC1hbGlhcywgYXBwLXRyYW5zZmVyLWFsaWFzLCBhcHAtc2V0dGluZ3MsIGFwcC1sb2dpbiB7XG4gIGZsZXg6IDEgMSBhdXRvO1xuICBwYWRkaW5nOiAzcmVtO1xuICBtaW4td2lkdGg6IDg1cmVtOyB9XG4gIGFwcC1tYWluIC5jb250ZW50LCBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXJlc3RvcmUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWFzc2lnbi1hbGlhcyAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWxvZ2luIC5jb250ZW50IHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC41KTtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgYXBwLW1haW4gLmNvbnRlbnQgLmhlYWQsIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50IC5oZWFkLCBhcHAtb3Blbi13YWxsZXQgLmNvbnRlbnQgLmhlYWQsIGFwcC1yZXN0b3JlLXdhbGxldCAuY29udGVudCAuaGVhZCwgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50IC5oZWFkLCBhcHAtd2FsbGV0LWRldGFpbHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hc3NpZ24tYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50IC5oZWFkLCBhcHAtdHJhbnNmZXItYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1zZXR0aW5ncyAuY29udGVudCAuaGVhZCwgYXBwLWxvZ2luIC5jb250ZW50IC5oZWFkIHtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMDtcbiAgICAgIGxlZnQ6IDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCAuYWRkLXdhbGxldCAuYWRkLXdhbGxldC1oZWxwIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5zZWVkLXBocmFzZS1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxNzFlMjc7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyOTJkMzE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQtZGV0YWlscyAuc2VlZC1waHJhc2Uge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2OyB9XG5cbmFwcC1zZXR0aW5ncyAuY29udGVudCB7XG4gIGhlaWdodDogMTAwJTtcbiAgb3ZlcmZsb3cteTogYXV0bztcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnRoZW1lLXNlbGVjdGlvbiB7XG4gICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpOyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cbiAgLnRoZW1lLWRhcmsgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2sgLmxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSAubGFiZWwge1xuICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cblxuYXBwLWxvZ2luIHtcbiAgbWluLXdpZHRoOiBpbmhlcml0OyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWYyNzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxYzFlMjE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBoMyB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIgYnV0dG9uIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTtcbiAgY29sb3I6ICNmZWZlZmU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM2M2EzZTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMWU4OGU1O1xuICBjb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdy5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50OmhvdmVyOm5vdCguYWN0aXZlKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDY5LCA4NSwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzOmFmdGVyIHtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KHRvIGJvdHRvbSwgdHJhbnNwYXJlbnQgMCUsICMxNzFmMjcgMTAwJSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgIzFjMWUyMSAxMDAlKTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgd2hpdGUgMTAwJSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3Mge1xuICBib3JkZXItYm90dG9tOiAwLjJyZW0gc29saWQgIzFmMjgzMzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmUzMzM3OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSkgIWltcG9ydGFudDtcbiAgY29sb3I6ICNlMGUwZTAgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSAhaW1wb3J0YW50O1xuICBjb2xvcjogI2UwZTBlMCAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxZTg4ZTUgIWltcG9ydGFudDtcbiAgY29sb3I6ICNmZmZmZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjUgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmICFpbXBvcnRhbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vZmZsaW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAub25saW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnN5bmNpbmcgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAubG9hZGluZyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuc3RhbmRhcmQge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pbXBvcnRhbnQge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5jcml0aWNhbCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLnRpbWUge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLnN0YW5kYXJkIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5pbXBvcnRhbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uY3JpdGljYWwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24udGltZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5oZWFkZXIgYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIC5hbGlhcyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3Mge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5hZGRyZXNzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyMywgMzEsIDM5LCAwLjUpOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI4LCAzMCwgMzMsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIC5pbmRpY2F0b3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYi5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2MiwgNjYsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWI6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQgLmZvcm0tc2VuZCAuc2VuZC1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZCAuZm9ybS1zZW5kIC5hZGRpdGlvbmFsLWRldGFpbHMge1xuICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1yZWNlaXZlIC5idG4tY29weS1hZGRyZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ci5sb2NrZWQtdHJhbnNhY3Rpb24ge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMSkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTgyMDJhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzIpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMykge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMgLmNvbmZpcm1hdGlvbiAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC51bmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnNlbmQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnJlY2VpdmVkIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWNkYTlkOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZ3JheSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLm5ldywgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLmFsZXJ0IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24uc2VsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ucHVyY2hhc2UsIC50aGVtZS1ncmF5IGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAucHVyY2hhc2Utc2VsZWN0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3QgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zdGF0ZXMge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgIzJiMzY0NDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgI2ViZWJlYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNDNmNGE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIgLnByb2dyZXNzLWJhci1mdWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbmFwcC1tZXNzYWdlcyB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCBzcGFuIHtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1lc3NhZ2VzIHRhYmxlIHRib2R5IHRyIHRkOmZpcnN0LWNoaWxkIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10eXBpbmctbWVzc2FnZSAuaGVhZCAuaW50ZXJsb2N1dG9yIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5kYXRlIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYTM1NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzMDM2M2M7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcIjtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICBsZWZ0OiAtMS4xcmVtO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzJhMzU0NDsgfVxuICAudGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzMwMzYzYzsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teTpiZWZvcmUge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxODIwMmE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWRlZGVkOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICBjb250ZW50OiBcIlwiO1xuICBkaXNwbGF5OiBibG9jaztcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICByaWdodDogLTEuMXJlbTtcbiAgdG9wOiAwO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmJ1ZGR5OmFmdGVyIHtcbiAgICBib3JkZXItdG9wLWNvbG9yOiAjMTgyMDJhOyB9XG4gIC50aGVtZS1ncmF5IGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICMyNTI5MmQ7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNlZGVkZWQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LWhlYWRlciAuZ2VuZXJhbCAubGFiZWwge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5vcHRpb25zIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG5hcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5zZWxlY3RlZCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gIGZsZXgtZ3JvdzogMTtcbiAgZm9udC1zaXplOiAxLjZyZW07IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC50aXRsZSB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzUxNTk2MDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLm9wdGlvbnMgYnV0dG9uLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLmlucHV0LWJsb2NrLWFsaWFzIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlOyB9XG4gIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDYuNXJlbTtcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcbiAgICBvdmVyZmxvdzogYXV0bztcbiAgICB3aWR0aDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdiB7XG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICAgIHBhZGRpbmc6IDFyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpOyB9XG4gICAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdjpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbmFwcC1jb250YWN0cywgYXBwLWFkZC1jb250YWN0cyxcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcbiAgZmxleDogMSAxIGF1dG87XG4gIHBhZGRpbmc6IDNyZW07XG4gIG1pbi13aWR0aDogODVyZW07IH1cbiAgYXBwLWNvbnRhY3RzIC5jb250ZW50LCBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LFxuICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmtcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXlcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmNvbnRlbnQsIC50aGVtZS13aGl0ZSBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LCAudGhlbWUtd2hpdGVcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjUpO1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICBhcHAtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hZGQtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsXG4gICAgYXBwLWNvbnRhY3Qtc2VuZCAuY29udGVudCAuaGVhZCwgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQgLmhlYWQge1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAwO1xuICAgICAgbGVmdDogMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIC5hbGlhcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgYnV0dG9uIHNwYW4ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgLmZvb3RlciB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIC5mb290ZXIgLmltcG9ydC1idG4ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWNvbnRhY3Qtc2VuZCAud2FsbGV0cy1zZWxlY3Rpb24gYnV0dG9uIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLmhlYWQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgZm9udC1zaXplOiAxLjNyZW07XG4gIHBhZGRpbmc6IDAgM3JlbTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogM3JlbTsgfVxuICAudGhlbWUtZGFyayAuaGVhZCB7XG4gICAgY29sb3I6ICM0ZGIxZmY7IH1cbiAgLnRoZW1lLWdyYXkgLmhlYWQge1xuICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSAuaGVhZCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIG1hcmdpbi1yaWdodDogMjBweDtcbiAgICBvdXRsaW5lLXN0eWxlOiBub25lOyB9XG4gICAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMC41cmVtO1xuICAgICAgcmlnaHQ6IC0xLjVyZW07XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctcmlnaHQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgbWFzay1zaXplOiBjb3ZlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZGFyayAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZ3JheSAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyA+IHNwYW46bm90KDpsYXN0LWNoaWxkKTphZnRlciwgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyBhOm5vdCg6bGFzdC1jaGlsZCk6YWZ0ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG4gIC5oZWFkIC5iYWNrLWJ0biB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIGNvbG9yOiAjNGRiMWZmO1xuICAgIGZvbnQtc2l6ZTogaW5oZXJpdDtcbiAgICBmb250LXdlaWdodDogNDAwO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XG4gICAgcGFkZGluZzogMDtcbiAgICBoZWlnaHQ6IGF1dG87IH1cbiAgICAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYmFjay5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi5zY3JvbGxlZC1jb250ZW50Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBjdXJzb3I6IGRlZmF1bHQ7XG4gIHdpZHRoOiAxcmVtO1xuICBoZWlnaHQ6IDFyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRyYWNrIHtcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcbiAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xuICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG50YWJsZSB7XG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xuICB3aWR0aDogMTAwJTsgfVxuICB0YWJsZSB0aGVhZCB7XG4gICAgdGV4dC1hbGlnbjogbGVmdDsgfVxuICAgIC50aGVtZS1kYXJrIHRhYmxlIHRoZWFkIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgICAudGhlbWUtd2hpdGUgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICNhMGE1YWI7IH1cbiAgICB0YWJsZSB0aGVhZCB0ciB7XG4gICAgICBoZWlnaHQ6IDRyZW07IH1cbiAgICAgIHRhYmxlIHRoZWFkIHRyIHRoIHtcbiAgICAgICAgcGFkZGluZzogMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IGJvdHRvbTsgfVxuICAgICAgICB0YWJsZSB0aGVhZCB0ciB0aDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRoZWFkIHRyIHRoOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cbiAgdGFibGUgdGJvZHkge1xuICAgIHRleHQtYWxpZ246IGxlZnQ7IH1cbiAgICAudGhlbWUtZGFyayB0YWJsZSB0Ym9keSB7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgdGFibGUgdGJvZHkgdHIge1xuICAgICAgaGVpZ2h0OiAzLjVyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZChvZGQpIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuICAgICAgLnRoZW1lLWdyYXkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG4gICAgICAudGhlbWUtd2hpdGUgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG4gICAgICB0YWJsZSB0Ym9keSB0ciB0ZCB7XG4gICAgICAgIGxpbmUtaGVpZ2h0OiAxLjdyZW07XG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTsgfVxuICAgICAgICB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRib2R5IHRyIHRkOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtTGlnaHQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDMwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA0MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtU2VtaUJvbGQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDYwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1Cb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA4MDA7IH1cblxuaHRtbCB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxMHB4OyB9XG5cbmJvZHkge1xuICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XG4gIGZvbnQtc2l6ZTogMS42cmVtO1xuICB3aWR0aDogMTAwdnc7XG4gIGhlaWdodDogMTAwdmg7IH1cbiAgYm9keS50aGVtZS1kYXJrIHtcbiAgICBiYWNrZ3JvdW5kOiAjMTMxOTIxIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS1ncmF5IHtcbiAgICBiYWNrZ3JvdW5kOiAjMTAxNDE3IHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS13aGl0ZSB7XG4gICAgYmFja2dyb3VuZDogI2VlZWVlZSB1cmwoXCJhc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgYmFja2dyb3VuZC1zaXplOiBjb3ZlcjsgfVxuICBib2R5IGFwcC1yb290IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTsgfVxuXG4udXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7IH1cbiIsIi5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcntiYWNrZ3JvdW5kOiNmZmY7Ym9yZGVyLWNvbG9yOiNiM2IzYjMgI2NjYyAjZDlkOWQ5fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcjpob3Zlcntib3gtc2hhZG93Om5vbmV9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy1hcnJvd3t0b3A6LTJweDtib3JkZXItY29sb3I6dHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzk5OTtib3JkZXItd2lkdGg6MCA1cHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lciAubmctYXJyb3c6aG92ZXJ7Ym9yZGVyLWNvbG9yOnRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzMzN9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC1ib3R0b20+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6MDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC10b3A+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MDtib3JkZXItdG9wLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtZm9jdXNlZDpub3QoLm5nLXNlbGVjdC1vcGVuZWQpPi5uZy1zZWxlY3QtY29udGFpbmVye2JvcmRlci1jb2xvcjojMDA3ZWZmO2JveC1zaGFkb3c6aW5zZXQgMCAxcHggMXB4IHJnYmEoMCwwLDAsMC4wNzUpLDAgMCAwIDNweCByZ2JhKDAsMTI2LDI1NSwwLjEpfS5uZy1zZWxlY3Qubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0IC5uZy1oYXMtdmFsdWUgLm5nLXBsYWNlaG9sZGVye2Rpc3BsYXk6bm9uZX0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2ZmZjtib3JkZXItcmFkaXVzOjRweDtib3JkZXI6MXB4IHNvbGlkICNjY2M7bWluLWhlaWdodDozNnB4O2FsaWduLWl0ZW1zOmNlbnRlcn0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyOmhvdmVye2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lcnthbGlnbi1pdGVtczpjZW50ZXI7cGFkZGluZy1sZWZ0OjEwcHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy1yaWdodDoxMHB4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1zaW5nbGUgLm5nLXNlbGVjdC1jb250YWluZXJ7aGVpZ2h0OjM2cHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtc2luZ2xlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3RvcDo1cHg7bGVmdDowO3BhZGRpbmctbGVmdDoxMHB4O3BhZGRpbmctcmlnaHQ6NTBweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy1pbnB1dHtwYWRkaW5nLXJpZ2h0OjEwcHg7cGFkZGluZy1sZWZ0OjUwcHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOTtib3JkZXI6MXB4IHNvbGlkICNlNmU2ZTZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nOjAgNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy10b3A6NXB4O3BhZGRpbmctbGVmdDo3cHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVye3BhZGRpbmctcmlnaHQ6N3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2ZvbnQtc2l6ZTouOWVtO21hcmdpbi1ib3R0b206NXB4O2JhY2tncm91bmQtY29sb3I6I2ViZjVmZjtib3JkZXItcmFkaXVzOjJweDttYXJnaW4tcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWV7bWFyZ2luLXJpZ2h0OjA7bWFyZ2luLWxlZnQ6NXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVke2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZS5uZy12YWx1ZS1kaXNhYmxlZCAubmctdmFsdWUtbGFiZWx7cGFkZGluZy1sZWZ0OjVweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVkIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nLWxlZnQ6MDtwYWRkaW5nLXJpZ2h0OjVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtbGFiZWx7ZGlzcGxheTppbmxpbmUtYmxvY2s7cGFkZGluZzoxcHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29ue2Rpc3BsYXk6aW5saW5lLWJsb2NrO3BhZGRpbmc6MXB4IDVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbjpob3ZlcntiYWNrZ3JvdW5kLWNvbG9yOiNkMWU4ZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ubGVmdHtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbi5sZWZ0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmO2JvcmRlci1yaWdodDpub25lfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29uLnJpZ2h0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ucmlnaHR7Ym9yZGVyLWxlZnQ6MDtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXR7cGFkZGluZzowIDAgM3B4IDNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3BhZGRpbmc6MCAzcHggM3B4IDB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7dG9wOjVweDtwYWRkaW5nLWJvdHRvbTo1cHg7cGFkZGluZy1sZWZ0OjNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXBsYWNlaG9sZGVye3BhZGRpbmctcmlnaHQ6M3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLWNsZWFyLXdyYXBwZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0IC5uZy1jbGVhci13cmFwcGVyOmhvdmVyIC5uZy1jbGVhcntjb2xvcjojRDAwMjFCfS5uZy1zZWxlY3QgLm5nLXNwaW5uZXItem9uZXtwYWRkaW5nOjVweCA1cHggMCAwfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctc3Bpbm5lci16b25le3BhZGRpbmc6NXB4IDAgMCA1cHh9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcnt3aWR0aDoyNXB4O3BhZGRpbmctcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcntwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH0ubmctc2VsZWN0IC5uZy1hcnJvdy13cmFwcGVyOmhvdmVyIC5uZy1hcnJvd3tib3JkZXItdG9wLWNvbG9yOiM2NjZ9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlciAubmctYXJyb3d7Ym9yZGVyLWNvbG9yOiM5OTkgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDo1cHggNXB4IDIuNXB4fS5uZy1kcm9wZG93bi1wYW5lbHtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjY2NjO2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpO2xlZnQ6MH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbXt0b3A6MTAwJTtib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1jb2xvcjojZTZlNmU2O21hcmdpbi10b3A6LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbSAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpsYXN0LWNoaWxke2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjRweDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjRweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcHtib3R0b206MTAwJTtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1jb2xvcjojZTZlNmU2O21hcmdpbi1ib3R0b206LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpmaXJzdC1jaGlsZHtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1oZWFkZXJ7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1mb290ZXJ7Ym9yZGVyLXRvcDoxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXB7dXNlci1zZWxlY3Q6bm9uZTtwYWRkaW5nOjhweCAxMHB4O2ZvbnQtd2VpZ2h0OjUwMDtjb2xvcjpyZ2JhKDAsMCwwLDAuNTQpO2N1cnNvcjpwb2ludGVyfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGdyb3VwLm5nLW9wdGlvbi1kaXNhYmxlZHtjdXJzb3I6ZGVmYXVsdH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tc2VsZWN0ZWQsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXAubmctb3B0aW9uLXNlbGVjdGVkLm5nLW9wdGlvbi1tYXJrZWR7YmFja2dyb3VuZC1jb2xvcjojZWJmNWZmO2ZvbnQtd2VpZ2h0OjYwMH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb257YmFja2dyb3VuZC1jb2xvcjojZmZmO2NvbG9yOnJnYmEoMCwwLDAsMC44Nyk7cGFkZGluZzo4cHggMTBweH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkLC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQubmctb3B0aW9uLW1hcmtlZHtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6I2ViZjVmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIC5uZy1vcHRpb24tbGFiZWwsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1zZWxlY3RlZC5uZy1vcHRpb24tbWFya2VkIC5uZy1vcHRpb24tbGFiZWx7Zm9udC13ZWlnaHQ6NjAwfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZjtjb2xvcjojMzMzfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tZGlzYWJsZWR7Y29sb3I6I2NjY30ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLWNoaWxke3BhZGRpbmctbGVmdDoyMnB4fVtkaXI9XCJydGxcIl0gLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1jaGlsZHtwYWRkaW5nLXJpZ2h0OjIycHg7cGFkZGluZy1sZWZ0OjB9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIC5uZy10YWctbGFiZWx7Zm9udC1zaXplOjgwJTtmb250LXdlaWdodDo0MDA7cGFkZGluZy1yaWdodDo1cHh9W2Rpcj1cInJ0bFwiXSAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24gLm5nLXRhZy1sYWJlbHtwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH1bZGlyPVwicnRsXCJdIC5uZy1kcm9wZG93bi1wYW5lbHtkaXJlY3Rpb246cnRsO3RleHQtYWxpZ246cmlnaHR9XG4iLCIvLyogKioqKioqKiByZXNldCAmIG5vcm1hbGl6ZSAqKioqKioqICAqLy9cclxuXHJcbi8vIGJveC1zaXppbmcgdGhlIHNhbWUgZm9yIGFsbCBlbGVtZW50c1xyXG5odG1sIHtcclxuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7XHJcbn1cclxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xyXG4gIGJveC1zaXppbmc6IGluaGVyaXQ7XHJcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBpbmhlcml0O1xyXG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcclxuICBtYXJnaW46IDA7XHJcbiAgcGFkZGluZzogMDtcclxuICBAaW5jbHVkZSB1blNlbGVjdDtcclxufVxyXG5cclxuaHRtbCwgYm9keSwgZGl2LCBzcGFuLCBhcHBsZXQsIG9iamVjdCwgaWZyYW1lLFxyXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXHJcbmEsIGFiYnIsIGFjcm9ueW0sIGFkZHJlc3MsIGJpZywgY2l0ZSwgY29kZSxcclxuZGVsLCBkZm4sIGVtLCBpbWcsIGlucywga2JkLCBxLCBzLCBzYW1wLFxyXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxyXG5iLCB1LCBpLCBjZW50ZXIsXHJcbmRsLCBkdCwgZGQsIG9sLCB1bCwgbGksXHJcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxyXG50YWJsZSwgY2FwdGlvbiwgdGJvZHksIHRmb290LCB0aGVhZCwgdHIsIHRoLCB0ZCxcclxuYXJ0aWNsZSwgYXNpZGUsIGNhbnZhcywgZGV0YWlscywgZW1iZWQsXHJcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcclxubWVudSwgbmF2LCBvdXRwdXQsIHJ1YnksIHNlY3Rpb24sIHN1bW1hcnksXHJcbnRpbWUsIG1hcmssIGF1ZGlvLCB2aWRlbyB7XHJcbiAgICBib3JkZXI6IDA7XHJcbiAgICBmb250LXNpemU6IDEwMCU7XHJcbiAgICBmb250OiBpbmhlcml0O1xyXG4gICAgdmVydGljYWwtYWxpZ246IGJhc2VsaW5lO1xyXG59XHJcbmFydGljbGUsIGFzaWRlLCBkZXRhaWxzLCBmaWdjYXB0aW9uLCBmaWd1cmUsXHJcbmZvb3RlciwgaGVhZGVyLCBoZ3JvdXAsIG1lbnUsIG5hdiwgc2VjdGlvbiB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxufVxyXG5cclxuYm9keSB7XHJcbiAgIGxpbmUtaGVpZ2h0OiAxO1xyXG4gICBmb250LXN0eWxlOiBub3JtYWw7XHJcbn1cclxub2wsIHVsIHtcclxuICAgIGxpc3Qtc3R5bGU6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZSwgcSB7XHJcbiAgICBxdW90ZXM6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZTpiZWZvcmUsIGJsb2NrcXVvdGU6YWZ0ZXIsXHJcbnE6YmVmb3JlLCBxOmFmdGVyIHtcclxuICAgIGNvbnRlbnQ6IG5vbmU7XHJcbn1cclxuXHJcbi8vdGFibGVcclxudGFibGUge1xyXG4gICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcclxuICAgIGJvcmRlci1zcGFjaW5nOiAwO1xyXG59XHJcbnRkLFxyXG50aCB7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5cclxuLy9mb3JtcyBlbGVtZW50XHJcbmlucHV0IHtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAmOi13ZWJraXQtYXV0b2ZpbGwge1xyXG4gICAgICAtd2Via2l0LWJveC1zaGFkb3c6IDAgMCAwIDEwMDBweCB3aGl0ZSBpbnNldDtcclxuICAgIH1cclxufVxyXG5cclxuYnV0dG9uLFxyXG5odG1sIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXHJcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcclxuaW5wdXRbdHlwZT1cInN1Ym1pdFwiXSB7XHJcbiAgLXdlYmtpdC1hcHBlYXJhbmNlOiBidXR0b247XHJcbiAgY3Vyc29yOiBwb2ludGVyO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbn1cclxuYnV0dG9uW2Rpc2FibGVkXSxcclxuaHRtbCBpbnB1dFtkaXNhYmxlZF0ge1xyXG4gIGN1cnNvcjogZGVmYXVsdDtcclxufVxyXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXHJcbmlucHV0OjotbW96LWZvY3VzLWlubmVyIHtcclxuICBib3JkZXI6IDA7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5pbnB1dCB7XHJcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IHRleHRmaWVsZDtcclxuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1kZWNvcmF0aW9uIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XHJcbn1cclxuXHJcblxyXG4vL2xpbmtcclxuYSB7XHJcblx0dGV4dC1kZWNvcmF0aW9uOiBub25lO1xyXG5cdCY6YWN0aXZlLFxyXG5cdCY6aG92ZXIsXHJcblx0Jjpmb2N1cyB7XHJcblx0XHRvdXRsaW5lOiAwO1xyXG5cdH1cclxufVxyXG5cclxuaSB7IGZvbnQtc3R5bGU6IGl0YWxpYzsgfVxyXG5iLCBzdHJvbmcgeyBmb250LXdlaWdodDogNzAwOyAgIH1cclxuXHJcbi8vIGltYWdlc1xyXG5pbWcge1xyXG5cdHdpZHRoOiBhdXRvO1xyXG5cdG1heC13aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IGF1dG87XHJcbiAgdmVydGljYWwtYWxpZ246IHRvcDtcclxuXHRib3JkZXI6IDA7XHJcbn1cclxuXHJcbi5oaWRkZW4ge1xyXG4gIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDtcclxufVxyXG4iLCIuYXBwLWNvbnRlbnQge1xyXG5cclxuICAucHJlbG9hZGVyIHtcclxuXHJcbiAgICAubG9hZGluZy1iYXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmJ1dHRvbiB7XHJcbiAgYm9yZGVyOiBub25lO1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNXJlbTtcclxuICBmb250LXdlaWdodDogNjAwO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbiAgcGFkZGluZzogMCAxcmVtO1xyXG4gIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAmOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgXHJcbiAgJi5ibHVlLWJ1dHRvbl9yZXNldHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhbHRlcm5hdGl2ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJjpob3ZlciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYuYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlbkJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYudHJhbnNwYXJlbnQtYnV0dG9uIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDFyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDEuN3JlbTtcclxuICAgICAgaGVpZ2h0OiAxLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuLmlucHV0LWJsb2NrIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtO1xyXG5cclxuICAud3JhcC1sYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICAgIG1pbi1oZWlnaHQ6IDIuNHJlbTtcclxuICB9XHJcblxyXG4gIGxhYmVsIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbnB1dFt0eXBlPSd0ZXh0J10sIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIHNlbGVjdCB7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICBwYWRkaW5nOiAwIDFyZW07XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50ZXh0YXJlYSB7XHJcbiAgICBoZWlnaHQ6IGF1dG87XHJcblxyXG4gICAgdGV4dGFyZWEge1xyXG4gICAgICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XHJcbiAgICAgIGJvcmRlcjogbm9uZTtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtaW4td2lkdGg6IDEwMCU7XHJcbiAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgbWluLWhlaWdodDogNy41cmVtO1xyXG4gICAgICBtYXgtaGVpZ2h0OiA3LjVyZW07XHJcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgICByZXNpemU6IG5vbmU7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5lcnJvci1ibG9jayB7XHJcbiAgICBmb250LXNpemU6IDFyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS40cmVtO1xyXG4gICAgYWxpZ24tc2VsZjogZmxleC1lbmQ7XHJcbiAgICB0ZXh0LWFsaWduOiByaWdodDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmVycm9yLXRleHQge1xyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gIH1cclxufVxyXG5cclxuaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyB7XHJcblxyXG4gICYgKyBsYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICBwYWRkaW5nLWxlZnQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgQGluY2x1ZGUgdW5TZWxlY3Q7XHJcbiAgfVxyXG5cclxuICAmOm5vdChjaGVja2VkKSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICBvcGFjaXR5OiAwO1xyXG5cclxuICAgICYgKyBsYWJlbCB7XHJcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIH1cclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAwLjdyZW07XHJcbiAgICAgIGxlZnQ6IDA7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXItcmFkaXVzOiA1MCU7XHJcbiAgICAgIHdpZHRoOiAxLjRyZW07XHJcbiAgICAgIGhlaWdodDogMS40cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAxcmVtO1xyXG4gICAgICBsZWZ0OiAwLjNyZW07XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcclxuICAgICAgb3BhY2l0eTogMDtcclxuICAgICAgd2lkdGg6IDAuOHJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjhyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICY6Y2hlY2tlZCB7XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgb3BhY2l0eTogMTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3gge1xyXG5cclxuICAmICsgbGFiZWwge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgcGFkZGluZy1sZWZ0OiAzLjZyZW07XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIEBpbmNsdWRlIHVuU2VsZWN0O1xyXG4gIH1cclxuXHJcbiAgJjpub3QoY2hlY2tlZCkge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiA1MCU7XHJcbiAgICBsZWZ0OiAxLjZyZW07XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICB2aXNpYmlsaXR5OiBoaWRkZW47XHJcblxyXG4gICAgJiArIGxhYmVsIHtcclxuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgICYgKyBsYWJlbDpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiAnJztcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IDUwJTtcclxuICAgICAgbGVmdDogMS42cmVtO1xyXG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICB3aWR0aDogMS40cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuNHJlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkIHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJjpjaGVja2VkIHtcclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLnN3aXRjaCB7XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAuY2lyY2xlIHtcclxuXHJcbiAgICAmLm9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICYub2ZmIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwIHtcclxuICBwYWRkaW5nOiAxcmVtIDJyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgYm94LXNoYWRvdzogdGhlbWVkKHRvb2x0aXBTaGFkb3cpO1xyXG4gICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcclxuICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC10b3Age1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogY2FsYyg1MCUgLSAwLjVyZW0pO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXRvcC1yaWdodCB7XHJcbiAgICBtYXJnaW4tdG9wOiAtMXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IC0xcmVtO1xyXG4gICAgICByaWdodDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKSB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0IHtcclxuICAgIG1hcmdpbi10b3A6IDFyZW07XHJcblxyXG4gICAgJjpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiBcIlwiO1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogLTFyZW07XHJcbiAgICAgIHJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtbGVmdCB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIHJpZ2h0OiAtMXJlbTtcclxuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XHJcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwLWRpbWVuc2lvbnMge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcbiAgICBvdmVyZmxvdzogYXV0bztcclxuICAgIG1heC13aWR0aDogMjByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5iYWxhbmNlLXRvb2x0aXAge1xyXG4gIHBhZGRpbmc6IDEuM3JlbTtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBiYWNrZ3JvdW5kOiB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcik7XHJcbiAgICBib3gtc2hhZG93OiB0aGVtZWQodG9vbHRpcFNoYWRvdyk7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuXHJcbiAgICAuYXZhaWxhYmxlIHtcclxuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtO1xyXG5cclxuICAgICAgYiB7XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5sb2NrZWQge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAwLjdyZW07XHJcblxyXG4gICAgICBiIHtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmxpbmsge1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wIHtcclxuICAgIG1hcmdpbi10b3A6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWxlZnQge1xyXG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmFjY291bnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XHJcbiAgICBtYXgtd2lkdGg6IDE4cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmNvbW1lbnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgd29yZC1icmVhazogYnJlYWstd29yZDtcclxuICAgIG1heC13aWR0aDogNTByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAyNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi51cGRhdGUtdG9vbHRpcCB7XHJcbiAgcGFkZGluZzogMS41cmVtO1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAmLmltcG9ydGFudCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJi5uZy10b29sdGlwLWxlZnQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YWZ0ZXIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcEltcG9ydGFudEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLmNyaXRpY2FsIHtcclxuICAgIHBhZGRpbmc6IDIuNXJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBDcml0aWNhbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC50b29sdGlwLWlubmVyIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtbGVmdC1ib3R0b20ge1xyXG5cclxuICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xyXG5cclxuICAgIC5zdGFuZGFyZC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuaW1wb3J0YW50LXVwZGF0ZSB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50VGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5jcml0aWNhbC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgfVxyXG5cclxuICAgIC53cm9uZy10aW1lIHtcclxuICAgICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXJnaW46IDEuNXJlbSAwO1xyXG4gICAgICB3aWR0aDogNXJlbTtcclxuICAgICAgaGVpZ2h0OiA1cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRvb2x0aXBDcml0aWNhbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTEuNXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgcmlnaHQ6IC0xcmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogMS41cmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmd4LWNvbnRleHRtZW51IHtcclxuXHJcbiAgLmRyb3Bkb3duLW1lbnUge1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgcGFkZGluZzogMDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxpIHtcclxuICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gIH1cclxuXHJcbiAgYSB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxuICAgIHBhZGRpbmc6IDAuNWVtIDFlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjaGFydE9wdGlvbnNIb3ZlckNvbG9yKTtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmctc2VsZWN0IHtcclxuXHJcbiAgJi5jdXN0b20tc2VsZWN0IHtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICYubmctc2VsZWN0LXNpbmdsZSB7XHJcbiAgICAgIC5uZy1zZWxlY3QtY29udGFpbmVyIHtcclxuICAgICAgICAubmctdmFsdWUtY29udGFpbmVyIHtcclxuICAgICAgICAgIC5uZy12YWx1ZSB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLXNlbGVjdC1jb250YWluZXIge1xyXG4gICAgICBib3JkZXI6IG5vbmU7XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDA7XHJcbiAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgaGVpZ2h0OiA0LjJyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5uZy12YWx1ZS1jb250YWluZXIge1xyXG4gICAgICAgIHBhZGRpbmc6IDA7XHJcblxyXG4gICAgICAgIC5uZy1pbnB1dCB7XHJcbiAgICAgICAgICB0b3A6IGF1dG87XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLWRyb3Bkb3duLXBhbmVsIHtcclxuICAgICAgYm9yZGVyOiBub25lO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIHtcclxuXHJcbiAgICAgICAgLm5nLW9wdGlvbiB7XHJcbiAgICAgICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgICAgIHBhZGRpbmc6IDFyZW07XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChpbnB1dEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tbWFya2VkIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzZWxlY3RIb3ZlckNvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tc2VsZWN0ZWQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdFNlbGVjdGVkQ29sb3IpO1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgY3Vyc29yOiBkZWZhdWx0O1xyXG4gICAgICAgICAgd2lkdGg6IDFyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDFyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOjotd2Via2l0LXNjcm9sbGJhci10cmFjayB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNsaXA6IHBhZGRpbmctYm94O1xyXG4gICAgICAgICAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tb2RhbC1jb250YWluZXIsIGFwcC1jb25maXJtLW1vZGFsICB7XHJcblxyXG4gIC5tb2RhbCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZChtb2RhbEJhY2tncm91bmQpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5jb250ZW50IHtcclxuXHJcbiAgICAgIC5pY29uLmVycm9yIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uLnN1Y2Nlc3Mge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbi5pbmZvIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmNsb3NlLWJ1dHRvbiB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNsb3NlQnV0dG9uQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMge1xyXG5cclxuICAudGFibGUge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBib3JkZXItdG9wOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5yb3cge1xyXG5cclxuICAgICAgLmNlbGwge1xyXG5cclxuICAgICAgICAmLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYua2V5LXZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1wcm9ncmVzcy1jb250YWluZXIge1xyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW9wZW4td2FsbGV0LW1vZGFsIHtcclxuXHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtc2VuZC1tb2RhbCB7XHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnRpdGxlIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59IiwiJHRoZW1lczogKFxyXG4gIGRhcms6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICMxMzE5MjEsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjMWYyODMzLFxyXG4gICAgb25saW5lQ29sb3I6ICM1Y2RhOWQsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICM0ZGIxZmYsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzVjZGE5ZCxcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0ZGIxZmYsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzgyZDdmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjNTliNWZkLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5Y2FkYjcsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNiN2QxZTAsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzhkZmNjNixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzYyZTBiMixcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzRkZDBlMSxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM4N2Y0ZjUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjNDJkNWU4LFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogIzJiMzY0NCxcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjMTcxZTI3LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogIzRkYjFmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgdGFibGVCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBtZXNzYWdlTXlCYWNrZ3JvdW5kQ29sb3I6ICMyYTM1NDQsXHJcbiAgICBtZXNzYWdlQnVkZHlCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcjogIzM0M2Y0YSxcclxuICAgIHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcjogIzJiMzY0NCxcclxuICAgIGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3I6ICM1NTY1NzYsXHJcbiAgICB0b29sdGlwQmFja2dyb3VuZENvbG9yOiAjNDI1MDVmLFxyXG4gICAgdG9vbHRpcEltcG9ydGFudFRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3I6ICM1ZjJiMTEsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3I6ICM1ZjFkMWQsXHJcbiAgICB0b29sdGlwU2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSksXHJcbiAgICBtb2RhbEJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZyksXHJcbiAgICBjbG9zZUJ1dHRvbkNvbG9yOiAjNTU2NTc2XHJcbiAgKSxcclxuICBncmF5OiAoXHJcbiAgICBib2R5QmFja2dyb3VuZENvbG9yOiAjMTAxNDE3LFxyXG4gICAgc2lkZWJhckJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAxKSxcclxuICAgIHNpZGViYXJCb3JkZXJDb2xvcjogIzJlMzMzNyxcclxuICAgIG9ubGluZUNvbG9yOiAjNDdjZjhkLFxyXG4gICAgb2ZmbGluZUNvbG9yOiAjZmY1MjUyLFxyXG4gICAgY29udGVudEJhY2tncm91bmRDb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpLFxyXG4gICAgbWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFsdGVybmF0aXZlVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgb3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBibHVlVGV4dENvbG9yOiAjNDJhNWY1LFxyXG4gICAgZ3JlZW5UZXh0Q29sb3I6ICM0N2NmOGQsXHJcbiAgICBvcmFuZ2VUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICByZWRUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICBibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNDJhNWY1LFxyXG4gICAgYmx1ZUJ1dHRvbkhvdmVyQ29sb3I6ICM4NmQ2ZmYsXHJcbiAgICBibHVlQnV0dG9uRm9jdXNDb2xvcjogIzVmYjZmYyxcclxuICAgIGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNzk4NDhmLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yOiAjYTFhZWJiLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Gb2N1c0NvbG9yOiAjOGE5NTlmLFxyXG4gICAgZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBncmVlbkJ1dHRvbkhvdmVyQ29sb3I6ICM3YmY2YzYsXHJcbiAgICBncmVlbkJ1dHRvbkZvY3VzQ29sb3I6ICM1Y2RjOWUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMzZWM1ZDcsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Ib3ZlckNvbG9yOiAjNzJlZGZlLFxyXG4gICAgdHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcjogIzUwZDBlMSxcclxuICAgIHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3I6ICMyZjM0MzgsXHJcbiAgICBpbnB1dEJhY2tncm91bmRDb2xvcjogIzI5MmQzMSxcclxuICAgIHNlbGVjdEhvdmVyQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHNlbGVjdFNlbGVjdGVkQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIHN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIGFjY291bnRIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpLFxyXG4gICAgYWNjb3VudE1haW5UZXh0Q29sb3I6ICNlMGUwZTAsXHJcbiAgICBhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBhY2NvdW50SW5kaWNhdG9yVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRJbmRpY2F0b3JCYWNrZ3JvdW5kQ29sb3I6ICM0MmE1ZjUsXHJcbiAgICB0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpLFxyXG4gICAgdGFiSG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjMzAzNjNjLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICMzNjNhM2UsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICMyOTJkMzEsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjNTE1OTYwLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogIzNlNDY0YyxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjNTUyNDBkLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmY1MjUyLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjNGMxOTE5LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZ3JheS5wbmcpLFxyXG4gICAgY2xvc2VCdXR0b25Db2xvcjogIzUxNTk2MFxyXG4gICksXHJcbiAgd2hpdGU6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICNlZWVlZWUsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjZWJlYmViLFxyXG4gICAgb25saW5lQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjNDM0NTRiLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICNmZWZlZmUsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogI2EwYTVhYixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICMyYzk1ZjEsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzQ2YzE3MixcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMyYzk1ZjEsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzVjYjNmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjMzc5ZmZhLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5MGE0YWUsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNhZWJlYzYsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzQ2YzE3MixcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzVhZDU4NixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzUzYzc3YyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzI2YjZjNyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM1MmNiZDksXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjMzFiZWNmLFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogI2ViZWJlYixcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjZTZlNmU2LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSgyMjQsIDIyNCwgMjI0LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSgzMCwgMTM2LCAyMjksIDEpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI0MCwgMjQwLCAyNDAsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2ZmZmZmZixcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzkxYmFmMSxcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICM0MzQ1NGIsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjZmZmLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjZWRlZGVkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICNkY2RjZGMsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICNlMGUwZTAsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZmZmZmYsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjZWY2YzAwLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjZTUzOTM1LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKSxcclxuICAgIGNsb3NlQnV0dG9uQ29sb3I6ICM0MzQ1NGJcclxuICApXHJcbik7XHJcblxyXG5cclxuXHJcblxyXG5cclxuIiwiYXBwLW1haW4sIGFwcC1jcmVhdGUtd2FsbGV0LCBhcHAtb3Blbi13YWxsZXQsIGFwcC1yZXN0b3JlLXdhbGxldCwgYXBwLXNlZWQtcGhyYXNlLCBhcHAtd2FsbGV0LWRldGFpbHMsIGFwcC1hc3NpZ24tYWxpYXMsIGFwcC1lZGl0LWFsaWFzLCBhcHAtdHJhbnNmZXItYWxpYXMsIGFwcC1zZXR0aW5ncywgYXBwLWxvZ2luIHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tYWluIHtcclxuXHJcbiAgLmNvbnRlbnQge1xyXG5cclxuICAgIC5hZGQtd2FsbGV0IHtcclxuXHJcbiAgICAgIC5hZGQtd2FsbGV0LWhlbHAge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZWVkLXBocmFzZSB7XHJcblxyXG4gIC5zZWVkLXBocmFzZS1jb250ZW50IHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXdhbGxldC1kZXRhaWxzIHtcclxuXHJcbiAgLnNlZWQtcGhyYXNlIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZXR0aW5ncyB7XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICAgIG92ZXJmbG93LXk6IGF1dG87XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuXHJcbiAgICAudGhlbWUtc2VsZWN0aW9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNjYWxlLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgICAuYnV0dG9uLWJsb2NrIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodGFiSW5hY3RpdmVCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLWxvZ2luIHtcclxuICBtaW4td2lkdGg6IGluaGVyaXQ7XHJcbn1cclxuIiwiYXBwLXNpZGViYXIge1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzaWRlYmFyQmFja2dyb3VuZENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLWFjY291bnRzIHtcclxuXHJcbiAgICAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIge1xyXG5cclxuICAgICAgaDMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNpZGViYXItYWNjb3VudHMtbGlzdCB7XHJcblxyXG4gICAgICAuc2lkZWJhci1hY2NvdW50IHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2lkZWJhci1hY2NvdW50LXJvdyB7XHJcblxyXG4gICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaW5kaWNhdG9yIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuXHJcbiAgICAgICAgICAgIC5wcm9ncmVzcy1iYXIge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmLmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnNpZGViYXItYWNjb3VudC1yb3cge1xyXG5cclxuICAgICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuc3dpdGNoIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpob3Zlcjpub3QoLmFjdGl2ZSkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCh0byBib3R0b20sIHRyYW5zcGFyZW50IDAlLCB0aGVtZWQoc2lkZWJhckJhY2tncm91bmRDb2xvcikgMTAwJSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXNldHRpbmdzIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkIHRoZW1lZChzaWRlYmFyQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC53cmFwLWJ1dHRvbiB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgYnV0dG9uIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGFjY291bnRCYWNrZ3JvdW5kQ29sb3IpIWltcG9ydGFudDtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcikhaW1wb3J0YW50O1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKSFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAuc3RhdHVzLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAub2ZmbGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvZmZsaW5lQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9ubGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvbmxpbmVDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAgIC5zeW5jaW5nIHtcclxuXHJcbiAgICAgICAgICAucHJvZ3Jlc3MtYmFyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5maWxsIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJGdWxsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sb2FkaW5nIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnVwZGF0ZS1jb250YWluZXIge1xyXG5cclxuICAgICAgLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmltcG9ydGFudCB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmNyaXRpY2FsIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAudGltZSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICAmLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5pbXBvcnRhbnQge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQob3JhbmdlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuY3JpdGljYWwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYudGltZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtd2FsbGV0IHtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLmhlYWRlciB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFsaWFzIHtcclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGFicyB7XHJcblxyXG4gICAgLnRhYnMtaGVhZGVyIHtcclxuXHJcbiAgICAgIC50YWIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZCh0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYkhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAudGFicy1jb250ZW50IHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXNlbmQge1xyXG5cclxuICAuZm9ybS1zZW5kIHtcclxuXHJcbiAgICAuc2VuZC1zZWxlY3Qge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuYWRkaXRpb25hbC1kZXRhaWxzIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkIHRoZW1lZCh0cmFuc3BhcmVudEJ1dHRvbkJvcmRlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXJlY2VpdmUge1xyXG5cclxuICAuYnRuLWNvcHktYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1oaXN0b3J5IHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgJi5sb2NrZWQtdHJhbnNhY3Rpb24ge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzEpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzIpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzMpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOm50aC1jaGlsZCg0bis0KSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cyB7XHJcblxyXG4gICAgICAgICAgLmNvbmZpcm1hdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnVubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zdGF0dXMuc2VuZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cy5yZWNlaXZlZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtY29udHJhY3RzIHtcclxuXHJcbiAgLndyYXAtdGFibGUge1xyXG5cclxuICAgIC5jb250cmFjdCB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICYubmV3LCAmLmFsZXJ0IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnB1cmNoYXNlLCAmLnNlbGwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtcHVyY2hhc2Uge1xyXG5cclxuICAuZm9ybS1wdXJjaGFzZSB7XHJcblxyXG4gICAgLnB1cmNoYXNlLXNlbGVjdCB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5wdXJjaGFzZS1zdGF0ZXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW1lc3NhZ2VzIHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgdGQ6Zmlyc3QtY2hpbGQge1xyXG5cclxuICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICBAaW5jbHVkZSB0ZXh0LXRydW5jYXRlO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtdHlwaW5nLW1lc3NhZ2Uge1xyXG5cclxuICAuaGVhZCB7XHJcblxyXG4gICAgLmludGVybG9jdXRvciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAubWVzc2FnZXMtY29udGVudCB7XHJcblxyXG4gICAgLm1lc3NhZ2VzLWxpc3Qge1xyXG5cclxuICAgICAgZGl2IHtcclxuXHJcbiAgICAgICAgJi5kYXRlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLm15IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJjpiZWZvcmUge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgICB0b3A6IDA7XHJcbiAgICAgICAgICAgIGxlZnQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIGJvcmRlcjogMS4ycmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYm9yZGVyLXRvcC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYnVkZHkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHBzZXVkbztcclxuICAgICAgICAgICAgcmlnaHQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgICAgYm9yZGVyOiAxLjJyZW0gc29saWQgdHJhbnNwYXJlbnQ7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBib3JkZXItdG9wLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXN0YWtpbmcge1xyXG5cclxuICAuY2hhcnQtaGVhZGVyIHtcclxuXHJcbiAgICAuZ2VuZXJhbCB7XHJcblxyXG4gICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9wdGlvbnMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNlbGVjdGVkIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxuICAgICAgZmxleC1ncm93OiAxO1xyXG4gICAgICBmb250LXNpemU6IDEuNnJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5jaGFydC1vcHRpb25zIHtcclxuXHJcbiAgICAudGl0bGUge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAub3B0aW9ucyB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY2hhcnRPcHRpb25zQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmlucHV0LWJsb2NrLWFsaWFzIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcblxyXG4gIC5hbGlhcy1kcm9wZG93biB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IDYuNXJlbTtcclxuICAgIG1heC1oZWlnaHQ6IDEwcmVtO1xyXG4gICAgb3ZlcmZsb3c6IGF1dG87XHJcbiAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICBkaXYge1xyXG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgcGFkZGluZzogMXJlbTtcclxuXHJcbiAgICAgICY6aG92ZXIge1xyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdEhvdmVyQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtY29udGFjdHMsIGFwcC1hZGQtY29udGFjdHMsXHJcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1jb250YWN0cyB7XHJcbiAgXHJcbiAgdGFibGUge1xyXG5cclxuICAgIC5hbGlhcyB7XHJcbiAgXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICBcclxuICAgICAgLmljb24ge1xyXG4gIFxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gIFxyXG4gICAgICBzcGFuIHtcclxuICAgICAgICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcilcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5mb290ZXIge1xyXG4gICAgXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICBcclxuICAgIC5pbXBvcnQtYnRuIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgXHJcbn1cclxuXHJcbmFwcC1jb250YWN0LXNlbmQge1xyXG4gIFxyXG4gIC53YWxsZXRzLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn0iLCIuaGVhZCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5icmVhZGNydW1icyB7XHJcblxyXG4gICAgPiBzcGFuLCBhIHtcclxuXHJcbiAgICAgICY6bm90KDpsYXN0LWNoaWxkKSB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDIwcHg7XHJcbiAgICAgICAgb3V0bGluZS1zdHlsZTogbm9uZTtcclxuXHJcbiAgICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgdG9wOiAwLjVyZW07XHJcbiAgICAgICAgICByaWdodDogLTEuNXJlbTtcclxuICAgICAgICAgIHdpZHRoOiAwLjlyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDAuOXJlbTtcclxuICAgICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy1yaWdodC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICBtYXNrLXNpemU6IGNvdmVyO1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYmFjay1idG4ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGNvbG9yOiAjNGRiMWZmO1xyXG4gICAgZm9udC1zaXplOiBpbmhlcml0O1xyXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgaGVpZ2h0OiBhdXRvO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9iYWNrLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDAuOXJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjlyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLnNjcm9sbGVkLWNvbnRlbnQge1xyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhciB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgIHdpZHRoOiAxcmVtO1xyXG4gICAgaGVpZ2h0OiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgfVxyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhci10aHVtYiB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNTU2NTc2O1xyXG4gICAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcclxuICAgIGJvcmRlcjogMC4yNXJlbSBzb2xpZCB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlci1yYWRpdXM6IDAuNXJlbTtcclxuICB9XHJcblxyXG4gICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgfVxyXG59XHJcbiIsInRhYmxlIHtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgdGhlYWQge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgdHIge1xyXG4gICAgICBoZWlnaHQ6IDRyZW07XHJcblxyXG4gICAgICB0aCB7XHJcbiAgICAgICAgcGFkZGluZzogMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogYm90dG9tO1xyXG5cclxuICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICAgIHBhZGRpbmctbGVmdDogM3JlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAzcmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGJvZHkge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICB0ciB7XHJcbiAgICAgIGhlaWdodDogMy41cmVtO1xyXG5cclxuICAgICAgJjpudGgtY2hpbGQob2RkKSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRkIHtcclxuICAgICAgICBsaW5lLWhlaWdodDogMS43cmVtO1xyXG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTtcclxuXHJcbiAgICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLWxlZnQ6IDNyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgICAgcGFkZGluZy1yaWdodDogM3JlbTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLy8gQkFTRVxyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL21peGlucyc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvbnVsbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvdGhlbWUnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL2Jhc2UnO1xyXG5cclxuLy8gTEFZT1VUXHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2xheW91dC9tYWluJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NldHRpbmdzJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NpZGViYXInO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9sYXlvdXQvd2FsbGV0JztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L2NvbnRhY3QnO1xyXG5cclxuLy8gTU9EVUxFU1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL2hlYWQnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL3Njcm9sbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL21vZHVsZXMvdGFibGUnO1xyXG5cclxuQGltcG9ydCBcIn5Abmctc2VsZWN0L25nLXNlbGVjdC90aGVtZXMvZGVmYXVsdC50aGVtZS5jc3NcIjtcclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1MaWdodC50dGYpO1xyXG4gIGZvbnQtd2VpZ2h0OiAzMDA7XHJcbn1cclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDQwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLVNlbWlCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDYwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLUJvbGQudHRmKTtcclxuICBmb250LXdlaWdodDogNzAwO1xyXG59XHJcblxyXG5AZm9udC1mYWNlIHtcclxuICBmb250LWZhbWlseTogT3BlblNhbnM7XHJcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDgwMDtcclxufVxyXG5cclxuXHJcbmh0bWwge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEwcHg7XHJcbn1cclxuXHJcbmJvZHkge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNnJlbTtcclxuICB3aWR0aDogMTAwdnc7XHJcbiAgaGVpZ2h0OiAxMDB2aDtcclxuXHJcbiAgJi50aGVtZS1kYXJrIHtcclxuICAgIGJhY2tncm91bmQ6ICMxMzE5MjEgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS1ncmF5IHtcclxuICAgIGJhY2tncm91bmQ6ICMxMDE0MTcgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS13aGl0ZSB7XHJcbiAgICBiYWNrZ3JvdW5kOiAjZWVlZWVlIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmdcIikgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcbiAgfVxyXG5cclxuICBhcHAtcm9vdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgfVxyXG59XHJcblxyXG4udXBkYXRlLXRvb2x0aXAge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */", '', '']] +module.exports = [[module.i, "/*\r\n* Implementation of themes\r\n*/\n.ng-select.ng-select-opened>.ng-select-container{background:#fff;border-color:#b3b3b3 #ccc #d9d9d9}\n.ng-select.ng-select-opened>.ng-select-container:hover{box-shadow:none}\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow:hover{border-color:transparent transparent #333}\n.ng-select.ng-select-opened.ng-select-bottom>.ng-select-container{border-bottom-right-radius:0;border-bottom-left-radius:0}\n.ng-select.ng-select-opened.ng-select-top>.ng-select-container{border-top-right-radius:0;border-top-left-radius:0}\n.ng-select.ng-select-focused:not(.ng-select-opened)>.ng-select-container{border-color:#007eff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 0 3px rgba(0,126,255,0.1)}\n.ng-select.ng-select-disabled>.ng-select-container{background-color:#f9f9f9}\n.ng-select .ng-has-value .ng-placeholder{display:none}\n.ng-select .ng-select-container{background-color:#fff;border-radius:4px;border:1px solid #ccc;min-height:36px;align-items:center}\n.ng-select .ng-select-container:hover{box-shadow:0 1px 0 rgba(0,0,0,0.06)}\n.ng-select .ng-select-container .ng-value-container{align-items:center;padding-left:10px}\n[dir=\"rtl\"] .ng-select .ng-select-container .ng-value-container{padding-right:10px;padding-left:0}\n.ng-select .ng-select-container .ng-value-container .ng-placeholder{color:#999}\n.ng-select.ng-select-single .ng-select-container{height:36px}\n.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{top:5px;left:0;padding-left:10px;padding-right:50px}\n[dir=\"rtl\"] .ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{padding-right:10px;padding-left:50px}\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value{background-color:#f9f9f9;border:1px solid #e6e6e6}\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-label{padding:0 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-top:5px;padding-left:7px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-right:7px;padding-left:0}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{font-size:.9em;margin-bottom:5px;background-color:#ebf5ff;border-radius:2px;margin-right:5px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{margin-right:0;margin-left:5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled{background-color:#f9f9f9}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:5px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:0;padding-right:5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-label{display:inline-block;padding:1px 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:inline-block;padding:1px 5px}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon:hover{background-color:#d1e8ff}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-right:1px solid #b8dbff}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-left:1px solid #b8dbff;border-right:none}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:1px solid #b8dbff}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:0;border-right:1px solid #b8dbff}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 0 3px 3px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 3px 3px 0}\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{top:5px;padding-bottom:5px;padding-left:3px}\n[dir=\"rtl\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-right:3px;padding-left:0}\n.ng-select .ng-clear-wrapper{color:#999}\n.ng-select .ng-clear-wrapper:hover .ng-clear{color:#D0021B}\n.ng-select .ng-spinner-zone{padding:5px 5px 0 0}\n[dir=\"rtl\"] .ng-select .ng-spinner-zone{padding:5px 0 0 5px}\n.ng-select .ng-arrow-wrapper{width:25px;padding-right:5px}\n[dir=\"rtl\"] .ng-select .ng-arrow-wrapper{padding-left:5px;padding-right:0}\n.ng-select .ng-arrow-wrapper:hover .ng-arrow{border-top-color:#666}\n.ng-select .ng-arrow-wrapper .ng-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px}\n.ng-dropdown-panel{background-color:#fff;border:1px solid #ccc;box-shadow:0 1px 0 rgba(0,0,0,0.06);left:0}\n.ng-dropdown-panel.ng-select-bottom{top:100%;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top-color:#e6e6e6;margin-top:-1px}\n.ng-dropdown-panel.ng-select-bottom .ng-dropdown-panel-items .ng-option:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px}\n.ng-dropdown-panel.ng-select-top{bottom:100%;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-color:#e6e6e6;margin-bottom:-1px}\n.ng-dropdown-panel.ng-select-top .ng-dropdown-panel-items .ng-option:first-child{border-top-right-radius:4px;border-top-left-radius:4px}\n.ng-dropdown-panel .ng-dropdown-header{border-bottom:1px solid #ccc;padding:5px 7px}\n.ng-dropdown-panel .ng-dropdown-footer{border-top:1px solid #ccc;padding:5px 7px}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:8px 10px;font-weight:500;color:rgba(0,0,0,0.54);cursor:pointer}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-disabled{cursor:default}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-marked{background-color:#f5faff}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected.ng-option-marked{background-color:#ebf5ff;font-weight:600}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option{background-color:#fff;color:rgba(0,0,0,0.87);padding:8px 10px}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked{color:#333;background-color:#ebf5ff}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected .ng-option-label,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked .ng-option-label{font-weight:600}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked{background-color:#f5faff;color:#333}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-disabled{color:#ccc}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-left:22px}\n[dir=\"rtl\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-right:22px;padding-left:0}\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{font-size:80%;font-weight:400;padding-right:5px}\n[dir=\"rtl\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{padding-left:5px;padding-right:0}\n[dir=\"rtl\"] .ng-dropdown-panel{direction:rtl;text-align:right}\nhtml {\n box-sizing: border-box;\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box; }\n*, *:before, *:after {\n box-sizing: inherit;\n -webkit-box-sizing: inherit;\n -moz-box-sizing: inherit;\n margin: 0;\n padding: 0;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n border: 0;\n font-size: 100%;\n font: inherit;\n vertical-align: baseline; }\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, menu, nav, section {\n display: block; }\nbody {\n line-height: 1;\n font-style: normal; }\nol, ul {\n list-style: none; }\nblockquote, q {\n quotes: none; }\nblockquote:before, blockquote:after,\nq:before, q:after {\n content: none; }\ntable {\n border-collapse: collapse;\n border-spacing: 0; }\ntd,\nth {\n padding: 0; }\ninput {\n outline: none; }\ninput:-webkit-autofill {\n -webkit-box-shadow: 0 0 0 1000px white inset; }\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n outline: none; }\nbutton[disabled],\nhtml input[disabled] {\n cursor: default; }\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0; }\ninput {\n line-height: normal; }\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box; }\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none; }\na {\n text-decoration: none; }\na:active, a:hover, a:focus {\n outline: 0; }\ni {\n font-style: italic; }\nb, strong {\n font-weight: 700; }\nimg {\n width: auto;\n max-width: 100%;\n height: auto;\n vertical-align: top;\n border: 0; }\n.hidden {\n display: none !important; }\n.theme-dark .app-content .preloader .loading-bar {\n background-color: #5cda9d; }\n.theme-gray .app-content .preloader .loading-bar {\n background-color: #47cf8d; }\n.theme-white .app-content .preloader .loading-bar {\n background-color: #46c172; }\nbutton {\n border: none;\n font-family: OpenSans, sans-serif;\n font-size: 1.5rem;\n font-weight: 600;\n outline: none;\n padding: 0 1rem;\n height: 4.2rem; }\n.theme-dark button:disabled:not(.transparent-button), .theme-dark button.blue-button_reset {\n background-color: #9cadb7;\n color: #111921; }\n.theme-gray button:disabled:not(.transparent-button), .theme-gray button.blue-button_reset {\n background-color: #79848f;\n color: #1a1a1a; }\n.theme-white button:disabled:not(.transparent-button), .theme-white button.blue-button_reset {\n background-color: #90a4ae;\n color: #fefefe; }\n.theme-dark button:disabled:not(.transparent-button):hover, .theme-dark button.blue-button_reset:hover {\n background-color: #b7d1e0; }\n.theme-gray button:disabled:not(.transparent-button):hover, .theme-gray button.blue-button_reset:hover {\n background-color: #a1aebb; }\n.theme-white button:disabled:not(.transparent-button):hover, .theme-white button.blue-button_reset:hover {\n background-color: #aebec6; }\n.theme-dark button:disabled:not(.transparent-button):focus, .theme-dark button.blue-button_reset:focus {\n background-color: #a7b9c2; }\n.theme-gray button:disabled:not(.transparent-button):focus, .theme-gray button.blue-button_reset:focus {\n background-color: #8a959f; }\n.theme-white button:disabled:not(.transparent-button):focus, .theme-white button.blue-button_reset:focus {\n background-color: #a7b9c2; }\n.theme-dark button.blue-button:not(:disabled) {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray button.blue-button:not(:disabled) {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white button.blue-button:not(:disabled) {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark button.blue-button:not(:disabled):hover {\n background-color: #82d7ff; }\n.theme-gray button.blue-button:not(:disabled):hover {\n background-color: #86d6ff; }\n.theme-white button.blue-button:not(:disabled):hover {\n background-color: #5cb3ff; }\n.theme-dark button.blue-button:not(:disabled):focus {\n background-color: #59b5fd; }\n.theme-gray button.blue-button:not(:disabled):focus {\n background-color: #5fb6fc; }\n.theme-white button.blue-button:not(:disabled):focus {\n background-color: #379ffa; }\n.theme-dark button.green-button:not(:disabled) {\n background-color: #5cda9d;\n color: #111921; }\n.theme-gray button.green-button:not(:disabled) {\n background-color: #47cf8d;\n color: #1a1a1a; }\n.theme-white button.green-button:not(:disabled) {\n background-color: #46c172;\n color: #fefefe; }\n.theme-dark button.green-button:not(:disabled):hover {\n background-color: #8dfcc6; }\n.theme-gray button.green-button:not(:disabled):hover {\n background-color: #7bf6c6; }\n.theme-white button.green-button:not(:disabled):hover {\n background-color: #5ad586; }\n.theme-dark button.green-button:not(:disabled):focus {\n background-color: #62e0b2; }\n.theme-gray button.green-button:not(:disabled):focus {\n background-color: #5cdc9e; }\n.theme-white button.green-button:not(:disabled):focus {\n background-color: #53c77c; }\n.theme-dark button.turquoise-button:not(:disabled) {\n background-color: #4dd0e1;\n color: #111921; }\n.theme-gray button.turquoise-button:not(:disabled) {\n background-color: #3ec5d7;\n color: #1a1a1a; }\n.theme-white button.turquoise-button:not(:disabled) {\n background-color: #26b6c7;\n color: #fefefe; }\n.theme-dark button.turquoise-button:not(:disabled):hover {\n background-color: #87f4f5; }\n.theme-gray button.turquoise-button:not(:disabled):hover {\n background-color: #72edfe; }\n.theme-white button.turquoise-button:not(:disabled):hover {\n background-color: #52cbd9; }\n.theme-dark button.turquoise-button:not(:disabled):focus {\n background-color: #42d5e8; }\n.theme-gray button.turquoise-button:not(:disabled):focus {\n background-color: #50d0e1; }\n.theme-white button.turquoise-button:not(:disabled):focus {\n background-color: #31becf; }\nbutton.transparent-button {\n display: flex;\n align-items: center;\n justify-content: center; }\n.theme-dark button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #2b3644;\n color: #e0e0e0; }\n.theme-gray button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #2f3438;\n color: #e0e0e0; }\n.theme-white button.transparent-button {\n background-color: transparent;\n border: 0.2rem solid #ebebeb;\n color: #43454b; }\nbutton.transparent-button .icon {\n margin-right: 1rem;\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\n mask: url('complete-testwallet.svg') no-repeat center;\n width: 1.7rem;\n height: 1.7rem; }\n.theme-dark button.transparent-button .icon {\n background-color: #e0e0e0; }\n.theme-gray button.transparent-button .icon {\n background-color: #e0e0e0; }\n.theme-white button.transparent-button .icon {\n background-color: #43454b; }\n.input-block {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.4rem; }\n.input-block .wrap-label {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n min-height: 2.4rem; }\n.input-block label {\n font-size: 1.3rem;\n line-height: 2.4rem; }\n.theme-dark .input-block label {\n color: #556576; }\n.theme-gray .input-block label {\n color: #565c62; }\n.theme-white .input-block label {\n color: #a0a5ab; }\n.input-block input[type='text'], .input-block input[type='password'], .input-block select {\n border: none;\n font-size: 1.4rem;\n outline: none;\n padding: 0 1rem;\n width: 100%;\n height: 4.2rem; }\n.theme-dark .input-block input[type='text'], .theme-dark .input-block input[type='password'], .theme-dark .input-block select {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block input[type='text'], .theme-gray .input-block input[type='password'], .theme-gray .input-block select {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block input[type='text'], .theme-white .input-block input[type='password'], .theme-white .input-block select {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block.textarea {\n height: auto; }\n.input-block.textarea textarea {\n font-family: OpenSans, sans-serif;\n border: none;\n font-size: 1.4rem;\n outline: none;\n padding: 1rem;\n width: 100%;\n min-width: 100%;\n height: 100%;\n min-height: 7.5rem;\n max-height: 7.5rem;\n overflow: auto;\n resize: none; }\n.theme-dark .input-block.textarea textarea {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block.textarea textarea {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block.textarea textarea {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block .error-block {\n font-size: 1rem;\n line-height: 1.4rem;\n align-self: flex-end;\n text-align: right; }\n.theme-dark .input-block .error-block {\n color: #ff5252; }\n.theme-gray .input-block .error-block {\n color: #ff5252; }\n.theme-white .input-block .error-block {\n color: #ff5252; }\n.theme-dark .error-text {\n color: #ff5252; }\n.theme-gray .error-text {\n color: #ff5252; }\n.theme-white .error-text {\n color: #ff5252; }\ninput[type='radio'].style-radio + label {\n display: flex;\n align-items: center;\n cursor: pointer;\n font-weight: 400;\n padding-left: 2.4rem;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n.theme-dark input[type='radio'].style-radio + label {\n color: #556576; }\n.theme-gray input[type='radio'].style-radio + label {\n color: #565c62; }\n.theme-white input[type='radio'].style-radio + label {\n color: #a0a5ab; }\ninput[type='radio'].style-radio:not(checked) {\n position: absolute;\n opacity: 0; }\ninput[type='radio'].style-radio:not(checked) + label {\n position: relative; }\ninput[type='radio'].style-radio:not(checked) + label:before {\n content: '';\n position: absolute;\n top: 0.7rem;\n left: 0;\n background: transparent;\n border-radius: 50%;\n width: 1.4rem;\n height: 1.4rem; }\n.theme-dark input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #4db1ff; }\n.theme-gray input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #42a5f5; }\n.theme-white input[type='radio'].style-radio:not(checked) + label:before {\n border: 0.1rem solid #2c95f1; }\ninput[type='radio'].style-radio:not(checked) + label:after {\n content: '';\n position: absolute;\n top: 1rem;\n left: 0.3rem;\n border-radius: 50%;\n opacity: 0;\n width: 0.8rem;\n height: 0.8rem; }\n.theme-dark input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #4db1ff; }\n.theme-gray input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #42a5f5; }\n.theme-white input[type='radio'].style-radio:not(checked) + label:after {\n background-color: #2c95f1; }\ninput[type='radio'].style-radio:checked + label:after {\n opacity: 1; }\ninput[type='checkbox'].style-checkbox + label {\n display: flex;\n align-items: center;\n cursor: pointer;\n font-weight: 400;\n padding-left: 3.6rem;\n -webkit-touch-collout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none; }\n.theme-dark input[type='checkbox'].style-checkbox + label {\n color: #556576; }\n.theme-gray input[type='checkbox'].style-checkbox + label {\n color: #565c62; }\n.theme-white input[type='checkbox'].style-checkbox + label {\n color: #a0a5ab; }\ninput[type='checkbox'].style-checkbox:not(checked) {\n position: absolute;\n top: 50%;\n left: 1.6rem;\n transform: translateY(-50%);\n visibility: hidden; }\ninput[type='checkbox'].style-checkbox:not(checked) + label {\n position: relative; }\ninput[type='checkbox'].style-checkbox:not(checked) + label:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 1.6rem;\n transform: translateY(-50%);\n background: transparent;\n width: 1.4rem;\n height: 1.4rem; }\n.theme-dark input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #4db1ff; }\n.theme-gray input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #42a5f5; }\n.theme-white input[type='checkbox'].style-checkbox:not(checked) + label:before {\n border: 0.1rem solid #2c95f1; }\ninput[type='checkbox'].style-checkbox:checked + label:before {\n background: url('complete-testwallet.svg'); }\n.theme-dark input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #4db1ff; }\n.theme-gray input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #42a5f5; }\n.theme-white input[type='checkbox'].style-checkbox:checked + label:before {\n background-color: #2c95f1; }\n.theme-dark .switch {\n background-color: #000000; }\n.theme-gray .switch {\n background-color: #000000; }\n.theme-white .switch {\n background-color: #e0e0e0; }\n.theme-dark .switch .circle.on {\n background-color: #4db1ff; }\n.theme-gray .switch .circle.on {\n background-color: #42a5f5; }\n.theme-white .switch .circle.on {\n background-color: #2c95f1; }\n.theme-dark .switch .circle.off {\n background-color: #556576; }\n.theme-gray .switch .circle.off {\n background-color: #565c62; }\n.theme-white .switch .circle.off {\n background-color: #a0a5ab; }\n.table-tooltip {\n padding: 1rem 2rem; }\n.theme-dark .table-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .table-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .table-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.table-tooltip .tooltip-inner {\n font-size: 1.3rem;\n line-height: 1.8rem;\n white-space: pre-wrap; }\n.table-tooltip.ng-tooltip-top {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n left: calc(50% - 0.5rem);\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top:after {\n border-color: #42505f transparent transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-top:after {\n border-color: #3e464c transparent transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-top:after {\n border-color: #ffffff transparent transparent transparent; }\n.table-tooltip.ng-tooltip-top-left {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top-left:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n left: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top-left:after {\n border-color: #42505f transparent transparent #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-top-left:after {\n border-color: #3e464c transparent transparent #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-top-left:after {\n border-color: #ffffff transparent transparent #ffffff; }\n.table-tooltip.ng-tooltip-top-right {\n margin-top: -1rem; }\n.table-tooltip.ng-tooltip-top-right:after {\n content: \"\";\n position: absolute;\n bottom: -1rem;\n right: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-top-right:after {\n border-color: #42505f #42505f transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-top-right:after {\n border-color: #3e464c #3e464c transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-top-right:after {\n border-color: #ffffff #ffffff transparent transparent; }\n.table-tooltip.ng-tooltip-bottom {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n left: calc(50% - 0.5rem);\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #42505f transparent; }\n.theme-gray .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #3e464c transparent; }\n.theme-white .table-tooltip.ng-tooltip-bottom:before {\n border-color: transparent transparent #ffffff transparent; }\n.table-tooltip.ng-tooltip-bottom-left {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom-left:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n left: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #42505f #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #3e464c #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-bottom-left:before {\n border-color: transparent transparent #ffffff #ffffff; }\n.table-tooltip.ng-tooltip-bottom-right {\n margin-top: 1rem; }\n.table-tooltip.ng-tooltip-bottom-right:before {\n content: \"\";\n position: absolute;\n top: -1rem;\n right: 0.7rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #42505f #42505f transparent; }\n.theme-gray .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #3e464c #3e464c transparent; }\n.theme-white .table-tooltip.ng-tooltip-bottom-right:before {\n border-color: transparent #ffffff #ffffff transparent; }\n.table-tooltip.ng-tooltip-left {\n margin-left: -1rem; }\n.table-tooltip.ng-tooltip-left:after {\n content: \"\";\n position: absolute;\n top: calc(50% - 0.5rem);\n right: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #42505f; }\n.theme-gray .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #3e464c; }\n.theme-white .table-tooltip.ng-tooltip-left:after {\n border-color: transparent transparent transparent #ffffff; }\n.table-tooltip.ng-tooltip-right {\n margin-left: 1rem; }\n.table-tooltip.ng-tooltip-right:before {\n content: \"\";\n position: absolute;\n top: calc(50% - 0.5rem);\n left: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #42505f transparent transparent; }\n.theme-gray .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #3e464c transparent transparent; }\n.theme-white .table-tooltip.ng-tooltip-right:before {\n border-color: transparent #ffffff transparent transparent; }\n.table-tooltip-dimensions .tooltip-inner {\n overflow: auto;\n max-width: 20rem;\n max-height: 10rem; }\n.balance-tooltip {\n padding: 1.3rem; }\n.theme-dark .balance-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .balance-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .balance-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.balance-tooltip .tooltip-inner {\n display: flex;\n flex-direction: column;\n font-size: 1.3rem; }\n.balance-tooltip .tooltip-inner .available {\n margin-bottom: 1.7rem; }\n.balance-tooltip .tooltip-inner .available b {\n font-weight: 600; }\n.balance-tooltip .tooltip-inner .locked {\n margin-bottom: 0.7rem; }\n.balance-tooltip .tooltip-inner .locked b {\n font-weight: 600; }\n.balance-tooltip .tooltip-inner .link {\n cursor: pointer; }\n.theme-dark .balance-tooltip .tooltip-inner .link {\n color: #4db1ff; }\n.theme-gray .balance-tooltip .tooltip-inner .link {\n color: #42a5f5; }\n.theme-white .balance-tooltip .tooltip-inner .link {\n color: #2c95f1; }\n.balance-tooltip.ng-tooltip-top {\n margin-top: -1rem; }\n.balance-tooltip.ng-tooltip-bottom {\n margin-top: 1rem; }\n.balance-tooltip.ng-tooltip-left {\n margin-left: -1rem; }\n.balance-tooltip.ng-tooltip-right {\n margin-left: 1rem; }\n.account-tooltip .tooltip-inner {\n word-break: break-word;\n max-width: 18rem; }\n.comment-tooltip .tooltip-inner {\n overflow: auto;\n word-break: break-word;\n max-width: 50rem;\n max-height: 25rem; }\n.update-tooltip {\n padding: 1.5rem; }\n.theme-dark .update-tooltip {\n background: #42505f;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-gray .update-tooltip {\n background: #3e464c;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\n color: #e0e0e0; }\n.theme-white .update-tooltip {\n background: #ffffff;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\n color: #43454b; }\n.theme-dark .update-tooltip.important {\n background: #5f2b11;\n color: #e0e0e0; }\n.theme-gray .update-tooltip.important {\n background: #55240d;\n color: #e0e0e0; }\n.theme-white .update-tooltip.important {\n background: #ef6c00;\n color: #ffffff; }\n.theme-dark .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #5f2b11 #5f2b11; }\n.theme-gray .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #55240d #55240d; }\n.theme-white .update-tooltip.important.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #ef6c00 #ef6c00; }\n.theme-dark .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #5f2b11 #5f2b11 transparent; }\n.theme-gray .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #55240d #55240d transparent; }\n.theme-white .update-tooltip.important.ng-tooltip-right-bottom:before {\n border-color: transparent #ef6c00 #ef6c00 transparent; }\n.update-tooltip.critical {\n padding: 2.5rem; }\n.theme-dark .update-tooltip.critical {\n background: #5f1d1d;\n color: #e0e0e0; }\n.theme-gray .update-tooltip.critical {\n background: #4c1919;\n color: #e0e0e0; }\n.theme-white .update-tooltip.critical {\n background: #e53935;\n color: #ffffff; }\n.update-tooltip.critical .tooltip-inner {\n display: flex;\n flex-direction: column;\n align-items: center; }\n.theme-dark .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #5f1d1d #5f1d1d; }\n.theme-gray .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #4c1919 #4c1919; }\n.theme-white .update-tooltip.critical.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #e53935 #e53935; }\n.theme-dark .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #5f1d1d #5f1d1d transparent; }\n.theme-gray .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #4c1919 #4c1919 transparent; }\n.theme-white .update-tooltip.critical.ng-tooltip-right-bottom:before {\n border-color: transparent #e53935 #e53935 transparent; }\n.update-tooltip .tooltip-inner {\n font-size: 1.3rem;\n line-height: 1.8rem;\n white-space: pre-wrap; }\n.update-tooltip .tooltip-inner .standard-update {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .standard-update {\n color: #4db1ff; }\n.theme-gray .update-tooltip .tooltip-inner .standard-update {\n color: #42a5f5; }\n.theme-white .update-tooltip .tooltip-inner .standard-update {\n color: #2c95f1; }\n.update-tooltip .tooltip-inner .important-update {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .important-update {\n color: #ff6f00; }\n.theme-gray .update-tooltip .tooltip-inner .important-update {\n color: #ff6f00; }\n.theme-white .update-tooltip .tooltip-inner .important-update {\n color: #ffffff; }\n.update-tooltip .tooltip-inner .critical-update {\n font-size: 1.5rem;\n line-height: 2.7rem;\n text-align: center; }\n.update-tooltip .tooltip-inner .wrong-time {\n font-size: 1.5rem;\n line-height: 2.7rem; }\n.theme-dark .update-tooltip .tooltip-inner .wrong-time {\n color: #ff6f00; }\n.theme-gray .update-tooltip .tooltip-inner .wrong-time {\n color: #ff6f00; }\n.theme-white .update-tooltip .tooltip-inner .wrong-time {\n color: #ffffff; }\n.update-tooltip .tooltip-inner .icon {\n margin: 1.5rem 0;\n width: 5rem;\n height: 5rem; }\n.theme-dark .update-tooltip .tooltip-inner .icon {\n background-color: #ff5252; }\n.theme-gray .update-tooltip .tooltip-inner .icon {\n background-color: #ff5252; }\n.theme-white .update-tooltip .tooltip-inner .icon {\n background-color: #ffffff; }\n.update-tooltip.ng-tooltip-left-bottom {\n margin-left: -1.5rem; }\n.update-tooltip.ng-tooltip-left-bottom:after {\n content: \"\";\n position: absolute;\n bottom: 0.6rem;\n right: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #42505f #42505f; }\n.theme-gray .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #3e464c #3e464c; }\n.theme-white .update-tooltip.ng-tooltip-left-bottom:after {\n border-color: transparent transparent #ffffff #ffffff; }\n.update-tooltip.ng-tooltip-right-bottom {\n margin-left: 1.5rem; }\n.update-tooltip.ng-tooltip-right-bottom:before {\n content: \"\";\n position: absolute;\n bottom: 0.6rem;\n left: -1rem;\n border-width: 0.5rem;\n border-style: solid; }\n.theme-dark .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #42505f #42505f transparent; }\n.theme-gray .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #3e464c #3e464c transparent; }\n.theme-white .update-tooltip.ng-tooltip-right-bottom:before {\n border-color: transparent #ffffff #ffffff transparent; }\n.ngx-contextmenu .dropdown-menu {\n border: none;\n padding: 0; }\n.theme-dark .ngx-contextmenu .dropdown-menu {\n background-color: #2b3644;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\n.theme-gray .ngx-contextmenu .dropdown-menu {\n background-color: #292d31;\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\n.theme-white .ngx-contextmenu .dropdown-menu {\n background-color: #e0e0e0;\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5); }\n.ngx-contextmenu li {\n display: block;\n font-family: OpenSans, sans-serif;\n font-size: 1.3rem;\n text-transform: uppercase;\n text-align: center; }\n.ngx-contextmenu a {\n display: block;\n padding: 0.5em 1em; }\n.theme-dark .ngx-contextmenu a {\n color: #e0e0e0; }\n.theme-gray .ngx-contextmenu a {\n color: #e0e0e0; }\n.theme-white .ngx-contextmenu a {\n color: #43454b; }\n.theme-dark .ngx-contextmenu a:hover {\n background-color: #556576;\n color: #e0e0e0; }\n.theme-gray .ngx-contextmenu a:hover {\n background-color: #515960;\n color: #e0e0e0; }\n.theme-white .ngx-contextmenu a:hover {\n background-color: #ffffff;\n color: #43454b; }\n.ng-select.custom-select {\n width: 100%; }\n.ng-select.custom-select.ng-select-single .ng-select-container .ng-value-container .ng-value {\n line-height: 1.8rem; }\n.ng-select.custom-select .ng-select-container {\n border: none;\n border-radius: 0;\n cursor: pointer;\n font-size: 1.4rem;\n outline: none;\n padding: 0 1rem;\n height: 4.2rem; }\n.theme-dark .ng-select.custom-select .ng-select-container {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-select-container {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-select-container {\n background-color: #e6e6e6;\n color: #43454b; }\n.ng-select.custom-select .ng-select-container .ng-value-container {\n padding: 0; }\n.ng-select.custom-select .ng-select-container .ng-value-container .ng-input {\n top: auto; }\n.ng-select.custom-select .ng-dropdown-panel {\n border: none; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel {\n background-color: #171e27; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel {\n background-color: #292d31; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel {\n background-color: #e6e6e6; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n font-size: 1.4rem;\n padding: 1rem; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\n background-color: #e6e6e6;\n color: #43454b; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(58, 69, 85, 0.5);\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(58, 62, 66, 0.5);\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\n background-color: rgba(240, 240, 240, 0.5);\n color: #43454b; }\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\n background-color: rgba(224, 224, 224, 0.5);\n color: #43454b; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar {\n background-color: transparent;\n cursor: default;\n width: 1rem;\n height: 1rem; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-track {\n background: transparent; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb {\n background-color: #556576;\n background-clip: padding-box;\n border: 0.25rem solid transparent;\n border-radius: 0.5rem; }\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb:hover {\n background-color: #556576; }\n.theme-dark app-modal-container .modal, .theme-dark app-confirm-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-modal-container .modal, .theme-gray app-confirm-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-modal-container .modal, .theme-white app-confirm-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-modal-container .modal .content .icon.error, .theme-dark app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-gray app-modal-container .modal .content .icon.error, .theme-gray app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-white app-modal-container .modal .content .icon.error, .theme-white app-confirm-modal .modal .content .icon.error {\n background-color: #ff5252; }\n.theme-dark app-modal-container .modal .content .icon.success, .theme-dark app-confirm-modal .modal .content .icon.success {\n background-color: #5cda9d; }\n.theme-gray app-modal-container .modal .content .icon.success, .theme-gray app-confirm-modal .modal .content .icon.success {\n background-color: #47cf8d; }\n.theme-white app-modal-container .modal .content .icon.success, .theme-white app-confirm-modal .modal .content .icon.success {\n background-color: #46c172; }\n.theme-dark app-modal-container .modal .content .icon.info, .theme-dark app-confirm-modal .modal .content .icon.info {\n background-color: #4db1ff; }\n.theme-gray app-modal-container .modal .content .icon.info, .theme-gray app-confirm-modal .modal .content .icon.info {\n background-color: #42a5f5; }\n.theme-white app-modal-container .modal .content .icon.info, .theme-white app-confirm-modal .modal .content .icon.info {\n background-color: #2c95f1; }\n.theme-dark app-modal-container .modal .action-button, .theme-dark app-confirm-modal .modal .action-button {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-modal-container .modal .action-button, .theme-gray app-confirm-modal .modal .action-button {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-modal-container .modal .action-button, .theme-white app-confirm-modal .modal .action-button {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark app-modal-container .modal .close-button .icon, .theme-dark app-confirm-modal .modal .close-button .icon {\n background-color: #556576; }\n.theme-gray app-modal-container .modal .close-button .icon, .theme-gray app-confirm-modal .modal .close-button .icon {\n background-color: #515960; }\n.theme-white app-modal-container .modal .close-button .icon, .theme-white app-confirm-modal .modal .close-button .icon {\n background-color: #43454b; }\n.theme-dark app-transaction-details .table {\n border-top: 0.2rem solid #2b3644; }\n.theme-gray app-transaction-details .table {\n border-top: 0.2rem solid #2f3438; }\n.theme-white app-transaction-details .table {\n border-top: 0.2rem solid #ebebeb; }\n.theme-dark app-transaction-details .table .row .cell.label {\n color: #556576; }\n.theme-gray app-transaction-details .table .row .cell.label {\n color: #565c62; }\n.theme-white app-transaction-details .table .row .cell.label {\n color: #a0a5ab; }\n.theme-dark app-transaction-details .table .row .cell.value {\n color: #e0e0e0; }\n.theme-gray app-transaction-details .table .row .cell.value {\n color: #e0e0e0; }\n.theme-white app-transaction-details .table .row .cell.value {\n color: #43454b; }\n.theme-dark app-transaction-details .table .row .cell.key-value {\n color: #4db1ff; }\n.theme-gray app-transaction-details .table .row .cell.key-value {\n color: #42a5f5; }\n.theme-white app-transaction-details .table .row .cell.key-value {\n color: #2c95f1; }\n.theme-dark app-progress-container .progress-bar-container {\n color: #e0e0e0; }\n.theme-gray app-progress-container .progress-bar-container {\n color: #e0e0e0; }\n.theme-white app-progress-container .progress-bar-container {\n color: #43454b; }\n.theme-dark app-progress-container .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-progress-container .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-progress-container .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #5cda9d; }\n.theme-gray app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #47cf8d; }\n.theme-white app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #46c172; }\n.theme-dark app-open-wallet-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-open-wallet-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-open-wallet-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-send-modal .modal {\n background: url('background-dark.png');\n color: #e0e0e0; }\n.theme-gray app-send-modal .modal {\n background: url('background-gray.png');\n color: #e0e0e0; }\n.theme-white app-send-modal .modal {\n background: url('background-white.png');\n color: #43454b; }\n.theme-dark app-send-modal .modal .title {\n border-bottom: 0.2rem solid #2b3644; }\n.theme-gray app-send-modal .modal .title {\n border-bottom: 0.2rem solid #2f3438; }\n.theme-white app-send-modal .modal .title {\n border-bottom: 0.2rem solid #ebebeb; }\n.theme-dark app-send-modal .modal .action-button {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-send-modal .modal .action-button {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-send-modal .modal .action-button {\n background-color: #2c95f1;\n color: #fefefe; }\napp-main, app-create-wallet, app-open-wallet, app-restore-wallet, app-seed-phrase, app-wallet-details, app-assign-alias, app-edit-alias, app-transfer-alias, app-settings, app-login {\n flex: 1 1 auto;\n padding: 3rem;\n min-width: 85rem; }\napp-main .content, app-create-wallet .content, app-open-wallet .content, app-restore-wallet .content, app-seed-phrase .content, app-wallet-details .content, app-assign-alias .content, app-edit-alias .content, app-transfer-alias .content, app-settings .content, app-login .content {\n position: relative;\n padding: 3rem;\n min-height: 100%; }\n.theme-dark app-main .content, .theme-dark app-create-wallet .content, .theme-dark app-open-wallet .content, .theme-dark app-restore-wallet .content, .theme-dark app-seed-phrase .content, .theme-dark app-wallet-details .content, .theme-dark app-assign-alias .content, .theme-dark app-edit-alias .content, .theme-dark app-transfer-alias .content, .theme-dark app-settings .content, .theme-dark app-login .content {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-main .content, .theme-gray app-create-wallet .content, .theme-gray app-open-wallet .content, .theme-gray app-restore-wallet .content, .theme-gray app-seed-phrase .content, .theme-gray app-wallet-details .content, .theme-gray app-assign-alias .content, .theme-gray app-edit-alias .content, .theme-gray app-transfer-alias .content, .theme-gray app-settings .content, .theme-gray app-login .content {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-main .content, .theme-white app-create-wallet .content, .theme-white app-open-wallet .content, .theme-white app-restore-wallet .content, .theme-white app-seed-phrase .content, .theme-white app-wallet-details .content, .theme-white app-assign-alias .content, .theme-white app-edit-alias .content, .theme-white app-transfer-alias .content, .theme-white app-settings .content, .theme-white app-login .content {\n background-color: rgba(255, 255, 255, 0.5);\n color: #43454b; }\napp-main .content .head, app-create-wallet .content .head, app-open-wallet .content .head, app-restore-wallet .content .head, app-seed-phrase .content .head, app-wallet-details .content .head, app-assign-alias .content .head, app-edit-alias .content .head, app-transfer-alias .content .head, app-settings .content .head, app-login .content .head {\n position: absolute;\n top: 0;\n left: 0; }\n.theme-dark app-main .content .add-wallet .add-wallet-help {\n color: #4db1ff; }\n.theme-gray app-main .content .add-wallet .add-wallet-help {\n color: #42a5f5; }\n.theme-white app-main .content .add-wallet .add-wallet-help {\n color: #2c95f1; }\n.theme-dark app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #4db1ff; }\n.theme-gray app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #42a5f5; }\n.theme-white app-main .content .add-wallet .add-wallet-help .icon {\n background-color: #2c95f1; }\n.theme-dark app-seed-phrase .seed-phrase-content {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray app-seed-phrase .seed-phrase-content {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white app-seed-phrase .seed-phrase-content {\n background-color: #e6e6e6;\n color: #43454b; }\n.theme-dark app-wallet-details .seed-phrase {\n background-color: #171e27; }\n.theme-gray app-wallet-details .seed-phrase {\n background-color: #292d31; }\n.theme-white app-wallet-details .seed-phrase {\n background-color: #e6e6e6; }\napp-settings .content {\n height: 100%;\n overflow-y: auto;\n display: flex;\n justify-content: space-between;\n flex-direction: column; }\n.theme-dark app-settings .content .theme-selection {\n color: #556576; }\n.theme-gray app-settings .content .theme-selection {\n color: #565c62; }\n.theme-white app-settings .content .theme-selection {\n color: #a0a5ab; }\n.theme-dark app-settings .content .scale-selection .button-block {\n background-color: rgba(23, 31, 39, 0.5); }\n.theme-gray app-settings .content .scale-selection .button-block {\n background-color: rgba(28, 30, 33, 0.5); }\n.theme-white app-settings .content .scale-selection .button-block {\n background-color: rgba(224, 224, 224, 0.5); }\n.theme-dark app-settings .content .scale-selection .button-block .label {\n color: #556576; }\n.theme-gray app-settings .content .scale-selection .button-block .label {\n color: #565c62; }\n.theme-white app-settings .content .scale-selection .button-block .label {\n color: #a0a5ab; }\n.theme-dark app-settings .content .scale-selection .button-block.active {\n background-color: #4db1ff; }\n.theme-gray app-settings .content .scale-selection .button-block.active {\n background-color: #42a5f5; }\n.theme-white app-settings .content .scale-selection .button-block.active {\n background-color: #2c95f1; }\n.theme-dark app-settings .content .scale-selection .button-block.active .label {\n color: #4db1ff; }\n.theme-gray app-settings .content .scale-selection .button-block.active .label {\n color: #42a5f5; }\n.theme-white app-settings .content .scale-selection .button-block.active .label {\n color: #2c95f1; }\napp-login {\n min-width: inherit; }\n.theme-dark app-sidebar {\n background-color: #171f27; }\n.theme-gray app-sidebar {\n background-color: #1c1e21; }\n.theme-white app-sidebar {\n background-color: white; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header button {\n color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\n background-color: transparent;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\n background-color: #2c95f1;\n color: #fefefe; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\n background-color: #1e88e5;\n color: #ffffff; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\n color: #91baf1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #000000;\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #000000;\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\n color: #91baf1; }\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\n background-color: rgba(240, 240, 240, 0.5); }\n.theme-dark app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, #171f27 100%); }\n.theme-gray app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, #1c1e21 100%); }\n.theme-white app-sidebar .sidebar-accounts:after {\n background: linear-gradient(to bottom, transparent 0%, white 100%); }\n.theme-dark app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #1f2833; }\n.theme-gray app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #2e3337; }\n.theme-white app-sidebar .sidebar-settings {\n border-bottom: 0.2rem solid #ebebeb; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button button {\n color: #e0e0e0; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button button {\n color: #e0e0e0; }\n.theme-white app-sidebar .sidebar-settings .wrap-button button {\n color: #43454b; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-settings .wrap-button button .icon {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: rgba(43, 54, 68, 0.5) !important;\n color: #e0e0e0 !important; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: rgba(37, 40, 43, 0.5) !important;\n color: #e0e0e0 !important; }\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button {\n background-color: #1e88e5 !important;\n color: #ffffff !important; }\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #4db1ff !important; }\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #42a5f5 !important; }\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button .icon {\n background-color: #ffffff !important; }\n.theme-dark app-sidebar .sidebar-synchronization-status {\n color: #556576; }\n.theme-gray app-sidebar .sidebar-synchronization-status {\n color: #565c62; }\n.theme-white app-sidebar .sidebar-synchronization-status {\n color: #a0a5ab; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .offline:before {\n background-color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .online:before {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #363a3e; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #5cda9d; }\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #47cf8d; }\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\n background-color: #46c172; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #42a5f5; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .standard {\n color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .important {\n color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .critical {\n color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .time {\n color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #4db1ff; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #42a5f5; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\n background-color: #2c95f1; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.important {\n background-color: #ff6f00; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\n background-color: #ff5252; }\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.time {\n background-color: #ff6f00; }\n.theme-dark app-wallet {\n color: #e0e0e0; }\n.theme-gray app-wallet {\n color: #e0e0e0; }\n.theme-white app-wallet {\n color: #43454b; }\n.theme-dark app-wallet .header button {\n color: #e0e0e0; }\n.theme-gray app-wallet .header button {\n color: #e0e0e0; }\n.theme-white app-wallet .header button {\n color: #43454b; }\n.theme-dark app-wallet .header button .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .header button .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .header button .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .header .alias .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .header .alias .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .header .alias .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .address {\n color: #4db1ff; }\n.theme-gray app-wallet .address {\n color: #42a5f5; }\n.theme-white app-wallet .address {\n color: #2c95f1; }\n.theme-dark app-wallet .address .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .address .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .address .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .tabs .tabs-header .tab {\n background-color: rgba(23, 31, 39, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab {\n background-color: rgba(28, 30, 33, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab {\n background-color: rgba(224, 224, 224, 0.5); }\n.theme-dark app-wallet .tabs .tabs-header .tab .icon {\n background-color: #4db1ff; }\n.theme-gray app-wallet .tabs .tabs-header .tab .icon {\n background-color: #42a5f5; }\n.theme-white app-wallet .tabs .tabs-header .tab .icon {\n background-color: #2c95f1; }\n.theme-dark app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #4db1ff;\n color: #111921; }\n.theme-gray app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #42a5f5;\n color: #1a1a1a; }\n.theme-white app-wallet .tabs .tabs-header .tab .indicator {\n background-color: #ffffff;\n color: #43454b; }\n.theme-dark app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(43, 54, 68, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(37, 40, 43, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab.active {\n background-color: rgba(255, 255, 255, 0.5); }\n.theme-dark app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\n background-color: #ffffff; }\n.theme-dark app-wallet .tabs .tabs-content {\n background-color: rgba(43, 54, 68, 0.5); }\n.theme-gray app-wallet .tabs .tabs-content {\n background-color: rgba(37, 40, 43, 0.5); }\n.theme-white app-wallet .tabs .tabs-content {\n background-color: rgba(255, 255, 255, 0.5); }\n.theme-dark app-send .form-send .send-select {\n color: #e0e0e0; }\n.theme-gray app-send .form-send .send-select {\n color: #e0e0e0; }\n.theme-white app-send .form-send .send-select {\n color: #43454b; }\n.theme-dark app-send .form-send .send-select .icon {\n background-color: #4db1ff; }\n.theme-gray app-send .form-send .send-select .icon {\n background-color: #42a5f5; }\n.theme-white app-send .form-send .send-select .icon {\n background-color: #2c95f1; }\n.theme-dark app-send .form-send .additional-details {\n border: 0.2rem solid #2b3644; }\n.theme-gray app-send .form-send .additional-details {\n border: 0.2rem solid #2f3438; }\n.theme-white app-send .form-send .additional-details {\n border: 0.2rem solid #ebebeb; }\n.theme-dark app-receive .btn-copy-address {\n background-color: #4db1ff; }\n.theme-gray app-receive .btn-copy-address {\n background-color: #42a5f5; }\n.theme-white app-receive .btn-copy-address {\n background-color: #2c95f1; }\n.theme-dark app-history table tbody tr.locked-transaction {\n color: #556576; }\n.theme-gray app-history table tbody tr.locked-transaction {\n color: #565c62; }\n.theme-white app-history table tbody tr.locked-transaction {\n color: #a0a5ab; }\n.theme-dark app-history table tbody tr:nth-child(4n+1) {\n background-color: #18202a; }\n.theme-gray app-history table tbody tr:nth-child(4n+1) {\n background-color: #25292d; }\n.theme-white app-history table tbody tr:nth-child(4n+1) {\n background-color: #ffffff; }\n.theme-dark app-history table tbody tr:nth-child(4n+2) {\n background-color: #18202a; }\n.theme-gray app-history table tbody tr:nth-child(4n+2) {\n background-color: #25292d; }\n.theme-white app-history table tbody tr:nth-child(4n+2) {\n background-color: #ffffff; }\n.theme-dark app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-gray app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-white app-history table tbody tr:nth-child(4n+3) {\n background-color: transparent; }\n.theme-dark app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-gray app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-white app-history table tbody tr:nth-child(4n+4) {\n background-color: transparent; }\n.theme-dark app-history table tbody tr .status .confirmation {\n background-color: #343f4a; }\n.theme-gray app-history table tbody tr .status .confirmation {\n background-color: #363a3e; }\n.theme-white app-history table tbody tr .status .confirmation {\n background-color: #dcdcdc; }\n.theme-dark app-history table tbody tr .status .confirmation .fill {\n background-color: #5cda9d; }\n.theme-gray app-history table tbody tr .status .confirmation .fill {\n background-color: #47cf8d; }\n.theme-white app-history table tbody tr .status .confirmation .fill {\n background-color: #46c172; }\n.theme-dark app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-gray app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-white app-history table tbody tr .lock-transaction {\n background-color: #ff6f00; }\n.theme-dark app-history table tbody tr .unlock-transaction {\n background-color: #4db1ff; }\n.theme-gray app-history table tbody tr .unlock-transaction {\n background-color: #42a5f5; }\n.theme-white app-history table tbody tr .unlock-transaction {\n background-color: #2c95f1; }\n.theme-dark app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-gray app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-white app-history table tbody tr .status.send .status-transaction {\n background-color: #ff5252; }\n.theme-dark app-history table tbody tr .status.received .status-transaction {\n background-color: #5cda9d; }\n.theme-gray app-history table tbody tr .status.received .status-transaction {\n background-color: #47cf8d; }\n.theme-white app-history table tbody tr .status.received .status-transaction {\n background-color: #46c172; }\n.theme-dark app-contracts .wrap-table .contract .icon.new, .theme-dark app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-gray app-contracts .wrap-table .contract .icon.new, .theme-gray app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-white app-contracts .wrap-table .contract .icon.new, .theme-white app-contracts .wrap-table .contract .icon.alert {\n background-color: #ff5252; }\n.theme-dark app-contracts .wrap-table .contract .icon.purchase, .theme-dark app-contracts .wrap-table .contract .icon.sell {\n background-color: #4db1ff; }\n.theme-gray app-contracts .wrap-table .contract .icon.purchase, .theme-gray app-contracts .wrap-table .contract .icon.sell {\n background-color: #42a5f5; }\n.theme-white app-contracts .wrap-table .contract .icon.purchase, .theme-white app-contracts .wrap-table .contract .icon.sell {\n background-color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .purchase-select {\n color: #e0e0e0; }\n.theme-gray app-purchase .form-purchase .purchase-select {\n color: #e0e0e0; }\n.theme-white app-purchase .form-purchase .purchase-select {\n color: #43454b; }\n.theme-dark app-purchase .form-purchase .purchase-select .icon {\n background-color: #4db1ff; }\n.theme-gray app-purchase .form-purchase .purchase-select .icon {\n background-color: #42a5f5; }\n.theme-white app-purchase .form-purchase .purchase-select .icon {\n background-color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .purchase-states {\n color: #4db1ff; }\n.theme-gray app-purchase .form-purchase .purchase-states {\n color: #42a5f5; }\n.theme-white app-purchase .form-purchase .purchase-states {\n color: #2c95f1; }\n.theme-dark app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #2b3644; }\n.theme-gray app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #2f3438; }\n.theme-white app-purchase .form-purchase .additional-details {\n border: 0.2rem solid #ebebeb; }\n.theme-dark app-purchase .progress-bar-container .progress-bar {\n background-color: #343f4a; }\n.theme-gray app-purchase .progress-bar-container .progress-bar {\n background-color: #363a3e; }\n.theme-white app-purchase .progress-bar-container .progress-bar {\n background-color: #dcdcdc; }\n.theme-dark app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #5cda9d; }\n.theme-gray app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #47cf8d; }\n.theme-white app-purchase .progress-bar-container .progress-bar .progress-bar-full {\n background-color: #46c172; }\napp-messages table tbody tr td:first-child span {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n.theme-dark app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-gray app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-white app-messages table tbody tr td:first-child .icon {\n background-color: #ff5252; }\n.theme-dark app-typing-message .head .interlocutor {\n color: #4db1ff; }\n.theme-gray app-typing-message .head .interlocutor {\n color: #42a5f5; }\n.theme-white app-typing-message .head .interlocutor {\n color: #2c95f1; }\n.theme-dark app-typing-message .messages-content .messages-list div.date {\n color: #556576; }\n.theme-gray app-typing-message .messages-content .messages-list div.date {\n color: #565c62; }\n.theme-white app-typing-message .messages-content .messages-list div.date {\n color: #a0a5ab; }\n.theme-dark app-typing-message .messages-content .messages-list div.my {\n background-color: #2a3544; }\n.theme-gray app-typing-message .messages-content .messages-list div.my {\n background-color: #30363c; }\n.theme-white app-typing-message .messages-content .messages-list div.my {\n background-color: #fff; }\napp-typing-message .messages-content .messages-list div.my:before {\n content: \"\";\n display: block;\n position: absolute;\n top: 0;\n left: -1.1rem;\n border: 1.2rem solid transparent; }\n.theme-dark app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #2a3544; }\n.theme-gray app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #30363c; }\n.theme-white app-typing-message .messages-content .messages-list div.my:before {\n border-top-color: #fff; }\n.theme-dark app-typing-message .messages-content .messages-list div.buddy {\n background-color: #18202a; }\n.theme-gray app-typing-message .messages-content .messages-list div.buddy {\n background-color: #25292d; }\n.theme-white app-typing-message .messages-content .messages-list div.buddy {\n background-color: #ededed; }\napp-typing-message .messages-content .messages-list div.buddy:after {\n content: \"\";\n display: block;\n position: absolute;\n right: -1.1rem;\n top: 0;\n border: 1.2rem solid transparent; }\n.theme-dark app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #18202a; }\n.theme-gray app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #25292d; }\n.theme-white app-typing-message .messages-content .messages-list div.buddy:after {\n border-top-color: #ededed; }\n.theme-dark app-staking .chart-header .general .label {\n color: #556576; }\n.theme-gray app-staking .chart-header .general .label {\n color: #565c62; }\n.theme-white app-staking .chart-header .general .label {\n color: #a0a5ab; }\n.theme-dark app-staking .chart-header .general .options {\n color: #e0e0e0; }\n.theme-gray app-staking .chart-header .general .options {\n color: #e0e0e0; }\n.theme-white app-staking .chart-header .general .options {\n color: #43454b; }\napp-staking .chart-header .selected {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n flex-grow: 1;\n font-size: 1.6rem; }\n.theme-dark app-staking .chart-options .title {\n color: #556576; }\n.theme-gray app-staking .chart-options .title {\n color: #565c62; }\n.theme-white app-staking .chart-options .title {\n color: #a0a5ab; }\n.theme-dark app-staking .chart-options .options button {\n color: #e0e0e0;\n background-color: #2b3644; }\n.theme-gray app-staking .chart-options .options button {\n color: #e0e0e0;\n background-color: #292d31; }\n.theme-white app-staking .chart-options .options button {\n color: #43454b;\n background-color: #e0e0e0; }\n.theme-dark app-staking .chart-options .options button.active {\n background-color: #556576; }\n.theme-gray app-staking .chart-options .options button.active {\n background-color: #515960; }\n.theme-white app-staking .chart-options .options button.active {\n background-color: #ffffff; }\n.input-block-alias {\n position: relative; }\n.input-block-alias .alias-dropdown {\n position: absolute;\n top: 6.5rem;\n max-height: 10rem;\n overflow: auto;\n width: 100%; }\n.theme-dark .input-block-alias .alias-dropdown {\n background-color: #171e27;\n color: #e0e0e0; }\n.theme-gray .input-block-alias .alias-dropdown {\n background-color: #292d31;\n color: #e0e0e0; }\n.theme-white .input-block-alias .alias-dropdown {\n background-color: #e6e6e6;\n color: #43454b; }\n.input-block-alias .alias-dropdown div {\n font-size: 1.4rem;\n padding: 1rem; }\n.theme-dark .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(58, 69, 85, 0.5); }\n.theme-gray .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(58, 62, 66, 0.5); }\n.theme-white .input-block-alias .alias-dropdown div:hover {\n background-color: rgba(240, 240, 240, 0.5); }\napp-contacts, app-add-contacts,\napp-contact-send, app-export-import {\n flex: 1 1 auto;\n padding: 3rem;\n min-width: 85rem; }\napp-contacts .content, app-add-contacts .content,\n app-contact-send .content, app-export-import .content {\n position: relative;\n padding: 3rem;\n min-height: 100%; }\n.theme-dark app-contacts .content, .theme-dark app-add-contacts .content, .theme-dark\n app-contact-send .content, .theme-dark app-export-import .content {\n background-color: rgba(43, 54, 68, 0.5);\n color: #e0e0e0; }\n.theme-gray app-contacts .content, .theme-gray app-add-contacts .content, .theme-gray\n app-contact-send .content, .theme-gray app-export-import .content {\n background-color: rgba(37, 40, 43, 0.5);\n color: #e0e0e0; }\n.theme-white app-contacts .content, .theme-white app-add-contacts .content, .theme-white\n app-contact-send .content, .theme-white app-export-import .content {\n background-color: rgba(255, 255, 255, 0.5);\n color: #43454b; }\napp-contacts .content .head, app-add-contacts .content .head,\n app-contact-send .content .head, app-export-import .content .head {\n position: absolute;\n top: 0;\n left: 0; }\n.theme-dark app-contacts table .alias {\n color: #4db1ff; }\n.theme-gray app-contacts table .alias {\n color: #42a5f5; }\n.theme-white app-contacts table .alias {\n color: #2c95f1; }\n.theme-dark app-contacts table button .icon {\n background-color: #4db1ff; }\n.theme-gray app-contacts table button .icon {\n background-color: #42a5f5; }\n.theme-white app-contacts table button .icon {\n background-color: #2c95f1; }\n.theme-dark app-contacts table button span {\n color: #e0e0e0; }\n.theme-gray app-contacts table button span {\n color: #e0e0e0; }\n.theme-white app-contacts table button span {\n color: #43454b; }\n.theme-dark app-contacts .footer {\n color: #4db1ff; }\n.theme-gray app-contacts .footer {\n color: #42a5f5; }\n.theme-white app-contacts .footer {\n color: #2c95f1; }\n.theme-dark app-contacts .footer .import-btn {\n color: #4db1ff; }\n.theme-gray app-contacts .footer .import-btn {\n color: #42a5f5; }\n.theme-white app-contacts .footer .import-btn {\n color: #2c95f1; }\n.theme-dark app-contacts .footer .import-btn .icon {\n background-color: #4db1ff; }\n.theme-gray app-contacts .footer .import-btn .icon {\n background-color: #42a5f5; }\n.theme-white app-contacts .footer .import-btn .icon {\n background-color: #2c95f1; }\n.theme-dark app-contact-send .wallets-selection button {\n color: #4db1ff; }\n.theme-gray app-contact-send .wallets-selection button {\n color: #42a5f5; }\n.theme-white app-contact-send .wallets-selection button {\n color: #2c95f1; }\n.head {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n font-size: 1.3rem;\n padding: 0 3rem;\n width: 100%;\n height: 3rem; }\n.theme-dark .head {\n color: #4db1ff; }\n.theme-gray .head {\n color: #42a5f5; }\n.theme-white .head {\n color: #2c95f1; }\n.head .breadcrumbs > span:not(:last-child), .head .breadcrumbs a:not(:last-child) {\n position: relative;\n cursor: pointer;\n margin-right: 20px;\n outline-style: none; }\n.head .breadcrumbs > span:not(:last-child):after, .head .breadcrumbs a:not(:last-child):after {\n content: \"\";\n display: block;\n position: absolute;\n top: 0.5rem;\n right: -1.5rem;\n width: 0.9rem;\n height: 0.9rem;\n -webkit-mask: url('arrow-right.svg') no-repeat center;\n mask: url('arrow-right.svg') no-repeat center;\n -webkit-mask-size: cover;\n mask-size: cover; }\n.theme-dark .head .breadcrumbs > span:not(:last-child):after, .theme-dark .head .breadcrumbs a:not(:last-child):after {\n background-color: #4db1ff; }\n.theme-gray .head .breadcrumbs > span:not(:last-child):after, .theme-gray .head .breadcrumbs a:not(:last-child):after {\n background-color: #42a5f5; }\n.theme-white .head .breadcrumbs > span:not(:last-child):after, .theme-white .head .breadcrumbs a:not(:last-child):after {\n background-color: #2c95f1; }\n.head .back-btn {\n display: flex;\n align-items: center;\n background-color: transparent;\n color: #4db1ff;\n font-size: inherit;\n font-weight: 400;\n line-height: 1.3rem;\n padding: 0;\n height: auto; }\n.head .back-btn .icon {\n margin-right: 0.7rem;\n -webkit-mask: url('back.svg') no-repeat center;\n mask: url('back.svg') no-repeat center;\n width: 0.9rem;\n height: 0.9rem; }\n.theme-dark .head .back-btn .icon {\n background-color: #4db1ff; }\n.theme-gray .head .back-btn .icon {\n background-color: #42a5f5; }\n.theme-white .head .back-btn .icon {\n background-color: #2c95f1; }\n.scrolled-content::-webkit-scrollbar {\n background-color: transparent;\n cursor: default;\n width: 1rem;\n height: 1rem; }\n.scrolled-content::-webkit-scrollbar-track {\n background: transparent; }\n.scrolled-content::-webkit-scrollbar-thumb {\n background-color: #556576;\n background-clip: padding-box;\n border: 0.25rem solid transparent;\n border-radius: 0.5rem; }\n.scrolled-content::-webkit-scrollbar-thumb:hover {\n background-color: #556576; }\ntable {\n font-size: 1.3rem;\n width: 100%; }\ntable thead {\n text-align: left; }\n.theme-dark table thead {\n color: #556576; }\n.theme-gray table thead {\n color: #565c62; }\n.theme-white table thead {\n color: #a0a5ab; }\ntable thead tr {\n height: 4rem; }\ntable thead tr th {\n padding: 1rem;\n vertical-align: bottom; }\ntable thead tr th:first-child {\n padding-left: 3rem; }\ntable thead tr th:last-child {\n padding-right: 3rem; }\ntable tbody {\n text-align: left; }\n.theme-dark table tbody {\n color: #e0e0e0; }\n.theme-gray table tbody {\n color: #e0e0e0; }\n.theme-white table tbody {\n color: #43454b; }\ntable tbody tr {\n height: 3.5rem; }\n.theme-dark table tbody tr:nth-child(odd) {\n background-color: #18202a; }\n.theme-gray table tbody tr:nth-child(odd) {\n background-color: #25292d; }\n.theme-white table tbody tr:nth-child(odd) {\n background-color: #ffffff; }\ntable tbody tr td {\n line-height: 1.7rem;\n padding: 0 1rem;\n vertical-align: middle;\n white-space: nowrap;\n max-width: 20rem; }\ntable tbody tr td:first-child {\n padding-left: 3rem; }\ntable tbody tr td:last-child {\n padding-right: 3rem; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Light.ttf');\n font-weight: 300; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Regular.ttf');\n font-weight: 400; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-SemiBold.ttf');\n font-weight: 600; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-Bold.ttf');\n font-weight: 700; }\n@font-face {\n font-family: OpenSans;\n src: url('OpenSans-ExtraBold.ttf');\n font-weight: 800; }\nhtml {\n font-family: OpenSans, sans-serif;\n font-size: 10px; }\nbody {\n font-family: OpenSans, sans-serif;\n font-size: 1.6rem;\n width: 100vw;\n height: 100vh; }\nbody.theme-dark {\n background: #131921 url('background-dark.png') no-repeat center;\n background-size: cover; }\nbody.theme-gray {\n background: #101417 url('background-gray.png') no-repeat center;\n background-size: cover; }\nbody.theme-white {\n background: #eeeeee url('background-white.png') no-repeat center;\n background-size: cover; }\nbody app-root {\n display: flex;\n width: 100%;\n height: 100%; }\n.update-tooltip .tooltip-inner .icon {\n -webkit-mask: url('update-alert.svg') no-repeat center;\n mask: url('update-alert.svg') no-repeat center; }\n\r\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX21peGlucy5zY3NzIiwic3JjL3N0eWxlcy5zY3NzIiwibm9kZV9tb2R1bGVzL0BuZy1zZWxlY3Qvbmctc2VsZWN0L3RoZW1lcy9kZWZhdWx0LnRoZW1lLmNzcyIsInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX251bGwuc2NzcyIsInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX2Jhc2Uuc2NzcyIsInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX3RoZW1lLnNjc3MiLCJzcmMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGxheW91dFxcX21haW4uc2NzcyIsInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcbGF5b3V0XFxfc2lkZWJhci5zY3NzIiwic3JjL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxsYXlvdXRcXF93YWxsZXQuc2NzcyIsInNyYy9DOlxcVXNlcnNcXEFkbWluXFxEZXNrdG9wXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcbGF5b3V0XFxfY29udGFjdC5zY3NzIiwic3JjL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfaGVhZC5zY3NzIiwic3JjL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfc2Nyb2xsLnNjc3MiLCJzcmMvQzpcXFVzZXJzXFxBZG1pblxcRGVza3RvcFxcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXG1vZHVsZXNcXF90YWJsZS5zY3NzIiwic3JjL0M6XFxVc2Vyc1xcQWRtaW5cXERlc2t0b3BcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcc3R5bGVzLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBOEVBOztDQzVFQztBQ0ZELGlEQUFpRCxlQUFlLENBQUMsaUNBQWlDO0FBQUMsdURBQXVELGVBQWU7QUFBQywyREFBMkQsUUFBUSxDQUFDLHlDQUF5QyxDQUFDLHNCQUFzQjtBQUFDLGlFQUFpRSx5Q0FBeUM7QUFBQyxrRUFBa0UsNEJBQTRCLENBQUMsMkJBQTJCO0FBQUMsK0RBQStELHlCQUF5QixDQUFDLHdCQUF3QjtBQUFDLHlFQUF5RSxvQkFBb0IsQ0FBQywwRUFBMEU7QUFBQyxtREFBbUQsd0JBQXdCO0FBQUMseUNBQXlDLFlBQVk7QUFBQyxnQ0FBZ0MscUJBQXFCLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsZUFBZSxDQUFDLGtCQUFrQjtBQUFDLHNDQUFzQyxtQ0FBbUM7QUFBQyxvREFBb0Qsa0JBQWtCLENBQUMsaUJBQWlCO0FBQUMsZ0VBQWdFLGtCQUFrQixDQUFDLGNBQWM7QUFBQyxvRUFBb0UsVUFBVTtBQUFDLGlEQUFpRCxXQUFXO0FBQUMsK0VBQStFLE9BQU8sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCO0FBQUMsMkZBQTJGLGtCQUFrQixDQUFDLGlCQUFpQjtBQUFDLG9HQUFvRyx3QkFBd0IsQ0FBQyx3QkFBd0I7QUFBQyxvSEFBb0gsYUFBYTtBQUFDLHVFQUF1RSxlQUFlLENBQUMsZ0JBQWdCO0FBQUMsbUZBQW1GLGlCQUFpQixDQUFDLGNBQWM7QUFBQyxpRkFBaUYsY0FBYyxDQUFDLGlCQUFpQixDQUFDLHdCQUF3QixDQUFDLGlCQUFpQixDQUFDLGdCQUFnQjtBQUFDLDZGQUE2RixjQUFjLENBQUMsZUFBZTtBQUFDLG1HQUFtRyx3QkFBd0I7QUFBQyxtSEFBbUgsZ0JBQWdCO0FBQUMsK0hBQStILGNBQWMsQ0FBQyxpQkFBaUI7QUFBQyxpR0FBaUcsb0JBQW9CLENBQUMsZUFBZTtBQUFDLGdHQUFnRyxvQkFBb0IsQ0FBQyxlQUFlO0FBQUMsc0dBQXNHLHdCQUF3QjtBQUFDLHFHQUFxRyw4QkFBOEI7QUFBQyxpSEFBaUgsNkJBQTZCLENBQUMsaUJBQWlCO0FBQUMsc0dBQXNHLDZCQUE2QjtBQUFDLGtIQUFrSCxhQUFhLENBQUMsOEJBQThCO0FBQUMsaUZBQWlGLG1CQUFtQjtBQUFDLDZGQUE2RixtQkFBbUI7QUFBQyx1RkFBdUYsT0FBTyxDQUFDLGtCQUFrQixDQUFDLGdCQUFnQjtBQUFDLG1HQUFtRyxpQkFBaUIsQ0FBQyxjQUFjO0FBQUMsNkJBQTZCLFVBQVU7QUFBQyw2Q0FBNkMsYUFBYTtBQUFDLDRCQUE0QixtQkFBbUI7QUFBQyx3Q0FBd0MsbUJBQW1CO0FBQUMsNkJBQTZCLFVBQVUsQ0FBQyxpQkFBaUI7QUFBQyx5Q0FBeUMsZ0JBQWdCLENBQUMsZUFBZTtBQUFDLDZDQUE2QyxxQkFBcUI7QUFBQyx1Q0FBdUMseUNBQXlDLENBQUMsa0JBQWtCLENBQUMsMEJBQTBCO0FBQUMsbUJBQW1CLHFCQUFxQixDQUFDLHFCQUFxQixDQUFDLG1DQUFtQyxDQUFDLE1BQU07QUFBQyxvQ0FBb0MsUUFBUSxDQUFDLDhCQUE4QixDQUFDLDZCQUE2QixDQUFDLHdCQUF3QixDQUFDLGVBQWU7QUFBQyxtRkFBbUYsOEJBQThCLENBQUMsNkJBQTZCO0FBQUMsaUNBQWlDLFdBQVcsQ0FBQywyQkFBMkIsQ0FBQywwQkFBMEIsQ0FBQywyQkFBMkIsQ0FBQyxrQkFBa0I7QUFBQyxpRkFBaUYsMkJBQTJCLENBQUMsMEJBQTBCO0FBQUMsdUNBQXVDLDRCQUE0QixDQUFDLGVBQWU7QUFBQyx1Q0FBdUMseUJBQXlCLENBQUMsZUFBZTtBQUFDLHlEQUF5RCx3QkFBZ0IsQ0FBaEIscUJBQWdCLENBQWhCLG9CQUFnQixDQUFoQixnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsc0JBQXNCLENBQUMsY0FBYztBQUFDLDRFQUE0RSxjQUFjO0FBQUMsMEVBQTBFLHdCQUF3QjtBQUFDLHlLQUF5Syx3QkFBd0IsQ0FBQyxlQUFlO0FBQUMsdURBQXVELHFCQUFxQixDQUFDLHNCQUFzQixDQUFDLGdCQUFnQjtBQUFDLHFLQUFxSyxVQUFVLENBQUMsd0JBQXdCO0FBQUMsdU1BQXVNLGVBQWU7QUFBQyx3RUFBd0Usd0JBQXdCLENBQUMsVUFBVTtBQUFDLDBFQUEwRSxVQUFVO0FBQUMsdUVBQXVFLGlCQUFpQjtBQUFDLG1GQUFtRixrQkFBa0IsQ0FBQyxjQUFjO0FBQUMscUVBQXFFLGFBQWEsQ0FBQyxlQUFlLENBQUMsaUJBQWlCO0FBQUMsaUZBQWlGLGdCQUFnQixDQUFDLGVBQWU7QUFBQywrQkFBK0IsYUFBYSxDQUFDLGdCQUFnQjtBQ0cvM087RUFDRSxzQkFBc0I7RUFDdEIsOEJBQThCO0VBQzlCLDJCQUEyQixFQUFBO0FBRTdCO0VBQ0UsbUJBQW1CO0VBQ25CLDJCQUEyQjtFQUMzQix3QkFBd0I7RUFDeEIsU0FBUztFQUNULFVBQVU7RUg4QlgsMkJBQTJCO0VBQzFCLHlCQUF5QjtFQUV6QixzQkFBc0I7RUFDdEIscUJBQXFCO0VBQ3JCLGlCQUFpQixFQUFBO0FHL0JuQjs7Ozs7Ozs7Ozs7OztFQWFJLFNBQVM7RUFDVCxlQUFlO0VBQ2YsYUFBYTtFQUNiLHdCQUF3QixFQUFBO0FBRTVCOztFQUVJLGNBQWMsRUFBQTtBQUdsQjtFQUNHLGNBQWM7RUFDZCxrQkFBa0IsRUFBQTtBQUVyQjtFQUNJLGdCQUFnQixFQUFBO0FBRXBCO0VBQ0ksWUFBWSxFQUFBO0FBRWhCOztFQUVJLGFBQWEsRUFBQTtBQUlqQjtFQUNJLHlCQUF5QjtFQUN6QixpQkFBaUIsRUFBQTtBQUVyQjs7RUFFRSxVQUFVLEVBQUE7QUFJWjtFQUNJLGFBQWEsRUFBQTtBQURqQjtJQUdNLDRDQUE0QyxFQUFBO0FBSWxEOzs7O0VBSUUsMEJBQTBCO0VBQzFCLGVBQWU7RUFDZixhQUFhLEVBQUE7QUFFZjs7RUFFRSxlQUFlLEVBQUE7QUFFakI7O0VBRUUsU0FBUztFQUNULFVBQVUsRUFBQTtBQUVaO0VBQ0UsbUJBQW1CLEVBQUE7QUFFckI7RUFDRSw2QkFBNkI7RUFDN0IsdUJBQXVCLEVBQUE7QUFFekI7O0VBRUUsd0JBQXdCLEVBQUE7QUFLMUI7RUFDQyxxQkFBcUIsRUFBQTtBQUR0QjtJQUtFLFVBQVUsRUFBQTtBQUlaO0VBQUksa0JBQWtCLEVBQUE7QUFDdEI7RUFBWSxnQkFBZ0IsRUFBQTtBQUc1QjtFQUNDLFdBQVc7RUFDWCxlQUFlO0VBQ2YsWUFBWTtFQUNYLG1CQUFtQjtFQUNwQixTQUFTLEVBQUE7QUFHVjtFQUNFLHdCQUF3QixFQUFBO0FIM0N0QjtFSTVFSSx5QkNzQ21DLEVBQUE7QUxzQ3ZDO0VJNUVJLHlCQzhGbUMsRUFBQTtBTGxCdkM7RUk1RUkseUJDc0ptQyxFQUFBO0FEaEozQztFQUNFLFlBQVk7RUFDWixpQ0FBaUM7RUFDakMsaUJBQWlCO0VBQ2pCLGdCQUFnQjtFQUNoQixhQUFhO0VBQ2IsZUFBZTtFQUNmLGNBQWMsRUFBQTtBSitEWjtJSXpERSx5QkNSb0M7SURTcEMsY0NsQjJCLEVBQUE7QUwwRTdCO0lJekRFLHlCQ2dEb0M7SUQvQ3BDLGNDc0MyQixFQUFBO0FMa0I3QjtJSXpERSx5QkN3R29DO0lEdkdwQyxjQzhGMkIsRUFBQTtBTHRDN0I7SUlsREkseUJDZDZCLEVBQUE7QUxnRWpDO0lJbERJLHlCQzBDNkIsRUFBQTtBTFFqQztJSWxESSx5QkNrRzZCLEVBQUE7QUxoRGpDO0lJM0NJLHlCQ3BCNkIsRUFBQTtBTCtEakM7SUkzQ0kseUJDb0M2QixFQUFBO0FMT2pDO0lJM0NJLHlCQzRGNkIsRUFBQTtBTGpEakM7SUluQ0UseUJDakNnQztJRGtDaEMsY0N4QzJCLEVBQUE7QUwwRTdCO0lJbkNFLHlCQ3VCZ0M7SUR0QmhDLGNDZ0IyQixFQUFBO0FMa0I3QjtJSW5DRSx5QkMrRWdDO0lEOUVoQyxjQ3dFMkIsRUFBQTtBTHRDN0I7SUk1QkkseUJDdkN5QixFQUFBO0FMbUU3QjtJSTVCSSx5QkNpQnlCLEVBQUE7QUxXN0I7SUk1QkkseUJDeUV5QixFQUFBO0FMN0M3QjtJSXJCSSx5QkM3Q3lCLEVBQUE7QUxrRTdCO0lJckJJLHlCQ1d5QixFQUFBO0FMVTdCO0lJckJJLHlCQ21FeUIsRUFBQTtBTDlDN0I7SUliRSx5QkNqRGlDO0lEa0RqQyxjQzlEMkIsRUFBQTtBTDBFN0I7SUliRSx5QkNPaUM7SUROakMsY0NOMkIsRUFBQTtBTGtCN0I7SUliRSx5QkMrRGlDO0lEOURqQyxjQ2tEMkIsRUFBQTtBTHRDN0I7SUlOSSx5QkN2RDBCLEVBQUE7QUw2RDlCO0lJTkkseUJDQzBCLEVBQUE7QUxLOUI7SUlOSSx5QkN5RDBCLEVBQUE7QUxuRDlCO0lJQ0kseUJDN0QwQixFQUFBO0FMNEQ5QjtJSUNJLHlCQ0wwQixFQUFBO0FMSTlCO0lJQ0kseUJDbUQwQixFQUFBO0FMcEQ5QjtJSVNFLHlCQ3BFcUM7SURxRXJDLGNDcEYyQixFQUFBO0FMMEU3QjtJSVNFLHlCQ1pxQztJRGFyQyxjQzVCMkIsRUFBQTtBTGtCN0I7SUlTRSx5QkM0Q3FDO0lEM0NyQyxjQzRCMkIsRUFBQTtBTHRDN0I7SUlnQkkseUJDMUU4QixFQUFBO0FMMERsQztJSWdCSSx5QkNsQjhCLEVBQUE7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SURpYmhELGNDOWRzQixFQUFBO0FMckN0QjtJSXlnQkUsbUJDMWlCc0M7SUQyaUJ0QyxjQzNqQjJCLEVBQUE7QUxpRDdCO0lJeWdCRSxtQkNsZnNDO0lEbWZ0QyxjQ25nQjJCLEVBQUE7QUxQN0I7SUl5Z0JFLG1CQzFic0M7SUQyYnRDLGNDM2MyQixFQUFBO0FML0Q3QjtJSWtoQk0scURDbmpCa0MsRUFBQTtBTGlDeEM7SUlraEJNLHFEQzNma0MsRUFBQTtBTHZCeEM7SUlraEJNLHFEQ25ja0MsRUFBQTtBTC9FeEM7SUk0aEJNLHFEQUFxSCxFQUFBO0FKNWhCM0g7SUk0aEJNLHFEQUFxSCxFQUFBO0FKNWhCM0g7SUk0aEJNLHFEQUFxSCxFQUFBO0FBL0IvSDtJQXNDSSxlQUFlLEVBQUE7QUpuaUJmO01Jc2lCRSxtQkNya0JxQztNRHNrQnJDLGNDeGxCMkIsRUFBQTtBTGlEN0I7TUlzaUJFLG1CQzdnQnFDO01EOGdCckMsY0NoaUIyQixFQUFBO0FMUDdCO01Jc2lCRSxtQkNyZHFDO01Ec2RyQyxjQ3hlMkIsRUFBQTtBRDhiakM7TUE4Q00sYUFBYTtNQUNiLHNCQUFzQjtNQUN0QixtQkFBbUIsRUFBQTtBSjdpQnJCO01JcWpCTSxxRENwbEJpQyxFQUFBO0FMK0J2QztNSXFqQk0scURDNWhCaUMsRUFBQTtBTHpCdkM7TUlxakJNLHFEQ3BlaUMsRUFBQTtBTGpGdkM7TUkrakJNLHFEQUFtSCxFQUFBO0FKL2pCekg7TUkrakJNLHFEQUFtSCxFQUFBO0FKL2pCekg7TUkrakJNLHFEQUFtSCxFQUFBO0FBbEU3SDtJQXlFSSxpQkFBaUI7SUFDakIsbUJBQW1CO0lBQ25CLHFCQUFxQixFQUFBO0FBM0V6QjtNQThFTSxpQkFBaUI7TUFDakIsbUJBQW1CLEVBQUE7QUo1a0JyQjtRSStrQkksY0N2cEJrQixFQUFBO0FMd0V0QjtRSStrQkksY0MvbEJrQixFQUFBO0FMZ0J0QjtRSStrQkksY0N2aUJrQixFQUFBO0FEcWQxQjtNQXVGTSxpQkFBaUI7TUFDakIsbUJBQW1CLEVBQUE7QUpybEJyQjtRSXdsQkksY0MxbkI4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ckIsY0Mvc0JjLEVBQUE7QUxyQ3RCO1FJMHZCVSx1Q0NoekI2QjtRRGl6QjdCLGNDdDBCWSxFQUFBO0FMMkV0QjtRSTB2QlUsdUNDeHZCNkI7UUR5dkI3QixjQzl3QlksRUFBQTtBTG1CdEI7UUkwdkJVLDBDQ2hzQmdDO1FEaXNCaEMsY0N0dEJZLEVBQUE7QUxyQ3RCO1FJa3dCVSx1Q0N2ekJnQztRRHd6QmhDLGNDOTBCWSxFQUFBO0FMMkV0QjtRSWt3QlUsdUNDL3ZCZ0M7UURnd0JoQyxjQ3R4QlksRUFBQTtBTG1CdEI7UUlrd0JVLDBDQ3ZzQm1DO1FEd3NCbkMsY0M5dEJZLEVBQUE7QUQwcEIxQjtNQTBFVSw2QkFBNkI7TUFDN0IsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7QUE3RXRCO01BaUZVLHVCQUF1QixFQUFBO0FBakZqQztNQXFGVSx5QkFBeUI7TUFDekIsNEJBQTRCO01BQzVCLGlDQUFpQztNQUNqQyxxQkFBcUIsRUFBQTtBQXhGL0I7TUE0RlUseUJBQXlCLEVBQUE7QUozeEIvQjtFSXV5QkUsc0NDcDBCMEQ7RURxMEIxRCxjQ24zQm9CLEVBQUE7QUwyRXRCO0VJdXlCRSxzQ0M1d0IwRDtFRDZ3QjFELGNDM3pCb0IsRUFBQTtBTG1CdEI7RUl1eUJFLHVDQ3B0QjJEO0VEcXRCM0QsY0Nud0JvQixFQUFBO0FMckN0QjtFSWd6Qk0seUJDcjNCZSxFQUFBO0FMcUVyQjtFSWd6Qk0seUJDN3pCZSxFQUFBO0FMYXJCO0VJZ3pCTSx5QkNyd0JlLEVBQUE7QUwzQ3JCO0VJdXpCTSx5QkM5M0JpQixFQUFBO0FMdUV2QjtFSXV6Qk0seUJDdDBCaUIsRUFBQTtBTGV2QjtFSXV6Qk0seUJDOXdCaUIsRUFBQTtBTHpDdkI7RUk4ekJNLHlCQ3Q0QmdCLEVBQUE7QUx3RXRCO0VJOHpCTSx5QkM5MEJnQixFQUFBO0FMZ0J0QjtFSTh6Qk0seUJDdHhCZ0IsRUFBQTtBTHhDdEI7RUlzMEJJLHlCQzk0QmtCO0VEKzRCbEIsY0NqNUJ5QixFQUFBO0FMMEU3QjtFSXMwQkkseUJDdDFCa0I7RUR1MUJsQixjQ3oxQnlCLEVBQUE7QUxrQjdCO0VJczBCSSx5QkM5eEJrQjtFRCt4QmxCLGNDanlCeUIsRUFBQTtBTHRDN0I7RUlnMUJNLHlCQzUyQm1CLEVBQUE7QUw0QnpCO0VJZzFCTSx5QkNwekJtQixFQUFBO0FMNUJ6QjtFSWcxQk0seUJDNXZCbUIsRUFBQTtBTHBGekI7RUk0MUJFLGdDQ3A1Qm1DLEVBQUE7QUx3RHJDO0VJNDFCRSxnQ0M1MUJtQyxFQUFBO0FMQXJDO0VJNDFCRSxnQ0NweUJtQyxFQUFBO0FMeERyQztFSXMyQlEsY0MvNkJrQixFQUFBO0FMeUUxQjtFSXMyQlEsY0N2M0JrQixFQUFBO0FMaUIxQjtFSXMyQlEsY0MvekJrQixFQUFBO0FMdkMxQjtFSTYyQlEsY0N4N0JjLEVBQUE7QUwyRXRCO0VJNjJCUSxjQ2g0QmMsRUFBQTtBTG1CdEI7RUk2MkJRLGNDeDBCYyxFQUFBO0FMckN0QjtFSW8zQlEsY0M1N0JjLEVBQUE7QUx3RXRCO0VJbzNCUSxjQ3A0QmMsRUFBQTtBTGdCdEI7RUlvM0JRLGNDNTBCYyxFQUFBO0FMeEN0QjtFSWk0QkUsY0M1OEJvQixFQUFBO0FMMkV0QjtFSWk0QkUsY0NwNUJvQixFQUFBO0FMbUJ0QjtFSWk0QkUsY0M1MUJvQixFQUFBO0FMckN0QjtFSXU0QkkseUJDOTZCK0IsRUFBQTtBTHVDbkM7RUl1NEJJLHlCQ3QzQitCLEVBQUE7QUxqQm5DO0VJdTRCSSx5QkM5ekIrQixFQUFBO0FMekVuQztFSTY0Qk0seUJDbjdCaUMsRUFBQTtBTHNDdkM7RUk2NEJNLHlCQzMzQmlDLEVBQUE7QUxsQnZDO0VJNjRCTSx5QkNuMEJpQyxFQUFBO0FMMUV2QztFSXk1QkUsc0NDdDdCMEQ7RUR1N0IxRCxjQ3IrQm9CLEVBQUE7QUwyRXRCO0VJeTVCRSxzQ0M5M0IwRDtFRCszQjFELGNDNzZCb0IsRUFBQTtBTG1CdEI7RUl5NUJFLHVDQ3QwQjJEO0VEdTBCM0QsY0NyM0JvQixFQUFBO0FMckN0QjtFSW02QkUsc0NDaDhCMEQ7RURpOEIxRCxjQy8rQm9CLEVBQUE7QUwyRXRCO0VJbTZCRSxzQ0N4NEIwRDtFRHk0QjFELGNDdjdCb0IsRUFBQTtBTG1CdEI7RUltNkJFLHVDQ2gxQjJEO0VEaTFCM0QsY0MvM0JvQixFQUFBO0FMckN0QjtFSTA2QkksbUNDbCtCaUMsRUFBQTtBTHdEckM7RUkwNkJJLG1DQzE2QmlDLEVBQUE7QUxBckM7RUkwNkJJLG1DQ2wzQmlDLEVBQUE7QUx4RHJDO0VJazdCSSx5QkMxL0JrQjtFRDIvQmxCLGNDNy9CeUIsRUFBQTtBTDBFN0I7RUlrN0JJLHlCQ2w4QmtCO0VEbThCbEIsY0NyOEJ5QixFQUFBO0FMa0I3QjtFSWs3QkkseUJDMTRCa0I7RUQyNEJsQixjQzc0QnlCLEVBQUE7QUN6SGpDO0VBQ0UsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUhsQjtJQU1JLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsZ0JBQWdCLEVBQUE7QU4yRWhCO01NeEVFLHVDREoyQztNQ0szQyxjREpvQixFQUFBO0FMMkV0QjtNTXhFRSx1Q0RvRDJDO01DbkQzQyxjRG9Eb0IsRUFBQTtBTG1CdEI7TU14RUUsMENENEc4QztNQzNHOUMsY0Q0R29CLEVBQUE7QUN4SDFCO01BZ0JNLGtCQUFrQjtNQUNsQixNQUFNO01BQ04sT0FBTyxFQUFBO0FOaUVUO0VNbkRNLGNEckJnQixFQUFBO0FMd0V0QjtFTW5ETSxjRG1DZ0IsRUFBQTtBTGdCdEI7RU1uRE0sY0QyRmdCLEVBQUE7QUx4Q3RCO0VNN0NRLHlCRDNCYyxFQUFBO0FMd0V0QjtFTTdDUSx5QkQ2QmMsRUFBQTtBTGdCdEI7RU03Q1EseUJEcUZjLEVBQUE7QUx4Q3RCO0VNaENFLHlCRHZCMkI7RUN3QjNCLGNENUNvQixFQUFBO0FMMkV0QjtFTWhDRSx5QkRpQzJCO0VDaEMzQixjRFlvQixFQUFBO0FMbUJ0QjtFTWhDRSx5QkR5RjJCO0VDeEYzQixjRG9Fb0IsRUFBQTtBTHJDdEI7RU1yQkUseUJEbEMyQixFQUFBO0FMdUQ3QjtFTXJCRSx5QkRzQjJCLEVBQUE7QUxEN0I7RU1yQkUseUJEOEUyQixFQUFBO0FDekVqQztFQUdJLFlBQVk7RUFDWixnQkFBZ0I7RUFDaEIsYUFBYTtFQUNiLDhCQUE4QjtFQUM5QixzQkFBc0IsRUFBQTtBTlN0QjtJTUpJLGNEckVzQixFQUFBO0FMeUUxQjtJTUpJLGNEYnNCLEVBQUE7QUxpQjFCO0lNSkksY0QyQ3NCLEVBQUE7QUx2QzFCO0lNS00sdUNEakQyQyxFQUFBO0FMNENqRDtJTUtNLHVDRE8yQyxFQUFBO0FMWmpEO0lNS00sMENEK0Q4QyxFQUFBO0FMcEVwRDtJTVdRLGNEcEZrQixFQUFBO0FMeUUxQjtJTVdRLGNENUJrQixFQUFBO0FMaUIxQjtJTVdRLGNENEJrQixFQUFBO0FMdkMxQjtJTWtCUSx5QkQxRmMsRUFBQTtBTHdFdEI7SU1rQlEseUJEbENjLEVBQUE7QUxnQnRCO0lNa0JRLHlCRHNCYyxFQUFBO0FMeEN0QjtJTXdCVSxjRGhHWSxFQUFBO0FMd0V0QjtJTXdCVSxjRHhDWSxFQUFBO0FMZ0J0QjtJTXdCVSxjRGdCWSxFQUFBO0FDUDFCO0VBQ0Usa0JBQWtCLEVBQUE7QU5sQ2hCO0VPaEZBLHlCRkEyQyxFQUFBO0FMZ0YzQztFT2hGQSx5QkZ3RDJDLEVBQUE7QUx3QjNDO0VPaEZBLHVCRmdIOEMsRUFBQTtBTGhDOUM7RU90RU0sY0ZMZ0IsRUFBQTtBTDJFdEI7RU90RU0sY0ZtRGdCLEVBQUE7QUxtQnRCO0VPdEVNLGNGMkdnQixFQUFBO0FMckN0QjtFTy9ETSxjRlRnQixFQUFBO0FMd0V0QjtFTy9ETSxjRitDZ0IsRUFBQTtBTGdCdEI7RU8vRE0sY0Z1R2dCLEVBQUE7QUx4Q3RCO0VPckRNLDZCQUE2QjtFQUM3QixjRnZCZ0IsRUFBQTtBTDJFdEI7RU9yRE0sNkJBQTZCO0VBQzdCLGNGaUNnQixFQUFBO0FMbUJ0QjtFT3JETSw2QkFBNkI7RUFDN0IsY0Z5RmdCLEVBQUE7QUxyQ3RCO0VPNUNVLGNGN0JnQixFQUFBO0FMeUUxQjtFTzVDVSxjRjJCZ0IsRUFBQTtBTGlCMUI7RU81Q1UsY0ZtRmdCLEVBQUE7QUx2QzFCO0VPckNVLHlCRm5DWSxFQUFBO0FMd0V0QjtFT3JDVSx5QkZxQlksRUFBQTtBTGdCdEI7RU9yQ1UseUJGNkVZLEVBQUE7QUx4Q3RCO0VPOUJVLHlCRnRDd0I7RUV1Q3hCLGNGN0NtQixFQUFBO0FMMEU3QjtFTzlCVSx5QkZrQndCO0VFakJ4QixjRldtQixFQUFBO0FMa0I3QjtFTzlCVSx5QkYwRXdCO0VFekV4QixjRm1FbUIsRUFBQTtBTHRDN0I7RU9wQlkseUJGbkJ1QixFQUFBO0FMdUNuQztFT3BCWSx5QkZxQ3VCLEVBQUE7QUxqQm5DO0VPcEJZLHlCRjZGdUIsRUFBQTtBTHpFbkM7RU9kYyx5QkYxRFEsRUFBQTtBTHdFdEI7RU9kYyx5QkZGUSxFQUFBO0FMZ0J0QjtFT2RjLHlCRnNEUSxFQUFBO0FMeEN0QjtFT0xVLGNGcEVnQixFQUFBO0FMeUUxQjtFT0xVLGNGWmdCLEVBQUE7QUxpQjFCO0VPTFUsY0Y0Q2dCLEVBQUE7QUx2QzFCO0VPR1EsdUNGdERxQztFRXVEckMsY0ZyRHFCLEVBQUE7QUxpRDdCO0VPR1EsdUNGRXFDO0VFRHJDLGNGR3FCLEVBQUE7QUxQN0I7RU9HUSx5QkYwRHFDO0VFekRyQyxjRjJEcUIsRUFBQTtBTC9EN0I7RU9ZWSxjRjVEcUIsRUFBQTtBTGdEakM7RU9ZWSxjRkpxQixFQUFBO0FMUmpDO0VPWVksY0ZvRHFCLEVBQUE7QUxoRWpDO0VPbUJZLHlCRmhFNEI7RUVpRTVCLGNGbkVzQixFQUFBO0FMK0NsQztFT21CWSx5QkZSNEI7RUVTNUIsY0ZYc0IsRUFBQTtBTFRsQztFT21CWSx5QkZnRDRCO0VFL0M1QixjRjZDc0IsRUFBQTtBTGpFbEM7RU8yQlkseUJGekV5QjtFRTBFekIsY0Z2R1UsRUFBQTtBTDJFdEI7RU8yQlkseUJGakJ5QjtFRWtCekIsY0YvQ1UsRUFBQTtBTG1CdEI7RU8yQlkseUJGdUN5QjtFRXRDekIsY0ZTVSxFQUFBO0FMckN0QjtFT21DWSxjRm5GcUIsRUFBQTtBTGdEakM7RU9tQ1ksY0YzQnFCLEVBQUE7QUxSakM7RU9tQ1ksY0Y2QnFCLEVBQUE7QUxoRWpDO0VPNENRLHVDRjlGMEMsRUFBQTtBTGtEbEQ7RU80Q1EsdUNGdEMwQyxFQUFBO0FMTmxEO0VPNENRLDBDRmtCNkMsRUFBQTtBTDlEckQ7RU9xREksb0VBQTJGLEVBQUE7QVByRC9GO0VPcURJLG9FQUEyRixFQUFBO0FQckQvRjtFT3FESSxrRUFBMkYsRUFBQTtBUHJEL0Y7RU82REUsbUNGNUl5QixFQUFBO0FMK0UzQjtFTzZERSxtQ0ZwRnlCLEVBQUE7QUx1QjNCO0VPNkRFLG1DRjVCeUIsRUFBQTtBTGpDM0I7RU9xRU0sY0ZoSmdCLEVBQUE7QUwyRXRCO0VPcUVNLGNGeEZnQixFQUFBO0FMbUJ0QjtFT3FFTSxjRmhDZ0IsRUFBQTtBTHJDdEI7RU8yRVEseUJGbkpjLEVBQUE7QUx3RXRCO0VPMkVRLHlCRjNGYyxFQUFBO0FMZ0J0QjtFTzJFUSx5QkZuQ2MsRUFBQTtBTHhDdEI7RU9xRlEsa0RBQTBEO0VBQzFELHlCQUE2QyxFQUFBO0FQdEZyRDtFT3FGUSxrREFBMEQ7RUFDMUQseUJBQTZDLEVBQUE7QVB0RnJEO0VPcUZRLG9DQUEwRDtFQUMxRCx5QkFBNkMsRUFBQTtBUHRGckQ7RU80RlUsb0NBQW1FLEVBQUE7QVA1RjdFO0VPNEZVLG9DQUFtRSxFQUFBO0FQNUY3RTtFTzRGVSxvQ0FBbUUsRUFBQTtBUDVGN0U7RU91R0UsY0ZoTHdCLEVBQUE7QUx5RTFCO0VPdUdFLGNGeEh3QixFQUFBO0FMaUIxQjtFT3VHRSxjRmhFd0IsRUFBQTtBTHZDMUI7RU8rR00seUJGNUxlLEVBQUE7QUw2RXJCO0VPK0dNLHlCRnBJZSxFQUFBO0FMcUJyQjtFTytHTSx5QkY1RWUsRUFBQTtBTG5DckI7RU9zSE0seUJGcE1jLEVBQUE7QUw4RXBCO0VPc0hNLHlCRjVJYyxFQUFBO0FMc0JwQjtFT3NITSx5QkZwRmMsRUFBQTtBTGxDcEI7RU9pSVUseUJGeEt5QixFQUFBO0FMdUNuQztFT2lJVSx5QkZoSHlCLEVBQUE7QUxqQm5DO0VPaUlVLHlCRnhEeUIsRUFBQTtBTHpFbkM7RU91SVkseUJGN0syQixFQUFBO0FMc0N2QztFT3VJWSx5QkZySDJCLEVBQUE7QUxsQnZDO0VPdUlZLHlCRjdEMkIsRUFBQTtBTDFFdkM7RU9nSlEseUJGdEwrQixFQUFBO0FMc0N2QztFT2dKUSx5QkY5SCtCLEVBQUE7QUxsQnZDO0VPZ0pRLHlCRnRFK0IsRUFBQTtBTDFFdkM7RU8ySk0sY0ZuT2dCLEVBQUE7QUx3RXRCO0VPMkpNLGNGM0tnQixFQUFBO0FMZ0J0QjtFTzJKTSxjRm5IZ0IsRUFBQTtBTHhDdEI7RU9rS00sY0Z4T2tCLEVBQUE7QUxzRXhCO0VPa0tNLGNGaExrQixFQUFBO0FMY3hCO0VPa0tNLGNGeEhrQixFQUFBO0FMMUN4QjtFT3lLTSxjRjlPZSxFQUFBO0FMcUVyQjtFT3lLTSxjRnRMZSxFQUFBO0FMYXJCO0VPeUtNLGNGOUhlLEVBQUE7QUwzQ3JCO0VPZ0xNLGNGdFBrQixFQUFBO0FMc0V4QjtFT2dMTSxjRjlMa0IsRUFBQTtBTGN4QjtFT2dMTSxjRnRJa0IsRUFBQTtBTDFDeEI7RU95TFEseUJGalFjLEVBQUE7QUx3RXRCO0VPeUxRLHlCRnpNYyxFQUFBO0FMZ0J0QjtFT3lMUSx5QkZqSmMsRUFBQTtBTHhDdEI7RU9nTVEseUJGdFFnQixFQUFBO0FMc0V4QjtFT2dNUSx5QkY5TWdCLEVBQUE7QUxjeEI7RU9nTVEseUJGdEpnQixFQUFBO0FMMUN4QjtFT3VNUSx5QkY1UWEsRUFBQTtBTHFFckI7RU91TVEseUJGcE5hLEVBQUE7QUxhckI7RU91TVEseUJGNUphLEVBQUE7QUwzQ3JCO0VPOE1RLHlCRnBSZ0IsRUFBQTtBTHNFeEI7RU84TVEseUJGNU5nQixFQUFBO0FMY3hCO0VPOE1RLHlCRnBLZ0IsRUFBQTtBTDFDeEI7RVFoRkEsY0hLc0IsRUFBQTtBTDJFdEI7RVFoRkEsY0g2RHNCLEVBQUE7QUxtQnRCO0VRaEZBLGNIcUhzQixFQUFBO0FMckN0QjtFUXhFSSxjSEhrQixFQUFBO0FMMkV0QjtFUXhFSSxjSHFEa0IsRUFBQTtBTG1CdEI7RVF4RUksY0g2R2tCLEVBQUE7QUxyQ3RCO0VRbEVNLHlCSE5nQixFQUFBO0FMd0V0QjtFUWxFTSx5QkhrRGdCLEVBQUE7QUxnQnRCO0VRbEVNLHlCSDBHZ0IsRUFBQTtBTHhDdEI7RVF4RE0seUJIaEJnQixFQUFBO0FMd0V0QjtFUXhETSx5Qkh3Q2dCLEVBQUE7QUxnQnRCO0VReERNLHlCSGdHZ0IsRUFBQTtBTHhDdEI7RVEvQ0UsY0h6Qm9CLEVBQUE7QUx3RXRCO0VRL0NFLGNIK0JvQixFQUFBO0FMZ0J0QjtFUS9DRSxjSHVGb0IsRUFBQTtBTHhDdEI7RVF6Q0kseUJIL0JrQixFQUFBO0FMd0V0QjtFUXpDSSx5Qkh5QmtCLEVBQUE7QUxnQnRCO0VRekNJLHlCSGlGa0IsRUFBQTtBTHhDdEI7RVE3Qk0sdUNIZjJDLEVBQUE7QUw0Q2pEO0VRN0JNLHVDSHlDMkMsRUFBQTtBTFpqRDtFUTdCTSwwQ0hpRzhDLEVBQUE7QUxwRXBEO0VRdkJRLHlCSGpEYyxFQUFBO0FMd0V0QjtFUXZCUSx5QkhPYyxFQUFBO0FMZ0J0QjtFUXZCUSx5QkgrRGMsRUFBQTtBTHhDdEI7RVFoQlEseUJIN0JnQztFRzhCaEMsY0hoQzBCLEVBQUE7QUwrQ2xDO0VRaEJRLHlCSDJCZ0M7RUcxQmhDLGNId0IwQixFQUFBO0FMVGxDO0VRaEJRLHlCSG1GZ0M7RUdsRmhDLGNIZ0YwQixFQUFBO0FMakVsQztFUVJRLHVDSHBFcUMsRUFBQTtBTDRFN0M7RVFSUSx1Q0hacUMsRUFBQTtBTG9CN0M7RVFSUSwwQ0g0Q3dDLEVBQUE7QUxwQ2hEO0VRRFEsdUNIMUNzQyxFQUFBO0FMMkM5QztFUURRLHVDSGNzQyxFQUFBO0FMYjlDO0VRRFEseUJIc0V3QixFQUFBO0FMckVoQztFUVFJLHVDSHBGeUMsRUFBQTtBTDRFN0M7RVFRSSx1Q0g1QnlDLEVBQUE7QUxvQjdDO0VRUUksMENINEI0QyxFQUFBO0FMcENoRDtFUXFCSSxjSGhHa0IsRUFBQTtBTDJFdEI7RVFxQkksY0h4Q2tCLEVBQUE7QUxtQnRCO0VRcUJJLGNIZ0JrQixFQUFBO0FMckN0QjtFUTJCTSx5QkhuR2dCLEVBQUE7QUx3RXRCO0VRMkJNLHlCSDNDZ0IsRUFBQTtBTGdCdEI7RVEyQk0seUJIYWdCLEVBQUE7QUx4Q3RCO0VRbUNJLDRCSDNGaUMsRUFBQTtBTHdEckM7RVFtQ0ksNEJIbkNpQyxFQUFBO0FMQXJDO0VRbUNJLDRCSHFCaUMsRUFBQTtBTHhEckM7RVE4Q0UseUJIdEhvQixFQUFBO0FMd0V0QjtFUThDRSx5Qkg5RG9CLEVBQUE7QUxnQnRCO0VROENFLHlCSE5vQixFQUFBO0FMeEN0QjtFUThEUSxjSHZJa0IsRUFBQTtBTHlFMUI7RVE4RFEsY0gvRWtCLEVBQUE7QUxpQjFCO0VROERRLGNIdkJrQixFQUFBO0FMdkMxQjtFUXFFUSx5QkgvR3FCLEVBQUE7QUwwQzdCO0VRcUVRLHlCSHZEcUIsRUFBQTtBTGQ3QjtFUXFFUSx5QkhDcUIsRUFBQTtBTHRFN0I7RVE0RVEseUJIdEhxQixFQUFBO0FMMEM3QjtFUTRFUSx5Qkg5RHFCLEVBQUE7QUxkN0I7RVE0RVEseUJITnFCLEVBQUE7QUx0RTdCO0VRbUZRLDZCQUE2QixFQUFBO0FSbkZyQztFUW1GUSw2QkFBNkIsRUFBQTtBUm5GckM7RVFtRlEsNkJBQTZCLEVBQUE7QVJuRnJDO0VRMEZRLDZCQUE2QixFQUFBO0FSMUZyQztFUTBGUSw2QkFBNkIsRUFBQTtBUjFGckM7RVEwRlEsNkJBQTZCLEVBQUE7QVIxRnJDO0VRbUdVLHlCSDFJeUIsRUFBQTtBTHVDbkM7RVFtR1UseUJIbEZ5QixFQUFBO0FMakJuQztFUW1HVSx5QkgxQnlCLEVBQUE7QUx6RW5DO0VReUdZLHlCSC9JMkIsRUFBQTtBTHNDdkM7RVF5R1kseUJIdkYyQixFQUFBO0FMbEJ2QztFUXlHWSx5QkgvQjJCLEVBQUE7QUwxRXZDO0VRa0hRLHlCSHhMZ0IsRUFBQTtBTHNFeEI7RVFrSFEseUJIaElnQixFQUFBO0FMY3hCO0VRa0hRLHlCSHhFZ0IsRUFBQTtBTDFDeEI7RVF5SFEseUJIak1jLEVBQUE7QUx3RXRCO0VReUhRLHlCSHpJYyxFQUFBO0FMZ0J0QjtFUXlIUSx5QkhqRmMsRUFBQTtBTHhDdEI7RVFrSVUseUJIdk1XLEVBQUE7QUxxRXJCO0VRa0lVLHlCSC9JVyxFQUFBO0FMYXJCO0VRa0lVLHlCSHZGVyxFQUFBO0FMM0NyQjtFUTRJVSx5QkhuTmEsRUFBQTtBTHVFdkI7RVE0SVUseUJIM0phLEVBQUE7QUxldkI7RVE0SVUseUJIbkdhLEVBQUE7QUx6Q3ZCO0VRZ0tRLHlCSHJPYSxFQUFBO0FMcUVyQjtFUWdLUSx5Qkg3S2EsRUFBQTtBTGFyQjtFUWdLUSx5QkhySGEsRUFBQTtBTDNDckI7RVF1S1EseUJIL09jLEVBQUE7QUx3RXRCO0VRdUtRLHlCSHZMYyxFQUFBO0FMZ0J0QjtFUXVLUSx5QkgvSGMsRUFBQTtBTHhDdEI7RVFzTEksY0hqUWtCLEVBQUE7QUwyRXRCO0VRc0xJLGNIek1rQixFQUFBO0FMbUJ0QjtFUXNMSSxjSGpKa0IsRUFBQTtBTHJDdEI7RVE0TE0seUJIcFFnQixFQUFBO0FMd0V0QjtFUTRMTSx5Qkg1TWdCLEVBQUE7QUxnQnRCO0VRNExNLHlCSHBKZ0IsRUFBQTtBTHhDdEI7RVFvTUksY0g1UWtCLEVBQUE7QUx3RXRCO0VRb01JLGNIcE5rQixFQUFBO0FMZ0J0QjtFUW9NSSxjSDVKa0IsRUFBQTtBTHhDdEI7RVEyTUksNEJIblFpQyxFQUFBO0FMd0RyQztFUTJNSSw0QkgzTWlDLEVBQUE7QUxBckM7RVEyTUksNEJIbkppQyxFQUFBO0FMeERyQztFUXFOSSx5Qkg1UCtCLEVBQUE7QUx1Q25DO0VRcU5JLHlCSHBNK0IsRUFBQTtBTGpCbkM7RVFxTkkseUJINUkrQixFQUFBO0FMekVuQztFUTJOTSx5QkhqUWlDLEVBQUE7QUxzQ3ZDO0VRMk5NLHlCSHpNaUMsRUFBQTtBTGxCdkM7RVEyTk0seUJIakppQyxFQUFBO0FHd0ozQztFUnBURSxnQkFBZ0I7RUFDaEIsdUJBQXVCO0VBQ3ZCLG1CQUFtQixFQUFBO0FBZ0ZqQjtFUW1QVSx5Qkh4VFcsRUFBQTtBTHFFckI7RVFtUFUseUJIaFFXLEVBQUE7QUxhckI7RVFtUFUseUJIeE1XLEVBQUE7QUwzQ3JCO0VRbVFJLGNIM1VrQixFQUFBO0FMd0V0QjtFUW1RSSxjSG5Sa0IsRUFBQTtBTGdCdEI7RVFtUUksY0gzTmtCLEVBQUE7QUx4Q3RCO0VRaVJRLGNIMVZrQixFQUFBO0FMeUUxQjtFUWlSUSxjSGxTa0IsRUFBQTtBTGlCMUI7RVFpUlEsY0gxT2tCLEVBQUE7QUx2QzFCO0VRd1JRLHlCSGpVeUIsRUFBQTtBTHlDakM7RVF3UlEseUJIelF5QixFQUFBO0FMZmpDO0VRd1JRLHNCSGpOc0IsRUFBQTtBR3FMbEM7RVJ0UUUsV0FEMEQ7RUFFMUQsY0FGNEI7RUFHNUIsa0JBSDRDO0VReVNsQyxNQUFNO0VBQ04sYUFBYTtFQUNiLGdDQUFnQyxFQUFBO0FSaFN4QztJUW1TVSx5Qkg1VXVCLEVBQUE7QUx5Q2pDO0lRbVNVLHlCSHBSdUIsRUFBQTtBTGZqQztJUW1TVSxzQkg1Tm9CLEVBQUE7QUx2RTlCO0VRMlNRLHlCSG5WNEIsRUFBQTtBTHdDcEM7RVEyU1EseUJIM1I0QixFQUFBO0FMaEJwQztFUTJTUSx5QkhuTzRCLEVBQUE7QUdvTHhDO0VSdFFFLFdBRDBEO0VBRTFELGNBRjRCO0VBRzVCLGtCQUg0QztFUTRUbEMsY0FBYztFQUNkLE1BQU07RUFDTixnQ0FBZ0MsRUFBQTtBUm5UeEM7SVFzVFUseUJIOVYwQixFQUFBO0FMd0NwQztJUXNUVSx5Qkh0UzBCLEVBQUE7QUxoQnBDO0lRc1RVLHlCSDlPMEIsRUFBQTtBTHhFcEM7RVF3VU0sY0hqWm9CLEVBQUE7QUx5RTFCO0VRd1VNLGNIelZvQixFQUFBO0FMaUIxQjtFUXdVTSxjSGpTb0IsRUFBQTtBTHZDMUI7RVErVU0sY0gxWmdCLEVBQUE7QUwyRXRCO0VRK1VNLGNIbFdnQixFQUFBO0FMbUJ0QjtFUStVTSxjSDFTZ0IsRUFBQTtBRzBSMUI7RUFzQk0sYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix5QkFBeUI7RUFDekIsWUFBWTtFQUNaLGlCQUFpQixFQUFBO0FSelZuQjtFUWtXSSxjSDNhc0IsRUFBQTtBTHlFMUI7RVFrV0ksY0huWHNCLEVBQUE7QUxpQjFCO0VRa1dJLGNIM1RzQixFQUFBO0FMdkMxQjtFUTJXTSxjSHRiZ0I7RUd1YmhCLHlCSGpaOEIsRUFBQTtBTHFDcEM7RVEyV00sY0g5WGdCO0VHK1hoQix5Qkh6VjhCLEVBQUE7QUxuQnBDO0VRMldNLGNIdFVnQjtFR3VVaEIseUJIalM4QixFQUFBO0FMM0VwQztFUWtYUSx5Qkh0WnVCLEVBQUE7QUxvQy9CO0VRa1hRLHlCSDlWdUIsRUFBQTtBTHBCL0I7RVFrWFEseUJIdFN1QixFQUFBO0FHOFNuQztFQUNFLGtCQUFrQixFQUFBO0FBRHBCO0lBSUksa0JBQWtCO0lBQ2xCLFdBQVc7SUFDWCxpQkFBaUI7SUFDakIsY0FBYztJQUNkLFdBQVcsRUFBQTtBUmxZWDtNUXFZRSx5Qkg1YjJCO01HNmIzQixjSGpkb0IsRUFBQTtBTDJFdEI7TVFxWUUseUJIcFkyQjtNR3FZM0IsY0h6Wm9CLEVBQUE7QUxtQnRCO01RcVlFLHlCSDVVMkI7TUc2VTNCLGNIaldvQixFQUFBO0FHcVYxQjtNQWdCTSxpQkFBaUI7TUFDakIsYUFBYSxFQUFBO0FSM1lmO1FRK1lNLHVDSHJjaUMsRUFBQTtBTHNEdkM7UVErWU0sdUNIN1lpQyxFQUFBO0FMRnZDO1FRK1lNLDBDSHJWb0MsRUFBQTtBSTdJOUM7O0VBRUUsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUpsQjs7SUFPSSxrQkFBa0I7SUFDbEIsYUFBYTtJQUNiLGdCQUFnQixFQUFBO0FUMEVoQjs7TVN2RUUsdUNKTDJDO01JTTNDLGNKTG9CLEVBQUE7QUwyRXRCOztNU3ZFRSx1Q0ptRDJDO01JbEQzQyxjSm1Eb0IsRUFBQTtBTG1CdEI7O01TdkVFLDBDSjJHOEM7TUkxRzlDLGNKMkdvQixFQUFBO0FJeEgxQjs7TUFpQk0sa0JBQWtCO01BQ2xCLE1BQU07TUFDTixPQUFPLEVBQUE7QVRnRVQ7RVNwRE0sY0pwQmdCLEVBQUE7QUx3RXRCO0VTcERNLGNKb0NnQixFQUFBO0FMZ0J0QjtFU3BETSxjSjRGZ0IsRUFBQTtBTHhDdEI7RVMzQ00seUJKN0JnQixFQUFBO0FMd0V0QjtFUzNDTSx5QkoyQmdCLEVBQUE7QUxnQnRCO0VTM0NNLHlCSm1GZ0IsRUFBQTtBTHhDdEI7RVNwQ00sY0p2Q2dCLEVBQUE7QUwyRXRCO0VTcENNLGNKaUJn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QWdCLEVBQUE7QUFHbEI7RUFDRSxxQkFBcUI7RUFDckIsZ0NBQWdEO0VBQ2hELGdCQUFnQixFQUFBO0FBR2xCO0VBQ0UscUJBQXFCO0VBQ3JCLGlDQUFpRDtFQUNqRCxnQkFBZ0IsRUFBQTtBQUdsQjtFQUNFLHFCQUFxQjtFQUNyQiw2QkFBNkM7RUFDN0MsZ0JBQWdCLEVBQUE7QUFHbEI7RUFDRSxxQkFBcUI7RUFDckIsa0NBQWtEO0VBQ2xELGdCQUFnQixFQUFBO0FBSWxCO0VBQ0UsaUNBQWlDO0VBQ2pDLGVBQWUsRUFBQTtBQUdqQjtFQUNFLGlDQUFpQztFQUNqQyxpQkFBaUI7RUFDakIsWUFBWTtFQUNaLGFBQWEsRUFBQTtBQUpmO0lBT0ksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBUjFCO0lBWUksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBYjFCO0lBaUJJLGdFQUE4RTtJQUM5RSxzQkFBc0IsRUFBQTtBQWxCMUI7SUFzQkksYUFBYTtJQUNiLFdBQVc7SUFDWCxZQUFZLEVBQUE7QUFJaEI7RUFLTSxzREFBeUQ7VUFBekQsOENBQXlELEVBQUEiLCJmaWxlIjoic3JjL3N0eWxlcy5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQG1peGluIHRleHQtdHJ1bmNhdGUge1xyXG4gIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxufVxyXG5AbWl4aW4gdGV4dFdyYXAge1xyXG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XHJcbiAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgd29yZC1icmVhazogYnJlYWstYWxsO1xyXG4gIGxpbmUtYnJlYWs6IHN0cmljdDtcclxuICAtd2Via2l0LWh5cGhlbnM6IGF1dG87XHJcbiAgLW1zLWh5cGhlbnM6IGF1dG87XHJcbiAgaHlwaGVuczogYXV0bztcclxufVxyXG5AbWl4aW4gY292ZXJCb3gge1xyXG5cdHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuXHR0b3A6IDA7XHJcblx0bGVmdDogMDtcclxuXHR3aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IDEwMCU7XHJcbn1cclxuQG1peGluIGFicyAoJHRvcDogYXV0bywgJHJpZ2h0OiBhdXRvLCAkYm90dG9tOiBhdXRvLCAkbGVmdDogYXV0bykge1xyXG4gIHRvcDogJHRvcDtcclxuICByaWdodDogJHJpZ2h0O1xyXG4gIGJvdHRvbTogJGJvdHRvbTtcclxuICBsZWZ0OiAkbGVmdDtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbn1cclxuQG1peGluIGNvdmVySW1nIHtcclxuXHRiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0O1xyXG5cdC13ZWJraXQtYmFja2dyb3VuZC1zaXplOiBjb3ZlcjtcclxuXHQtby1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG5cdGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcblx0YmFja2dyb3VuZC1wb3NpdGlvbjogNTAlIDUwJTtcclxufVxyXG5AbWl4aW4gdmFsaW5nQm94IHtcclxuXHRwb3NpdGlvbjogYWJzb2x1dGU7XHJcblx0dG9wOiAgNTAlO1xyXG5cdGxlZnQ6IDUwJTtcclxuXHR0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTtcclxufVxyXG5AbWl4aW4gdW5TZWxlY3Qge1xyXG5cdC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcclxuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcclxuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcclxuICB1c2VyLXNlbGVjdDogbm9uZTtcclxufVxyXG5AbWl4aW4gbWF4MTE5OSB7IC8vIG1ha2V0IDExNzFcclxuICBAbWVkaWEgKG1heC13aWR0aDogMTE5OXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDExNzAgeyAvLyBtYWtldHMgOTkyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExNzBweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXg5OTEgeyAvLyBtYWtldHMgNzYyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDk5MXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDc2MSB7IC8vIG1ha2V0cyA1NzZcclxuICBAbWVkaWEgKG1heC13aWR0aDogNzYxcHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbWF4NTc1IHsgLy8gbWFrZXRzIDQwMFxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA1NzVweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtb2JpbGUge1xyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiAzOTlweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBpY29DZW50ZXIge1xyXG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcclxuICAgIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlciBjZW50ZXI7XHJcbn1cclxuQG1peGluIHBzZXVkbyAoJGRpc3BsYXk6IGJsb2NrLCAkcG9zOiBhYnNvbHV0ZSwgJGNvbnRlbnQ6ICcnKXtcclxuICBjb250ZW50OiAkY29udGVudDtcclxuICBkaXNwbGF5OiAkZGlzcGxheTtcclxuICBwb3NpdGlvbjogJHBvcztcclxufVxyXG5cclxuLypcclxuKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGVtZXNcclxuKi9cclxuQG1peGluIHRoZW1pZnkoJHRoZW1lczogJHRoZW1lcykge1xyXG4gIEBlYWNoICR0aGVtZSwgJG1hcCBpbiAkdGhlbWVzIHtcclxuICAgIC50aGVtZS0jeyR0aGVtZX0gJiB7XHJcbiAgICAgICR0aGVtZS1tYXA6ICgpICFnbG9iYWw7XHJcbiAgICAgIEBlYWNoICRrZXksICRzdWJtYXAgaW4gJG1hcCB7XHJcbiAgICAgICAgJHZhbHVlOiBtYXAtZ2V0KG1hcC1nZXQoJHRoZW1lcywgJHRoZW1lKSwgJyN7JGtleX0nKTtcclxuICAgICAgICAkdGhlbWUtbWFwOiBtYXAtbWVyZ2UoJHRoZW1lLW1hcCwgKCRrZXk6ICR2YWx1ZSkpICFnbG9iYWw7XHJcbiAgICAgIH1cclxuICAgICAgQGNvbnRlbnQ7XHJcbiAgICAgICR0aGVtZS1tYXA6IG51bGwgIWdsb2JhbDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbkBmdW5jdGlvbiB0aGVtZWQoJGtleSkge1xyXG4gIEByZXR1cm4gbWFwLWdldCgkdGhlbWUtbWFwLCAka2V5KTtcclxufVxyXG4iLCIvKlxyXG4qIEltcGxlbWVudGF0aW9uIG9mIHRoZW1lc1xyXG4qL1xuQGltcG9ydCB1cmwofkBuZy1zZWxlY3Qvbmctc2VsZWN0L3RoZW1lcy9kZWZhdWx0LnRoZW1lLmNzcyk7XG5odG1sIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7IH1cblxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xuICBib3gtc2l6aW5nOiBpbmhlcml0O1xuICAtd2Via2l0LWJveC1zaXppbmc6IGluaGVyaXQ7XG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcbiAgbWFyZ2luOiAwO1xuICBwYWRkaW5nOiAwO1xuICAtd2Via2l0LXRvdWNoLWNvbGxvdXQ6IG5vbmU7XG4gIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1vei11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1zLXVzZXItc2VsZWN0OiBub25lO1xuICB1c2VyLXNlbGVjdDogbm9uZTsgfVxuXG5odG1sLCBib2R5LCBkaXYsIHNwYW4sIGFwcGxldCwgb2JqZWN0LCBpZnJhbWUsXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXG5hLCBhYmJyLCBhY3JvbnltLCBhZGRyZXNzLCBiaWcsIGNpdGUsIGNvZGUsXG5kZWwsIGRmbiwgZW0sIGltZywgaW5zLCBrYmQsIHEsIHMsIHNhbXAsXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxuYiwgdSwgaSwgY2VudGVyLFxuZGwsIGR0LCBkZCwgb2wsIHVsLCBsaSxcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxudGFibGUsIGNhcHRpb24sIHRib2R5LCB0Zm9vdCwgdGhlYWQsIHRyLCB0aCwgdGQsXG5hcnRpY2xlLCBhc2lkZSwgY2FudmFzLCBkZXRhaWxzLCBlbWJlZCxcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcbm1lbnUsIG5hdiwgb3V0cHV0LCBydWJ5LCBzZWN0aW9uLCBzdW1tYXJ5LFxudGltZSwgbWFyaywgYXVkaW8sIHZpZGVvIHtcbiAgYm9yZGVyOiAwO1xuICBmb250LXNpemU6IDEwMCU7XG4gIGZvbnQ6IGluaGVyaXQ7XG4gIHZlcnRpY2FsLWFsaWduOiBiYXNlbGluZTsgfVxuXG5hcnRpY2xlLCBhc2lkZSwgZGV0YWlscywgZmlnY2FwdGlvbiwgZmlndXJlLFxuZm9vdGVyLCBoZWFkZXIsIGhncm91cCwgbWVudSwgbmF2LCBzZWN0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7IH1cblxuYm9keSB7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICBmb250LXN0eWxlOiBub3JtYWw7IH1cblxub2wsIHVsIHtcbiAgbGlzdC1zdHlsZTogbm9uZTsgfVxuXG5ibG9ja3F1b3RlLCBxIHtcbiAgcXVvdGVzOiBub25lOyB9XG5cbmJsb2NrcXVvdGU6YmVmb3JlLCBibG9ja3F1b3RlOmFmdGVyLFxucTpiZWZvcmUsIHE6YWZ0ZXIge1xuICBjb250ZW50OiBub25lOyB9XG5cbnRhYmxlIHtcbiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcbiAgYm9yZGVyLXNwYWNpbmc6IDA7IH1cblxudGQsXG50aCB7XG4gIHBhZGRpbmc6IDA7IH1cblxuaW5wdXQge1xuICBvdXRsaW5lOiBub25lOyB9XG4gIGlucHV0Oi13ZWJraXQtYXV0b2ZpbGwge1xuICAgIC13ZWJraXQtYm94LXNoYWRvdzogMCAwIDAgMTAwMHB4IHdoaXRlIGluc2V0OyB9XG5cbmJ1dHRvbixcbmh0bWwgaW5wdXRbdHlwZT1cImJ1dHRvblwiXSxcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcbmlucHV0W3R5cGU9XCJzdWJtaXRcIl0ge1xuICAtd2Via2l0LWFwcGVhcmFuY2U6IGJ1dHRvbjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBvdXRsaW5lOiBub25lOyB9XG5cbmJ1dHRvbltkaXNhYmxlZF0sXG5odG1sIGlucHV0W2Rpc2FibGVkXSB7XG4gIGN1cnNvcjogZGVmYXVsdDsgfVxuXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXG5pbnB1dDo6LW1vei1mb2N1cy1pbm5lciB7XG4gIGJvcmRlcjogMDtcbiAgcGFkZGluZzogMDsgfVxuXG5pbnB1dCB7XG4gIGxpbmUtaGVpZ2h0OiBub3JtYWw7IH1cblxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXSB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDsgfVxuXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXTo6LXdlYmtpdC1zZWFyY2gtZGVjb3JhdGlvbiB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTsgfVxuXG5hIHtcbiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOyB9XG4gIGE6YWN0aXZlLCBhOmhvdmVyLCBhOmZvY3VzIHtcbiAgICBvdXRsaW5lOiAwOyB9XG5cbmkge1xuICBmb250LXN0eWxlOiBpdGFsaWM7IH1cblxuYiwgc3Ryb25nIHtcbiAgZm9udC13ZWlnaHQ6IDcwMDsgfVxuXG5pbWcge1xuICB3aWR0aDogYXV0bztcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IGF1dG87XG4gIHZlcnRpY2FsLWFsaWduOiB0b3A7XG4gIGJvcmRlcjogMDsgfVxuXG4uaGlkZGVuIHtcbiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS1kYXJrIC5hcHAtY29udGVudCAucHJlbG9hZGVyIC5sb2FkaW5nLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG5idXR0b24ge1xuICBib3JkZXI6IG5vbmU7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxLjVyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIG91dGxpbmU6IG5vbmU7XG4gIHBhZGRpbmc6IDAgMXJlbTtcbiAgaGVpZ2h0OiA0LjJyZW07IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0IHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjOWNhZGI3O1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbiksIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzc5ODQ4ZjtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzkwYTRhZTtcbiAgICBjb2xvcjogI2ZlZmVmZTsgfVxuICAudGhlbWUtZGFyayBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNiN2QxZTA7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKTpob3ZlciwgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTFhZWJiOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYWViZWM2OyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldDpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2E3YjljMjsgfVxuICAudGhlbWUtZ3JheSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmZvY3VzLCAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4YTk1OWY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNhN2I5YzI7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmO1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzgyZDdmZjsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4NmQ2ZmY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjYjNmZjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1OWI1ZmQ7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWZiNmZjOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzNzlmZmE7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDtcbiAgICBjb2xvcjogIzExMTkyMTsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkO1xuICAgIGNvbG9yOiAjMWExYTFhOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4ZGZjYzY7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzdiZjZjNjsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVhZDU4NjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjJlMGIyOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1Y2RjOWU7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1M2M3N2M7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGQwZTE7XG4gICAgY29sb3I6ICMxMTE5MjE7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzZWM1ZDc7XG4gICAgY29sb3I6ICMxYTFhMWE7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjZiNmM3O1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjODdmNGY1OyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzJlZGZlOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUyY2JkOTsgfVxuICAudGhlbWUtZGFyayBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyZDVlODsgfVxuICAudGhlbWUtZ3JheSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUwZDBlMTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzMWJlY2Y7IH1cbiAgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOyB9XG4gICAgLnRoZW1lLWRhcmsgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyYjM2NDQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmYzNDM4O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7XG4gICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgIGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAxcmVtO1xuICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgd2lkdGg6IDEuN3JlbTtcbiAgICAgIGhlaWdodDogMS43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQzNDU0YjsgfVxuXG4uaW5wdXQtYmxvY2sge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtOyB9XG4gIC5pbnB1dC1ibG9jayAud3JhcC1sYWJlbCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbiAgICBtaW4taGVpZ2h0OiAyLjRyZW07IH1cbiAgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICBmb250LXNpemU6IDEuM3JlbTtcbiAgICBsaW5lLWhlaWdodDogMi40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBsYWJlbCB7XG4gICAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ndGV4dCddLCAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLmlucHV0LWJsb2NrIHNlbGVjdCB7XG4gICAgYm9yZGVyOiBub25lO1xuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgIG91dGxpbmU6IG5vbmU7XG4gICAgcGFkZGluZzogMCAxcmVtO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogNC4ycmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1ncmF5IC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBpbnB1dFt0eXBlPSd0ZXh0J10sIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC5pbnB1dC1ibG9jay50ZXh0YXJlYSB7XG4gICAgaGVpZ2h0OiBhdXRvOyB9XG4gICAgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgICAgb3V0bGluZTogbm9uZTtcbiAgICAgIHBhZGRpbmc6IDFyZW07XG4gICAgICB3aWR0aDogMTAwJTtcbiAgICAgIG1pbi13aWR0aDogMTAwJTtcbiAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgIG1pbi1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG1heC1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xuICAgICAgcmVzaXplOiBub25lOyB9XG4gICAgICAudGhlbWUtZGFyayAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICBmb250LXNpemU6IDFyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuNHJlbTtcbiAgICBhbGlnbi1zZWxmOiBmbGV4LWVuZDtcbiAgICB0ZXh0LWFsaWduOiByaWdodDsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cbiAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICAgIGNvbG9yOiAjZmY1MjUyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgLmVycm9yLXRleHQge1xuICBjb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbmlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgZm9udC13ZWlnaHQ6IDQwMDtcbiAgcGFkZGluZy1sZWZ0OiAyLjRyZW07XG4gIC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcbiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLWtodG1sLXVzZXItc2VsZWN0OiBub25lO1xuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xuICAtbXMtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIHVzZXItc2VsZWN0OiBub25lOyB9XG4gIC50aGVtZS1kYXJrIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gICAgY29sb3I6ICM1NTY1NzY7IH1cbiAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgb3BhY2l0eTogMDsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDAuN3JlbTtcbiAgICBsZWZ0OiAwO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICB3aWR0aDogMS40cmVtO1xuICAgIGhlaWdodDogMS40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzRkYjFmZjsgfVxuICAgIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YmVmb3JlIHtcbiAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkICM0MmE1ZjU7IH1cbiAgICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzJjOTVmMTsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsOmFmdGVyIHtcbiAgICBjb250ZW50OiAnJztcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAxcmVtO1xuICAgIGxlZnQ6IDAuM3JlbTtcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgb3BhY2l0eTogMDtcbiAgICB3aWR0aDogMC44cmVtO1xuICAgIGhlaWdodDogMC44cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gICAgLnRoZW1lLXdoaXRlIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YWZ0ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOmNoZWNrZWQgKyBsYWJlbDphZnRlciB7XG4gIG9wYWNpdHk6IDE7IH1cblxuaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LXdlaWdodDogNDAwO1xuICBwYWRkaW5nLWxlZnQ6IDMuNnJlbTtcbiAgLXdlYmtpdC10b3VjaC1jb2xsb3V0OiBub25lO1xuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xuICAta2h0bWwtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tb3otdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6bm90KGNoZWNrZWQpIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDUwJTtcbiAgbGVmdDogMS42cmVtO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjsgfVxuICBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiAxLjZyZW07XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIHdpZHRoOiAxLjRyZW07XG4gICAgaGVpZ2h0OiAxLjRyZW07IH1cbiAgICAudGhlbWUtZGFyayBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzQyYTVmNTsgfVxuICAgIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjMmM5NWYxOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zyk7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS13aGl0ZSAuc3dpdGNoIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayAuc3dpdGNoIC5jaXJjbGUub24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vZmYge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTBhNWFiOyB9XG5cbi50YWJsZS10b29sdGlwIHtcbiAgcGFkZGluZzogMXJlbSAycmVtOyB9XG4gIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcCB7XG4gICAgYmFja2dyb3VuZDogIzNlNDY0YztcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAudGFibGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gICAgZm9udC1zaXplOiAxLjNyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3Age1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3A6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAtMXJlbTtcbiAgICAgIGxlZnQ6IDAuN3JlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICByaWdodDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6ICNmZmZmZmYgI2ZmZmZmZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tOmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIGxlZnQ6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b206YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGMgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQ7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLWxlZnQ6YmVmb3JlIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IC0xcmVtO1xuICAgICAgbGVmdDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgI2ZmZmZmZjsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIHJpZ2h0OiAwLjdyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICMzZTQ2NGMgIzNlNDY0YyB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIHJpZ2h0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cbiAgICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBsZWZ0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS1ncmF5IC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQ6YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cblxuLnRhYmxlLXRvb2x0aXAtZGltZW5zaW9ucyAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICBtYXgtd2lkdGg6IDIwcmVtO1xuICBtYXgtaGVpZ2h0OiAxMHJlbTsgfVxuXG4uYmFsYW5jZS10b29sdGlwIHtcbiAgcGFkZGluZzogMS4zcmVtOyB9XG4gIC50aGVtZS1kYXJrIC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICM0MjUwNWY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS1ncmF5IC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZm9udC1zaXplOiAxLjNyZW07IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMC43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgIGN1cnNvcjogcG9pbnRlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmJhbGFuY2UtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAubGluayB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLXRvcCB7XG4gICAgbWFyZ2luLXRvcDogLTFyZW07IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAuYmFsYW5jZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gIC5iYWxhbmNlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cblxuLmFjY291bnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XG4gIG1heC13aWR0aDogMThyZW07IH1cblxuLmNvbW1lbnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICB3b3JkLWJyZWFrOiBicmVhay13b3JkO1xuICBtYXgtd2lkdGg6IDUwcmVtO1xuICBtYXgtaGVpZ2h0OiAyNXJlbTsgfVxuXG4udXBkYXRlLXRvb2x0aXAge1xuICBwYWRkaW5nOiAxLjVyZW07IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICNmZmZmZmY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpO1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQge1xuICAgIGJhY2tncm91bmQ6ICM1ZjJiMTE7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogIzU1MjQwZDtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogI2VmNmMwMDtcbiAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuaW1wb3J0YW50Lm5nLXRvb2x0aXAtbGVmdC1ib3R0b206YWZ0ZXIge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExOyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNTUyNDBkICM1NTI0MGQ7IH1cbiAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjZWY2YzAwICNlZjZjMDA7IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExIHRyYW5zcGFyZW50OyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1yaWdodC1ib3R0b206YmVmb3JlIHtcbiAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1NTI0MGQgIzU1MjQwZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2VmNmMwMCAjZWY2YzAwIHRyYW5zcGFyZW50OyB9XG4gIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgcGFkZGluZzogMi41cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICM1ZjFkMWQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgICBiYWNrZ3JvdW5kOiAjNGMxOTE5O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICNlNTM5MzU7XG4gICAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCAudG9vbHRpcC1pbm5lciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7IH1cbiAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuY3JpdGljYWwubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzRjMTkxOSAjNGMxOTE5OyB9XG4gICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2U1MzkzNSAjZTUzOTM1OyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZCB0cmFuc3BhcmVudDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjNGMxOTE5ICM0YzE5MTkgdHJhbnNwYXJlbnQ7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNlNTM5MzUgI2U1MzkzNSB0cmFuc3BhcmVudDsgfVxuICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIge1xuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgICBjb2xvcjogIzJjOTVmMTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmltcG9ydGFudC11cGRhdGUge1xuICAgICAgICBjb2xvcjogI2ZmNmYwMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmZmZmZmOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5jcml0aWNhbC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xuICAgICAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZjZmMDA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAud3JvbmctdGltZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZmZmZmY7IH1cbiAgICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgbWFyZ2luOiAxLjVyZW0gMDtcbiAgICAgIHdpZHRoOiA1cmVtO1xuICAgICAgaGVpZ2h0OiA1cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xLjVyZW07IH1cbiAgICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAwLjZyZW07XG4gICAgICByaWdodDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmICM0MjUwNWY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjM2U0NjRjICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmOyB9XG4gIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogMC42cmVtO1xuICAgICAgbGVmdDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgIzQyNTA1ZiB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICBib3JkZXI6IG5vbmU7XG4gIHBhZGRpbmc6IDA7IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJiMzY0NDtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgbGkge1xuICBkaXNwbGF5OiBibG9jaztcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xuICBmb250LXNpemU6IDEuM3JlbTtcbiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgYSB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBwYWRkaW5nOiAwLjVlbSAxZW07IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSBhIHtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGE6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuXG4ubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qge1xuICB3aWR0aDogMTAwJTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSB7XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICBoZWlnaHQ6IDQuMnJlbTsgfVxuICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtZ3JheSAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciB7XG4gICAgICBwYWRkaW5nOiAwOyB9XG4gICAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXQge1xuICAgICAgICB0b3A6IGF1dG87IH1cbiAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgYm9yZGVyOiBub25lOyB9XG4gICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3OyB9XG4gICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjsgfVxuICAgIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgZm9udC1zaXplOiAxLjRyZW07XG4gICAgICBwYWRkaW5nOiAxcmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLW1hcmtlZCB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjQwLCAyNDAsIDI0MCwgMC41KTtcbiAgICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXM6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgICAgY3Vyc29yOiBkZWZhdWx0O1xuICAgICAgd2lkdGg6IDFyZW07XG4gICAgICBoZWlnaHQ6IDFyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xuICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICAgIGJhY2tncm91bmQtY2xpcDogcGFkZGluZy1ib3g7XG4gICAgICBib3JkZXI6IDAuMjVyZW0gc29saWQgdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwsIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZyk7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWdyYXkgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3IsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmFjdGlvbi1idXR0b24sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSB7XG4gIGJvcmRlci10b3A6IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmxhYmVsIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHJhbnNhY3Rpb24tZGV0YWlscyAudGFibGUgLnJvdyAuY2VsbC52YWx1ZSB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmtleS12YWx1ZSB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNjNhM2U7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZGFyay5wbmcpO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtb3Blbi13YWxsZXQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKTtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC50aXRsZSB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmYzNDM4OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbmFwcC1tYWluLCBhcHAtY3JlYXRlLXdhbGxldCwgYXBwLW9wZW4td2FsbGV0LCBhcHAtcmVzdG9yZS13YWxsZXQsIGFwcC1zZWVkLXBocmFzZSwgYXBwLXdhbGxldC1kZXRhaWxzLCBhcHAtYXNzaWduLWFsaWFzLCBhcHAtZWRpdC1hbGlhcywgYXBwLXRyYW5zZmVyLWFsaWFzLCBhcHAtc2V0dGluZ3MsIGFwcC1sb2dpbiB7XG4gIGZsZXg6IDEgMSBhdXRvO1xuICBwYWRkaW5nOiAzcmVtO1xuICBtaW4td2lkdGg6IDg1cmVtOyB9XG4gIGFwcC1tYWluIC5jb250ZW50LCBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXJlc3RvcmUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWFzc2lnbi1hbGlhcyAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWxvZ2luIC5jb250ZW50IHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC41KTtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgYXBwLW1haW4gLmNvbnRlbnQgLmhlYWQsIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50IC5oZWFkLCBhcHAtb3Blbi13YWxsZXQgLmNvbnRlbnQgLmhlYWQsIGFwcC1yZXN0b3JlLXdhbGxldCAuY29udGVudCAuaGVhZCwgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50IC5oZWFkLCBhcHAtd2FsbGV0LWRldGFpbHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hc3NpZ24tYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50IC5oZWFkLCBhcHAtdHJhbnNmZXItYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1zZXR0aW5ncyAuY29udGVudCAuaGVhZCwgYXBwLWxvZ2luIC5jb250ZW50IC5oZWFkIHtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMDtcbiAgICAgIGxlZnQ6IDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCAuYWRkLXdhbGxldCAuYWRkLXdhbGxldC1oZWxwIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5zZWVkLXBocmFzZS1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxNzFlMjc7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyOTJkMzE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQtZGV0YWlscyAuc2VlZC1waHJhc2Uge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2OyB9XG5cbmFwcC1zZXR0aW5ncyAuY29udGVudCB7XG4gIGhlaWdodDogMTAwJTtcbiAgb3ZlcmZsb3cteTogYXV0bztcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnRoZW1lLXNlbGVjdGlvbiB7XG4gICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpOyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cbiAgLnRoZW1lLWRhcmsgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2sgLmxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSAubGFiZWwge1xuICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cblxuYXBwLWxvZ2luIHtcbiAgbWluLXdpZHRoOiBpbmhlcml0OyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWYyNzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxYzFlMjE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBoMyB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIgYnV0dG9uIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTtcbiAgY29sb3I6ICNmZWZlZmU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM2M2EzZTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMWU4OGU1O1xuICBjb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdy5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50OmhvdmVyOm5vdCguYWN0aXZlKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDY5LCA4NSwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzOmFmdGVyIHtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KHRvIGJvdHRvbSwgdHJhbnNwYXJlbnQgMCUsICMxNzFmMjcgMTAwJSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgIzFjMWUyMSAxMDAlKTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgd2hpdGUgMTAwJSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3Mge1xuICBib3JkZXItYm90dG9tOiAwLjJyZW0gc29saWQgIzFmMjgzMzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmUzMzM3OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSkgIWltcG9ydGFudDtcbiAgY29sb3I6ICNlMGUwZTAgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSAhaW1wb3J0YW50O1xuICBjb2xvcjogI2UwZTBlMCAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxZTg4ZTUgIWltcG9ydGFudDtcbiAgY29sb3I6ICNmZmZmZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjUgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmICFpbXBvcnRhbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vZmZsaW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAub25saW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnN5bmNpbmcgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAubG9hZGluZyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuc3RhbmRhcmQge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pbXBvcnRhbnQge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5jcml0aWNhbCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLnRpbWUge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLnN0YW5kYXJkIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5pbXBvcnRhbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uY3JpdGljYWwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24udGltZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5oZWFkZXIgYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIC5hbGlhcyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3Mge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5hZGRyZXNzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyMywgMzEsIDM5LCAwLjUpOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI4LCAzMCwgMzMsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIC5pbmRpY2F0b3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYi5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2MiwgNjYsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWI6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQgLmZvcm0tc2VuZCAuc2VuZC1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZCAuZm9ybS1zZW5kIC5hZGRpdGlvbmFsLWRldGFpbHMge1xuICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1yZWNlaXZlIC5idG4tY29weS1hZGRyZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ci5sb2NrZWQtdHJhbnNhY3Rpb24ge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMSkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTgyMDJhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzIpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMykge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMgLmNvbmZpcm1hdGlvbiAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC51bmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnNlbmQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnJlY2VpdmVkIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWNkYTlkOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZ3JheSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLm5ldywgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLmFsZXJ0IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24uc2VsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ucHVyY2hhc2UsIC50aGVtZS1ncmF5IGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAucHVyY2hhc2Utc2VsZWN0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3QgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zdGF0ZXMge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgIzJiMzY0NDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgI2ViZWJlYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNDNmNGE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIgLnByb2dyZXNzLWJhci1mdWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbmFwcC1tZXNzYWdlcyB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCBzcGFuIHtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1lc3NhZ2VzIHRhYmxlIHRib2R5IHRyIHRkOmZpcnN0LWNoaWxkIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10eXBpbmctbWVzc2FnZSAuaGVhZCAuaW50ZXJsb2N1dG9yIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5kYXRlIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYTM1NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzMDM2M2M7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcIjtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICBsZWZ0OiAtMS4xcmVtO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzJhMzU0NDsgfVxuICAudGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzMwMzYzYzsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teTpiZWZvcmUge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxODIwMmE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWRlZGVkOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICBjb250ZW50OiBcIlwiO1xuICBkaXNwbGF5OiBibG9jaztcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICByaWdodDogLTEuMXJlbTtcbiAgdG9wOiAwO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmJ1ZGR5OmFmdGVyIHtcbiAgICBib3JkZXItdG9wLWNvbG9yOiAjMTgyMDJhOyB9XG4gIC50aGVtZS1ncmF5IGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICMyNTI5MmQ7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNlZGVkZWQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LWhlYWRlciAuZ2VuZXJhbCAubGFiZWwge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5vcHRpb25zIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG5hcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5zZWxlY3RlZCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gIGZsZXgtZ3JvdzogMTtcbiAgZm9udC1zaXplOiAxLjZyZW07IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC50aXRsZSB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzUxNTk2MDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLm9wdGlvbnMgYnV0dG9uLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLmlucHV0LWJsb2NrLWFsaWFzIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlOyB9XG4gIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDYuNXJlbTtcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcbiAgICBvdmVyZmxvdzogYXV0bztcbiAgICB3aWR0aDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdiB7XG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICAgIHBhZGRpbmc6IDFyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpOyB9XG4gICAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdjpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbmFwcC1jb250YWN0cywgYXBwLWFkZC1jb250YWN0cyxcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcbiAgZmxleDogMSAxIGF1dG87XG4gIHBhZGRpbmc6IDNyZW07XG4gIG1pbi13aWR0aDogODVyZW07IH1cbiAgYXBwLWNvbnRhY3RzIC5jb250ZW50LCBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LFxuICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmtcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXlcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmNvbnRlbnQsIC50aGVtZS13aGl0ZSBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LCAudGhlbWUtd2hpdGVcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjUpO1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICBhcHAtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hZGQtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsXG4gICAgYXBwLWNvbnRhY3Qtc2VuZCAuY29udGVudCAuaGVhZCwgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQgLmhlYWQge1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAwO1xuICAgICAgbGVmdDogMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIC5hbGlhcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgYnV0dG9uIHNwYW4ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgLmZvb3RlciB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIC5mb290ZXIgLmltcG9ydC1idG4ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWNvbnRhY3Qtc2VuZCAud2FsbGV0cy1zZWxlY3Rpb24gYnV0dG9uIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLmhlYWQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgZm9udC1zaXplOiAxLjNyZW07XG4gIHBhZGRpbmc6IDAgM3JlbTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogM3JlbTsgfVxuICAudGhlbWUtZGFyayAuaGVhZCB7XG4gICAgY29sb3I6ICM0ZGIxZmY7IH1cbiAgLnRoZW1lLWdyYXkgLmhlYWQge1xuICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSAuaGVhZCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIG1hcmdpbi1yaWdodDogMjBweDtcbiAgICBvdXRsaW5lLXN0eWxlOiBub25lOyB9XG4gICAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMC41cmVtO1xuICAgICAgcmlnaHQ6IC0xLjVyZW07XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctcmlnaHQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgbWFzay1zaXplOiBjb3ZlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZGFyayAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZ3JheSAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyA+IHNwYW46bm90KDpsYXN0LWNoaWxkKTphZnRlciwgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyBhOm5vdCg6bGFzdC1jaGlsZCk6YWZ0ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG4gIC5oZWFkIC5iYWNrLWJ0biB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIGNvbG9yOiAjNGRiMWZmO1xuICAgIGZvbnQtc2l6ZTogaW5oZXJpdDtcbiAgICBmb250LXdlaWdodDogNDAwO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XG4gICAgcGFkZGluZzogMDtcbiAgICBoZWlnaHQ6IGF1dG87IH1cbiAgICAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYmFjay5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi5zY3JvbGxlZC1jb250ZW50Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBjdXJzb3I6IGRlZmF1bHQ7XG4gIHdpZHRoOiAxcmVtO1xuICBoZWlnaHQ6IDFyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRyYWNrIHtcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcbiAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xuICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG50YWJsZSB7XG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xuICB3aWR0aDogMTAwJTsgfVxuICB0YWJsZSB0aGVhZCB7XG4gICAgdGV4dC1hbGlnbjogbGVmdDsgfVxuICAgIC50aGVtZS1kYXJrIHRhYmxlIHRoZWFkIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgICAudGhlbWUtd2hpdGUgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICNhMGE1YWI7IH1cbiAgICB0YWJsZSB0aGVhZCB0ciB7XG4gICAgICBoZWlnaHQ6IDRyZW07IH1cbiAgICAgIHRhYmxlIHRoZWFkIHRyIHRoIHtcbiAgICAgICAgcGFkZGluZzogMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IGJvdHRvbTsgfVxuICAgICAgICB0YWJsZSB0aGVhZCB0ciB0aDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRoZWFkIHRyIHRoOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cbiAgdGFibGUgdGJvZHkge1xuICAgIHRleHQtYWxpZ246IGxlZnQ7IH1cbiAgICAudGhlbWUtZGFyayB0YWJsZSB0Ym9keSB7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgdGFibGUgdGJvZHkgdHIge1xuICAgICAgaGVpZ2h0OiAzLjVyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZChvZGQpIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuICAgICAgLnRoZW1lLWdyYXkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG4gICAgICAudGhlbWUtd2hpdGUgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG4gICAgICB0YWJsZSB0Ym9keSB0ciB0ZCB7XG4gICAgICAgIGxpbmUtaGVpZ2h0OiAxLjdyZW07XG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTsgfVxuICAgICAgICB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRib2R5IHRyIHRkOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtTGlnaHQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDMwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA0MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtU2VtaUJvbGQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDYwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1Cb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA4MDA7IH1cblxuaHRtbCB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxMHB4OyB9XG5cbmJvZHkge1xuICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XG4gIGZvbnQtc2l6ZTogMS42cmVtO1xuICB3aWR0aDogMTAwdnc7XG4gIGhlaWdodDogMTAwdmg7IH1cbiAgYm9keS50aGVtZS1kYXJrIHtcbiAgICBiYWNrZ3JvdW5kOiAjMTMxOTIxIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS1ncmF5IHtcbiAgICBiYWNrZ3JvdW5kOiAjMTAxNDE3IHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS13aGl0ZSB7XG4gICAgYmFja2dyb3VuZDogI2VlZWVlZSB1cmwoXCJhc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgYmFja2dyb3VuZC1zaXplOiBjb3ZlcjsgfVxuICBib2R5IGFwcC1yb290IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTsgfVxuXG4udXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7IH1cbiIsIi5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcntiYWNrZ3JvdW5kOiNmZmY7Ym9yZGVyLWNvbG9yOiNiM2IzYjMgI2NjYyAjZDlkOWQ5fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcjpob3Zlcntib3gtc2hhZG93Om5vbmV9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy1hcnJvd3t0b3A6LTJweDtib3JkZXItY29sb3I6dHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzk5OTtib3JkZXItd2lkdGg6MCA1cHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lciAubmctYXJyb3c6aG92ZXJ7Ym9yZGVyLWNvbG9yOnRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzMzN9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC1ib3R0b20+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6MDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC10b3A+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MDtib3JkZXItdG9wLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtZm9jdXNlZDpub3QoLm5nLXNlbGVjdC1vcGVuZWQpPi5uZy1zZWxlY3QtY29udGFpbmVye2JvcmRlci1jb2xvcjojMDA3ZWZmO2JveC1zaGFkb3c6aW5zZXQgMCAxcHggMXB4IHJnYmEoMCwwLDAsMC4wNzUpLDAgMCAwIDNweCByZ2JhKDAsMTI2LDI1NSwwLjEpfS5uZy1zZWxlY3Qubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0IC5uZy1oYXMtdmFsdWUgLm5nLXBsYWNlaG9sZGVye2Rpc3BsYXk6bm9uZX0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2ZmZjtib3JkZXItcmFkaXVzOjRweDtib3JkZXI6MXB4IHNvbGlkICNjY2M7bWluLWhlaWdodDozNnB4O2FsaWduLWl0ZW1zOmNlbnRlcn0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyOmhvdmVye2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lcnthbGlnbi1pdGVtczpjZW50ZXI7cGFkZGluZy1sZWZ0OjEwcHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy1yaWdodDoxMHB4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1zaW5nbGUgLm5nLXNlbGVjdC1jb250YWluZXJ7aGVpZ2h0OjM2cHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtc2luZ2xlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3RvcDo1cHg7bGVmdDowO3BhZGRpbmctbGVmdDoxMHB4O3BhZGRpbmctcmlnaHQ6NTBweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy1pbnB1dHtwYWRkaW5nLXJpZ2h0OjEwcHg7cGFkZGluZy1sZWZ0OjUwcHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOTtib3JkZXI6MXB4IHNvbGlkICNlNmU2ZTZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nOjAgNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy10b3A6NXB4O3BhZGRpbmctbGVmdDo3cHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVye3BhZGRpbmctcmlnaHQ6N3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2ZvbnQtc2l6ZTouOWVtO21hcmdpbi1ib3R0b206NXB4O2JhY2tncm91bmQtY29sb3I6I2ViZjVmZjtib3JkZXItcmFkaXVzOjJweDttYXJnaW4tcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWV7bWFyZ2luLXJpZ2h0OjA7bWFyZ2luLWxlZnQ6NXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVke2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZS5uZy12YWx1ZS1kaXNhYmxlZCAubmctdmFsdWUtbGFiZWx7cGFkZGluZy1sZWZ0OjVweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVkIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nLWxlZnQ6MDtwYWRkaW5nLXJpZ2h0OjVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtbGFiZWx7ZGlzcGxheTppbmxpbmUtYmxvY2s7cGFkZGluZzoxcHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29ue2Rpc3BsYXk6aW5saW5lLWJsb2NrO3BhZGRpbmc6MXB4IDVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbjpob3ZlcntiYWNrZ3JvdW5kLWNvbG9yOiNkMWU4ZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ubGVmdHtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbi5sZWZ0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmO2JvcmRlci1yaWdodDpub25lfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29uLnJpZ2h0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ucmlnaHR7Ym9yZGVyLWxlZnQ6MDtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXR7cGFkZGluZzowIDAgM3B4IDNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3BhZGRpbmc6MCAzcHggM3B4IDB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7dG9wOjVweDtwYWRkaW5nLWJvdHRvbTo1cHg7cGFkZGluZy1sZWZ0OjNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXBsYWNlaG9sZGVye3BhZGRpbmctcmlnaHQ6M3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLWNsZWFyLXdyYXBwZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0IC5uZy1jbGVhci13cmFwcGVyOmhvdmVyIC5uZy1jbGVhcntjb2xvcjojRDAwMjFCfS5uZy1zZWxlY3QgLm5nLXNwaW5uZXItem9uZXtwYWRkaW5nOjVweCA1cHggMCAwfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctc3Bpbm5lci16b25le3BhZGRpbmc6NXB4IDAgMCA1cHh9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcnt3aWR0aDoyNXB4O3BhZGRpbmctcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcntwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH0ubmctc2VsZWN0IC5uZy1hcnJvdy13cmFwcGVyOmhvdmVyIC5uZy1hcnJvd3tib3JkZXItdG9wLWNvbG9yOiM2NjZ9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlciAubmctYXJyb3d7Ym9yZGVyLWNvbG9yOiM5OTkgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDo1cHggNXB4IDIuNXB4fS5uZy1kcm9wZG93bi1wYW5lbHtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjY2NjO2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpO2xlZnQ6MH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbXt0b3A6MTAwJTtib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1jb2xvcjojZTZlNmU2O21hcmdpbi10b3A6LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbSAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpsYXN0LWNoaWxke2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjRweDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjRweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcHtib3R0b206MTAwJTtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1jb2xvcjojZTZlNmU2O21hcmdpbi1ib3R0b206LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpmaXJzdC1jaGlsZHtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1oZWFkZXJ7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1mb290ZXJ7Ym9yZGVyLXRvcDoxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXB7dXNlci1zZWxlY3Q6bm9uZTtwYWRkaW5nOjhweCAxMHB4O2ZvbnQtd2VpZ2h0OjUwMDtjb2xvcjpyZ2JhKDAsMCwwLDAuNTQpO2N1cnNvcjpwb2ludGVyfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGdyb3VwLm5nLW9wdGlvbi1kaXNhYmxlZHtjdXJzb3I6ZGVmYXVsdH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tc2VsZWN0ZWQsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXAubmctb3B0aW9uLXNlbGVjdGVkLm5nLW9wdGlvbi1tYXJrZWR7YmFja2dyb3VuZC1jb2xvcjojZWJmNWZmO2ZvbnQtd2VpZ2h0OjYwMH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb257YmFja2dyb3VuZC1jb2xvcjojZmZmO2NvbG9yOnJnYmEoMCwwLDAsMC44Nyk7cGFkZGluZzo4cHggMTBweH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkLC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQubmctb3B0aW9uLW1hcmtlZHtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6I2ViZjVmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIC5uZy1vcHRpb24tbGFiZWwsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1zZWxlY3RlZC5uZy1vcHRpb24tbWFya2VkIC5uZy1vcHRpb24tbGFiZWx7Zm9udC13ZWlnaHQ6NjAwfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZjtjb2xvcjojMzMzfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tZGlzYWJsZWR7Y29sb3I6I2NjY30ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLWNoaWxke3BhZGRpbmctbGVmdDoyMnB4fVtkaXI9XCJydGxcIl0gLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1jaGlsZHtwYWRkaW5nLXJpZ2h0OjIycHg7cGFkZGluZy1sZWZ0OjB9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIC5uZy10YWctbGFiZWx7Zm9udC1zaXplOjgwJTtmb250LXdlaWdodDo0MDA7cGFkZGluZy1yaWdodDo1cHh9W2Rpcj1cInJ0bFwiXSAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24gLm5nLXRhZy1sYWJlbHtwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH1bZGlyPVwicnRsXCJdIC5uZy1kcm9wZG93bi1wYW5lbHtkaXJlY3Rpb246cnRsO3RleHQtYWxpZ246cmlnaHR9XG4iLCIvLyogKioqKioqKiByZXNldCAmIG5vcm1hbGl6ZSAqKioqKioqICAqLy9cclxuXHJcbi8vIGJveC1zaXppbmcgdGhlIHNhbWUgZm9yIGFsbCBlbGVtZW50c1xyXG5odG1sIHtcclxuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7XHJcbn1cclxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xyXG4gIGJveC1zaXppbmc6IGluaGVyaXQ7XHJcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBpbmhlcml0O1xyXG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcclxuICBtYXJnaW46IDA7XHJcbiAgcGFkZGluZzogMDtcclxuICBAaW5jbHVkZSB1blNlbGVjdDtcclxufVxyXG5cclxuaHRtbCwgYm9keSwgZGl2LCBzcGFuLCBhcHBsZXQsIG9iamVjdCwgaWZyYW1lLFxyXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXHJcbmEsIGFiYnIsIGFjcm9ueW0sIGFkZHJlc3MsIGJpZywgY2l0ZSwgY29kZSxcclxuZGVsLCBkZm4sIGVtLCBpbWcsIGlucywga2JkLCBxLCBzLCBzYW1wLFxyXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxyXG5iLCB1LCBpLCBjZW50ZXIsXHJcbmRsLCBkdCwgZGQsIG9sLCB1bCwgbGksXHJcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxyXG50YWJsZSwgY2FwdGlvbiwgdGJvZHksIHRmb290LCB0aGVhZCwgdHIsIHRoLCB0ZCxcclxuYXJ0aWNsZSwgYXNpZGUsIGNhbnZhcywgZGV0YWlscywgZW1iZWQsXHJcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcclxubWVudSwgbmF2LCBvdXRwdXQsIHJ1YnksIHNlY3Rpb24sIHN1bW1hcnksXHJcbnRpbWUsIG1hcmssIGF1ZGlvLCB2aWRlbyB7XHJcbiAgICBib3JkZXI6IDA7XHJcbiAgICBmb250LXNpemU6IDEwMCU7XHJcbiAgICBmb250OiBpbmhlcml0O1xyXG4gICAgdmVydGljYWwtYWxpZ246IGJhc2VsaW5lO1xyXG59XHJcbmFydGljbGUsIGFzaWRlLCBkZXRhaWxzLCBmaWdjYXB0aW9uLCBmaWd1cmUsXHJcbmZvb3RlciwgaGVhZGVyLCBoZ3JvdXAsIG1lbnUsIG5hdiwgc2VjdGlvbiB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxufVxyXG5cclxuYm9keSB7XHJcbiAgIGxpbmUtaGVpZ2h0OiAxO1xyXG4gICBmb250LXN0eWxlOiBub3JtYWw7XHJcbn1cclxub2wsIHVsIHtcclxuICAgIGxpc3Qtc3R5bGU6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZSwgcSB7XHJcbiAgICBxdW90ZXM6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZTpiZWZvcmUsIGJsb2NrcXVvdGU6YWZ0ZXIsXHJcbnE6YmVmb3JlLCBxOmFmdGVyIHtcclxuICAgIGNvbnRlbnQ6IG5vbmU7XHJcbn1cclxuXHJcbi8vdGFibGVcclxudGFibGUge1xyXG4gICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcclxuICAgIGJvcmRlci1zcGFjaW5nOiAwO1xyXG59XHJcbnRkLFxyXG50aCB7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5cclxuLy9mb3JtcyBlbGVtZW50XHJcbmlucHV0IHtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAmOi13ZWJraXQtYXV0b2ZpbGwge1xyXG4gICAgICAtd2Via2l0LWJveC1zaGFkb3c6IDAgMCAwIDEwMDBweCB3aGl0ZSBpbnNldDtcclxuICAgIH1cclxufVxyXG5cclxuYnV0dG9uLFxyXG5odG1sIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXHJcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcclxuaW5wdXRbdHlwZT1cInN1Ym1pdFwiXSB7XHJcbiAgLXdlYmtpdC1hcHBlYXJhbmNlOiBidXR0b247XHJcbiAgY3Vyc29yOiBwb2ludGVyO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbn1cclxuYnV0dG9uW2Rpc2FibGVkXSxcclxuaHRtbCBpbnB1dFtkaXNhYmxlZF0ge1xyXG4gIGN1cnNvcjogZGVmYXVsdDtcclxufVxyXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXHJcbmlucHV0OjotbW96LWZvY3VzLWlubmVyIHtcclxuICBib3JkZXI6IDA7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5pbnB1dCB7XHJcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IHRleHRmaWVsZDtcclxuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1kZWNvcmF0aW9uIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XHJcbn1cclxuXHJcblxyXG4vL2xpbmtcclxuYSB7XHJcblx0dGV4dC1kZWNvcmF0aW9uOiBub25lO1xyXG5cdCY6YWN0aXZlLFxyXG5cdCY6aG92ZXIsXHJcblx0Jjpmb2N1cyB7XHJcblx0XHRvdXRsaW5lOiAwO1xyXG5cdH1cclxufVxyXG5cclxuaSB7IGZvbnQtc3R5bGU6IGl0YWxpYzsgfVxyXG5iLCBzdHJvbmcgeyBmb250LXdlaWdodDogNzAwOyAgIH1cclxuXHJcbi8vIGltYWdlc1xyXG5pbWcge1xyXG5cdHdpZHRoOiBhdXRvO1xyXG5cdG1heC13aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IGF1dG87XHJcbiAgdmVydGljYWwtYWxpZ246IHRvcDtcclxuXHRib3JkZXI6IDA7XHJcbn1cclxuXHJcbi5oaWRkZW4ge1xyXG4gIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDtcclxufVxyXG4iLCIuYXBwLWNvbnRlbnQge1xyXG5cclxuICAucHJlbG9hZGVyIHtcclxuXHJcbiAgICAubG9hZGluZy1iYXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmJ1dHRvbiB7XHJcbiAgYm9yZGVyOiBub25lO1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNXJlbTtcclxuICBmb250LXdlaWdodDogNjAwO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbiAgcGFkZGluZzogMCAxcmVtO1xyXG4gIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAmOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgXHJcbiAgJi5ibHVlLWJ1dHRvbl9yZXNldHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhbHRlcm5hdGl2ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJjpob3ZlciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYuYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlbkJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYudHJhbnNwYXJlbnQtYnV0dG9uIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDFyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDEuN3JlbTtcclxuICAgICAgaGVpZ2h0OiAxLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuLmlucHV0LWJsb2NrIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtO1xyXG5cclxuICAud3JhcC1sYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICAgIG1pbi1oZWlnaHQ6IDIuNHJlbTtcclxuICB9XHJcblxyXG4gIGxhYmVsIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbnB1dFt0eXBlPSd0ZXh0J10sIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIHNlbGVjdCB7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICBwYWRkaW5nOiAwIDFyZW07XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50ZXh0YXJlYSB7XHJcbiAgICBoZWlnaHQ6IGF1dG87XHJcblxyXG4gICAgdGV4dGFyZWEge1xyXG4gICAgICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XHJcbiAgICAgIGJvcmRlcjogbm9uZTtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtaW4td2lkdGg6IDEwMCU7XHJcbiAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgbWluLWhlaWdodDogNy41cmVtO1xyXG4gICAgICBtYXgtaGVpZ2h0OiA3LjVyZW07XHJcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgICByZXNpemU6IG5vbmU7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5lcnJvci1ibG9jayB7XHJcbiAgICBmb250LXNpemU6IDFyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS40cmVtO1xyXG4gICAgYWxpZ24tc2VsZjogZmxleC1lbmQ7XHJcbiAgICB0ZXh0LWFsaWduOiByaWdodDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmVycm9yLXRleHQge1xyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gIH1cclxufVxyXG5cclxuaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyB7XHJcblxyXG4gICYgKyBsYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICBwYWRkaW5nLWxlZnQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgQGluY2x1ZGUgdW5TZWxlY3Q7XHJcbiAgfVxyXG5cclxuICAmOm5vdChjaGVja2VkKSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICBvcGFjaXR5OiAwO1xyXG5cclxuICAgICYgKyBsYWJlbCB7XHJcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIH1cclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAwLjdyZW07XHJcbiAgICAgIGxlZnQ6IDA7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXItcmFkaXVzOiA1MCU7XHJcbiAgICAgIHdpZHRoOiAxLjRyZW07XHJcbiAgICAgIGhlaWdodDogMS40cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAxcmVtO1xyXG4gICAgICBsZWZ0OiAwLjNyZW07XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcclxuICAgICAgb3BhY2l0eTogMDtcclxuICAgICAgd2lkdGg6IDAuOHJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjhyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICY6Y2hlY2tlZCB7XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgb3BhY2l0eTogMTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3gge1xyXG5cclxuICAmICsgbGFiZWwge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgcGFkZGluZy1sZWZ0OiAzLjZyZW07XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIEBpbmNsdWRlIHVuU2VsZWN0O1xyXG4gIH1cclxuXHJcbiAgJjpub3QoY2hlY2tlZCkge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiA1MCU7XHJcbiAgICBsZWZ0OiAxLjZyZW07XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICB2aXNpYmlsaXR5OiBoaWRkZW47XHJcblxyXG4gICAgJiArIGxhYmVsIHtcclxuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgICYgKyBsYWJlbDpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiAnJztcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IDUwJTtcclxuICAgICAgbGVmdDogMS42cmVtO1xyXG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICB3aWR0aDogMS40cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuNHJlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkIHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJjpjaGVja2VkIHtcclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLnN3aXRjaCB7XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAuY2lyY2xlIHtcclxuXHJcbiAgICAmLm9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICYub2ZmIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwIHtcclxuICBwYWRkaW5nOiAxcmVtIDJyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgYm94LXNoYWRvdzogdGhlbWVkKHRvb2x0aXBTaGFkb3cpO1xyXG4gICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcclxuICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC10b3Age1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogY2FsYyg1MCUgLSAwLjVyZW0pO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXRvcC1yaWdodCB7XHJcbiAgICBtYXJnaW4tdG9wOiAtMXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IC0xcmVtO1xyXG4gICAgICByaWdodDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKSB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0IHtcclxuICAgIG1hcmdpbi10b3A6IDFyZW07XHJcblxyXG4gICAgJjpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiBcIlwiO1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogLTFyZW07XHJcbiAgICAgIHJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtbGVmdCB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIHJpZ2h0OiAtMXJlbTtcclxuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XHJcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwLWRpbWVuc2lvbnMge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcbiAgICBvdmVyZmxvdzogYXV0bztcclxuICAgIG1heC13aWR0aDogMjByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5iYWxhbmNlLXRvb2x0aXAge1xyXG4gIHBhZGRpbmc6IDEuM3JlbTtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBiYWNrZ3JvdW5kOiB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcik7XHJcbiAgICBib3gtc2hhZG93OiB0aGVtZWQodG9vbHRpcFNoYWRvdyk7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuXHJcbiAgICAuYXZhaWxhYmxlIHtcclxuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtO1xyXG5cclxuICAgICAgYiB7XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5sb2NrZWQge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAwLjdyZW07XHJcblxyXG4gICAgICBiIHtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmxpbmsge1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wIHtcclxuICAgIG1hcmdpbi10b3A6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWxlZnQge1xyXG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmFjY291bnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XHJcbiAgICBtYXgtd2lkdGg6IDE4cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmNvbW1lbnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgd29yZC1icmVhazogYnJlYWstd29yZDtcclxuICAgIG1heC13aWR0aDogNTByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAyNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi51cGRhdGUtdG9vbHRpcCB7XHJcbiAgcGFkZGluZzogMS41cmVtO1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAmLmltcG9ydGFudCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJi5uZy10b29sdGlwLWxlZnQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YWZ0ZXIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcEltcG9ydGFudEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLmNyaXRpY2FsIHtcclxuICAgIHBhZGRpbmc6IDIuNXJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBDcml0aWNhbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC50b29sdGlwLWlubmVyIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtbGVmdC1ib3R0b20ge1xyXG5cclxuICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xyXG5cclxuICAgIC5zdGFuZGFyZC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuaW1wb3J0YW50LXVwZGF0ZSB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50VGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5jcml0aWNhbC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgfVxyXG5cclxuICAgIC53cm9uZy10aW1lIHtcclxuICAgICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXJnaW46IDEuNXJlbSAwO1xyXG4gICAgICB3aWR0aDogNXJlbTtcclxuICAgICAgaGVpZ2h0OiA1cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRvb2x0aXBDcml0aWNhbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTEuNXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgcmlnaHQ6IC0xcmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogMS41cmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmd4LWNvbnRleHRtZW51IHtcclxuXHJcbiAgLmRyb3Bkb3duLW1lbnUge1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgcGFkZGluZzogMDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxpIHtcclxuICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gIH1cclxuXHJcbiAgYSB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxuICAgIHBhZGRpbmc6IDAuNWVtIDFlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjaGFydE9wdGlvbnNIb3ZlckNvbG9yKTtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmctc2VsZWN0IHtcclxuXHJcbiAgJi5jdXN0b20tc2VsZWN0IHtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICYubmctc2VsZWN0LXNpbmdsZSB7XHJcbiAgICAgIC5uZy1zZWxlY3QtY29udGFpbmVyIHtcclxuICAgICAgICAubmctdmFsdWUtY29udGFpbmVyIHtcclxuICAgICAgICAgIC5uZy12YWx1ZSB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLXNlbGVjdC1jb250YWluZXIge1xyXG4gICAgICBib3JkZXI6IG5vbmU7XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDA7XHJcbiAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgaGVpZ2h0OiA0LjJyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5uZy12YWx1ZS1jb250YWluZXIge1xyXG4gICAgICAgIHBhZGRpbmc6IDA7XHJcblxyXG4gICAgICAgIC5uZy1pbnB1dCB7XHJcbiAgICAgICAgICB0b3A6IGF1dG87XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLWRyb3Bkb3duLXBhbmVsIHtcclxuICAgICAgYm9yZGVyOiBub25lO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIHtcclxuXHJcbiAgICAgICAgLm5nLW9wdGlvbiB7XHJcbiAgICAgICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgICAgIHBhZGRpbmc6IDFyZW07XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChpbnB1dEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tbWFya2VkIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzZWxlY3RIb3ZlckNvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tc2VsZWN0ZWQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdFNlbGVjdGVkQ29sb3IpO1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgY3Vyc29yOiBkZWZhdWx0O1xyXG4gICAgICAgICAgd2lkdGg6IDFyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDFyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOjotd2Via2l0LXNjcm9sbGJhci10cmFjayB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNsaXA6IHBhZGRpbmctYm94O1xyXG4gICAgICAgICAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tb2RhbC1jb250YWluZXIsIGFwcC1jb25maXJtLW1vZGFsICB7XHJcblxyXG4gIC5tb2RhbCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZChtb2RhbEJhY2tncm91bmQpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5jb250ZW50IHtcclxuXHJcbiAgICAgIC5pY29uLmVycm9yIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uLnN1Y2Nlc3Mge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbi5pbmZvIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmNsb3NlLWJ1dHRvbiB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNsb3NlQnV0dG9uQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMge1xyXG5cclxuICAudGFibGUge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBib3JkZXItdG9wOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5yb3cge1xyXG5cclxuICAgICAgLmNlbGwge1xyXG5cclxuICAgICAgICAmLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYua2V5LXZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1wcm9ncmVzcy1jb250YWluZXIge1xyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW9wZW4td2FsbGV0LW1vZGFsIHtcclxuXHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtc2VuZC1tb2RhbCB7XHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnRpdGxlIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59IiwiJHRoZW1lczogKFxyXG4gIGRhcms6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICMxMzE5MjEsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjMWYyODMzLFxyXG4gICAgb25saW5lQ29sb3I6ICM1Y2RhOWQsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICM0ZGIxZmYsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzVjZGE5ZCxcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0ZGIxZmYsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzgyZDdmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjNTliNWZkLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5Y2FkYjcsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNiN2QxZTAsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzhkZmNjNixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzYyZTBiMixcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzRkZDBlMSxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM4N2Y0ZjUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjNDJkNWU4LFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogIzJiMzY0NCxcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjMTcxZTI3LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogIzRkYjFmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgdGFibGVCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBtZXNzYWdlTXlCYWNrZ3JvdW5kQ29sb3I6ICMyYTM1NDQsXHJcbiAgICBtZXNzYWdlQnVkZHlCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcjogIzM0M2Y0YSxcclxuICAgIHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcjogIzJiMzY0NCxcclxuICAgIGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3I6ICM1NTY1NzYsXHJcbiAgICB0b29sdGlwQmFja2dyb3VuZENvbG9yOiAjNDI1MDVmLFxyXG4gICAgdG9vbHRpcEltcG9ydGFudFRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3I6ICM1ZjJiMTEsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3I6ICM1ZjFkMWQsXHJcbiAgICB0b29sdGlwU2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSksXHJcbiAgICBtb2RhbEJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZyksXHJcbiAgICBjbG9zZUJ1dHRvbkNvbG9yOiAjNTU2NTc2XHJcbiAgKSxcclxuICBncmF5OiAoXHJcbiAgICBib2R5QmFja2dyb3VuZENvbG9yOiAjMTAxNDE3LFxyXG4gICAgc2lkZWJhckJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAxKSxcclxuICAgIHNpZGViYXJCb3JkZXJDb2xvcjogIzJlMzMzNyxcclxuICAgIG9ubGluZUNvbG9yOiAjNDdjZjhkLFxyXG4gICAgb2ZmbGluZUNvbG9yOiAjZmY1MjUyLFxyXG4gICAgY29udGVudEJhY2tncm91bmRDb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpLFxyXG4gICAgbWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFsdGVybmF0aXZlVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgb3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBibHVlVGV4dENvbG9yOiAjNDJhNWY1LFxyXG4gICAgZ3JlZW5UZXh0Q29sb3I6ICM0N2NmOGQsXHJcbiAgICBvcmFuZ2VUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICByZWRUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICBibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNDJhNWY1LFxyXG4gICAgYmx1ZUJ1dHRvbkhvdmVyQ29sb3I6ICM4NmQ2ZmYsXHJcbiAgICBibHVlQnV0dG9uRm9jdXNDb2xvcjogIzVmYjZmYyxcclxuICAgIGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNzk4NDhmLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yOiAjYTFhZWJiLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Gb2N1c0NvbG9yOiAjOGE5NTlmLFxyXG4gICAgZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBncmVlbkJ1dHRvbkhvdmVyQ29sb3I6ICM3YmY2YzYsXHJcbiAgICBncmVlbkJ1dHRvbkZvY3VzQ29sb3I6ICM1Y2RjOWUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMzZWM1ZDcsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Ib3ZlckNvbG9yOiAjNzJlZGZlLFxyXG4gICAgdHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcjogIzUwZDBlMSxcclxuICAgIHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3I6ICMyZjM0MzgsXHJcbiAgICBpbnB1dEJhY2tncm91bmRDb2xvcjogIzI5MmQzMSxcclxuICAgIHNlbGVjdEhvdmVyQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHNlbGVjdFNlbGVjdGVkQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIHN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIGFjY291bnRIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpLFxyXG4gICAgYWNjb3VudE1haW5UZXh0Q29sb3I6ICNlMGUwZTAsXHJcbiAgICBhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBhY2NvdW50SW5kaWNhdG9yVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRJbmRpY2F0b3JCYWNrZ3JvdW5kQ29sb3I6ICM0MmE1ZjUsXHJcbiAgICB0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpLFxyXG4gICAgdGFiSG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjMzAzNjNjLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICMzNjNhM2UsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICMyOTJkMzEsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjNTE1OTYwLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogIzNlNDY0YyxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjNTUyNDBkLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmY1MjUyLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjNGMxOTE5LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZ3JheS5wbmcpLFxyXG4gICAgY2xvc2VCdXR0b25Db2xvcjogIzUxNTk2MFxyXG4gICksXHJcbiAgd2hpdGU6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICNlZWVlZWUsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjZWJlYmViLFxyXG4gICAgb25saW5lQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjNDM0NTRiLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICNmZWZlZmUsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogI2EwYTVhYixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICMyYzk1ZjEsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzQ2YzE3MixcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMyYzk1ZjEsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzVjYjNmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjMzc5ZmZhLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5MGE0YWUsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNhZWJlYzYsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzQ2YzE3MixcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzVhZDU4NixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzUzYzc3YyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzI2YjZjNyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM1MmNiZDksXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjMzFiZWNmLFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogI2ViZWJlYixcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjZTZlNmU2LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSgyMjQsIDIyNCwgMjI0LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSgzMCwgMTM2LCAyMjksIDEpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI0MCwgMjQwLCAyNDAsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2ZmZmZmZixcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzkxYmFmMSxcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICM0MzQ1NGIsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjZmZmLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjZWRlZGVkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICNkY2RjZGMsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICNlMGUwZTAsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZmZmZmYsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjZWY2YzAwLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjZTUzOTM1LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKSxcclxuICAgIGNsb3NlQnV0dG9uQ29sb3I6ICM0MzQ1NGJcclxuICApXHJcbik7XHJcblxyXG5cclxuXHJcblxyXG5cclxuIiwiYXBwLW1haW4sIGFwcC1jcmVhdGUtd2FsbGV0LCBhcHAtb3Blbi13YWxsZXQsIGFwcC1yZXN0b3JlLXdhbGxldCwgYXBwLXNlZWQtcGhyYXNlLCBhcHAtd2FsbGV0LWRldGFpbHMsIGFwcC1hc3NpZ24tYWxpYXMsIGFwcC1lZGl0LWFsaWFzLCBhcHAtdHJhbnNmZXItYWxpYXMsIGFwcC1zZXR0aW5ncywgYXBwLWxvZ2luIHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tYWluIHtcclxuXHJcbiAgLmNvbnRlbnQge1xyXG5cclxuICAgIC5hZGQtd2FsbGV0IHtcclxuXHJcbiAgICAgIC5hZGQtd2FsbGV0LWhlbHAge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZWVkLXBocmFzZSB7XHJcblxyXG4gIC5zZWVkLXBocmFzZS1jb250ZW50IHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXdhbGxldC1kZXRhaWxzIHtcclxuXHJcbiAgLnNlZWQtcGhyYXNlIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZXR0aW5ncyB7XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICAgIG92ZXJmbG93LXk6IGF1dG87XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuXHJcbiAgICAudGhlbWUtc2VsZWN0aW9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNjYWxlLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgICAuYnV0dG9uLWJsb2NrIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodGFiSW5hY3RpdmVCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLWxvZ2luIHtcclxuICBtaW4td2lkdGg6IGluaGVyaXQ7XHJcbn1cclxuIiwiYXBwLXNpZGViYXIge1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzaWRlYmFyQmFja2dyb3VuZENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLWFjY291bnRzIHtcclxuXHJcbiAgICAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIge1xyXG5cclxuICAgICAgaDMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNpZGViYXItYWNjb3VudHMtbGlzdCB7XHJcblxyXG4gICAgICAuc2lkZWJhci1hY2NvdW50IHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2lkZWJhci1hY2NvdW50LXJvdyB7XHJcblxyXG4gICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaW5kaWNhdG9yIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuXHJcbiAgICAgICAgICAgIC5wcm9ncmVzcy1iYXIge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmLmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnNpZGViYXItYWNjb3VudC1yb3cge1xyXG5cclxuICAgICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuc3dpdGNoIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpob3Zlcjpub3QoLmFjdGl2ZSkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCh0byBib3R0b20sIHRyYW5zcGFyZW50IDAlLCB0aGVtZWQoc2lkZWJhckJhY2tncm91bmRDb2xvcikgMTAwJSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXNldHRpbmdzIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkIHRoZW1lZChzaWRlYmFyQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC53cmFwLWJ1dHRvbiB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgYnV0dG9uIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGFjY291bnRCYWNrZ3JvdW5kQ29sb3IpIWltcG9ydGFudDtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcikhaW1wb3J0YW50O1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKSFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAuc3RhdHVzLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAub2ZmbGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvZmZsaW5lQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9ubGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvbmxpbmVDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAgIC5zeW5jaW5nIHtcclxuXHJcbiAgICAgICAgICAucHJvZ3Jlc3MtYmFyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5maWxsIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJGdWxsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sb2FkaW5nIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnVwZGF0ZS1jb250YWluZXIge1xyXG5cclxuICAgICAgLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmltcG9ydGFudCB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmNyaXRpY2FsIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAudGltZSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICAmLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5pbXBvcnRhbnQge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQob3JhbmdlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuY3JpdGljYWwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYudGltZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtd2FsbGV0IHtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLmhlYWRlciB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFsaWFzIHtcclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGFicyB7XHJcblxyXG4gICAgLnRhYnMtaGVhZGVyIHtcclxuXHJcbiAgICAgIC50YWIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZCh0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYkhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAudGFicy1jb250ZW50IHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXNlbmQge1xyXG5cclxuICAuZm9ybS1zZW5kIHtcclxuXHJcbiAgICAuc2VuZC1zZWxlY3Qge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuYWRkaXRpb25hbC1kZXRhaWxzIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkIHRoZW1lZCh0cmFuc3BhcmVudEJ1dHRvbkJvcmRlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXJlY2VpdmUge1xyXG5cclxuICAuYnRuLWNvcHktYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1oaXN0b3J5IHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgJi5sb2NrZWQtdHJhbnNhY3Rpb24ge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzEpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzIpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzMpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOm50aC1jaGlsZCg0bis0KSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cyB7XHJcblxyXG4gICAgICAgICAgLmNvbmZpcm1hdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnVubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zdGF0dXMuc2VuZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cy5yZWNlaXZlZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtY29udHJhY3RzIHtcclxuXHJcbiAgLndyYXAtdGFibGUge1xyXG5cclxuICAgIC5jb250cmFjdCB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICYubmV3LCAmLmFsZXJ0IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnB1cmNoYXNlLCAmLnNlbGwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtcHVyY2hhc2Uge1xyXG5cclxuICAuZm9ybS1wdXJjaGFzZSB7XHJcblxyXG4gICAgLnB1cmNoYXNlLXNlbGVjdCB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5wdXJjaGFzZS1zdGF0ZXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW1lc3NhZ2VzIHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgdGQ6Zmlyc3QtY2hpbGQge1xyXG5cclxuICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICBAaW5jbHVkZSB0ZXh0LXRydW5jYXRlO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtdHlwaW5nLW1lc3NhZ2Uge1xyXG5cclxuICAuaGVhZCB7XHJcblxyXG4gICAgLmludGVybG9jdXRvciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAubWVzc2FnZXMtY29udGVudCB7XHJcblxyXG4gICAgLm1lc3NhZ2VzLWxpc3Qge1xyXG5cclxuICAgICAgZGl2IHtcclxuXHJcbiAgICAgICAgJi5kYXRlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLm15IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJjpiZWZvcmUge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgICB0b3A6IDA7XHJcbiAgICAgICAgICAgIGxlZnQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIGJvcmRlcjogMS4ycmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYm9yZGVyLXRvcC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYnVkZHkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHBzZXVkbztcclxuICAgICAgICAgICAgcmlnaHQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgICAgYm9yZGVyOiAxLjJyZW0gc29saWQgdHJhbnNwYXJlbnQ7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBib3JkZXItdG9wLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXN0YWtpbmcge1xyXG5cclxuICAuY2hhcnQtaGVhZGVyIHtcclxuXHJcbiAgICAuZ2VuZXJhbCB7XHJcblxyXG4gICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9wdGlvbnMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNlbGVjdGVkIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxuICAgICAgZmxleC1ncm93OiAxO1xyXG4gICAgICBmb250LXNpemU6IDEuNnJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5jaGFydC1vcHRpb25zIHtcclxuXHJcbiAgICAudGl0bGUge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAub3B0aW9ucyB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY2hhcnRPcHRpb25zQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmlucHV0LWJsb2NrLWFsaWFzIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcblxyXG4gIC5hbGlhcy1kcm9wZG93biB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IDYuNXJlbTtcclxuICAgIG1heC1oZWlnaHQ6IDEwcmVtO1xyXG4gICAgb3ZlcmZsb3c6IGF1dG87XHJcbiAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICBkaXYge1xyXG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgcGFkZGluZzogMXJlbTtcclxuXHJcbiAgICAgICY6aG92ZXIge1xyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdEhvdmVyQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtY29udGFjdHMsIGFwcC1hZGQtY29udGFjdHMsXHJcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1jb250YWN0cyB7XHJcbiAgXHJcbiAgdGFibGUge1xyXG5cclxuICAgIC5hbGlhcyB7XHJcbiAgXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICBcclxuICAgICAgLmljb24ge1xyXG4gIFxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gIFxyXG4gICAgICBzcGFuIHtcclxuICAgICAgICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcilcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5mb290ZXIge1xyXG4gICAgXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICBcclxuICAgIC5pbXBvcnQtYnRuIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgXHJcbn1cclxuXHJcbmFwcC1jb250YWN0LXNlbmQge1xyXG4gIFxyXG4gIC53YWxsZXRzLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn0iLCIuaGVhZCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5icmVhZGNydW1icyB7XHJcblxyXG4gICAgPiBzcGFuLCBhIHtcclxuXHJcbiAgICAgICY6bm90KDpsYXN0LWNoaWxkKSB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDIwcHg7XHJcbiAgICAgICAgb3V0bGluZS1zdHlsZTogbm9uZTtcclxuXHJcbiAgICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgdG9wOiAwLjVyZW07XHJcbiAgICAgICAgICByaWdodDogLTEuNXJlbTtcclxuICAgICAgICAgIHdpZHRoOiAwLjlyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDAuOXJlbTtcclxuICAgICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy1yaWdodC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICBtYXNrLXNpemU6IGNvdmVyO1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYmFjay1idG4ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGNvbG9yOiAjNGRiMWZmO1xyXG4gICAgZm9udC1zaXplOiBpbmhlcml0O1xyXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgaGVpZ2h0OiBhdXRvO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9iYWNrLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDAuOXJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjlyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLnNjcm9sbGVkLWNvbnRlbnQge1xyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhciB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgIHdpZHRoOiAxcmVtO1xyXG4gICAgaGVpZ2h0OiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgfVxyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhci10aHVtYiB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNTU2NTc2O1xyXG4gICAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcclxuICAgIGJvcmRlcjogMC4yNXJlbSBzb2xpZCB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlci1yYWRpdXM6IDAuNXJlbTtcclxuICB9XHJcblxyXG4gICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgfVxyXG59XHJcbiIsInRhYmxlIHtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgdGhlYWQge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgdHIge1xyXG4gICAgICBoZWlnaHQ6IDRyZW07XHJcblxyXG4gICAgICB0aCB7XHJcbiAgICAgICAgcGFkZGluZzogMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogYm90dG9tO1xyXG5cclxuICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICAgIHBhZGRpbmctbGVmdDogM3JlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAzcmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGJvZHkge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICB0ciB7XHJcbiAgICAgIGhlaWdodDogMy41cmVtO1xyXG5cclxuICAgICAgJjpudGgtY2hpbGQob2RkKSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRkIHtcclxuICAgICAgICBsaW5lLWhlaWdodDogMS43cmVtO1xyXG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTtcclxuXHJcbiAgICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLWxlZnQ6IDNyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgICAgcGFkZGluZy1yaWdodDogM3JlbTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLy8gQkFTRVxyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL21peGlucyc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvbnVsbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvdGhlbWUnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL2Jhc2UnO1xyXG5cclxuLy8gTEFZT1VUXHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2xheW91dC9tYWluJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NldHRpbmdzJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NpZGViYXInO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9sYXlvdXQvd2FsbGV0JztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L2NvbnRhY3QnO1xyXG5cclxuLy8gTU9EVUxFU1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL2hlYWQnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL3Njcm9sbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL21vZHVsZXMvdGFibGUnO1xyXG5cclxuQGltcG9ydCBcIn5Abmctc2VsZWN0L25nLXNlbGVjdC90aGVtZXMvZGVmYXVsdC50aGVtZS5jc3NcIjtcclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1MaWdodC50dGYpO1xyXG4gIGZvbnQtd2VpZ2h0OiAzMDA7XHJcbn1cclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDQwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLVNlbWlCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDYwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLUJvbGQudHRmKTtcclxuICBmb250LXdlaWdodDogNzAwO1xyXG59XHJcblxyXG5AZm9udC1mYWNlIHtcclxuICBmb250LWZhbWlseTogT3BlblNhbnM7XHJcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDgwMDtcclxufVxyXG5cclxuXHJcbmh0bWwge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEwcHg7XHJcbn1cclxuXHJcbmJvZHkge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNnJlbTtcclxuICB3aWR0aDogMTAwdnc7XHJcbiAgaGVpZ2h0OiAxMDB2aDtcclxuXHJcbiAgJi50aGVtZS1kYXJrIHtcclxuICAgIGJhY2tncm91bmQ6ICMxMzE5MjEgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS1ncmF5IHtcclxuICAgIGJhY2tncm91bmQ6ICMxMDE0MTcgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS13aGl0ZSB7XHJcbiAgICBiYWNrZ3JvdW5kOiAjZWVlZWVlIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmdcIikgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcbiAgfVxyXG5cclxuICBhcHAtcm9vdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgfVxyXG59XHJcblxyXG4udXBkYXRlLXRvb2x0aXAge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */", '', '']] /***/ }), @@ -557,7 +557,7 @@ if(false) {} /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -module.exports = __webpack_require__(/*! D:\Projects\zano\src\gui\qt-daemon\html_source\src\styles.scss */"./src/styles.scss"); +module.exports = __webpack_require__(/*! C:\Users\Admin\Desktop\zano\src\gui\qt-daemon\html_source\src\styles.scss */"./src/styles.scss"); /***/ }) diff --git a/src/gui/qt-daemon/html/styles.js.map b/src/gui/qt-daemon/html/styles.js.map index d485a8cf..c7719e9a 100644 --- a/src/gui/qt-daemon/html/styles.js.map +++ b/src/gui/qt-daemon/html/styles.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///./src/styles.scss","webpack:///./node_modules/style-loader/lib/addStyles.js","webpack:///./node_modules/style-loader/lib/urls.js","webpack:///./src/styles.scss?4266"],"names":[],"mappings":"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CA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;;AAEA,cAAc,mBAAO,CAAC,uDAAQ;;AAE9B;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA,iBAAiB,mBAAmB;AACpC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,iBAAiB,sBAAsB;AACvC;;AAEA;AACA,mBAAmB,2BAA2B;;AAE9C;AACA;AACA;AACA;AACA;;AAEA;AACA,gBAAgB,mBAAmB;AACnC;AACA;;AAEA;AACA;;AAEA,iBAAiB,2BAA2B;AAC5C;AACA;;AAEA,QAAQ,uBAAuB;AAC/B;AACA;AACA,GAAG;AACH;;AAEA,iBAAiB,uBAAuB;AACxC;AACA;;AAEA,2BAA2B;AAC3B;AACA;AACA;;AAEA;AACA;AACA;;AAEA,gBAAgB,iBAAiB;AACjC;AACA;AACA;AACA;AACA;AACA,cAAc;;AAEd,kDAAkD,sBAAsB;AACxE;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA;AACA,EAAE;AACF;AACA,EAAE;AACF;AACA;AACA,EAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,EAAE;AACF;;AAEA;AACA,KAAK,KAAwC,EAAE,EAE7C;;AAEF,QAAQ,sBAAiB;AACzB;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,CAAC;;AAED;AACA;;AAEA;AACA;AACA,EAAE;AACF;AACA;;AAEA;;AAEA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,EAAE;AACF;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uDAAuD;AACvD;;AAEA,6BAA6B,mBAAmB;;AAEhD;;AAEA;;AAEA;AACA;;;;;;;;;;;;;AC9YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,WAAW,EAAE;AACrD,wCAAwC,WAAW,EAAE;;AAErD;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA,sCAAsC;AACtC,GAAG;AACH;AACA,8DAA8D;AAC9D;;AAEA;AACA;AACA,EAAE;;AAEF;AACA;AACA;;;;;;;;;;;;;ACvFA,cAAc,mBAAO,CAAC,4ZAA0N;;AAEhP,4CAA4C,QAAS;;AAErD;AACA;;;;AAIA,eAAe;;AAEf;AACA;;AAEA,aAAa,mBAAO,CAAC,mGAAgD;;AAErE;;AAEA,GAAG,KAAU,EAAE,E","file":"styles.js","sourcesContent":["module.exports = [[module.id, \"/*\\r\\n* Implementation of themes\\r\\n*/\\n.ng-select.ng-select-opened>.ng-select-container{background:#fff;border-color:#b3b3b3 #ccc #d9d9d9}\\n.ng-select.ng-select-opened>.ng-select-container:hover{box-shadow:none}\\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}\\n.ng-select.ng-select-opened>.ng-select-container .ng-arrow:hover{border-color:transparent transparent #333}\\n.ng-select.ng-select-opened.ng-select-bottom>.ng-select-container{border-bottom-right-radius:0;border-bottom-left-radius:0}\\n.ng-select.ng-select-opened.ng-select-top>.ng-select-container{border-top-right-radius:0;border-top-left-radius:0}\\n.ng-select.ng-select-focused:not(.ng-select-opened)>.ng-select-container{border-color:#007eff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 0 3px rgba(0,126,255,0.1)}\\n.ng-select.ng-select-disabled>.ng-select-container{background-color:#f9f9f9}\\n.ng-select .ng-has-value .ng-placeholder{display:none}\\n.ng-select .ng-select-container{background-color:#fff;border-radius:4px;border:1px solid #ccc;min-height:36px;align-items:center}\\n.ng-select .ng-select-container:hover{box-shadow:0 1px 0 rgba(0,0,0,0.06)}\\n.ng-select .ng-select-container .ng-value-container{align-items:center;padding-left:10px}\\n[dir=\\\"rtl\\\"] .ng-select .ng-select-container .ng-value-container{padding-right:10px;padding-left:0}\\n.ng-select .ng-select-container .ng-value-container .ng-placeholder{color:#999}\\n.ng-select.ng-select-single .ng-select-container{height:36px}\\n.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{top:5px;left:0;padding-left:10px;padding-right:50px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{padding-right:10px;padding-left:50px}\\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value{background-color:#f9f9f9;border:1px solid #e6e6e6}\\n.ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-label{padding:0 5px}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-top:5px;padding-left:7px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-right:7px;padding-left:0}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{font-size:.9em;margin-bottom:5px;background-color:#ebf5ff;border-radius:2px;margin-right:5px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{margin-right:0;margin-left:5px}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled{background-color:#f9f9f9}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:5px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:0;padding-right:5px}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-label{display:inline-block;padding:1px 5px}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:inline-block;padding:1px 5px}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon:hover{background-color:#d1e8ff}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-right:1px solid #b8dbff}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-left:1px solid #b8dbff;border-right:none}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:1px solid #b8dbff}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:0;border-right:1px solid #b8dbff}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 0 3px 3px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding:0 3px 3px 0}\\n.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{top:5px;padding-bottom:5px;padding-left:3px}\\n[dir=\\\"rtl\\\"] .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-right:3px;padding-left:0}\\n.ng-select .ng-clear-wrapper{color:#999}\\n.ng-select .ng-clear-wrapper:hover .ng-clear{color:#D0021B}\\n.ng-select .ng-spinner-zone{padding:5px 5px 0 0}\\n[dir=\\\"rtl\\\"] .ng-select .ng-spinner-zone{padding:5px 0 0 5px}\\n.ng-select .ng-arrow-wrapper{width:25px;padding-right:5px}\\n[dir=\\\"rtl\\\"] .ng-select .ng-arrow-wrapper{padding-left:5px;padding-right:0}\\n.ng-select .ng-arrow-wrapper:hover .ng-arrow{border-top-color:#666}\\n.ng-select .ng-arrow-wrapper .ng-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px}\\n.ng-dropdown-panel{background-color:#fff;border:1px solid #ccc;box-shadow:0 1px 0 rgba(0,0,0,0.06);left:0}\\n.ng-dropdown-panel.ng-select-bottom{top:100%;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top-color:#e6e6e6;margin-top:-1px}\\n.ng-dropdown-panel.ng-select-bottom .ng-dropdown-panel-items .ng-option:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px}\\n.ng-dropdown-panel.ng-select-top{bottom:100%;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-color:#e6e6e6;margin-bottom:-1px}\\n.ng-dropdown-panel.ng-select-top .ng-dropdown-panel-items .ng-option:first-child{border-top-right-radius:4px;border-top-left-radius:4px}\\n.ng-dropdown-panel .ng-dropdown-header{border-bottom:1px solid #ccc;padding:5px 7px}\\n.ng-dropdown-panel .ng-dropdown-footer{border-top:1px solid #ccc;padding:5px 7px}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:8px 10px;font-weight:500;color:rgba(0,0,0,0.54);cursor:pointer}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-disabled{cursor:default}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-marked{background-color:#f5faff}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected.ng-option-marked{background-color:#ebf5ff;font-weight:600}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option{background-color:#fff;color:rgba(0,0,0,0.87);padding:8px 10px}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked{color:#333;background-color:#ebf5ff}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected .ng-option-label,.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected.ng-option-marked .ng-option-label{font-weight:600}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked{background-color:#f5faff;color:#333}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-disabled{color:#ccc}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-left:22px}\\n[dir=\\\"rtl\\\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-right:22px;padding-left:0}\\n.ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{font-size:80%;font-weight:400;padding-right:5px}\\n[dir=\\\"rtl\\\"] .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{padding-left:5px;padding-right:0}\\n[dir=\\\"rtl\\\"] .ng-dropdown-panel{direction:rtl;text-align:right}\\nhtml {\\n box-sizing: border-box;\\n -webkit-box-sizing: border-box;\\n -moz-box-sizing: border-box; }\\n*, *:before, *:after {\\n box-sizing: inherit;\\n -webkit-box-sizing: inherit;\\n -moz-box-sizing: inherit;\\n margin: 0;\\n padding: 0;\\n -webkit-touch-collout: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none; }\\nhtml, body, div, span, applet, object, iframe,\\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\\na, abbr, acronym, address, big, cite, code,\\ndel, dfn, em, img, ins, kbd, q, s, samp,\\nsmall, strike, strong, sub, sup, tt, var,\\nb, u, i, center,\\ndl, dt, dd, ol, ul, li,\\nfieldset, form, label, legend,\\ntable, caption, tbody, tfoot, thead, tr, th, td,\\narticle, aside, canvas, details, embed,\\nfigure, figcaption, footer, header, hgroup,\\nmenu, nav, output, ruby, section, summary,\\ntime, mark, audio, video {\\n border: 0;\\n font-size: 100%;\\n font: inherit;\\n vertical-align: baseline; }\\narticle, aside, details, figcaption, figure,\\nfooter, header, hgroup, menu, nav, section {\\n display: block; }\\nbody {\\n line-height: 1;\\n font-style: normal; }\\nol, ul {\\n list-style: none; }\\nblockquote, q {\\n quotes: none; }\\nblockquote:before, blockquote:after,\\nq:before, q:after {\\n content: none; }\\ntable {\\n border-collapse: collapse;\\n border-spacing: 0; }\\ntd,\\nth {\\n padding: 0; }\\ninput {\\n outline: none; }\\ninput:-webkit-autofill {\\n -webkit-box-shadow: 0 0 0 1000px white inset; }\\nbutton,\\nhtml input[type=\\\"button\\\"],\\ninput[type=\\\"reset\\\"],\\ninput[type=\\\"submit\\\"] {\\n -webkit-appearance: button;\\n cursor: pointer;\\n outline: none; }\\nbutton[disabled],\\nhtml input[disabled] {\\n cursor: default; }\\nbutton::-moz-focus-inner,\\ninput::-moz-focus-inner {\\n border: 0;\\n padding: 0; }\\ninput {\\n line-height: normal; }\\ninput[type=\\\"search\\\"] {\\n -webkit-appearance: textfield;\\n box-sizing: content-box; }\\ninput[type=\\\"search\\\"]::-webkit-search-cancel-button,\\ninput[type=\\\"search\\\"]::-webkit-search-decoration {\\n -webkit-appearance: none; }\\na {\\n text-decoration: none; }\\na:active, a:hover, a:focus {\\n outline: 0; }\\ni {\\n font-style: italic; }\\nb, strong {\\n font-weight: 700; }\\nimg {\\n width: auto;\\n max-width: 100%;\\n height: auto;\\n vertical-align: top;\\n border: 0; }\\n.hidden {\\n display: none !important; }\\n.theme-dark .app-content .preloader .loading-bar {\\n background-color: #5cda9d; }\\n.theme-gray .app-content .preloader .loading-bar {\\n background-color: #47cf8d; }\\n.theme-white .app-content .preloader .loading-bar {\\n background-color: #46c172; }\\nbutton {\\n border: none;\\n font-family: OpenSans, sans-serif;\\n font-size: 1.5rem;\\n font-weight: 600;\\n outline: none;\\n padding: 0 1rem;\\n height: 4.2rem; }\\n.theme-dark button:disabled:not(.transparent-button), .theme-dark button.blue-button_reset {\\n background-color: #9cadb7;\\n color: #111921; }\\n.theme-gray button:disabled:not(.transparent-button), .theme-gray button.blue-button_reset {\\n background-color: #79848f;\\n color: #1a1a1a; }\\n.theme-white button:disabled:not(.transparent-button), .theme-white button.blue-button_reset {\\n background-color: #90a4ae;\\n color: #fefefe; }\\n.theme-dark button:disabled:not(.transparent-button):hover, .theme-dark button.blue-button_reset:hover {\\n background-color: #b7d1e0; }\\n.theme-gray button:disabled:not(.transparent-button):hover, .theme-gray button.blue-button_reset:hover {\\n background-color: #a1aebb; }\\n.theme-white button:disabled:not(.transparent-button):hover, .theme-white button.blue-button_reset:hover {\\n background-color: #aebec6; }\\n.theme-dark button:disabled:not(.transparent-button):focus, .theme-dark button.blue-button_reset:focus {\\n background-color: #a7b9c2; }\\n.theme-gray button:disabled:not(.transparent-button):focus, .theme-gray button.blue-button_reset:focus {\\n background-color: #8a959f; }\\n.theme-white button:disabled:not(.transparent-button):focus, .theme-white button.blue-button_reset:focus {\\n background-color: #a7b9c2; }\\n.theme-dark button.blue-button:not(:disabled) {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray button.blue-button:not(:disabled) {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white button.blue-button:not(:disabled) {\\n background-color: #2c95f1;\\n color: #fefefe; }\\n.theme-dark button.blue-button:not(:disabled):hover {\\n background-color: #82d7ff; }\\n.theme-gray button.blue-button:not(:disabled):hover {\\n background-color: #86d6ff; }\\n.theme-white button.blue-button:not(:disabled):hover {\\n background-color: #5cb3ff; }\\n.theme-dark button.blue-button:not(:disabled):focus {\\n background-color: #59b5fd; }\\n.theme-gray button.blue-button:not(:disabled):focus {\\n background-color: #5fb6fc; }\\n.theme-white button.blue-button:not(:disabled):focus {\\n background-color: #379ffa; }\\n.theme-dark button.green-button:not(:disabled) {\\n background-color: #5cda9d;\\n color: #111921; }\\n.theme-gray button.green-button:not(:disabled) {\\n background-color: #47cf8d;\\n color: #1a1a1a; }\\n.theme-white button.green-button:not(:disabled) {\\n background-color: #46c172;\\n color: #fefefe; }\\n.theme-dark button.green-button:not(:disabled):hover {\\n background-color: #8dfcc6; }\\n.theme-gray button.green-button:not(:disabled):hover {\\n background-color: #7bf6c6; }\\n.theme-white button.green-button:not(:disabled):hover {\\n background-color: #5ad586; }\\n.theme-dark button.green-button:not(:disabled):focus {\\n background-color: #62e0b2; }\\n.theme-gray button.green-button:not(:disabled):focus {\\n background-color: #5cdc9e; }\\n.theme-white button.green-button:not(:disabled):focus {\\n background-color: #53c77c; }\\n.theme-dark button.turquoise-button:not(:disabled) {\\n background-color: #4dd0e1;\\n color: #111921; }\\n.theme-gray button.turquoise-button:not(:disabled) {\\n background-color: #3ec5d7;\\n color: #1a1a1a; }\\n.theme-white button.turquoise-button:not(:disabled) {\\n background-color: #26b6c7;\\n color: #fefefe; }\\n.theme-dark button.turquoise-button:not(:disabled):hover {\\n background-color: #87f4f5; }\\n.theme-gray button.turquoise-button:not(:disabled):hover {\\n background-color: #72edfe; }\\n.theme-white button.turquoise-button:not(:disabled):hover {\\n background-color: #52cbd9; }\\n.theme-dark button.turquoise-button:not(:disabled):focus {\\n background-color: #42d5e8; }\\n.theme-gray button.turquoise-button:not(:disabled):focus {\\n background-color: #50d0e1; }\\n.theme-white button.turquoise-button:not(:disabled):focus {\\n background-color: #31becf; }\\nbutton.transparent-button {\\n display: flex;\\n align-items: center;\\n justify-content: center; }\\n.theme-dark button.transparent-button {\\n background-color: transparent;\\n border: 0.2rem solid #2b3644;\\n color: #e0e0e0; }\\n.theme-gray button.transparent-button {\\n background-color: transparent;\\n border: 0.2rem solid #2f3438;\\n color: #e0e0e0; }\\n.theme-white button.transparent-button {\\n background-color: transparent;\\n border: 0.2rem solid #ebebeb;\\n color: #43454b; }\\nbutton.transparent-button .icon {\\n margin-right: 1rem;\\n -webkit-mask: url('complete-testwallet.svg') no-repeat center;\\n mask: url('complete-testwallet.svg') no-repeat center;\\n width: 1.7rem;\\n height: 1.7rem; }\\n.theme-dark button.transparent-button .icon {\\n background-color: #e0e0e0; }\\n.theme-gray button.transparent-button .icon {\\n background-color: #e0e0e0; }\\n.theme-white button.transparent-button .icon {\\n background-color: #43454b; }\\n.input-block {\\n display: flex;\\n flex-direction: column;\\n align-items: flex-start;\\n margin-bottom: 0.4rem; }\\n.input-block .wrap-label {\\n display: flex;\\n align-items: center;\\n justify-content: flex-start;\\n min-height: 2.4rem; }\\n.input-block label {\\n font-size: 1.3rem;\\n line-height: 2.4rem; }\\n.theme-dark .input-block label {\\n color: #556576; }\\n.theme-gray .input-block label {\\n color: #565c62; }\\n.theme-white .input-block label {\\n color: #a0a5ab; }\\n.input-block input[type='text'], .input-block input[type='password'], .input-block select {\\n border: none;\\n font-size: 1.4rem;\\n outline: none;\\n padding: 0 1rem;\\n width: 100%;\\n height: 4.2rem; }\\n.theme-dark .input-block input[type='text'], .theme-dark .input-block input[type='password'], .theme-dark .input-block select {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray .input-block input[type='text'], .theme-gray .input-block input[type='password'], .theme-gray .input-block select {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white .input-block input[type='text'], .theme-white .input-block input[type='password'], .theme-white .input-block select {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.input-block.textarea {\\n height: auto; }\\n.input-block.textarea textarea {\\n font-family: OpenSans, sans-serif;\\n border: none;\\n font-size: 1.4rem;\\n outline: none;\\n padding: 1rem;\\n width: 100%;\\n min-width: 100%;\\n height: 100%;\\n min-height: 7.5rem;\\n max-height: 7.5rem;\\n overflow: auto;\\n resize: none; }\\n.theme-dark .input-block.textarea textarea {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray .input-block.textarea textarea {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white .input-block.textarea textarea {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.input-block .error-block {\\n font-size: 1rem;\\n line-height: 1.4rem;\\n align-self: flex-end;\\n text-align: right; }\\n.theme-dark .input-block .error-block {\\n color: #ff5252; }\\n.theme-gray .input-block .error-block {\\n color: #ff5252; }\\n.theme-white .input-block .error-block {\\n color: #ff5252; }\\n.theme-dark .error-text {\\n color: #ff5252; }\\n.theme-gray .error-text {\\n color: #ff5252; }\\n.theme-white .error-text {\\n color: #ff5252; }\\ninput[type='radio'].style-radio + label {\\n display: flex;\\n align-items: center;\\n cursor: pointer;\\n font-weight: 400;\\n padding-left: 2.4rem;\\n -webkit-touch-collout: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none; }\\n.theme-dark input[type='radio'].style-radio + label {\\n color: #556576; }\\n.theme-gray input[type='radio'].style-radio + label {\\n color: #565c62; }\\n.theme-white input[type='radio'].style-radio + label {\\n color: #a0a5ab; }\\ninput[type='radio'].style-radio:not(checked) {\\n position: absolute;\\n opacity: 0; }\\ninput[type='radio'].style-radio:not(checked) + label {\\n position: relative; }\\ninput[type='radio'].style-radio:not(checked) + label:before {\\n content: '';\\n position: absolute;\\n top: 0.7rem;\\n left: 0;\\n background: transparent;\\n border-radius: 50%;\\n width: 1.4rem;\\n height: 1.4rem; }\\n.theme-dark input[type='radio'].style-radio:not(checked) + label:before {\\n border: 0.1rem solid #4db1ff; }\\n.theme-gray input[type='radio'].style-radio:not(checked) + label:before {\\n border: 0.1rem solid #42a5f5; }\\n.theme-white input[type='radio'].style-radio:not(checked) + label:before {\\n border: 0.1rem solid #2c95f1; }\\ninput[type='radio'].style-radio:not(checked) + label:after {\\n content: '';\\n position: absolute;\\n top: 1rem;\\n left: 0.3rem;\\n border-radius: 50%;\\n opacity: 0;\\n width: 0.8rem;\\n height: 0.8rem; }\\n.theme-dark input[type='radio'].style-radio:not(checked) + label:after {\\n background-color: #4db1ff; }\\n.theme-gray input[type='radio'].style-radio:not(checked) + label:after {\\n background-color: #42a5f5; }\\n.theme-white input[type='radio'].style-radio:not(checked) + label:after {\\n background-color: #2c95f1; }\\ninput[type='radio'].style-radio:checked + label:after {\\n opacity: 1; }\\ninput[type='checkbox'].style-checkbox + label {\\n display: flex;\\n align-items: center;\\n cursor: pointer;\\n font-weight: 400;\\n padding-left: 3.6rem;\\n -webkit-touch-collout: none;\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n -ms-user-select: none;\\n user-select: none; }\\n.theme-dark input[type='checkbox'].style-checkbox + label {\\n color: #556576; }\\n.theme-gray input[type='checkbox'].style-checkbox + label {\\n color: #565c62; }\\n.theme-white input[type='checkbox'].style-checkbox + label {\\n color: #a0a5ab; }\\ninput[type='checkbox'].style-checkbox:not(checked) {\\n position: absolute;\\n top: 50%;\\n left: 1.6rem;\\n transform: translateY(-50%);\\n visibility: hidden; }\\ninput[type='checkbox'].style-checkbox:not(checked) + label {\\n position: relative; }\\ninput[type='checkbox'].style-checkbox:not(checked) + label:before {\\n content: '';\\n position: absolute;\\n top: 50%;\\n left: 1.6rem;\\n transform: translateY(-50%);\\n background: transparent;\\n width: 1.4rem;\\n height: 1.4rem; }\\n.theme-dark input[type='checkbox'].style-checkbox:not(checked) + label:before {\\n border: 0.1rem solid #4db1ff; }\\n.theme-gray input[type='checkbox'].style-checkbox:not(checked) + label:before {\\n border: 0.1rem solid #42a5f5; }\\n.theme-white input[type='checkbox'].style-checkbox:not(checked) + label:before {\\n border: 0.1rem solid #2c95f1; }\\ninput[type='checkbox'].style-checkbox:checked + label:before {\\n background: url('complete-testwallet.svg'); }\\n.theme-dark input[type='checkbox'].style-checkbox:checked + label:before {\\n background-color: #4db1ff; }\\n.theme-gray input[type='checkbox'].style-checkbox:checked + label:before {\\n background-color: #42a5f5; }\\n.theme-white input[type='checkbox'].style-checkbox:checked + label:before {\\n background-color: #2c95f1; }\\n.theme-dark .switch {\\n background-color: #000000; }\\n.theme-gray .switch {\\n background-color: #000000; }\\n.theme-white .switch {\\n background-color: #e0e0e0; }\\n.theme-dark .switch .circle.on {\\n background-color: #4db1ff; }\\n.theme-gray .switch .circle.on {\\n background-color: #42a5f5; }\\n.theme-white .switch .circle.on {\\n background-color: #2c95f1; }\\n.theme-dark .switch .circle.off {\\n background-color: #556576; }\\n.theme-gray .switch .circle.off {\\n background-color: #565c62; }\\n.theme-white .switch .circle.off {\\n background-color: #a0a5ab; }\\n.table-tooltip {\\n padding: 1rem 2rem; }\\n.theme-dark .table-tooltip {\\n background: #42505f;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-gray .table-tooltip {\\n background: #3e464c;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-white .table-tooltip {\\n background: #ffffff;\\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\\n color: #43454b; }\\n.table-tooltip .tooltip-inner {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n white-space: pre-wrap; }\\n.table-tooltip.ng-tooltip-top {\\n margin-top: -1rem; }\\n.table-tooltip.ng-tooltip-top:after {\\n content: \\\"\\\";\\n position: absolute;\\n bottom: -1rem;\\n left: calc(50% - 0.5rem);\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-top:after {\\n border-color: #42505f transparent transparent transparent; }\\n.theme-gray .table-tooltip.ng-tooltip-top:after {\\n border-color: #3e464c transparent transparent transparent; }\\n.theme-white .table-tooltip.ng-tooltip-top:after {\\n border-color: #ffffff transparent transparent transparent; }\\n.table-tooltip.ng-tooltip-top-left {\\n margin-top: -1rem; }\\n.table-tooltip.ng-tooltip-top-left:after {\\n content: \\\"\\\";\\n position: absolute;\\n bottom: -1rem;\\n left: 0.7rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-top-left:after {\\n border-color: #42505f transparent transparent #42505f; }\\n.theme-gray .table-tooltip.ng-tooltip-top-left:after {\\n border-color: #3e464c transparent transparent #3e464c; }\\n.theme-white .table-tooltip.ng-tooltip-top-left:after {\\n border-color: #ffffff transparent transparent #ffffff; }\\n.table-tooltip.ng-tooltip-top-right {\\n margin-top: -1rem; }\\n.table-tooltip.ng-tooltip-top-right:after {\\n content: \\\"\\\";\\n position: absolute;\\n bottom: -1rem;\\n right: 0.7rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-top-right:after {\\n border-color: #42505f #42505f transparent transparent; }\\n.theme-gray .table-tooltip.ng-tooltip-top-right:after {\\n border-color: #3e464c #3e464c transparent transparent; }\\n.theme-white .table-tooltip.ng-tooltip-top-right:after {\\n border-color: #ffffff #ffffff transparent transparent; }\\n.table-tooltip.ng-tooltip-bottom {\\n margin-top: 1rem; }\\n.table-tooltip.ng-tooltip-bottom:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: -1rem;\\n left: calc(50% - 0.5rem);\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-bottom:before {\\n border-color: transparent transparent #42505f transparent; }\\n.theme-gray .table-tooltip.ng-tooltip-bottom:before {\\n border-color: transparent transparent #3e464c transparent; }\\n.theme-white .table-tooltip.ng-tooltip-bottom:before {\\n border-color: transparent transparent #ffffff transparent; }\\n.table-tooltip.ng-tooltip-bottom-left {\\n margin-top: 1rem; }\\n.table-tooltip.ng-tooltip-bottom-left:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: -1rem;\\n left: 0.7rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-bottom-left:before {\\n border-color: transparent transparent #42505f #42505f; }\\n.theme-gray .table-tooltip.ng-tooltip-bottom-left:before {\\n border-color: transparent transparent #3e464c #3e464c; }\\n.theme-white .table-tooltip.ng-tooltip-bottom-left:before {\\n border-color: transparent transparent #ffffff #ffffff; }\\n.table-tooltip.ng-tooltip-bottom-right {\\n margin-top: 1rem; }\\n.table-tooltip.ng-tooltip-bottom-right:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: -1rem;\\n right: 0.7rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-bottom-right:before {\\n border-color: transparent #42505f #42505f transparent; }\\n.theme-gray .table-tooltip.ng-tooltip-bottom-right:before {\\n border-color: transparent #3e464c #3e464c transparent; }\\n.theme-white .table-tooltip.ng-tooltip-bottom-right:before {\\n border-color: transparent #ffffff #ffffff transparent; }\\n.table-tooltip.ng-tooltip-left {\\n margin-left: -1rem; }\\n.table-tooltip.ng-tooltip-left:after {\\n content: \\\"\\\";\\n position: absolute;\\n top: calc(50% - 0.5rem);\\n right: -1rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-left:after {\\n border-color: transparent transparent transparent #42505f; }\\n.theme-gray .table-tooltip.ng-tooltip-left:after {\\n border-color: transparent transparent transparent #3e464c; }\\n.theme-white .table-tooltip.ng-tooltip-left:after {\\n border-color: transparent transparent transparent #ffffff; }\\n.table-tooltip.ng-tooltip-right {\\n margin-left: 1rem; }\\n.table-tooltip.ng-tooltip-right:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: calc(50% - 0.5rem);\\n left: -1rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .table-tooltip.ng-tooltip-right:before {\\n border-color: transparent #42505f transparent transparent; }\\n.theme-gray .table-tooltip.ng-tooltip-right:before {\\n border-color: transparent #3e464c transparent transparent; }\\n.theme-white .table-tooltip.ng-tooltip-right:before {\\n border-color: transparent #ffffff transparent transparent; }\\n.table-tooltip-dimensions .tooltip-inner {\\n overflow: auto;\\n max-width: 20rem;\\n max-height: 10rem; }\\n.balance-tooltip {\\n padding: 1.3rem; }\\n.theme-dark .balance-tooltip {\\n background: #42505f;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-gray .balance-tooltip {\\n background: #3e464c;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-white .balance-tooltip {\\n background: #ffffff;\\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\\n color: #43454b; }\\n.balance-tooltip .tooltip-inner {\\n display: flex;\\n flex-direction: column;\\n font-size: 1.3rem; }\\n.balance-tooltip .tooltip-inner .available {\\n margin-bottom: 1.7rem; }\\n.balance-tooltip .tooltip-inner .available b {\\n font-weight: 600; }\\n.balance-tooltip .tooltip-inner .locked {\\n margin-bottom: 0.7rem; }\\n.balance-tooltip .tooltip-inner .locked b {\\n font-weight: 600; }\\n.balance-tooltip .tooltip-inner .link {\\n cursor: pointer; }\\n.theme-dark .balance-tooltip .tooltip-inner .link {\\n color: #4db1ff; }\\n.theme-gray .balance-tooltip .tooltip-inner .link {\\n color: #42a5f5; }\\n.theme-white .balance-tooltip .tooltip-inner .link {\\n color: #2c95f1; }\\n.balance-tooltip.ng-tooltip-top {\\n margin-top: -1rem; }\\n.balance-tooltip.ng-tooltip-bottom {\\n margin-top: 1rem; }\\n.balance-tooltip.ng-tooltip-left {\\n margin-left: -1rem; }\\n.balance-tooltip.ng-tooltip-right {\\n margin-left: 1rem; }\\n.account-tooltip .tooltip-inner {\\n word-break: break-word;\\n max-width: 18rem; }\\n.comment-tooltip .tooltip-inner {\\n overflow: auto;\\n word-break: break-word;\\n max-width: 50rem;\\n max-height: 25rem; }\\n.update-tooltip {\\n padding: 1.5rem; }\\n.theme-dark .update-tooltip {\\n background: #42505f;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-gray .update-tooltip {\\n background: #3e464c;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5);\\n color: #e0e0e0; }\\n.theme-white .update-tooltip {\\n background: #ffffff;\\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5);\\n color: #43454b; }\\n.theme-dark .update-tooltip.important {\\n background: #5f2b11;\\n color: #e0e0e0; }\\n.theme-gray .update-tooltip.important {\\n background: #55240d;\\n color: #e0e0e0; }\\n.theme-white .update-tooltip.important {\\n background: #ef6c00;\\n color: #ffffff; }\\n.theme-dark .update-tooltip.important.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #5f2b11 #5f2b11; }\\n.theme-gray .update-tooltip.important.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #55240d #55240d; }\\n.theme-white .update-tooltip.important.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #ef6c00 #ef6c00; }\\n.theme-dark .update-tooltip.important.ng-tooltip-right-bottom:before {\\n border-color: transparent #5f2b11 #5f2b11 transparent; }\\n.theme-gray .update-tooltip.important.ng-tooltip-right-bottom:before {\\n border-color: transparent #55240d #55240d transparent; }\\n.theme-white .update-tooltip.important.ng-tooltip-right-bottom:before {\\n border-color: transparent #ef6c00 #ef6c00 transparent; }\\n.update-tooltip.critical {\\n padding: 2.5rem; }\\n.theme-dark .update-tooltip.critical {\\n background: #5f1d1d;\\n color: #e0e0e0; }\\n.theme-gray .update-tooltip.critical {\\n background: #4c1919;\\n color: #e0e0e0; }\\n.theme-white .update-tooltip.critical {\\n background: #e53935;\\n color: #ffffff; }\\n.update-tooltip.critical .tooltip-inner {\\n display: flex;\\n flex-direction: column;\\n align-items: center; }\\n.theme-dark .update-tooltip.critical.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #5f1d1d #5f1d1d; }\\n.theme-gray .update-tooltip.critical.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #4c1919 #4c1919; }\\n.theme-white .update-tooltip.critical.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #e53935 #e53935; }\\n.theme-dark .update-tooltip.critical.ng-tooltip-right-bottom:before {\\n border-color: transparent #5f1d1d #5f1d1d transparent; }\\n.theme-gray .update-tooltip.critical.ng-tooltip-right-bottom:before {\\n border-color: transparent #4c1919 #4c1919 transparent; }\\n.theme-white .update-tooltip.critical.ng-tooltip-right-bottom:before {\\n border-color: transparent #e53935 #e53935 transparent; }\\n.update-tooltip .tooltip-inner {\\n font-size: 1.3rem;\\n line-height: 1.8rem;\\n white-space: pre-wrap; }\\n.update-tooltip .tooltip-inner .standard-update {\\n font-size: 1.5rem;\\n line-height: 2.7rem; }\\n.theme-dark .update-tooltip .tooltip-inner .standard-update {\\n color: #4db1ff; }\\n.theme-gray .update-tooltip .tooltip-inner .standard-update {\\n color: #42a5f5; }\\n.theme-white .update-tooltip .tooltip-inner .standard-update {\\n color: #2c95f1; }\\n.update-tooltip .tooltip-inner .important-update {\\n font-size: 1.5rem;\\n line-height: 2.7rem; }\\n.theme-dark .update-tooltip .tooltip-inner .important-update {\\n color: #ff6f00; }\\n.theme-gray .update-tooltip .tooltip-inner .important-update {\\n color: #ff6f00; }\\n.theme-white .update-tooltip .tooltip-inner .important-update {\\n color: #ffffff; }\\n.update-tooltip .tooltip-inner .critical-update {\\n font-size: 1.5rem;\\n line-height: 2.7rem;\\n text-align: center; }\\n.update-tooltip .tooltip-inner .wrong-time {\\n font-size: 1.5rem;\\n line-height: 2.7rem; }\\n.theme-dark .update-tooltip .tooltip-inner .wrong-time {\\n color: #ff6f00; }\\n.theme-gray .update-tooltip .tooltip-inner .wrong-time {\\n color: #ff6f00; }\\n.theme-white .update-tooltip .tooltip-inner .wrong-time {\\n color: #ffffff; }\\n.update-tooltip .tooltip-inner .icon {\\n margin: 1.5rem 0;\\n width: 5rem;\\n height: 5rem; }\\n.theme-dark .update-tooltip .tooltip-inner .icon {\\n background-color: #ff5252; }\\n.theme-gray .update-tooltip .tooltip-inner .icon {\\n background-color: #ff5252; }\\n.theme-white .update-tooltip .tooltip-inner .icon {\\n background-color: #ffffff; }\\n.update-tooltip.ng-tooltip-left-bottom {\\n margin-left: -1.5rem; }\\n.update-tooltip.ng-tooltip-left-bottom:after {\\n content: \\\"\\\";\\n position: absolute;\\n bottom: 0.6rem;\\n right: -1rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .update-tooltip.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #42505f #42505f; }\\n.theme-gray .update-tooltip.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #3e464c #3e464c; }\\n.theme-white .update-tooltip.ng-tooltip-left-bottom:after {\\n border-color: transparent transparent #ffffff #ffffff; }\\n.update-tooltip.ng-tooltip-right-bottom {\\n margin-left: 1.5rem; }\\n.update-tooltip.ng-tooltip-right-bottom:before {\\n content: \\\"\\\";\\n position: absolute;\\n bottom: 0.6rem;\\n left: -1rem;\\n border-width: 0.5rem;\\n border-style: solid; }\\n.theme-dark .update-tooltip.ng-tooltip-right-bottom:before {\\n border-color: transparent #42505f #42505f transparent; }\\n.theme-gray .update-tooltip.ng-tooltip-right-bottom:before {\\n border-color: transparent #3e464c #3e464c transparent; }\\n.theme-white .update-tooltip.ng-tooltip-right-bottom:before {\\n border-color: transparent #ffffff #ffffff transparent; }\\n.ngx-contextmenu .dropdown-menu {\\n border: none;\\n padding: 0; }\\n.theme-dark .ngx-contextmenu .dropdown-menu {\\n background-color: #2b3644;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\\n.theme-gray .ngx-contextmenu .dropdown-menu {\\n background-color: #292d31;\\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.5); }\\n.theme-white .ngx-contextmenu .dropdown-menu {\\n background-color: #e0e0e0;\\n box-shadow: 0 0 1rem rgba(120, 120, 120, 0.5); }\\n.ngx-contextmenu li {\\n display: block;\\n font-family: OpenSans, sans-serif;\\n font-size: 1.3rem;\\n text-transform: uppercase;\\n text-align: center; }\\n.ngx-contextmenu a {\\n display: block;\\n padding: 0.5em 1em; }\\n.theme-dark .ngx-contextmenu a {\\n color: #e0e0e0; }\\n.theme-gray .ngx-contextmenu a {\\n color: #e0e0e0; }\\n.theme-white .ngx-contextmenu a {\\n color: #43454b; }\\n.theme-dark .ngx-contextmenu a:hover {\\n background-color: #556576;\\n color: #e0e0e0; }\\n.theme-gray .ngx-contextmenu a:hover {\\n background-color: #515960;\\n color: #e0e0e0; }\\n.theme-white .ngx-contextmenu a:hover {\\n background-color: #ffffff;\\n color: #43454b; }\\n.ng-select.custom-select {\\n width: 100%; }\\n.ng-select.custom-select.ng-select-single .ng-select-container .ng-value-container .ng-value {\\n line-height: 1.8rem; }\\n.ng-select.custom-select .ng-select-container {\\n border: none;\\n border-radius: 0;\\n cursor: pointer;\\n font-size: 1.4rem;\\n outline: none;\\n padding: 0 1rem;\\n height: 4.2rem; }\\n.theme-dark .ng-select.custom-select .ng-select-container {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray .ng-select.custom-select .ng-select-container {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white .ng-select.custom-select .ng-select-container {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.ng-select.custom-select .ng-select-container .ng-value-container {\\n padding: 0; }\\n.ng-select.custom-select .ng-select-container .ng-value-container .ng-input {\\n top: auto; }\\n.ng-select.custom-select .ng-dropdown-panel {\\n border: none; }\\n.theme-dark .ng-select.custom-select .ng-dropdown-panel {\\n background-color: #171e27; }\\n.theme-gray .ng-select.custom-select .ng-dropdown-panel {\\n background-color: #292d31; }\\n.theme-white .ng-select.custom-select .ng-dropdown-panel {\\n background-color: #e6e6e6; }\\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\\n font-size: 1.4rem;\\n padding: 1rem; }\\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\\n background-color: rgba(58, 69, 85, 0.5);\\n color: #e0e0e0; }\\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\\n background-color: rgba(58, 62, 66, 0.5);\\n color: #e0e0e0; }\\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked {\\n background-color: rgba(240, 240, 240, 0.5);\\n color: #43454b; }\\n.theme-dark .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\\n background-color: rgba(43, 54, 68, 0.5);\\n color: #e0e0e0; }\\n.theme-gray .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\\n background-color: rgba(37, 40, 43, 0.5);\\n color: #e0e0e0; }\\n.theme-white .ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected {\\n background-color: rgba(224, 224, 224, 0.5);\\n color: #43454b; }\\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar {\\n background-color: transparent;\\n cursor: default;\\n width: 1rem;\\n height: 1rem; }\\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-track {\\n background: transparent; }\\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb {\\n background-color: #556576;\\n background-clip: padding-box;\\n border: 0.25rem solid transparent;\\n border-radius: 0.5rem; }\\n.ng-select.custom-select .ng-dropdown-panel .ng-dropdown-panel-items::-webkit-scrollbar-thumb:hover {\\n background-color: #556576; }\\n.theme-dark app-modal-container .modal, .theme-dark app-confirm-modal .modal {\\n background: url('background-dark.png');\\n color: #e0e0e0; }\\n.theme-gray app-modal-container .modal, .theme-gray app-confirm-modal .modal {\\n background: url('background-gray.png');\\n color: #e0e0e0; }\\n.theme-white app-modal-container .modal, .theme-white app-confirm-modal .modal {\\n background: url('background-white.png');\\n color: #43454b; }\\n.theme-dark app-modal-container .modal .content .icon.error, .theme-dark app-confirm-modal .modal .content .icon.error {\\n background-color: #ff5252; }\\n.theme-gray app-modal-container .modal .content .icon.error, .theme-gray app-confirm-modal .modal .content .icon.error {\\n background-color: #ff5252; }\\n.theme-white app-modal-container .modal .content .icon.error, .theme-white app-confirm-modal .modal .content .icon.error {\\n background-color: #ff5252; }\\n.theme-dark app-modal-container .modal .content .icon.success, .theme-dark app-confirm-modal .modal .content .icon.success {\\n background-color: #5cda9d; }\\n.theme-gray app-modal-container .modal .content .icon.success, .theme-gray app-confirm-modal .modal .content .icon.success {\\n background-color: #47cf8d; }\\n.theme-white app-modal-container .modal .content .icon.success, .theme-white app-confirm-modal .modal .content .icon.success {\\n background-color: #46c172; }\\n.theme-dark app-modal-container .modal .content .icon.info, .theme-dark app-confirm-modal .modal .content .icon.info {\\n background-color: #4db1ff; }\\n.theme-gray app-modal-container .modal .content .icon.info, .theme-gray app-confirm-modal .modal .content .icon.info {\\n background-color: #42a5f5; }\\n.theme-white app-modal-container .modal .content .icon.info, .theme-white app-confirm-modal .modal .content .icon.info {\\n background-color: #2c95f1; }\\n.theme-dark app-modal-container .modal .action-button, .theme-dark app-confirm-modal .modal .action-button {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray app-modal-container .modal .action-button, .theme-gray app-confirm-modal .modal .action-button {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white app-modal-container .modal .action-button, .theme-white app-confirm-modal .modal .action-button {\\n background-color: #2c95f1;\\n color: #fefefe; }\\n.theme-dark app-modal-container .modal .close-button .icon, .theme-dark app-confirm-modal .modal .close-button .icon {\\n background-color: #556576; }\\n.theme-gray app-modal-container .modal .close-button .icon, .theme-gray app-confirm-modal .modal .close-button .icon {\\n background-color: #515960; }\\n.theme-white app-modal-container .modal .close-button .icon, .theme-white app-confirm-modal .modal .close-button .icon {\\n background-color: #43454b; }\\n.theme-dark app-transaction-details .table {\\n border-top: 0.2rem solid #2b3644; }\\n.theme-gray app-transaction-details .table {\\n border-top: 0.2rem solid #2f3438; }\\n.theme-white app-transaction-details .table {\\n border-top: 0.2rem solid #ebebeb; }\\n.theme-dark app-transaction-details .table .row .cell.label {\\n color: #556576; }\\n.theme-gray app-transaction-details .table .row .cell.label {\\n color: #565c62; }\\n.theme-white app-transaction-details .table .row .cell.label {\\n color: #a0a5ab; }\\n.theme-dark app-transaction-details .table .row .cell.value {\\n color: #e0e0e0; }\\n.theme-gray app-transaction-details .table .row .cell.value {\\n color: #e0e0e0; }\\n.theme-white app-transaction-details .table .row .cell.value {\\n color: #43454b; }\\n.theme-dark app-transaction-details .table .row .cell.key-value {\\n color: #4db1ff; }\\n.theme-gray app-transaction-details .table .row .cell.key-value {\\n color: #42a5f5; }\\n.theme-white app-transaction-details .table .row .cell.key-value {\\n color: #2c95f1; }\\n.theme-dark app-progress-container .progress-bar-container {\\n color: #e0e0e0; }\\n.theme-gray app-progress-container .progress-bar-container {\\n color: #e0e0e0; }\\n.theme-white app-progress-container .progress-bar-container {\\n color: #43454b; }\\n.theme-dark app-progress-container .progress-bar-container .progress-bar {\\n background-color: #343f4a; }\\n.theme-gray app-progress-container .progress-bar-container .progress-bar {\\n background-color: #363a3e; }\\n.theme-white app-progress-container .progress-bar-container .progress-bar {\\n background-color: #dcdcdc; }\\n.theme-dark app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #5cda9d; }\\n.theme-gray app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #47cf8d; }\\n.theme-white app-progress-container .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #46c172; }\\n.theme-dark app-open-wallet-modal .modal {\\n background: url('background-dark.png');\\n color: #e0e0e0; }\\n.theme-gray app-open-wallet-modal .modal {\\n background: url('background-gray.png');\\n color: #e0e0e0; }\\n.theme-white app-open-wallet-modal .modal {\\n background: url('background-white.png');\\n color: #43454b; }\\n.theme-dark app-send-modal .modal {\\n background: url('background-dark.png');\\n color: #e0e0e0; }\\n.theme-gray app-send-modal .modal {\\n background: url('background-gray.png');\\n color: #e0e0e0; }\\n.theme-white app-send-modal .modal {\\n background: url('background-white.png');\\n color: #43454b; }\\n.theme-dark app-send-modal .modal .title {\\n border-bottom: 0.2rem solid #2b3644; }\\n.theme-gray app-send-modal .modal .title {\\n border-bottom: 0.2rem solid #2f3438; }\\n.theme-white app-send-modal .modal .title {\\n border-bottom: 0.2rem solid #ebebeb; }\\n.theme-dark app-send-modal .modal .action-button {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray app-send-modal .modal .action-button {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white app-send-modal .modal .action-button {\\n background-color: #2c95f1;\\n color: #fefefe; }\\napp-main, app-create-wallet, app-open-wallet, app-restore-wallet, app-seed-phrase, app-wallet-details, app-assign-alias, app-edit-alias, app-transfer-alias, app-settings, app-login {\\n flex: 1 1 auto;\\n padding: 3rem;\\n min-width: 85rem; }\\napp-main .content, app-create-wallet .content, app-open-wallet .content, app-restore-wallet .content, app-seed-phrase .content, app-wallet-details .content, app-assign-alias .content, app-edit-alias .content, app-transfer-alias .content, app-settings .content, app-login .content {\\n position: relative;\\n padding: 3rem;\\n min-height: 100%; }\\n.theme-dark app-main .content, .theme-dark app-create-wallet .content, .theme-dark app-open-wallet .content, .theme-dark app-restore-wallet .content, .theme-dark app-seed-phrase .content, .theme-dark app-wallet-details .content, .theme-dark app-assign-alias .content, .theme-dark app-edit-alias .content, .theme-dark app-transfer-alias .content, .theme-dark app-settings .content, .theme-dark app-login .content {\\n background-color: rgba(43, 54, 68, 0.5);\\n color: #e0e0e0; }\\n.theme-gray app-main .content, .theme-gray app-create-wallet .content, .theme-gray app-open-wallet .content, .theme-gray app-restore-wallet .content, .theme-gray app-seed-phrase .content, .theme-gray app-wallet-details .content, .theme-gray app-assign-alias .content, .theme-gray app-edit-alias .content, .theme-gray app-transfer-alias .content, .theme-gray app-settings .content, .theme-gray app-login .content {\\n background-color: rgba(37, 40, 43, 0.5);\\n color: #e0e0e0; }\\n.theme-white app-main .content, .theme-white app-create-wallet .content, .theme-white app-open-wallet .content, .theme-white app-restore-wallet .content, .theme-white app-seed-phrase .content, .theme-white app-wallet-details .content, .theme-white app-assign-alias .content, .theme-white app-edit-alias .content, .theme-white app-transfer-alias .content, .theme-white app-settings .content, .theme-white app-login .content {\\n background-color: rgba(255, 255, 255, 0.5);\\n color: #43454b; }\\napp-main .content .head, app-create-wallet .content .head, app-open-wallet .content .head, app-restore-wallet .content .head, app-seed-phrase .content .head, app-wallet-details .content .head, app-assign-alias .content .head, app-edit-alias .content .head, app-transfer-alias .content .head, app-settings .content .head, app-login .content .head {\\n position: absolute;\\n top: 0;\\n left: 0; }\\n.theme-dark app-main .content .add-wallet .add-wallet-help {\\n color: #4db1ff; }\\n.theme-gray app-main .content .add-wallet .add-wallet-help {\\n color: #42a5f5; }\\n.theme-white app-main .content .add-wallet .add-wallet-help {\\n color: #2c95f1; }\\n.theme-dark app-main .content .add-wallet .add-wallet-help .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-main .content .add-wallet .add-wallet-help .icon {\\n background-color: #42a5f5; }\\n.theme-white app-main .content .add-wallet .add-wallet-help .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-seed-phrase .seed-phrase-content {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray app-seed-phrase .seed-phrase-content {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white app-seed-phrase .seed-phrase-content {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.theme-dark app-wallet-details .seed-phrase {\\n background-color: #171e27; }\\n.theme-gray app-wallet-details .seed-phrase {\\n background-color: #292d31; }\\n.theme-white app-wallet-details .seed-phrase {\\n background-color: #e6e6e6; }\\napp-settings .content {\\n height: 100%;\\n overflow-y: auto;\\n display: flex;\\n justify-content: space-between;\\n flex-direction: column; }\\n.theme-dark app-settings .content .theme-selection {\\n color: #556576; }\\n.theme-gray app-settings .content .theme-selection {\\n color: #565c62; }\\n.theme-white app-settings .content .theme-selection {\\n color: #a0a5ab; }\\n.theme-dark app-settings .content .scale-selection .button-block {\\n background-color: rgba(23, 31, 39, 0.5); }\\n.theme-gray app-settings .content .scale-selection .button-block {\\n background-color: rgba(28, 30, 33, 0.5); }\\n.theme-white app-settings .content .scale-selection .button-block {\\n background-color: rgba(224, 224, 224, 0.5); }\\n.theme-dark app-settings .content .scale-selection .button-block .label {\\n color: #556576; }\\n.theme-gray app-settings .content .scale-selection .button-block .label {\\n color: #565c62; }\\n.theme-white app-settings .content .scale-selection .button-block .label {\\n color: #a0a5ab; }\\n.theme-dark app-settings .content .scale-selection .button-block.active {\\n background-color: #4db1ff; }\\n.theme-gray app-settings .content .scale-selection .button-block.active {\\n background-color: #42a5f5; }\\n.theme-white app-settings .content .scale-selection .button-block.active {\\n background-color: #2c95f1; }\\n.theme-dark app-settings .content .scale-selection .button-block.active .label {\\n color: #4db1ff; }\\n.theme-gray app-settings .content .scale-selection .button-block.active .label {\\n color: #42a5f5; }\\n.theme-white app-settings .content .scale-selection .button-block.active .label {\\n color: #2c95f1; }\\napp-login {\\n min-width: inherit; }\\n.theme-dark app-sidebar {\\n background-color: #171f27; }\\n.theme-gray app-sidebar {\\n background-color: #1c1e21; }\\n.theme-white app-sidebar {\\n background-color: white; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\\n color: #e0e0e0; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\\n color: #e0e0e0; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header h3 {\\n color: #43454b; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-header button {\\n color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-header button {\\n color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-header button {\\n color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\\n background-color: transparent;\\n color: #e0e0e0; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\\n background-color: transparent;\\n color: #e0e0e0; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account {\\n background-color: transparent;\\n color: #43454b; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\\n color: #556576; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\\n color: #565c62; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .text {\\n color: #a0a5ab; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\\n background-color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .indicator {\\n background-color: #2c95f1;\\n color: #fefefe; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\\n background-color: #343f4a; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\\n background-color: #363a3e; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar {\\n background-color: #dcdcdc; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\\n background-color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\\n background-color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row .progress-bar-container .progress-bar .fill {\\n background-color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\\n color: #556576; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\\n color: #565c62; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account .sidebar-account-row.account-synchronization {\\n color: #a0a5ab; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\\n background-color: rgba(43, 54, 68, 0.5);\\n color: #e0e0e0; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\\n background-color: rgba(37, 40, 43, 0.5);\\n color: #e0e0e0; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active {\\n background-color: #1e88e5;\\n color: #ffffff; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\\n color: #556576; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\\n color: #565c62; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .text {\\n color: #91baf1; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .indicator {\\n background-color: #ffffff;\\n color: #43454b; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\\n background-color: #000000;\\n color: #e0e0e0; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\\n background-color: #000000;\\n color: #e0e0e0; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row .switch {\\n background-color: #ffffff;\\n color: #43454b; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\\n color: #556576; }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\\n color: #565c62; }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account.active .sidebar-account-row.account-synchronization {\\n color: #91baf1; }\\n.theme-dark app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\\n background-color: rgba(58, 69, 85, 0.5); }\\n.theme-gray app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\\n background-color: rgba(58, 62, 66, 0.5); }\\n.theme-white app-sidebar .sidebar-accounts .sidebar-accounts-list .sidebar-account:hover:not(.active) {\\n background-color: rgba(240, 240, 240, 0.5); }\\n.theme-dark app-sidebar .sidebar-accounts:after {\\n background: linear-gradient(to bottom, transparent 0%, #171f27 100%); }\\n.theme-gray app-sidebar .sidebar-accounts:after {\\n background: linear-gradient(to bottom, transparent 0%, #1c1e21 100%); }\\n.theme-white app-sidebar .sidebar-accounts:after {\\n background: linear-gradient(to bottom, transparent 0%, white 100%); }\\n.theme-dark app-sidebar .sidebar-settings {\\n border-bottom: 0.2rem solid #1f2833; }\\n.theme-gray app-sidebar .sidebar-settings {\\n border-bottom: 0.2rem solid #2e3337; }\\n.theme-white app-sidebar .sidebar-settings {\\n border-bottom: 0.2rem solid #ebebeb; }\\n.theme-dark app-sidebar .sidebar-settings .wrap-button button {\\n color: #e0e0e0; }\\n.theme-gray app-sidebar .sidebar-settings .wrap-button button {\\n color: #e0e0e0; }\\n.theme-white app-sidebar .sidebar-settings .wrap-button button {\\n color: #43454b; }\\n.theme-dark app-sidebar .sidebar-settings .wrap-button button .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-settings .wrap-button button .icon {\\n background-color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-settings .wrap-button button .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button {\\n background-color: rgba(43, 54, 68, 0.5) !important;\\n color: #e0e0e0 !important; }\\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button {\\n background-color: rgba(37, 40, 43, 0.5) !important;\\n color: #e0e0e0 !important; }\\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button {\\n background-color: #1e88e5 !important;\\n color: #ffffff !important; }\\n.theme-dark app-sidebar .sidebar-settings .wrap-button.active button .icon {\\n background-color: #4db1ff !important; }\\n.theme-gray app-sidebar .sidebar-settings .wrap-button.active button .icon {\\n background-color: #42a5f5 !important; }\\n.theme-white app-sidebar .sidebar-settings .wrap-button.active button .icon {\\n background-color: #ffffff !important; }\\n.theme-dark app-sidebar .sidebar-synchronization-status {\\n color: #556576; }\\n.theme-gray app-sidebar .sidebar-synchronization-status {\\n color: #565c62; }\\n.theme-white app-sidebar .sidebar-synchronization-status {\\n color: #a0a5ab; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .offline:before {\\n background-color: #ff5252; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .offline:before {\\n background-color: #ff5252; }\\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .offline:before {\\n background-color: #ff5252; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .online:before {\\n background-color: #5cda9d; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .online:before {\\n background-color: #47cf8d; }\\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .online:before {\\n background-color: #46c172; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\\n background-color: #343f4a; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\\n background-color: #363a3e; }\\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar {\\n background-color: #dcdcdc; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\\n background-color: #5cda9d; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\\n background-color: #47cf8d; }\\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .syncing .progress-bar .fill {\\n background-color: #46c172; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\\n background-color: #5cda9d; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\\n background-color: #47cf8d; }\\n.theme-white app-sidebar .sidebar-synchronization-status .status-container .progress-bar-container .loading {\\n background-color: #46c172; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .standard {\\n color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .standard {\\n color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .standard {\\n color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .important {\\n color: #ff6f00; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .important {\\n color: #ff6f00; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .important {\\n color: #ff6f00; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .critical {\\n color: #ff5252; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .critical {\\n color: #ff5252; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .critical {\\n color: #ff5252; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .time {\\n color: #ff6f00; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .time {\\n color: #ff6f00; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .time {\\n color: #ff6f00; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\\n background-color: #4db1ff; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\\n background-color: #42a5f5; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.standard {\\n background-color: #2c95f1; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.important {\\n background-color: #ff6f00; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.important {\\n background-color: #ff6f00; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.important {\\n background-color: #ff6f00; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\\n background-color: #ff5252; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\\n background-color: #ff5252; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.critical {\\n background-color: #ff5252; }\\n.theme-dark app-sidebar .sidebar-synchronization-status .update-container .icon.time {\\n background-color: #ff6f00; }\\n.theme-gray app-sidebar .sidebar-synchronization-status .update-container .icon.time {\\n background-color: #ff6f00; }\\n.theme-white app-sidebar .sidebar-synchronization-status .update-container .icon.time {\\n background-color: #ff6f00; }\\n.theme-dark app-wallet {\\n color: #e0e0e0; }\\n.theme-gray app-wallet {\\n color: #e0e0e0; }\\n.theme-white app-wallet {\\n color: #43454b; }\\n.theme-dark app-wallet .header button {\\n color: #e0e0e0; }\\n.theme-gray app-wallet .header button {\\n color: #e0e0e0; }\\n.theme-white app-wallet .header button {\\n color: #43454b; }\\n.theme-dark app-wallet .header button .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-wallet .header button .icon {\\n background-color: #42a5f5; }\\n.theme-white app-wallet .header button .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-wallet .header .alias .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-wallet .header .alias .icon {\\n background-color: #42a5f5; }\\n.theme-white app-wallet .header .alias .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-wallet .address {\\n color: #4db1ff; }\\n.theme-gray app-wallet .address {\\n color: #42a5f5; }\\n.theme-white app-wallet .address {\\n color: #2c95f1; }\\n.theme-dark app-wallet .address .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-wallet .address .icon {\\n background-color: #42a5f5; }\\n.theme-white app-wallet .address .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-wallet .tabs .tabs-header .tab {\\n background-color: rgba(23, 31, 39, 0.5); }\\n.theme-gray app-wallet .tabs .tabs-header .tab {\\n background-color: rgba(28, 30, 33, 0.5); }\\n.theme-white app-wallet .tabs .tabs-header .tab {\\n background-color: rgba(224, 224, 224, 0.5); }\\n.theme-dark app-wallet .tabs .tabs-header .tab .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-wallet .tabs .tabs-header .tab .icon {\\n background-color: #42a5f5; }\\n.theme-white app-wallet .tabs .tabs-header .tab .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-wallet .tabs .tabs-header .tab .indicator {\\n background-color: #4db1ff;\\n color: #111921; }\\n.theme-gray app-wallet .tabs .tabs-header .tab .indicator {\\n background-color: #42a5f5;\\n color: #1a1a1a; }\\n.theme-white app-wallet .tabs .tabs-header .tab .indicator {\\n background-color: #ffffff;\\n color: #43454b; }\\n.theme-dark app-wallet .tabs .tabs-header .tab.active {\\n background-color: rgba(43, 54, 68, 0.5); }\\n.theme-gray app-wallet .tabs .tabs-header .tab.active {\\n background-color: rgba(37, 40, 43, 0.5); }\\n.theme-white app-wallet .tabs .tabs-header .tab.active {\\n background-color: rgba(255, 255, 255, 0.5); }\\n.theme-dark app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\\n background-color: rgba(58, 69, 85, 0.5); }\\n.theme-gray app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\\n background-color: rgba(58, 62, 66, 0.5); }\\n.theme-white app-wallet .tabs .tabs-header .tab:hover:not(.active):not(.disabled) {\\n background-color: #ffffff; }\\n.theme-dark app-wallet .tabs .tabs-content {\\n background-color: rgba(43, 54, 68, 0.5); }\\n.theme-gray app-wallet .tabs .tabs-content {\\n background-color: rgba(37, 40, 43, 0.5); }\\n.theme-white app-wallet .tabs .tabs-content {\\n background-color: rgba(255, 255, 255, 0.5); }\\n.theme-dark app-send .form-send .send-select {\\n color: #e0e0e0; }\\n.theme-gray app-send .form-send .send-select {\\n color: #e0e0e0; }\\n.theme-white app-send .form-send .send-select {\\n color: #43454b; }\\n.theme-dark app-send .form-send .send-select .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-send .form-send .send-select .icon {\\n background-color: #42a5f5; }\\n.theme-white app-send .form-send .send-select .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-send .form-send .additional-details {\\n border: 0.2rem solid #2b3644; }\\n.theme-gray app-send .form-send .additional-details {\\n border: 0.2rem solid #2f3438; }\\n.theme-white app-send .form-send .additional-details {\\n border: 0.2rem solid #ebebeb; }\\n.theme-dark app-receive .btn-copy-address {\\n background-color: #4db1ff; }\\n.theme-gray app-receive .btn-copy-address {\\n background-color: #42a5f5; }\\n.theme-white app-receive .btn-copy-address {\\n background-color: #2c95f1; }\\n.theme-dark app-history table tbody tr.locked-transaction {\\n color: #556576; }\\n.theme-gray app-history table tbody tr.locked-transaction {\\n color: #565c62; }\\n.theme-white app-history table tbody tr.locked-transaction {\\n color: #a0a5ab; }\\n.theme-dark app-history table tbody tr:nth-child(4n+1) {\\n background-color: #18202a; }\\n.theme-gray app-history table tbody tr:nth-child(4n+1) {\\n background-color: #25292d; }\\n.theme-white app-history table tbody tr:nth-child(4n+1) {\\n background-color: #ffffff; }\\n.theme-dark app-history table tbody tr:nth-child(4n+2) {\\n background-color: #18202a; }\\n.theme-gray app-history table tbody tr:nth-child(4n+2) {\\n background-color: #25292d; }\\n.theme-white app-history table tbody tr:nth-child(4n+2) {\\n background-color: #ffffff; }\\n.theme-dark app-history table tbody tr:nth-child(4n+3) {\\n background-color: transparent; }\\n.theme-gray app-history table tbody tr:nth-child(4n+3) {\\n background-color: transparent; }\\n.theme-white app-history table tbody tr:nth-child(4n+3) {\\n background-color: transparent; }\\n.theme-dark app-history table tbody tr:nth-child(4n+4) {\\n background-color: transparent; }\\n.theme-gray app-history table tbody tr:nth-child(4n+4) {\\n background-color: transparent; }\\n.theme-white app-history table tbody tr:nth-child(4n+4) {\\n background-color: transparent; }\\n.theme-dark app-history table tbody tr .status .confirmation {\\n background-color: #343f4a; }\\n.theme-gray app-history table tbody tr .status .confirmation {\\n background-color: #363a3e; }\\n.theme-white app-history table tbody tr .status .confirmation {\\n background-color: #dcdcdc; }\\n.theme-dark app-history table tbody tr .status .confirmation .fill {\\n background-color: #5cda9d; }\\n.theme-gray app-history table tbody tr .status .confirmation .fill {\\n background-color: #47cf8d; }\\n.theme-white app-history table tbody tr .status .confirmation .fill {\\n background-color: #46c172; }\\n.theme-dark app-history table tbody tr .lock-transaction {\\n background-color: #ff6f00; }\\n.theme-gray app-history table tbody tr .lock-transaction {\\n background-color: #ff6f00; }\\n.theme-white app-history table tbody tr .lock-transaction {\\n background-color: #ff6f00; }\\n.theme-dark app-history table tbody tr .unlock-transaction {\\n background-color: #4db1ff; }\\n.theme-gray app-history table tbody tr .unlock-transaction {\\n background-color: #42a5f5; }\\n.theme-white app-history table tbody tr .unlock-transaction {\\n background-color: #2c95f1; }\\n.theme-dark app-history table tbody tr .status.send .status-transaction {\\n background-color: #ff5252; }\\n.theme-gray app-history table tbody tr .status.send .status-transaction {\\n background-color: #ff5252; }\\n.theme-white app-history table tbody tr .status.send .status-transaction {\\n background-color: #ff5252; }\\n.theme-dark app-history table tbody tr .status.received .status-transaction {\\n background-color: #5cda9d; }\\n.theme-gray app-history table tbody tr .status.received .status-transaction {\\n background-color: #47cf8d; }\\n.theme-white app-history table tbody tr .status.received .status-transaction {\\n background-color: #46c172; }\\n.theme-dark app-contracts .wrap-table .contract .icon.new, .theme-dark app-contracts .wrap-table .contract .icon.alert {\\n background-color: #ff5252; }\\n.theme-gray app-contracts .wrap-table .contract .icon.new, .theme-gray app-contracts .wrap-table .contract .icon.alert {\\n background-color: #ff5252; }\\n.theme-white app-contracts .wrap-table .contract .icon.new, .theme-white app-contracts .wrap-table .contract .icon.alert {\\n background-color: #ff5252; }\\n.theme-dark app-contracts .wrap-table .contract .icon.purchase, .theme-dark app-contracts .wrap-table .contract .icon.sell {\\n background-color: #4db1ff; }\\n.theme-gray app-contracts .wrap-table .contract .icon.purchase, .theme-gray app-contracts .wrap-table .contract .icon.sell {\\n background-color: #42a5f5; }\\n.theme-white app-contracts .wrap-table .contract .icon.purchase, .theme-white app-contracts .wrap-table .contract .icon.sell {\\n background-color: #2c95f1; }\\n.theme-dark app-purchase .form-purchase .purchase-select {\\n color: #e0e0e0; }\\n.theme-gray app-purchase .form-purchase .purchase-select {\\n color: #e0e0e0; }\\n.theme-white app-purchase .form-purchase .purchase-select {\\n color: #43454b; }\\n.theme-dark app-purchase .form-purchase .purchase-select .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-purchase .form-purchase .purchase-select .icon {\\n background-color: #42a5f5; }\\n.theme-white app-purchase .form-purchase .purchase-select .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-purchase .form-purchase .purchase-states {\\n color: #4db1ff; }\\n.theme-gray app-purchase .form-purchase .purchase-states {\\n color: #42a5f5; }\\n.theme-white app-purchase .form-purchase .purchase-states {\\n color: #2c95f1; }\\n.theme-dark app-purchase .form-purchase .additional-details {\\n border: 0.2rem solid #2b3644; }\\n.theme-gray app-purchase .form-purchase .additional-details {\\n border: 0.2rem solid #2f3438; }\\n.theme-white app-purchase .form-purchase .additional-details {\\n border: 0.2rem solid #ebebeb; }\\n.theme-dark app-purchase .progress-bar-container .progress-bar {\\n background-color: #343f4a; }\\n.theme-gray app-purchase .progress-bar-container .progress-bar {\\n background-color: #363a3e; }\\n.theme-white app-purchase .progress-bar-container .progress-bar {\\n background-color: #dcdcdc; }\\n.theme-dark app-purchase .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #5cda9d; }\\n.theme-gray app-purchase .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #47cf8d; }\\n.theme-white app-purchase .progress-bar-container .progress-bar .progress-bar-full {\\n background-color: #46c172; }\\napp-messages table tbody tr td:first-child span {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap; }\\n.theme-dark app-messages table tbody tr td:first-child .icon {\\n background-color: #ff5252; }\\n.theme-gray app-messages table tbody tr td:first-child .icon {\\n background-color: #ff5252; }\\n.theme-white app-messages table tbody tr td:first-child .icon {\\n background-color: #ff5252; }\\n.theme-dark app-typing-message .head .interlocutor {\\n color: #4db1ff; }\\n.theme-gray app-typing-message .head .interlocutor {\\n color: #42a5f5; }\\n.theme-white app-typing-message .head .interlocutor {\\n color: #2c95f1; }\\n.theme-dark app-typing-message .messages-content .messages-list div.date {\\n color: #556576; }\\n.theme-gray app-typing-message .messages-content .messages-list div.date {\\n color: #565c62; }\\n.theme-white app-typing-message .messages-content .messages-list div.date {\\n color: #a0a5ab; }\\n.theme-dark app-typing-message .messages-content .messages-list div.my {\\n background-color: #2a3544; }\\n.theme-gray app-typing-message .messages-content .messages-list div.my {\\n background-color: #30363c; }\\n.theme-white app-typing-message .messages-content .messages-list div.my {\\n background-color: #fff; }\\napp-typing-message .messages-content .messages-list div.my:before {\\n content: \\\"\\\";\\n display: block;\\n position: absolute;\\n top: 0;\\n left: -1.1rem;\\n border: 1.2rem solid transparent; }\\n.theme-dark app-typing-message .messages-content .messages-list div.my:before {\\n border-top-color: #2a3544; }\\n.theme-gray app-typing-message .messages-content .messages-list div.my:before {\\n border-top-color: #30363c; }\\n.theme-white app-typing-message .messages-content .messages-list div.my:before {\\n border-top-color: #fff; }\\n.theme-dark app-typing-message .messages-content .messages-list div.buddy {\\n background-color: #18202a; }\\n.theme-gray app-typing-message .messages-content .messages-list div.buddy {\\n background-color: #25292d; }\\n.theme-white app-typing-message .messages-content .messages-list div.buddy {\\n background-color: #ededed; }\\napp-typing-message .messages-content .messages-list div.buddy:after {\\n content: \\\"\\\";\\n display: block;\\n position: absolute;\\n right: -1.1rem;\\n top: 0;\\n border: 1.2rem solid transparent; }\\n.theme-dark app-typing-message .messages-content .messages-list div.buddy:after {\\n border-top-color: #18202a; }\\n.theme-gray app-typing-message .messages-content .messages-list div.buddy:after {\\n border-top-color: #25292d; }\\n.theme-white app-typing-message .messages-content .messages-list div.buddy:after {\\n border-top-color: #ededed; }\\n.theme-dark app-staking .chart-header .general .label {\\n color: #556576; }\\n.theme-gray app-staking .chart-header .general .label {\\n color: #565c62; }\\n.theme-white app-staking .chart-header .general .label {\\n color: #a0a5ab; }\\n.theme-dark app-staking .chart-header .general .options {\\n color: #e0e0e0; }\\n.theme-gray app-staking .chart-header .general .options {\\n color: #e0e0e0; }\\n.theme-white app-staking .chart-header .general .options {\\n color: #43454b; }\\napp-staking .chart-header .selected {\\n display: flex;\\n align-items: center;\\n justify-content: flex-end;\\n flex-grow: 1;\\n font-size: 1.6rem; }\\n.theme-dark app-staking .chart-options .title {\\n color: #556576; }\\n.theme-gray app-staking .chart-options .title {\\n color: #565c62; }\\n.theme-white app-staking .chart-options .title {\\n color: #a0a5ab; }\\n.theme-dark app-staking .chart-options .options button {\\n color: #e0e0e0;\\n background-color: #2b3644; }\\n.theme-gray app-staking .chart-options .options button {\\n color: #e0e0e0;\\n background-color: #292d31; }\\n.theme-white app-staking .chart-options .options button {\\n color: #43454b;\\n background-color: #e0e0e0; }\\n.theme-dark app-staking .chart-options .options button.active {\\n background-color: #556576; }\\n.theme-gray app-staking .chart-options .options button.active {\\n background-color: #515960; }\\n.theme-white app-staking .chart-options .options button.active {\\n background-color: #ffffff; }\\n.input-block-alias {\\n position: relative; }\\n.input-block-alias .alias-dropdown {\\n position: absolute;\\n top: 6.5rem;\\n max-height: 10rem;\\n overflow: auto;\\n width: 100%; }\\n.theme-dark .input-block-alias .alias-dropdown {\\n background-color: #171e27;\\n color: #e0e0e0; }\\n.theme-gray .input-block-alias .alias-dropdown {\\n background-color: #292d31;\\n color: #e0e0e0; }\\n.theme-white .input-block-alias .alias-dropdown {\\n background-color: #e6e6e6;\\n color: #43454b; }\\n.input-block-alias .alias-dropdown div {\\n font-size: 1.4rem;\\n padding: 1rem; }\\n.theme-dark .input-block-alias .alias-dropdown div:hover {\\n background-color: rgba(58, 69, 85, 0.5); }\\n.theme-gray .input-block-alias .alias-dropdown div:hover {\\n background-color: rgba(58, 62, 66, 0.5); }\\n.theme-white .input-block-alias .alias-dropdown div:hover {\\n background-color: rgba(240, 240, 240, 0.5); }\\napp-contacts, app-add-contacts,\\napp-contact-send, app-export-import {\\n flex: 1 1 auto;\\n padding: 3rem;\\n min-width: 85rem; }\\napp-contacts .content, app-add-contacts .content,\\n app-contact-send .content, app-export-import .content {\\n position: relative;\\n padding: 3rem;\\n min-height: 100%; }\\n.theme-dark app-contacts .content, .theme-dark app-add-contacts .content, .theme-dark\\n app-contact-send .content, .theme-dark app-export-import .content {\\n background-color: rgba(43, 54, 68, 0.5);\\n color: #e0e0e0; }\\n.theme-gray app-contacts .content, .theme-gray app-add-contacts .content, .theme-gray\\n app-contact-send .content, .theme-gray app-export-import .content {\\n background-color: rgba(37, 40, 43, 0.5);\\n color: #e0e0e0; }\\n.theme-white app-contacts .content, .theme-white app-add-contacts .content, .theme-white\\n app-contact-send .content, .theme-white app-export-import .content {\\n background-color: rgba(255, 255, 255, 0.5);\\n color: #43454b; }\\napp-contacts .content .head, app-add-contacts .content .head,\\n app-contact-send .content .head, app-export-import .content .head {\\n position: absolute;\\n top: 0;\\n left: 0; }\\n.theme-dark app-contacts table .alias {\\n color: #4db1ff; }\\n.theme-gray app-contacts table .alias {\\n color: #42a5f5; }\\n.theme-white app-contacts table .alias {\\n color: #2c95f1; }\\n.theme-dark app-contacts table button .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-contacts table button .icon {\\n background-color: #42a5f5; }\\n.theme-white app-contacts table button .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-contacts table button span {\\n color: #e0e0e0; }\\n.theme-gray app-contacts table button span {\\n color: #e0e0e0; }\\n.theme-white app-contacts table button span {\\n color: #43454b; }\\n.theme-dark app-contacts .footer {\\n color: #4db1ff; }\\n.theme-gray app-contacts .footer {\\n color: #42a5f5; }\\n.theme-white app-contacts .footer {\\n color: #2c95f1; }\\n.theme-dark app-contacts .footer .import-btn {\\n color: #4db1ff; }\\n.theme-gray app-contacts .footer .import-btn {\\n color: #42a5f5; }\\n.theme-white app-contacts .footer .import-btn {\\n color: #2c95f1; }\\n.theme-dark app-contacts .footer .import-btn .icon {\\n background-color: #4db1ff; }\\n.theme-gray app-contacts .footer .import-btn .icon {\\n background-color: #42a5f5; }\\n.theme-white app-contacts .footer .import-btn .icon {\\n background-color: #2c95f1; }\\n.theme-dark app-contact-send .wallets-selection button {\\n color: #4db1ff; }\\n.theme-gray app-contact-send .wallets-selection button {\\n color: #42a5f5; }\\n.theme-white app-contact-send .wallets-selection button {\\n color: #2c95f1; }\\n.head {\\n display: flex;\\n align-items: flex-end;\\n justify-content: space-between;\\n font-size: 1.3rem;\\n padding: 0 3rem;\\n width: 100%;\\n height: 3rem; }\\n.theme-dark .head {\\n color: #4db1ff; }\\n.theme-gray .head {\\n color: #42a5f5; }\\n.theme-white .head {\\n color: #2c95f1; }\\n.head .breadcrumbs > span:not(:last-child), .head .breadcrumbs a:not(:last-child) {\\n position: relative;\\n cursor: pointer;\\n margin-right: 20px;\\n outline-style: none; }\\n.head .breadcrumbs > span:not(:last-child):after, .head .breadcrumbs a:not(:last-child):after {\\n content: \\\"\\\";\\n display: block;\\n position: absolute;\\n top: 0.5rem;\\n right: -1.5rem;\\n width: 0.9rem;\\n height: 0.9rem;\\n -webkit-mask: url('arrow-right.svg') no-repeat center;\\n mask: url('arrow-right.svg') no-repeat center;\\n -webkit-mask-size: cover;\\n mask-size: cover; }\\n.theme-dark .head .breadcrumbs > span:not(:last-child):after, .theme-dark .head .breadcrumbs a:not(:last-child):after {\\n background-color: #4db1ff; }\\n.theme-gray .head .breadcrumbs > span:not(:last-child):after, .theme-gray .head .breadcrumbs a:not(:last-child):after {\\n background-color: #42a5f5; }\\n.theme-white .head .breadcrumbs > span:not(:last-child):after, .theme-white .head .breadcrumbs a:not(:last-child):after {\\n background-color: #2c95f1; }\\n.head .back-btn {\\n display: flex;\\n align-items: center;\\n background-color: transparent;\\n color: #4db1ff;\\n font-size: inherit;\\n font-weight: 400;\\n line-height: 1.3rem;\\n padding: 0;\\n height: auto; }\\n.head .back-btn .icon {\\n margin-right: 0.7rem;\\n -webkit-mask: url('back.svg') no-repeat center;\\n mask: url('back.svg') no-repeat center;\\n width: 0.9rem;\\n height: 0.9rem; }\\n.theme-dark .head .back-btn .icon {\\n background-color: #4db1ff; }\\n.theme-gray .head .back-btn .icon {\\n background-color: #42a5f5; }\\n.theme-white .head .back-btn .icon {\\n background-color: #2c95f1; }\\n.scrolled-content::-webkit-scrollbar {\\n background-color: transparent;\\n cursor: default;\\n width: 1rem;\\n height: 1rem; }\\n.scrolled-content::-webkit-scrollbar-track {\\n background: transparent; }\\n.scrolled-content::-webkit-scrollbar-thumb {\\n background-color: #556576;\\n background-clip: padding-box;\\n border: 0.25rem solid transparent;\\n border-radius: 0.5rem; }\\n.scrolled-content::-webkit-scrollbar-thumb:hover {\\n background-color: #556576; }\\ntable {\\n font-size: 1.3rem;\\n width: 100%; }\\ntable thead {\\n text-align: left; }\\n.theme-dark table thead {\\n color: #556576; }\\n.theme-gray table thead {\\n color: #565c62; }\\n.theme-white table thead {\\n color: #a0a5ab; }\\ntable thead tr {\\n height: 4rem; }\\ntable thead tr th {\\n padding: 1rem;\\n vertical-align: bottom; }\\ntable thead tr th:first-child {\\n padding-left: 3rem; }\\ntable thead tr th:last-child {\\n padding-right: 3rem; }\\ntable tbody {\\n text-align: left; }\\n.theme-dark table tbody {\\n color: #e0e0e0; }\\n.theme-gray table tbody {\\n color: #e0e0e0; }\\n.theme-white table tbody {\\n color: #43454b; }\\ntable tbody tr {\\n height: 3.5rem; }\\n.theme-dark table tbody tr:nth-child(odd) {\\n background-color: #18202a; }\\n.theme-gray table tbody tr:nth-child(odd) {\\n background-color: #25292d; }\\n.theme-white table tbody tr:nth-child(odd) {\\n background-color: #ffffff; }\\ntable tbody tr td {\\n line-height: 1.7rem;\\n padding: 0 1rem;\\n vertical-align: middle;\\n white-space: nowrap;\\n max-width: 20rem; }\\ntable tbody tr td:first-child {\\n padding-left: 3rem; }\\ntable tbody tr td:last-child {\\n padding-right: 3rem; }\\n@font-face {\\n font-family: OpenSans;\\n src: url('OpenSans-Light.ttf');\\n font-weight: 300; }\\n@font-face {\\n font-family: OpenSans;\\n src: url('OpenSans-Regular.ttf');\\n font-weight: 400; }\\n@font-face {\\n font-family: OpenSans;\\n src: url('OpenSans-SemiBold.ttf');\\n font-weight: 600; }\\n@font-face {\\n font-family: OpenSans;\\n src: url('OpenSans-Bold.ttf');\\n font-weight: 700; }\\n@font-face {\\n font-family: OpenSans;\\n src: url('OpenSans-ExtraBold.ttf');\\n font-weight: 800; }\\nhtml {\\n font-family: OpenSans, sans-serif;\\n font-size: 10px; }\\nbody {\\n font-family: OpenSans, sans-serif;\\n font-size: 1.6rem;\\n width: 100vw;\\n height: 100vh; }\\nbody.theme-dark {\\n background: #131921 url('background-dark.png') no-repeat center;\\n background-size: cover; }\\nbody.theme-gray {\\n background: #101417 url('background-gray.png') no-repeat center;\\n background-size: cover; }\\nbody.theme-white {\\n background: #eeeeee url('background-white.png') no-repeat center;\\n background-size: cover; }\\nbody app-root {\\n display: flex;\\n width: 100%;\\n height: 100%; }\\n.update-tooltip .tooltip-inner .icon {\\n -webkit-mask: url('update-alert.svg') no-repeat center;\\n mask: url('update-alert.svg') no-repeat center; }\\n\\r\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxiYXNlXFxfbWl4aW5zLnNjc3MiLCJzcmMvc3R5bGVzLnNjc3MiLCJub2RlX21vZHVsZXMvQG5nLXNlbGVjdC9uZy1zZWxlY3QvdGhlbWVzL2RlZmF1bHQudGhlbWUuY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGJhc2VcXF9udWxsLnNjc3MiLCJzcmMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcYmFzZVxcX2Jhc2Uuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxiYXNlXFxfdGhlbWUuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxsYXlvdXRcXF9tYWluLnNjc3MiLCJzcmMvRDpcXFByb2plY3RzXFx6YW5vXFxzcmNcXGd1aVxccXQtZGFlbW9uXFxodG1sX3NvdXJjZS9zcmNcXGFzc2V0c1xcc2Nzc1xcbGF5b3V0XFxfc2lkZWJhci5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGxheW91dFxcX3dhbGxldC5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXGxheW91dFxcX2NvbnRhY3Quc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfaGVhZC5zY3NzIiwic3JjL0Q6XFxQcm9qZWN0c1xcemFub1xcc3JjXFxndWlcXHF0LWRhZW1vblxcaHRtbF9zb3VyY2Uvc3JjXFxhc3NldHNcXHNjc3NcXG1vZHVsZXNcXF9zY3JvbGwuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcYXNzZXRzXFxzY3NzXFxtb2R1bGVzXFxfdGFibGUuc2NzcyIsInNyYy9EOlxcUHJvamVjdHNcXHphbm9cXHNyY1xcZ3VpXFxxdC1kYWVtb25cXGh0bWxfc291cmNlL3NyY1xcc3R5bGVzLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBOEVBOztDQzVFQztBQ0ZELGlEQUFpRCxlQUFlLENBQUMsaUNBQWlDO0FBQUMsdURBQXVELGVBQWU7QUFBQywyREFBMkQsUUFBUSxDQUFDLHlDQUF5QyxDQUFDLHNCQUFzQjtBQUFDLGlFQUFpRSx5Q0FBeUM7QUFBQyxrRUFBa0UsNEJBQTRCLENBQUMsMkJBQTJCO0FBQUMsK0RBQStELHlCQUF5QixDQUFDLHdCQUF3QjtBQUFDLHlFQUF5RSxvQkFBb0IsQ0FBQywwRUFBMEU7QUFBQyxtREFBbUQsd0JBQXdCO0FBQUMseUNBQXlDLFlBQVk7QUFBQyxnQ0FBZ0MscUJBQXFCLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsZUFBZSxDQUFDLGtCQUFrQjtBQUFDLHNDQUFzQyxtQ0FBbUM7QUFBQyxvREFBb0Qsa0JBQWtCLENBQUMsaUJBQWlCO0FBQUMsZ0VBQWdFLGtCQUFrQixDQUFDLGNBQWM7QUFBQyxvRUFBb0UsVUFBVTtBQUFDLGlEQUFpRCxXQUFXO0FBQUMsK0VBQStFLE9BQU8sQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCO0FBQUMsMkZBQTJGLGtCQUFrQixDQUFDLGlCQUFpQjtBQUFDLG9HQUFvRyx3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SUkzQ0kseUJDb0M2QixFQUFBO0FMT2pDO0lJM0NJLHlCQzRGNkIsRUFBQTtBTGpEakM7SUluQ0UseUJDakNnQztJRGtDaEMsY0N4QzJCLEVBQUE7QUwwRTdCO0lJbkNFLHlCQ3VCZ0M7SUR0QmhDLGNDZ0IyQixFQUFBO0FMa0I3QjtJSW5DRSx5QkMrRWdDO0lEOUVoQyxjQ3dFMkIsRUFBQTtBTHRDN0I7SUk1QkkseUJDdkN5QixFQUFBO0FMbUU3QjtJSTVCSSx5QkNpQnlCLEVBQUE7QUxXN0I7SUk1QkkseUJDeUV5QixFQUFBO0FMN0M3QjtJSXJCSSx5QkM3Q3lCLEVBQUE7QUxrRTdCO0lJckJJLHlCQ1d5QixFQUFBO0FMVTdCO0lJckJJLHlCQ21FeUIsRUFBQTtBTDlDN0I7SUliRSx5QkNqRGlDO0lEa0RqQyxjQzlEMkIsRUFBQTtBTDBFN0I7SUliRSx5QkNPaUM7SUROakMsY0NOMkIsRUFBQTtBTGtCN0I7SUliRSx5QkMrRGlDO0lEOURqQyxjQ2tEMkIsRUFBQTtBTHRDN0I7SUlOSSx5QkN2RDBCLEVBQUE7QUw2RDlCO0lJTkkseUJDQzBCLEVBQUE7QUxLOUI7SUlOSSx5QkN5RDBCLEVBQUE7QUxuRDlCO0lJQ0kseUJDN0QwQixFQUFBO0FMNEQ5QjtJSUNJLHlCQ0wwQixFQUFBO0FMSTlCO0lJQ0kseUJDbUQwQixFQUFBO0FMcEQ5QjtJSVNFLHlCQ3BFcUM7SURxRXJDLGNDcEYyQixFQUFBO0FMMEU3QjtJSVNFLHlCQ1pxQztJRGFyQyxjQzVCMkIsRUFBQTtBTGtCN0I7SUlTRSx5QkM0Q3FDO0lEM0NyQyxjQzRCMkIsRUFBQTtBTHRDN0I7SUlnQkkseUJDMUU4QixFQUFBO0FMMERsQztJSWdCSSx5QkNsQjhCLEVBQUE7QUxFbEM7SUlnQkkseUJDc0M4QixFQUFBO0FMdERsQztJSXVCSSx5QkNoRjhCLEVBQUE7QUx5RGxDO0lJdUJJLHlCQ3hCOEIsRUFBQTtBTENsQztJSXVCSSx5QkNnQzhCLEVBQUE7QUQ3SHRDO0lBbUdJLGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsdUJBQXVCLEVBQUE7QUovQnZC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LGNDcnNCb0IsRUFBQTtBTG1CdEI7SUlrckJFLGNDN29Cb0IsRUFBQTtBTHJDdEI7SUl3ckJJLHlCQzV0QjJCO0lENnRCM0IsY0Nwd0JrQixFQUFBO0FMMkV0QjtJSXdyQkkseUJDcHFCMkI7SURxcUIzQixjQzVzQmtCLEVBQUE7QUxtQnRCO0lJd3JCSSx5QkM1bUIyQjtJRDZtQjNCLGNDcHBCa0IsRUFBQTtBRDBwQjFCO0VBR0ksV0FBVyxFQUFBO0FBSGY7SUFTWSxtQkFBbUIsRUFBQTtBQVQvQjtJQWdCTSxZQUFZO0lBQ1osZ0JBQWdCO0lBQ2hCLGVBQWU7SUFDZixpQkFBaUI7SUFDakIsYUFBYTtJQUNiLGVBQWU7SUFDZixjQUFjLEVBQUE7QUpydEJoQjtNSXd0QkkseUJDL3dCeUI7TURneEJ6QixjQ3B5QmtCLEVBQUE7QUwyRXRCO01Jd3RCSSx5QkN2dEJ5QjtNRHd0QnpCLGNDNXVCa0IsRUFBQTtBTG1CdEI7TUl3dEJJLHlCQy9wQnlCO01EZ3FCekIsY0NwckJrQixFQUFBO0FEMHBCMUI7TUE4QlEsVUFBVSxFQUFBO0FBOUJsQjtRQWlDVSxTQUFTLEVBQUE7QUFqQ25CO0lBdUNNLFlBQVksRUFBQTtBSnR1QmQ7TUl5dUJJLHlCQ2h5QnlCLEVBQUE7QUx1RDdCO01JeXVCSSx5QkN4dUJ5QixFQUFBO0FMRDdCO01JeXVCSSx5QkNockJ5QixFQUFBO0FEc29CakM7TUFnRFUsaUJBQWlCO01BQ2pCLGFBQWEsRUFBQTtBSmh2Qm5CO1FJbXZCUSx5QkMxeUJxQjtRRDJ5QnJCLGNDL3pCYyxFQUFBO0FMMkV0QjtRSW12QlEseUJDbHZCcUI7UURtdkJyQixjQ3Z3QmMsRUFBQTtBTG1CdEI7UUltdkJRLHlCQzFyQnFCO1FEMnJCckIsY0Mvc0JjLEVBQUE7QUxyQ3RCO1FJMHZCVSx1Q0NoekI2QjtRRGl6QjdCLGNDdDBCWSxFQUFBO0FMMkV0QjtRSTB2QlUsdUNDeHZCNkI7UUR5dkI3QixjQzl3QlksRUFBQTtBTG1CdEI7UUkwdkJVLDBDQ2hzQmdDO1FEaXNCaEMsY0N0dEJZLEVBQUE7QUxyQ3RCO1FJa3dCVSx1Q0N2ekJnQztRRHd6QmhDLGNDOTBCWSxFQUFBO0FMMkV0QjtRSWt3QlUsdUNDL3ZCZ0M7UURnd0JoQyxjQ3R4QlksRUFBQTtBTG1CdEI7UUlrd0JVLDBDQ3ZzQm1DO1FEd3NCbkMsY0M5dEJZLEVBQUE7QUQwcEIxQjtNQTBFVSw2QkFBNkI7TUFDN0IsZUFBZTtNQUNmLFdBQVc7TUFDWCxZQUFZLEVBQUE7QUE3RXRCO01BaUZVLHVCQUF1QixFQUFBO0FBakZqQztNQXFGVSx5QkFBeUI7TUFDekIsNEJBQTRCO01BQzVCLGlDQUFpQztNQUNqQyxxQkFBcUIsRUFBQTtBQXhGL0I7TUE0RlUseUJBQXlCLEVBQUE7QUozeEIvQjtFSXV5QkUsc0NDcDBCMEQ7RURxMEIxRCxjQ24zQm9CLEVBQUE7QUwyRXRCO0VJdXlCRSxzQ0M1d0IwRDtFRDZ3QjFELGNDM3pCb0IsRUFBQTtBTG1CdEI7RUl1eUJFLHVDQ3B0QjJEO0VEcXRCM0QsY0Nud0JvQixFQUFBO0FMckN0QjtFSWd6Qk0seUJDcjNCZSxFQUFBO0FMcUVyQjtFSWd6Qk0seUJDN3pCZSxFQUFBO0FMYXJCO0VJZ3pCTSx5QkNyd0JlLEVBQUE7QUwzQ3JCO0VJdXpCTSx5QkM5M0JpQixFQUFBO0FMdUV2QjtFSXV6Qk0seUJDdDBCaUIsRUFBQTtBTGV2QjtFSXV6Qk0seUJDOXdCaUIsRUFBQTtBTHpDdkI7RUk4ekJNLHlCQ3Q0QmdCLEVBQUE7QUx3RXRCO0VJOHpCTSx5QkM5MEJnQixFQUFBO0FMZ0J0QjtFSTh6Qk0seUJDdHhCZ0IsRUFBQTtBTHhDdEI7RUlzMEJJLHlCQzk0QmtCO0VEKzRCbEIsY0NqNUJ5QixFQUFBO0FMMEU3QjtFSXMwQkkseUJDdDFCa0I7RUR1MUJsQixjQ3oxQnlCLEVBQUE7QUxrQjdCO0VJczBCSSx5QkM5eEJrQjtFRCt4QmxCLGNDanlCeUIsRUFBQTtBTHRDN0I7RUlnMUJNLHlCQzUyQm1CLEVBQUE7QUw0QnpCO0VJZzFCTSx5QkNwekJtQixFQUFBO0FMNUJ6QjtFSWcxQk0seUJDNXZCbUIsRUFBQTtBTHBGekI7RUk0MUJFLGdDQ3A1Qm1DLEVBQUE7QUx3RHJDO0VJNDFCRSxnQ0M1MUJtQyxFQUFBO0FMQXJDO0VJNDFCRSxnQ0NweUJtQyxFQUFBO0FMeERyQztFSXMyQlEsY0MvNkJrQixFQUFBO0FMeUUxQjtFSXMyQlEsY0N2M0JrQixFQUFBO0FMaUIxQjtFSXMyQlEsY0MvekJrQixFQUFBO0FMdkMxQjtFSTYyQlEsY0N4N0JjLEVBQUE7QUwyRXRCO0VJNjJCUSxjQ2g0QmMsRUFBQTtBTG1CdEI7RUk2MkJRLGNDeDBCYyxFQUFBO0FMckN0QjtFSW8zQlEsY0M1N0JjLEVBQUE7QUx3RXRCO0VJbzNCUSxjQ3A0QmMsRUFBQTtBTGdCdEI7RUlvM0JRLGNDNTBCYyxFQUFBO0FMeEN0QjtFSWk0QkUsY0M1OEJvQixFQUFBO0FMMkV0QjtFSWk0QkUsY0NwNUJvQixFQUFBO0FMbUJ0QjtFSWk0QkUsY0M1MUJvQixFQUFBO0FMckN0QjtFSXU0QkkseUJDOTZCK0IsRUFBQTtBTHVDbkM7RUl1NEJJLHlCQ3QzQitCLEVBQUE7QUxqQm5DO0VJdTRCSSx5QkM5ekIrQixFQUFBO0FMekVuQztFSTY0Qk0seUJDbjdCaUMsRUFBQTtBTHNDdkM7RUk2NEJNLHlCQzMzQmlDLEVBQUE7QUxsQnZDO0VJNjRCTSx5QkNuMEJpQyxFQUFBO0FMMUV2QztFSXk1QkUsc0NDdDdCMEQ7RUR1N0IxRCxjQ3IrQm9CLEVBQUE7QUwyRXRCO0VJeTVCRSxzQ0M5M0IwRDtFRCszQjFELGNDNzZCb0IsRUFBQTtBTG1CdEI7RUl5NUJFLHVDQ3QwQjJEO0VEdTBCM0QsY0NyM0JvQixFQUFBO0FMckN0QjtFSW02QkUsc0NDaDhCMEQ7RURpOEIxRCxjQy8rQm9CLEVBQUE7QUwyRXRCO0VJbTZCRSxzQ0N4NEIwRDtFRHk0QjFELGNDdjdCb0IsRUFBQTtBTG1CdEI7RUltNkJFLHVDQ2gxQjJEO0VEaTFCM0QsY0MvM0JvQixFQUFBO0FMckN0QjtFSTA2QkksbUNDbCtCaUMsRUFBQTtBTHdEckM7RUkwNkJJLG1DQzE2QmlDLEVBQUE7QUxBckM7RUkwNkJJLG1DQ2wzQmlDLEVBQUE7QUx4RHJDO0VJazdCSSx5QkMxL0JrQjtFRDIvQmxCLGNDNy9CeUIsRUFBQTtBTDBFN0I7RUlrN0JJLHlCQ2w4QmtCO0VEbThCbEIsY0NyOEJ5QixFQUFBO0FMa0I3QjtFSWs3QkkseUJDMTRCa0I7RUQyNEJsQixjQzc0QnlCLEVBQUE7QUN6SGpDO0VBQ0UsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUhsQjtJQU1JLGtCQUFrQjtJQUNsQixhQUFhO0lBQ2IsZ0JBQWdCLEVBQUE7QU4yRWhCO01NeEVFLHVDREoyQztNQ0szQyxjREpvQixFQUFBO0FMMkV0QjtNTXhFRSx1Q0RvRDJDO01DbkQzQyxjRG9Eb0IsRUFBQTtBTG1CdEI7TU14RUUsMENENEc4QztNQzNHOUMsY0Q0R29CLEVBQUE7QUN4SDFCO01BZ0JNLGtCQUFrQjtNQUNsQixNQUFNO01BQ04sT0FBTyxFQUFBO0FOaUVUO0VNbkRNLGNEckJnQixFQUFBO0FMd0V0QjtFTW5ETSxjRG1DZ0IsRUFBQTtBTGdCdEI7RU1uRE0sY0QyRmdCLEVBQUE7QUx4Q3RCO0VNN0NRLHlCRDNCYyxFQUFBO0FMd0V0QjtFTTdDUSx5QkQ2QmMsRUFBQTtBTGdCdEI7RU03Q1EseUJEcUZjLEVBQUE7QUx4Q3RCO0VNaENFLHlCRHZCMkI7RUN3QjNCLGNENUNvQixFQUFBO0FMMkV0QjtFTWhDRSx5QkRpQzJCO0VDaEMzQixjRFlvQixFQUFBO0FMbUJ0QjtFTWhDRSx5QkR5RjJCO0VDeEYzQixjRG9Fb0IsRUFBQTtBTHJDdEI7RU1yQkUseUJEbEMyQixFQUFBO0FMdUQ3QjtFTXJCRSx5QkRzQjJCLEVBQUE7QUxEN0I7RU1yQkUseUJEOEUyQixFQUFBO0FDekVqQztFQUdJLFlBQVk7RUFDWixnQkFBZ0I7RUFDaEIsYUFBYTtFQUNiLDhCQUE4QjtFQUM5QixzQkFBc0IsRUFBQTtBTlN0QjtJTUpJLGNEckVzQixFQUFBO0FMeUUxQjtJTUpJLGNEYnNCLEVBQUE7QUxpQjFCO0lNSkksY0QyQ3NCLEVBQUE7QUx2QzFCO0lNS00sdUNEakQyQyxFQUFBO0FMNENqRDtJTUtNLHVDRE8yQyxFQUFBO0FMWmpEO0lNS00sMENEK0Q4QyxFQUFBO0FMcEVwRDtJTVdRLGNEcEZrQixFQUFBO0FMeUUxQjtJTVdRLGNENUJrQixFQUFBO0FMaUIxQjtJTVdRLGNENEJrQixFQUFBO0FMdkMxQjtJTWtCUSx5QkQxRmMsRUFBQTtBTHdFdEI7SU1rQlEseUJEbENjLEVBQUE7QUxnQnRCO0lNa0JRLHlCRHNCYyxFQUFBO0FMeEN0QjtJTXdCVSxjRGhHWSxFQUFBO0FMd0V0QjtJTXdCVSxjRHhDWSxFQUFBO0FMZ0J0QjtJTXdCVSxjRGdCWSxFQUFBO0FDUDFCO0VBQ0Usa0JBQWtCLEVBQUE7QU5sQ2hCO0VPaEZBLHlCRkEyQyxFQUFBO0FMZ0YzQztFT2hGQSx5QkZ3RDJDLEVBQUE7QUx3QjNDO0VPaEZBLHVCRmdIOEMsRUFBQTtBTGhDOUM7RU90RU0sY0ZMZ0IsRUFBQTtBTDJFdEI7RU90RU0sY0ZtRGdCLEVBQUE7QUxtQnRCO0VPdEVNLGNGMkdnQixFQUFBO0FMckN0QjtFTy9ETSxjRlRnQixFQUFBO0FMd0V0QjtFTy9ETSxjRitDZ0IsRUFBQTtBTGdCdEI7RU8vRE0sY0Z1R2dCLEVBQUE7QUx4Q3RCO0VPckRNLDZCQUE2QjtFQUM3QixjRnZCZ0IsRUFBQTtBTDJFdEI7RU9yRE0sNkJBQTZCO0VBQzdCLGNGaUNnQixFQUFBO0FMbUJ0QjtFT3JETSw2QkFBNkI7RUFDN0IsY0Z5RmdCLEVBQUE7QUxyQ3RCO0VPNUNVLGNGN0JnQixFQUFBO0FMeUUxQjtFTzVDVSxjRjJCZ0IsRUFBQTtBTGlCMUI7RU81Q1UsY0ZtRmdCLEVBQUE7QUx2QzFCO0VPckNVLHlCRm5DWSxFQUFBO0FMd0V0QjtFT3JDVSx5QkZxQlksRUFBQTtBTGdCdEI7RU9yQ1UseUJGNkVZLEVBQUE7QUx4Q3RCO0VPOUJVLHlCRnRDd0I7RUV1Q3hCLGNGN0NtQixFQUFBO0FMMEU3QjtFTzlCVSx5QkZrQndCO0VFakJ4QixjRldtQixFQUFBO0FMa0I3QjtFTzlCVSx5QkYwRXdCO0VFekV4QixjRm1FbUIsRUFBQTtBTHRDN0I7RU9wQlkseUJGbkJ1QixFQUFBO0FMdUNuQztFT3BCWSx5QkZxQ3VCLEVBQUE7QUxqQm5DO0VPcEJZLHlCRjZGdUIsRUFBQTtBTHpFbkM7RU9kYyx5QkYxRFEsRUFBQTtBTHdFdEI7RU9kYyx5QkZGUSxFQUFBO0FMZ0J0QjtFT2RjLHlCRnNEUSxFQUFBO0FMeEN0QjtFT0xVLGNGcEVnQixFQUFBO0FMeUUxQjtFT0xVLGNGWmdCLEVBQUE7QUxpQjFCO0VPTFUsY0Y0Q2dCLEVBQUE7QUx2QzFCO0VPR1EsdUNGdERxQztFRXVEckMsY0ZyRHFCLEVBQUE7QUxpRDdCO0VPR1EsdUNGRXFDO0VFRHJDLGNGR3FCLEVBQUE7QUxQN0I7RU9HUSx5QkYwRHFDO0VFekRyQyxjRjJEcUIsRUFBQTtBTC9EN0I7RU9ZWSxjRjVEcUIsRUFBQTtBTGdEakM7RU9ZWSxjRkpxQixFQUFBO0FMUmpDO0VPWVksY0ZvRHFCLEVBQUE7QUxoRWpDO0VPbUJZLHlCRmhFNEI7RUVpRTVCLGNGbkVzQixFQUFBO0FMK0NsQztFT21CWSx5QkZSNEI7RUVTNUIsY0ZYc0IsRUFBQTtBTFRsQztFT21CWSx5QkZnRDRCO0VFL0M1QixjRjZDc0IsRUFBQTtBTGpFbEM7RU8yQlkseUJGekV5QjtFRTBFekIsY0Z2R1UsRUFBQTtBTDJFdEI7RU8yQlkseUJGakJ5QjtFRWtCekIsY0YvQ1UsRUFBQTtBTG1CdEI7RU8yQlkseUJGdUN5QjtFRXRDekIsY0ZTVSxFQUFBO0FMckN0QjtFT21DWSxjRm5GcUIsRUFBQTtBTGdEakM7RU9tQ1ksY0YzQnFCLEVBQUE7QUxSakM7RU9tQ1ksY0Y2QnFCLEVBQUE7QUxoRWpDO0VPNENRLHVDRjlGMEMsRUFBQTtBTGtEbEQ7RU80Q1EsdUNGdEMwQyxFQUFBO0FMTmxEO0VPNENRLDBDRmtCNkMsRUFBQTtBTDlEckQ7RU9xREksb0VBQTJGLEVBQUE7QVByRC9GO0VPcURJLG9FQUEyRixFQUFBO0FQckQvRjtFT3FESSxrRUFBMkYsRUFBQTtBUHJEL0Y7RU82REUsbUNGNUl5QixFQUFBO0FMK0UzQjtFTzZERSxtQ0ZwRnlCLEVBQUE7QUx1QjNCO0VPNkRFLG1DRjVCeUIsRUFBQTtBTGpDM0I7RU9xRU0sY0ZoSmdCLEVBQUE7QUwyRXRCO0VPcUVNLGNGeEZnQixFQUFBO0FMbUJ0QjtFT3FFTSxjRmhDZ0IsRUFBQTtBTHJDdEI7RU8yRVEseUJGbkpjLEVBQUE7QUx3RXRCO0VPMkVRLHlCRjNGYyxFQUFBO0FMZ0J0QjtFTzJFUSx5QkZuQ2MsRUFBQTtBTHhDdEI7RU9xRlEsa0RBQTBEO0VBQzFELHlCQUE2QyxFQUFBO0FQdEZyRDtFT3FGUSxrREFBMEQ7RUFDMUQseUJBQTZDLEVBQUE7QVB0RnJEO0VPcUZRLG9DQUEwRDtFQUMxRCx5QkFBNkMsRUFBQTtBUHRGckQ7RU80RlUsb0NBQW1FLEVBQUE7QVA1RjdFO0VPNEZVLG9DQUFtRSxFQUFBO0FQNUY3RTtFTzRGVSxvQ0FBbUUsRUFBQTtBUDVGN0U7RU91R0UsY0ZoTHdCLEVBQUE7QUx5RTFCO0VPdUdFLGNGeEh3QixFQUFBO0FMaUIxQjtFT3VHRSxjRmhFd0IsRUFBQTtBTHZDMUI7RU8rR00seUJGNUxlLEVBQUE7QUw2RXJCO0VPK0dNLHlCRnBJZSxFQUFBO0FMcUJyQjtFTytHTSx5QkY1RWUsRUFBQTtBTG5DckI7RU9zSE0seUJGcE1jLEVBQUE7QUw4RXBCO0VPc0hNLHlCRjVJYyxFQUFBO0FMc0JwQjtFT3NITSx5QkZwRmMsRUFBQTtBTGxDcEI7RU9pSVUseUJGeEt5QixFQUFBO0FMdUNuQztFT2lJVSx5QkZoSHlCLEVBQUE7QUxqQm5DO0VPaUlVLHlCRnhEeUIsRUFBQTtBTHpFbkM7RU91SVkseUJGN0syQixFQUFBO0FMc0N2QztFT3VJWSx5QkZySDJCLEVBQUE7QUxsQnZDO0VPdUlZLHlCRjdEMkIsRUFBQTtBTDFFdkM7RU9nSlEseUJGdEwrQixFQUFBO0FMc0N2QztFT2dKUSx5QkY5SCtCLEVBQUE7QUxsQnZDO0VPZ0pRLHlCRnRFK0IsRUFBQTtBTDFFdkM7RU8ySk0sY0ZuT2dCLEVBQUE7QUx3RXRCO0VPMkpNLGNGM0tnQixFQUFBO0FMZ0J0QjtFTzJKTSxjRm5IZ0IsRUFBQTtBTHhDdEI7RU9rS00sY0Z4T2tCLEVBQUE7QUxzRXhCO0VPa0tNLGNGaExrQixFQUFBO0FMY3hCO0VPa0tNLGNGeEhrQixFQUFBO0FMMUN4QjtFT3lLTSxjRjlPZSxFQUFBO0FMcUVyQjtFT3lLTSxjRnRMZSxFQUFBO0FMYXJCO0VPeUtNLGNGOUhlLEVBQUE7QUwzQ3JCO0VPZ0xNLGNGdFBrQixFQUFBO0FMc0V4QjtFT2dMTSxjRjlMa0IsRUFBQTtBTGN4QjtFT2dMTSxjRnRJa0IsRUFBQTtBTDFDeEI7RU95TFEseUJGalFjLEVBQUE7QUx3RXRCO0VPeUxRLHlCRnpNYyxFQUFBO0FMZ0J0QjtFT3lMUSx5QkZqSmMsRUFBQTtBTHhDdEI7RU9nTVEseUJGdFFnQixFQUFBO0FMc0V4QjtFT2dNUSx5QkY5TWdCLEVBQUE7QUxjeEI7RU9nTVEseUJGdEpnQixFQUFBO0FMMUN4QjtFT3VNUSx5QkY1UWEsRUFBQTtBTHFFckI7RU91TVEseUJGcE5hLEVBQUE7QUxhckI7RU91TVEseUJGNUphLEVBQUE7QUwzQ3JCO0VPOE1RLHlCRnBSZ0IsRUFBQTtBTHNFeEI7RU84TVEseUJGNU5nQixFQUFBO0FMY3hCO0VPOE1RLHlCRnBLZ0IsRUFBQTtBTDFDeEI7RVFoRkEsY0hLc0IsRUFBQTtBTDJFdEI7RVFoRkEsY0g2RHNCLEVBQUE7QUxtQnRCO0VRaEZBLGNIcUhzQixFQUFBO0FMckN0QjtFUXhFSSxjSEhrQixFQUFBO0FMMkV0QjtFUXhFSSxjSHFEa0IsRUFBQTtBTG1CdEI7RVF4RUksY0g2R2tCLEVBQUE7QUxyQ3RCO0VRbEVNLHlCSE5nQixFQUFBO0FMd0V0QjtFUWxFTSx5QkhrRGdCLEVBQUE7QUxnQnRCO0VRbEVNLHlCSDBHZ0IsRUFBQTtBTHhDdEI7RVF4RE0seUJIaEJnQixFQUFBO0FMd0V0QjtFUXhETSx5Qkh3Q2dCLEVBQUE7QUxnQnRCO0VReERNLHlCSGdHZ0IsRUFBQTtBTHhDdEI7RVEvQ0UsY0h6Qm9CLEVBQUE7QUx3RXRCO0VRL0NFLGNIK0JvQixFQUFBO0FMZ0J0QjtFUS9DRSxjSHVGb0IsRUFBQTtBTHhDdEI7RVF6Q0kseUJIL0JrQixFQUFBO0FMd0V0QjtFUXpDSSx5Qkh5QmtCLEVBQUE7QUxnQnRCO0VRekNJLHlCSGlGa0IsRUFBQTtBTHhDdEI7RVE3Qk0sdUNIZjJDLEVBQUE7QUw0Q2pEO0VRN0JNLHVDSHlDMkMsRUFBQTtBTFpqRDtFUTdCTSwwQ0hpRzhDLEVBQUE7QUxwRXBEO0VRdkJRLHlCSGpEYyxFQUFBO0FMd0V0QjtFUXZCUSx5QkhPYyxFQUFBO0FMZ0J0QjtFUXZCUSx5QkgrRGMsRUFBQTtBTHhDdEI7RVFoQlEseUJIN0JnQztFRzhCaEMsY0hoQzBCLEVBQUE7QUwrQ2xDO0VRaEJRLHlCSDJCZ0M7RUcxQmhDLGNId0IwQixFQUFBO0FMVGxDO0VRaEJRLHlCSG1GZ0M7RUdsRmhDLGNIZ0YwQixFQUFBO0FMakVsQztFUVJRLHVDSHBFcUMsRUFBQTtBTDRFN0M7RVFSUSx1Q0hacUMsRUFBQTtBTG9CN0M7RVFSUSwwQ0g0Q3dDLEVBQUE7QUxwQ2hEO0VRRFEsdUNIMUNzQyxFQUFBO0FMMkM5QztFUURRLHVDSGNzQyxFQUFBO0FMYjlDO0VRRFEseUJIc0V3QixFQUFBO0FMckVoQztFUVFJLHVDSHBGeUMsRUFBQTtBTDRFN0M7RVFRSSx1Q0g1QnlDLEVBQUE7QUxvQjdDO0VRUUksMENINEI0QyxFQUFBO0FMcENoRDtFUXFCSSxjSGhHa0IsRUFBQTtBTDJFdEI7RVFxQkksY0h4Q2tCLEVBQUE7QUxtQnRCO0VRcUJJLGNIZ0JrQixFQUFBO0FMckN0QjtFUTJCTSx5QkhuR2dCLEVBQUE7QUx3RXRCO0VRMkJNLHlCSDNDZ0IsRUFBQTtBTGdCdEI7RVEyQk0seUJIYWdCLEVBQUE7QUx4Q3RCO0VRbUNJLDRCSDNGaUMsRUFBQTtBTHdEckM7RVFtQ0ksNEJIbkNpQyxFQUFBO0FMQXJDO0VRbUNJLDRCSHFCaUMsRUFBQTtBTHhEckM7RVE4Q0UseUJIdEhvQixFQUFBO0FMd0V0QjtFUThDRSx5Qkg5RG9CLEVBQUE7QUxnQnRCO0VROENFLHlCSE5vQixFQUFBO0FMeEN0QjtFUThEUSxjSHZJa0IsRUFBQTtBTHlFMUI7RVE4RFEsY0gvRWtCLEVBQUE7QUxpQjFCO0VROERRLGNIdkJrQixFQUFBO0FMdkMxQjtFUXFFUSx5QkgvR3FCLEVBQUE7QUwwQzdCO0VRcUVRLHlCSHZEcUIsRUFBQTtBTGQ3QjtFUXFFUSx5QkhDcUIsRUFBQTtBTHRFN0I7RVE0RVEseUJIdEhxQixFQUFBO0FMMEM3QjtFUTRFUSx5Qkg5RHFCLEVBQUE7QUxkN0I7RVE0RVEseUJITnFCLEVBQUE7QUx0RTdCO0VRbUZRLDZCQUE2QixFQUFBO0FSbkZyQztFUW1GUSw2QkFBNkIsRUFBQTtBUm5GckM7RVFtRlEsNkJBQTZCLEVBQUE7QVJuRnJDO0VRMEZRLDZCQUE2QixFQUFBO0FSMUZyQztFUTBGUSw2QkFBNkIsRUFBQTtBUjFGckM7RVEwRlEsNkJBQTZCLEVBQUE7QVIxRnJDO0VRbUdVLHlCSDFJeUIsRUFBQTtBTHVDbkM7RVFtR1UseUJIbEZ5QixFQUFBO0FMakJuQztFUW1HVSx5QkgxQnlCLEVBQUE7QUx6RW5DO0VReUdZLHlCSC9JMkIsRUFBQTtBTHNDdkM7RVF5R1kseUJIdkYyQixFQUFBO0FMbEJ2QztFUXlHWSx5QkgvQjJCLEVBQUE7QUwxRXZDO0VRa0hRLHlCSHhMZ0IsRUFBQTtBTHNFeEI7RVFrSFEseUJIaElnQixFQUFBO0FMY3hCO0VRa0hRLHlCSHhFZ0IsRUFBQTtBTDFDeEI7RVF5SFEseUJIak1jLEVBQUE7QUx3RXRCO0VReUhRLHlCSHpJYyxFQUFBO0FMZ0J0QjtFUXlIUSx5QkhqRmMsRUFBQTtBTHhDdEI7RVFrSVUseUJIdk1XLEVBQUE7QUxxRXJCO0VRa0lVLHlCSC9JVyxFQUFBO0FMYXJCO0VRa0lVLHlCSHZGVyxFQUFBO0FMM0NyQjtFUTRJVSx5QkhuTmEsRUFBQTtBTHVFdkI7RVE0SVUseUJIM0phLEVBQUE7QUxldkI7RVE0SVUseUJIbkdhLEVBQUE7QUx6Q3ZCO0VRZ0tRLHlCSHJPYSxFQUFBO0FMcUVyQjtFUWdLUSx5Qkg3S2EsRUFBQTtBTGFyQjtFUWdLUSx5QkhySGEsRUFBQTtBTDNDckI7RVF1S1EseUJIL09jLEVBQUE7QUx3RXRCO0VRdUtRLHlCSHZMYyxFQUFBO0FMZ0J0QjtFUXVLUSx5QkgvSGMsRUFBQTtBTHhDdEI7RVFzTEksY0hqUWtCLEVBQUE7QUwyRXRCO0VRc0xJLGNIek1rQixFQUFBO0FMbUJ0QjtFUXNMSSxjSGpKa0IsRUFBQTtBTHJDdEI7RVE0TE0seUJIcFFnQixFQUFBO0FMd0V0QjtFUTRMTSx5Qkg1TWdCLEVBQUE7QUxnQnRCO0VRNExNLHlCSHBKZ0IsRUFBQTtBTHhDdEI7RVFvTUksY0g1UWtCLEVBQUE7QUx3RXRCO0VRb01JLGNIcE5rQixFQUFBO0FMZ0J0QjtFUW9NSSxjSDVKa0IsRUFBQTtBTHhDdEI7RVEyTUksNEJIblFpQyxFQUFBO0FMd0RyQztFUTJNSSw0QkgzTWlDLEVBQUE7QUxBckM7RVEyTUksNEJIbkppQyxFQUFBO0FMeERyQztFUXFOSSx5Qkg1UCtCLEVBQUE7QUx1Q25DO0VRcU5JLHlCSHBNK0IsRUFBQTtBTGpCbkM7RVFxTkkseUJINUkrQixFQUFBO0FMekVuQztFUTJOTSx5QkhqUWlDLEVBQUE7QUxzQ3ZDO0VRMk5NLHlCSHpNaUMsRUFBQTtBTGxCdkM7RVEyTk0seUJIakppQyxFQUFBO0FHd0ozQztFUnBURSxnQkFBZ0I7RUFDaEIsdUJBQXVCO0VBQ3ZCLG1CQUFtQixFQUFBO0FBZ0ZqQjtFUW1QVSx5Qkh4VFcsRUFBQTtBTHFFckI7RVFtUFUseUJIaFFXLEVBQUE7QUxhckI7RVFtUFUseUJIeE1XLEVBQUE7QUwzQ3JCO0VRbVFJLGNIM1VrQixFQUFBO0FMd0V0QjtFUW1RSSxjSG5Sa0IsRUFBQTtBTGdCdEI7RVFtUUksY0gzTmtCLEVBQUE7QUx4Q3RCO0VRaVJRLGNIMVZrQixFQUFBO0FMeUUxQjtFUWlSUSxjSGxTa0IsRUFBQTtBTGlCMUI7RVFpUlEsY0gxT2tCLEVBQUE7QUx2QzFCO0VRd1JRLHlCSGpVeUIsRUFBQTtBTHlDakM7RVF3UlEseUJIelF5QixFQUFBO0FMZmpDO0VRd1JRLHNCSGpOc0IsRUFBQTtBR3FMbEM7RVJ0UUUsV0FEMEQ7RUFFMUQsY0FGNEI7RUFHNUIsa0JBSDRDO0VReVNsQyxNQUFNO0VBQ04sYUFBYTtFQUNiLGdDQUFnQyxFQUFBO0FSaFN4QztJUW1TVSx5Qkg1VXVCLEVBQUE7QUx5Q2pDO0lRbVNVLHlCSHBSdUIsRUFBQTtBTGZqQztJUW1TVSxzQkg1Tm9CLEVBQUE7QUx2RTlCO0VRMlNRLHlCSG5WNEIsRUFBQTtBTHdDcEM7RVEyU1EseUJIM1I0QixFQUFBO0FMaEJwQztFUTJTUSx5QkhuTzRCLEVBQUE7QUdvTHhDO0VSdFFFLFdBRDBEO0VBRTFELGNBRjRCO0VBRzVCLGtCQUg0QztFUTRUbEMsY0FBYztFQUNkLE1BQU07RUFDTixnQ0FBZ0MsRUFBQTtBUm5UeEM7SVFzVFUseUJIOVYwQixFQUFBO0FMd0NwQztJUXNUVSx5Qkh0UzBCLEVBQUE7QUxoQnBDO0lRc1RVLHlCSDlPMEIsRUFBQTtBTHhFcEM7RVF3VU0sY0hqWm9CLEVBQUE7QUx5RTFCO0VRd1VNLGNIelZvQixFQUFBO0FMaUIxQjtFUXdVTSxjSGpTb0IsRUFBQTtBTHZDMUI7RVErVU0sY0gxWmdCLEVBQUE7QUwyRXRCO0VRK1VNLGNIbFdnQixFQUFBO0FMbUJ0QjtFUStVTSxjSDFTZ0IsRUFBQTtBRzBSMUI7RUFzQk0sYUFBYTtFQUNiLG1CQUFtQjtFQUNuQix5QkFBeUI7RUFDekIsWUFBWTtFQUNaLGlCQUFpQixFQUFBO0FSelZuQjtFUWtXSSxjSDNhc0IsRUFBQTtBTHlFMUI7RVFrV0ksY0huWHNCLEVBQUE7QUxpQjFCO0VRa1dJLGNIM1RzQixFQUFBO0FMdkMxQjtFUTJXTSxjSHRiZ0I7RUd1YmhCLHlCSGpaOEIsRUFBQTtBTHFDcEM7RVEyV00sY0g5WGdCO0VHK1hoQix5Qkh6VjhCLEVBQUE7QUxuQnBDO0VRMldNLGNIdFVnQjtFR3VVaEIseUJIalM4QixFQUFBO0FMM0VwQztFUWtYUSx5Qkh0WnVCLEVBQUE7QUxvQy9CO0VRa1hRLHlCSDlWdUIsRUFBQTtBTHBCL0I7RVFrWFEseUJIdFN1QixFQUFBO0FHOFNuQztFQUNFLGtCQUFrQixFQUFBO0FBRHBCO0lBSUksa0JBQWtCO0lBQ2xCLFdBQVc7SUFDWCxpQkFBaUI7SUFDakIsY0FBYztJQUNkLFdBQVcsRUFBQTtBUmxZWDtNUXFZRSx5Qkg1YjJCO01HNmIzQixjSGpkb0IsRUFBQTtBTDJFdEI7TVFxWUUseUJIcFkyQjtNR3FZM0IsY0h6Wm9CLEVBQUE7QUxtQnRCO01RcVlFLHlCSDVVMkI7TUc2VTNCLGNIaldvQixFQUFBO0FHcVYxQjtNQWdCTSxpQkFBaUI7TUFDakIsYUFBYSxFQUFBO0FSM1lmO1FRK1lNLHVDSHJjaUMsRUFBQTtBTHNEdkM7UVErWU0sdUNIN1lpQyxFQUFBO0FMRnZDO1FRK1lNLDBDSHJWb0MsRUFBQTtBSTdJOUM7O0VBRUUsY0FBYztFQUNkLGFBQWE7RUFDYixnQkFBZ0IsRUFBQTtBQUpsQjs7SUFPSSxrQkFBa0I7SUFDbEIsYUFBYTtJQUNiLGdCQUFnQixFQUFBO0FUMEVoQjs7TVN2RUUsdUNKTDJDO01JTTNDLGNKTG9CLEVBQUE7QUwyRXRCOztNU3ZFRSx1Q0ptRDJDO01JbEQzQyxjSm1Eb0IsRUFBQTtBTG1CdEI7O01TdkVFLDBDSjJHOEM7TUkxRzlDLGNKMkdvQixFQUFBO0FJeEgxQjs7TUFpQk0sa0JBQWtCO01BQ2xCLE1BQU07TUFDTixPQUFPLEVBQUE7QVRnRVQ7RVNwRE0sY0pwQmdCLEVBQUE7QUx3RXRCO0VTcERNLGNKb0NnQixFQUFBO0FMZ0J0QjtFU3BETSxjSjRGZ0IsRUFBQTtBTHhDdEI7RVMzQ00seUJKN0JnQixFQUFBO0FMd0V0QjtFUzNDTSx5QkoyQmdCLEVBQUE7QUxnQnRCO0VTM0NNLHlCSm1GZ0IsRUFBQTtBTHhDdEI7RVNwQ00sY0p2Q2dCLEVBQUE7QUwyRXRCO0VTcENNLGNKaUJnQixFQUFBO0FMbUJ0QjtFU3BDTSxjSnlFZ0IsRUFBQTtBTHJDdEI7RVMzQkUsY0o3Q29CLEVBQUE7QUx3RXRCO0VTM0JFLGNKV29CLEVBQUE7QUxnQnRCO0VTM0JFLGNKbUVvQixFQUFBO0FMeEN0QjtFU3JCSSxjSm5Ea0IsRUFBQTtBTHdFdEI7RVNyQkksY0pLa0IsRUFBQTtB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QUFHbEI7RUFDRSxxQkFBcUI7RUFDckIsa0NBQWtEO0VBQ2xELGdCQUFnQixFQUFBO0FBSWxCO0VBQ0UsaUNBQWlDO0VBQ2pDLGVBQWUsRUFBQTtBQUdqQjtFQUNFLGlDQUFpQztFQUNqQyxpQkFBaUI7RUFDakIsWUFBWTtFQUNaLGFBQWEsRUFBQTtBQUpmO0lBT0ksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBUjFCO0lBWUksK0RBQTZFO0lBQzdFLHNCQUFzQixFQUFBO0FBYjFCO0lBaUJJLGdFQUE4RTtJQUM5RSxzQkFBc0IsRUFBQTtBQWxCMUI7SUFzQkksYUFBYTtJQUNiLFdBQVc7SUFDWCxZQUFZLEVBQUE7QUFJaEI7RUFLTSxzREFBeUQ7VUFBekQsOENBQXlELEVBQUEiLCJmaWxlIjoic3JjL3N0eWxlcy5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiQG1peGluIHRleHQtdHJ1bmNhdGUge1xyXG4gIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XHJcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcclxufVxyXG5AbWl4aW4gdGV4dFdyYXAge1xyXG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XHJcbiAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcclxuICB3b3JkLXdyYXA6IGJyZWFrLXdvcmQ7XHJcbiAgd29yZC1icmVhazogYnJlYWstYWxsO1xyXG4gIGxpbmUtYnJlYWs6IHN0cmljdDtcclxuICAtd2Via2l0LWh5cGhlbnM6IGF1dG87XHJcbiAgLW1zLWh5cGhlbnM6IGF1dG87XHJcbiAgaHlwaGVuczogYXV0bztcclxufVxyXG5AbWl4aW4gY292ZXJCb3gge1xyXG5cdHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuXHR0b3A6IDA7XHJcblx0bGVmdDogMDtcclxuXHR3aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IDEwMCU7XHJcbn1cclxuQG1peGluIGFicyAoJHRvcDogYXV0bywgJHJpZ2h0OiBhdXRvLCAkYm90dG9tOiBhdXRvLCAkbGVmdDogYXV0bykge1xyXG4gIHRvcDogJHRvcDtcclxuICByaWdodDogJHJpZ2h0O1xyXG4gIGJvdHRvbTogJGJvdHRvbTtcclxuICBsZWZ0OiAkbGVmdDtcclxuICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbn1cclxuQG1peGluIGNvdmVySW1nIHtcclxuXHRiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0O1xyXG5cdC13ZWJraXQtYmFja2dyb3VuZC1zaXplOiBjb3ZlcjtcclxuXHQtby1iYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG5cdGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcblx0YmFja2dyb3VuZC1wb3NpdGlvbjogNTAlIDUwJTtcclxufVxyXG5AbWl4aW4gdmFsaW5nQm94IHtcclxuXHRwb3NpdGlvbjogYWJzb2x1dGU7XHJcblx0dG9wOiAgNTAlO1xyXG5cdGxlZnQ6IDUwJTtcclxuXHR0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAtNTAlKTtcclxufVxyXG5AbWl4aW4gdW5TZWxlY3Qge1xyXG5cdC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcclxuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcclxuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xyXG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcclxuICB1c2VyLXNlbGVjdDogbm9uZTtcclxufVxyXG5AbWl4aW4gbWF4MTE5OSB7IC8vIG1ha2V0IDExNzFcclxuICBAbWVkaWEgKG1heC13aWR0aDogMTE5OXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDExNzAgeyAvLyBtYWtldHMgOTkyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExNzBweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtYXg5OTEgeyAvLyBtYWtldHMgNzYyXHJcbiAgQG1lZGlhIChtYXgtd2lkdGg6IDk5MXB4KSB7IEBjb250ZW50OyB9XHJcbn1cclxuQG1peGluIG1heDc2MSB7IC8vIG1ha2V0cyA1NzZcclxuICBAbWVkaWEgKG1heC13aWR0aDogNzYxcHgpIHsgQGNvbnRlbnQ7IH1cclxufVxyXG5AbWl4aW4gbWF4NTc1IHsgLy8gbWFrZXRzIDQwMFxyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA1NzVweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBtb2JpbGUge1xyXG4gIEBtZWRpYSAobWF4LXdpZHRoOiAzOTlweCkgeyBAY29udGVudDsgfVxyXG59XHJcbkBtaXhpbiBpY29DZW50ZXIge1xyXG4gICAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcclxuICAgIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlciBjZW50ZXI7XHJcbn1cclxuQG1peGluIHBzZXVkbyAoJGRpc3BsYXk6IGJsb2NrLCAkcG9zOiBhYnNvbHV0ZSwgJGNvbnRlbnQ6ICcnKXtcclxuICBjb250ZW50OiAkY29udGVudDtcclxuICBkaXNwbGF5OiAkZGlzcGxheTtcclxuICBwb3NpdGlvbjogJHBvcztcclxufVxyXG5cclxuLypcclxuKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGVtZXNcclxuKi9cclxuQG1peGluIHRoZW1pZnkoJHRoZW1lczogJHRoZW1lcykge1xyXG4gIEBlYWNoICR0aGVtZSwgJG1hcCBpbiAkdGhlbWVzIHtcclxuICAgIC50aGVtZS0jeyR0aGVtZX0gJiB7XHJcbiAgICAgICR0aGVtZS1tYXA6ICgpICFnbG9iYWw7XHJcbiAgICAgIEBlYWNoICRrZXksICRzdWJtYXAgaW4gJG1hcCB7XHJcbiAgICAgICAgJHZhbHVlOiBtYXAtZ2V0KG1hcC1nZXQoJHRoZW1lcywgJHRoZW1lKSwgJyN7JGtleX0nKTtcclxuICAgICAgICAkdGhlbWUtbWFwOiBtYXAtbWVyZ2UoJHRoZW1lLW1hcCwgKCRrZXk6ICR2YWx1ZSkpICFnbG9iYWw7XHJcbiAgICAgIH1cclxuICAgICAgQGNvbnRlbnQ7XHJcbiAgICAgICR0aGVtZS1tYXA6IG51bGwgIWdsb2JhbDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbkBmdW5jdGlvbiB0aGVtZWQoJGtleSkge1xyXG4gIEByZXR1cm4gbWFwLWdldCgkdGhlbWUtbWFwLCAka2V5KTtcclxufVxyXG4iLCIvKlxyXG4qIEltcGxlbWVudGF0aW9uIG9mIHRoZW1lc1xyXG4qL1xuQGltcG9ydCB1cmwofkBuZy1zZWxlY3Qvbmctc2VsZWN0L3RoZW1lcy9kZWZhdWx0LnRoZW1lLmNzcyk7XG5odG1sIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7IH1cblxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xuICBib3gtc2l6aW5nOiBpbmhlcml0O1xuICAtd2Via2l0LWJveC1zaXppbmc6IGluaGVyaXQ7XG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcbiAgbWFyZ2luOiAwO1xuICBwYWRkaW5nOiAwO1xuICAtd2Via2l0LXRvdWNoLWNvbGxvdXQ6IG5vbmU7XG4gIC13ZWJraXQtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1raHRtbC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1vei11c2VyLXNlbGVjdDogbm9uZTtcbiAgLW1zLXVzZXItc2VsZWN0OiBub25lO1xuICB1c2VyLXNlbGVjdDogbm9uZTsgfVxuXG5odG1sLCBib2R5LCBkaXYsIHNwYW4sIGFwcGxldCwgb2JqZWN0LCBpZnJhbWUsXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXG5hLCBhYmJyLCBhY3JvbnltLCBhZGRyZXNzLCBiaWcsIGNpdGUsIGNvZGUsXG5kZWwsIGRmbiwgZW0sIGltZywgaW5zLCBrYmQsIHEsIHMsIHNhbXAsXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxuYiwgdSwgaSwgY2VudGVyLFxuZGwsIGR0LCBkZCwgb2wsIHVsLCBsaSxcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxudGFibGUsIGNhcHRpb24sIHRib2R5LCB0Zm9vdCwgdGhlYWQsIHRyLCB0aCwgdGQsXG5hcnRpY2xlLCBhc2lkZSwgY2FudmFzLCBkZXRhaWxzLCBlbWJlZCxcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcbm1lbnUsIG5hdiwgb3V0cHV0LCBydWJ5LCBzZWN0aW9uLCBzdW1tYXJ5LFxudGltZSwgbWFyaywgYXVkaW8sIHZpZGVvIHtcbiAgYm9yZGVyOiAwO1xuICBmb250LXNpemU6IDEwMCU7XG4gIGZvbnQ6IGluaGVyaXQ7XG4gIHZlcnRpY2FsLWFsaWduOiBiYXNlbGluZTsgfVxuXG5hcnRpY2xlLCBhc2lkZSwgZGV0YWlscywgZmlnY2FwdGlvbiwgZmlndXJlLFxuZm9vdGVyLCBoZWFkZXIsIGhncm91cCwgbWVudSwgbmF2LCBzZWN0aW9uIHtcbiAgZGlzcGxheTogYmxvY2s7IH1cblxuYm9keSB7XG4gIGxpbmUtaGVpZ2h0OiAxO1xuICBmb250LXN0eWxlOiBub3JtYWw7IH1cblxub2wsIHVsIHtcbiAgbGlzdC1zdHlsZTogbm9uZTsgfVxuXG5ibG9ja3F1b3RlLCBxIHtcbiAgcXVvdGVzOiBub25lOyB9XG5cbmJsb2NrcXVvdGU6YmVmb3JlLCBibG9ja3F1b3RlOmFmdGVyLFxucTpiZWZvcmUsIHE6YWZ0ZXIge1xuICBjb250ZW50OiBub25lOyB9XG5cbnRhYmxlIHtcbiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcbiAgYm9yZGVyLXNwYWNpbmc6IDA7IH1cblxudGQsXG50aCB7XG4gIHBhZGRpbmc6IDA7IH1cblxuaW5wdXQge1xuICBvdXRsaW5lOiBub25lOyB9XG4gIGlucHV0Oi13ZWJraXQtYXV0b2ZpbGwge1xuICAgIC13ZWJraXQtYm94LXNoYWRvdzogMCAwIDAgMTAwMHB4IHdoaXRlIGluc2V0OyB9XG5cbmJ1dHRvbixcbmh0bWwgaW5wdXRbdHlwZT1cImJ1dHRvblwiXSxcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcbmlucHV0W3R5cGU9XCJzdWJtaXRcIl0ge1xuICAtd2Via2l0LWFwcGVhcmFuY2U6IGJ1dHRvbjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBvdXRsaW5lOiBub25lOyB9XG5cbmJ1dHRvbltkaXNhYmxlZF0sXG5odG1sIGlucHV0W2Rpc2FibGVkXSB7XG4gIGN1cnNvcjogZGVmYXVsdDsgfVxuXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXG5pbnB1dDo6LW1vei1mb2N1cy1pbm5lciB7XG4gIGJvcmRlcjogMDtcbiAgcGFkZGluZzogMDsgfVxuXG5pbnB1dCB7XG4gIGxpbmUtaGVpZ2h0OiBub3JtYWw7IH1cblxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXSB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDsgfVxuXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxuaW5wdXRbdHlwZT1cInNlYXJjaFwiXTo6LXdlYmtpdC1zZWFyY2gtZGVjb3JhdGlvbiB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTsgfVxuXG5hIHtcbiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOyB9XG4gIGE6YWN0aXZlLCBhOmhvdmVyLCBhOmZvY3VzIHtcbiAgICBvdXRsaW5lOiAwOyB9XG5cbmkge1xuICBmb250LXN0eWxlOiBpdGFsaWM7IH1cblxuYiwgc3Ryb25nIHtcbiAgZm9udC13ZWlnaHQ6IDcwMDsgfVxuXG5pbWcge1xuICB3aWR0aDogYXV0bztcbiAgbWF4LXdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IGF1dG87XG4gIHZlcnRpY2FsLWFsaWduOiB0b3A7XG4gIGJvcmRlcjogMDsgfVxuXG4uaGlkZGVuIHtcbiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS1kYXJrIC5hcHAtY29udGVudCAucHJlbG9hZGVyIC5sb2FkaW5nLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgLmFwcC1jb250ZW50IC5wcmVsb2FkZXIgLmxvYWRpbmctYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG5idXR0b24ge1xuICBib3JkZXI6IG5vbmU7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxLjVyZW07XG4gIGZvbnQtd2VpZ2h0OiA2MDA7XG4gIG91dGxpbmU6IG5vbmU7XG4gIHBhZGRpbmc6IDAgMXJlbTtcbiAgaGVpZ2h0OiA0LjJyZW07IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0IHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjOWNhZGI3O1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbiksIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzc5ODQ4ZjtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldCB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzkwYTRhZTtcbiAgICBjb2xvcjogI2ZlZmVmZTsgfVxuICAudGhlbWUtZGFyayBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNiN2QxZTA7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKTpob3ZlciwgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTFhZWJiOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmhvdmVyLCAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uX3Jlc2V0OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjYWViZWM2OyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbl9yZXNldDpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2E3YjljMjsgfVxuICAudGhlbWUtZ3JheSBidXR0b246ZGlzYWJsZWQ6bm90KC50cmFuc3BhcmVudC1idXR0b24pOmZvY3VzLCAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4YTk1OWY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbjpkaXNhYmxlZDpub3QoLnRyYW5zcGFyZW50LWJ1dHRvbik6Zm9jdXMsIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b25fcmVzZXQ6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNhN2I5YzI7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmO1xuICAgIGNvbG9yOiAjMTExOTIxOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgICBjb2xvcjogIzFhMWExYTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzgyZDdmZjsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4NmQ2ZmY7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ibHVlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjYjNmZjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1OWI1ZmQ7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmJsdWUtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWZiNmZjOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzNzlmZmE7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDtcbiAgICBjb2xvcjogIzExMTkyMTsgfVxuICAudGhlbWUtZ3JheSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkO1xuICAgIGNvbG9yOiAjMWExYTFhOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyO1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM4ZGZjYzY7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzdiZjZjNjsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLmdyZWVuLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzVhZDU4NjsgfVxuICAudGhlbWUtZGFyayBidXR0b24uZ3JlZW4tYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmZvY3VzIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNjJlMGIyOyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1Y2RjOWU7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1M2M3N2M7IH1cbiAgLnRoZW1lLWRhcmsgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGQwZTE7XG4gICAgY29sb3I6ICMxMTE5MjE7IH1cbiAgLnRoZW1lLWdyYXkgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzZWM1ZDc7XG4gICAgY29sb3I6ICMxYTFhMWE7IH1cbiAgLnRoZW1lLXdoaXRlIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjZiNmM3O1xuICAgIGNvbG9yOiAjZmVmZWZlOyB9XG4gIC50aGVtZS1kYXJrIGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjODdmNGY1OyB9XG4gIC50aGVtZS1ncmF5IGJ1dHRvbi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzJlZGZlOyB9XG4gIC50aGVtZS13aGl0ZSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUyY2JkOTsgfVxuICAudGhlbWUtZGFyayBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyZDVlODsgfVxuICAudGhlbWUtZ3JheSBidXR0b24udHVycXVvaXNlLWJ1dHRvbjpub3QoOmRpc2FibGVkKTpmb2N1cyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzUwZDBlMTsgfVxuICAudGhlbWUtd2hpdGUgYnV0dG9uLnR1cnF1b2lzZS1idXR0b246bm90KDpkaXNhYmxlZCk6Zm9jdXMge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMzMWJlY2Y7IH1cbiAgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyOyB9XG4gICAgLnRoZW1lLWRhcmsgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyYjM2NDQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmYzNDM4O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7XG4gICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgIGJ1dHRvbi50cmFuc3BhcmVudC1idXR0b24gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAxcmVtO1xuICAgICAgbWFzazogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgd2lkdGg6IDEuN3JlbTtcbiAgICAgIGhlaWdodDogMS43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgYnV0dG9uLnRyYW5zcGFyZW50LWJ1dHRvbiAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSBidXR0b24udHJhbnNwYXJlbnQtYnV0dG9uIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQzNDU0YjsgfVxuXG4uaW5wdXQtYmxvY2sge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtOyB9XG4gIC5pbnB1dC1ibG9jayAud3JhcC1sYWJlbCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbiAgICBtaW4taGVpZ2h0OiAyLjRyZW07IH1cbiAgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICBmb250LXNpemU6IDEuM3JlbTtcbiAgICBsaW5lLWhlaWdodDogMi40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGxhYmVsIHtcbiAgICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBsYWJlbCB7XG4gICAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ndGV4dCddLCAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLmlucHV0LWJsb2NrIHNlbGVjdCB7XG4gICAgYm9yZGVyOiBub25lO1xuICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgIG91dGxpbmU6IG5vbmU7XG4gICAgcGFkZGluZzogMCAxcmVtO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogNC4ycmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWRhcmsgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3RleHQnXSwgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIC50aGVtZS1ncmF5IC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBpbnB1dFt0eXBlPSd0ZXh0J10sIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sgaW5wdXRbdHlwZT0ncGFzc3dvcmQnXSwgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayBzZWxlY3Qge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC5pbnB1dC1ibG9jay50ZXh0YXJlYSB7XG4gICAgaGVpZ2h0OiBhdXRvOyB9XG4gICAgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgIGZvbnQtc2l6ZTogMS40cmVtO1xuICAgICAgb3V0bGluZTogbm9uZTtcbiAgICAgIHBhZGRpbmc6IDFyZW07XG4gICAgICB3aWR0aDogMTAwJTtcbiAgICAgIG1pbi13aWR0aDogMTAwJTtcbiAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgIG1pbi1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG1heC1oZWlnaHQ6IDcuNXJlbTtcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xuICAgICAgcmVzaXplOiBub25lOyB9XG4gICAgICAudGhlbWUtZGFyayAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLnRleHRhcmVhIHRleHRhcmVhIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaW5wdXQtYmxvY2sudGV4dGFyZWEgdGV4dGFyZWEge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICBmb250LXNpemU6IDFyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuNHJlbTtcbiAgICBhbGlnbi1zZWxmOiBmbGV4LWVuZDtcbiAgICB0ZXh0LWFsaWduOiByaWdodDsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cbiAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2sgLmVycm9yLWJsb2NrIHtcbiAgICAgIGNvbG9yOiAjZmY1MjUyOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jayAuZXJyb3ItYmxvY2sge1xuICAgICAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgLmVycm9yLXRleHQge1xuICBjb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSAuZXJyb3ItdGV4dCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbmlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGN1cnNvcjogcG9pbnRlcjtcbiAgZm9udC13ZWlnaHQ6IDQwMDtcbiAgcGFkZGluZy1sZWZ0OiAyLjRyZW07XG4gIC13ZWJraXQtdG91Y2gtY29sbG91dDogbm9uZTtcbiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcbiAgLWtodG1sLXVzZXItc2VsZWN0OiBub25lO1xuICAtbW96LXVzZXItc2VsZWN0OiBub25lO1xuICAtbXMtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIHVzZXItc2VsZWN0OiBub25lOyB9XG4gIC50aGVtZS1kYXJrIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW8gKyBsYWJlbCB7XG4gICAgY29sb3I6ICM1NTY1NzY7IH1cbiAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyArIGxhYmVsIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgb3BhY2l0eTogMDsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDAuN3JlbTtcbiAgICBsZWZ0OiAwO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICB3aWR0aDogMS40cmVtO1xuICAgIGhlaWdodDogMS40cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzRkYjFmZjsgfVxuICAgIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YmVmb3JlIHtcbiAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkICM0MmE1ZjU7IH1cbiAgICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzJjOTVmMTsgfVxuICBpbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOm5vdChjaGVja2VkKSArIGxhYmVsOmFmdGVyIHtcbiAgICBjb250ZW50OiAnJztcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAxcmVtO1xuICAgIGxlZnQ6IDAuM3JlbTtcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgb3BhY2l0eTogMDtcbiAgICB3aWR0aDogMC44cmVtO1xuICAgIGhlaWdodDogMC44cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbzpub3QoY2hlY2tlZCkgKyBsYWJlbDphZnRlciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gICAgLnRoZW1lLXdoaXRlIGlucHV0W3R5cGU9J3JhZGlvJ10uc3R5bGUtcmFkaW86bm90KGNoZWNrZWQpICsgbGFiZWw6YWZ0ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG5pbnB1dFt0eXBlPSdyYWRpbyddLnN0eWxlLXJhZGlvOmNoZWNrZWQgKyBsYWJlbDphZnRlciB7XG4gIG9wYWNpdHk6IDE7IH1cblxuaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LXdlaWdodDogNDAwO1xuICBwYWRkaW5nLWxlZnQ6IDMuNnJlbTtcbiAgLXdlYmtpdC10b3VjaC1jb2xsb3V0OiBub25lO1xuICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xuICAta2h0bWwtdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tb3otdXNlci1zZWxlY3Q6IG5vbmU7XG4gIC1tcy11c2VyLXNlbGVjdDogbm9uZTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveCArIGxhYmVsIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjNTY1YzYyOyB9XG4gIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94ICsgbGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6bm90KGNoZWNrZWQpIHtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICB0b3A6IDUwJTtcbiAgbGVmdDogMS42cmVtO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjsgfVxuICBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7IH1cbiAgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgIGNvbnRlbnQ6ICcnO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiAxLjZyZW07XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKC01MCUpO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIHdpZHRoOiAxLjRyZW07XG4gICAgaGVpZ2h0OiAxLjRyZW07IH1cbiAgICAudGhlbWUtZGFyayBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjNGRiMWZmOyB9XG4gICAgLnRoZW1lLWdyYXkgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpub3QoY2hlY2tlZCkgKyBsYWJlbDpiZWZvcmUge1xuICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgIzQyYTVmNTsgfVxuICAgIC50aGVtZS13aGl0ZSBpbnB1dFt0eXBlPSdjaGVja2JveCddLnN0eWxlLWNoZWNrYm94Om5vdChjaGVja2VkKSArIGxhYmVsOmJlZm9yZSB7XG4gICAgICBib3JkZXI6IDAuMXJlbSBzb2xpZCAjMmM5NWYxOyB9XG5cbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zyk7IH1cbiAgLnRoZW1lLWRhcmsgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3g6Y2hlY2tlZCArIGxhYmVsOmJlZm9yZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAudGhlbWUtd2hpdGUgaW5wdXRbdHlwZT0nY2hlY2tib3gnXS5zdHlsZS1jaGVja2JveDpjaGVja2VkICsgbGFiZWw6YmVmb3JlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyB9XG5cbi50aGVtZS13aGl0ZSAuc3dpdGNoIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayAuc3dpdGNoIC5jaXJjbGUub24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgLnN3aXRjaCAuY2lyY2xlLm9mZiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIC5zd2l0Y2ggLmNpcmNsZS5vZmYge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjYTBhNWFiOyB9XG5cbi50YWJsZS10b29sdGlwIHtcbiAgcGFkZGluZzogMXJlbSAycmVtOyB9XG4gIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcCB7XG4gICAgYmFja2dyb3VuZDogIzNlNDY0YztcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAudGFibGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gICAgZm9udC1zaXplOiAxLjNyZW07XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3Age1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3A6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAtMXJlbTtcbiAgICAgIGxlZnQ6IDAuN3JlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtbGVmdDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjZmZmZmZmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQge1xuICAgIG1hcmdpbi10b3A6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogLTFyZW07XG4gICAgICByaWdodDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXRvcC1yaWdodDphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC10b3AtcmlnaHQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6ICNmZmZmZmYgI2ZmZmZmZiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tOmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIGxlZnQ6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b206YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGMgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQ7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLWxlZnQ6YmVmb3JlIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IC0xcmVtO1xuICAgICAgbGVmdDogMC43cmVtO1xuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkOyB9XG4gICAgICAudGhlbWUtZGFyayAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1sZWZ0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1ib3R0b20tbGVmdDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmYgI2ZmZmZmZjsgfVxuICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodCB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAgIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAtMXJlbTtcbiAgICAgIHJpZ2h0OiAwLjdyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzQyNTA1ZiAjNDI1MDVmIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbS1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICMzZTQ2NGMgIzNlNDY0YyB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0OmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG4gIC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gICAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcbiAgICAgIHJpZ2h0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0OmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQ6YWZ0ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICNmZmZmZmY7IH1cbiAgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cbiAgICAudGFibGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0OmJlZm9yZSB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XG4gICAgICBsZWZ0OiAtMXJlbTtcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cbiAgICAgIC50aGVtZS1ncmF5IC50YWJsZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQ6YmVmb3JlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjM2U0NjRjIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnRhYmxlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodDpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNmZmZmZmYgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7IH1cblxuLnRhYmxlLXRvb2x0aXAtZGltZW5zaW9ucyAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICBtYXgtd2lkdGg6IDIwcmVtO1xuICBtYXgtaGVpZ2h0OiAxMHJlbTsgfVxuXG4uYmFsYW5jZS10b29sdGlwIHtcbiAgcGFkZGluZzogMS4zcmVtOyB9XG4gIC50aGVtZS1kYXJrIC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICM0MjUwNWY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS1ncmF5IC5iYWxhbmNlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMTIwLCAxMjAsIDEyMCwgMC41KTtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZm9udC1zaXplOiAxLjNyZW07IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5hdmFpbGFibGUgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMC43cmVtOyB9XG4gICAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5sb2NrZWQgYiB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7IH1cbiAgICAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgIGN1cnNvcjogcG9pbnRlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmJhbGFuY2UtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAubGluayB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuYmFsYW5jZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5saW5rIHtcbiAgICAgICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLXRvcCB7XG4gICAgbWFyZ2luLXRvcDogLTFyZW07IH1cbiAgLmJhbGFuY2UtdG9vbHRpcC5uZy10b29sdGlwLWJvdHRvbSB7XG4gICAgbWFyZ2luLXRvcDogMXJlbTsgfVxuICAuYmFsYW5jZS10b29sdGlwLm5nLXRvb2x0aXAtbGVmdCB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtOyB9XG4gIC5iYWxhbmNlLXRvb2x0aXAubmctdG9vbHRpcC1yaWdodCB7XG4gICAgbWFyZ2luLWxlZnQ6IDFyZW07IH1cblxuLmFjY291bnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XG4gIG1heC13aWR0aDogMThyZW07IH1cblxuLmNvbW1lbnQtdG9vbHRpcCAudG9vbHRpcC1pbm5lciB7XG4gIG92ZXJmbG93OiBhdXRvO1xuICB3b3JkLWJyZWFrOiBicmVhay13b3JkO1xuICBtYXgtd2lkdGg6IDUwcmVtO1xuICBtYXgtaGVpZ2h0OiAyNXJlbTsgfVxuXG4udXBkYXRlLXRvb2x0aXAge1xuICBwYWRkaW5nOiAxLjVyZW07IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIHtcbiAgICBiYWNrZ3JvdW5kOiAjNDI1MDVmO1xuICAgIGJveC1zaGFkb3c6IDAgMCAxcmVtIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICMzZTQ2NGM7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpO1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAge1xuICAgIGJhY2tncm91bmQ6ICNmZmZmZmY7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpO1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQge1xuICAgIGJhY2tncm91bmQ6ICM1ZjJiMTE7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogIzU1MjQwZDtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudCB7XG4gICAgYmFja2dyb3VuZDogI2VmNmMwMDtcbiAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuaW1wb3J0YW50Lm5nLXRvb2x0aXAtbGVmdC1ib3R0b206YWZ0ZXIge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExOyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNTUyNDBkICM1NTI0MGQ7IH1cbiAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjZWY2YzAwICNlZjZjMDA7IH1cbiAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzVmMmIxMSAjNWYyYjExIHRyYW5zcGFyZW50OyB9XG4gIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5pbXBvcnRhbnQubmctdG9vbHRpcC1yaWdodC1ib3R0b206YmVmb3JlIHtcbiAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1NTI0MGQgIzU1MjQwZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmltcG9ydGFudC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2VmNmMwMCAjZWY2YzAwIHRyYW5zcGFyZW50OyB9XG4gIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgcGFkZGluZzogMi41cmVtOyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICM1ZjFkMWQ7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCB7XG4gICAgICBiYWNrZ3JvdW5kOiAjNGMxOTE5O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsIHtcbiAgICAgIGJhY2tncm91bmQ6ICNlNTM5MzU7XG4gICAgICBjb2xvcjogI2ZmZmZmZjsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbCAudG9vbHRpcC1pbm5lciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7IH1cbiAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAuY3JpdGljYWwubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzRjMTkxOSAjNGMxOTE5OyB9XG4gICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2U1MzkzNSAjZTUzOTM1OyB9XG4gICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM1ZjFkMWQgIzVmMWQxZCB0cmFuc3BhcmVudDsgfVxuICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5jcml0aWNhbC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCAjNGMxOTE5ICM0YzE5MTkgdHJhbnNwYXJlbnQ7IH1cbiAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLmNyaXRpY2FsLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICNlNTM5MzUgI2U1MzkzNSB0cmFuc3BhcmVudDsgfVxuICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIge1xuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLnN0YW5kYXJkLXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5zdGFuZGFyZC11cGRhdGUge1xuICAgICAgICBjb2xvcjogIzJjOTVmMTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmltcG9ydGFudC11cGRhdGUge1xuICAgICAgICBjb2xvcjogI2ZmNmYwMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAuaW1wb3J0YW50LXVwZGF0ZSB7XG4gICAgICAgIGNvbG9yOiAjZmZmZmZmOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5jcml0aWNhbC11cGRhdGUge1xuICAgICAgZm9udC1zaXplOiAxLjVyZW07XG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xuICAgICAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG4gICAgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTsgfVxuICAgICAgLnRoZW1lLWRhcmsgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZjZmMDA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcCAudG9vbHRpcC1pbm5lciAud3JvbmctdGltZSB7XG4gICAgICAgIGNvbG9yOiAjZmY2ZjAwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC53cm9uZy10aW1lIHtcbiAgICAgICAgY29sb3I6ICNmZmZmZmY7IH1cbiAgICAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgbWFyZ2luOiAxLjVyZW0gMDtcbiAgICAgIHdpZHRoOiA1cmVtO1xuICAgICAgaGVpZ2h0OiA1cmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtZ3JheSAudXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwIC50b29sdGlwLWlubmVyIC5pY29uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IC0xLjVyZW07IH1cbiAgICAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICBjb250ZW50OiBcIlwiO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgYm90dG9tOiAwLjZyZW07XG4gICAgICByaWdodDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjNDI1MDVmICM0MjUwNWY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLWxlZnQtYm90dG9tOmFmdGVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCAjM2U0NjRjICMzZTQ2NGM7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAudXBkYXRlLXRvb2x0aXAubmctdG9vbHRpcC1sZWZ0LWJvdHRvbTphZnRlciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmOyB9XG4gIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XG4gICAgbWFyZ2luLWxlZnQ6IDEuNXJlbTsgfVxuICAgIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgY29udGVudDogXCJcIjtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIGJvdHRvbTogMC42cmVtO1xuICAgICAgbGVmdDogLTFyZW07XG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7IH1cbiAgICAgIC50aGVtZS1kYXJrIC51cGRhdGUtdG9vbHRpcC5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbTpiZWZvcmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50ICM0MjUwNWYgIzQyNTA1ZiB0cmFuc3BhcmVudDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgIzNlNDY0YyAjM2U0NjRjIHRyYW5zcGFyZW50OyB9XG4gICAgICAudGhlbWUtd2hpdGUgLnVwZGF0ZS10b29sdGlwLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tOmJlZm9yZSB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgI2ZmZmZmZiAjZmZmZmZmIHRyYW5zcGFyZW50OyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICBib3JkZXI6IG5vbmU7XG4gIHBhZGRpbmc6IDA7IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJiMzY0NDtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgLm5neC1jb250ZXh0bWVudSAuZHJvcGRvd24tbWVudSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICBib3gtc2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSk7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgLmRyb3Bkb3duLW1lbnUge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICNlMGUwZTA7XG4gICAgYm94LXNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgbGkge1xuICBkaXNwbGF5OiBibG9jaztcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xuICBmb250LXNpemU6IDEuM3JlbTtcbiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgdGV4dC1hbGlnbjogY2VudGVyOyB9XG5cbi5uZ3gtY29udGV4dG1lbnUgYSB7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBwYWRkaW5nOiAwLjVlbSAxZW07IH1cbiAgLnRoZW1lLWRhcmsgLm5neC1jb250ZXh0bWVudSBhIHtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gIC50aGVtZS13aGl0ZSAubmd4LWNvbnRleHRtZW51IGEge1xuICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gIC50aGVtZS1kYXJrIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAudGhlbWUtZ3JheSAubmd4LWNvbnRleHRtZW51IGE6aG92ZXIge1xuICAgIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7XG4gICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgLnRoZW1lLXdoaXRlIC5uZ3gtY29udGV4dG1lbnUgYTpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjtcbiAgICBjb2xvcjogIzQzNDU0YjsgfVxuXG4ubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qge1xuICB3aWR0aDogMTAwJTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSB7XG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTsgfVxuICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICBoZWlnaHQ6IDQuMnJlbTsgfVxuICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtZ3JheSAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzI5MmQzMTtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctc2VsZWN0LWNvbnRhaW5lciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciB7XG4gICAgICBwYWRkaW5nOiAwOyB9XG4gICAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXQge1xuICAgICAgICB0b3A6IGF1dG87IH1cbiAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgYm9yZGVyOiBub25lOyB9XG4gICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3OyB9XG4gICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG4gICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjsgfVxuICAgIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgZm9udC1zaXplOiAxLjRyZW07XG4gICAgICBwYWRkaW5nOiAxcmVtOyB9XG4gICAgICAudGhlbWUtZGFyayAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgICBjb2xvcjogIzQzNDU0YjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2VkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLW1hcmtlZCB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjQwLCAyNDAsIDI0MCwgMC41KTtcbiAgICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAgIC50aGVtZS1kYXJrIC5uZy1zZWxlY3QuY3VzdG9tLXNlbGVjdCAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpO1xuICAgICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgICAgLnRoZW1lLWdyYXkgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgICAudGhlbWUtd2hpdGUgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7XG4gICAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgLm5nLXNlbGVjdC5jdXN0b20tc2VsZWN0IC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXM6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgICAgY3Vyc29yOiBkZWZhdWx0O1xuICAgICAgd2lkdGg6IDFyZW07XG4gICAgICBoZWlnaHQ6IDFyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xuICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgICAgIGJhY2tncm91bmQtY2xpcDogcGFkZGluZy1ib3g7XG4gICAgICBib3JkZXI6IDAuMjVyZW0gc29saWQgdHJhbnNwYXJlbnQ7XG4gICAgICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cbiAgICAubmctc2VsZWN0LmN1c3RvbS1zZWxlY3QgLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtczo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwsIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZyk7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5lcnJvciwgLnRoZW1lLWdyYXkgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmVycm9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3IsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uZXJyb3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY29udGVudCAuaWNvbi5zdWNjZXNzLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLnN1Y2Nlc3MsIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNvbnRlbnQgLmljb24uc3VjY2VzcyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jb250ZW50IC5pY29uLmluZm8sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmNvbnRlbnQgLmljb24uaW5mbywgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY29udGVudCAuaWNvbi5pbmZvIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLWRhcmsgYXBwLWNvbmZpcm0tbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLW1vZGFsLWNvbnRhaW5lciAubW9kYWwgLmFjdGlvbi1idXR0b24sIC50aGVtZS1ncmF5IGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiwgLnRoZW1lLXdoaXRlIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS1kYXJrIGFwcC1jb25maXJtLW1vZGFsIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbW9kYWwtY29udGFpbmVyIC5tb2RhbCAuY2xvc2UtYnV0dG9uIC5pY29uLCAudGhlbWUtZ3JheSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1MTU5NjA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1tb2RhbC1jb250YWluZXIgLm1vZGFsIC5jbG9zZS1idXR0b24gLmljb24sIC50aGVtZS13aGl0ZSBhcHAtY29uZmlybS1tb2RhbCAubW9kYWwgLmNsb3NlLWJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIHtcbiAgYm9yZGVyLXRvcDogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSB7XG4gIGJvcmRlci10b3A6IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmxhYmVsIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwubGFiZWwge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHJhbnNhY3Rpb24tZGV0YWlscyAudGFibGUgLnJvdyAuY2VsbC52YWx1ZSB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLnZhbHVlIHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMgLnRhYmxlIC5yb3cgLmNlbGwua2V5LXZhbHVlIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10cmFuc2FjdGlvbi1kZXRhaWxzIC50YWJsZSAucm93IC5jZWxsLmtleS12YWx1ZSB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHJvZ3Jlc3MtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNjNhM2U7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXByb2dyZXNzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5wcm9ncmVzcy1iYXItZnVsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wcm9ncmVzcy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZGFyay5wbmcpO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtb3Blbi13YWxsZXQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1vcGVuLXdhbGxldC1tb2RhbCAubW9kYWwge1xuICBiYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKTtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIHtcbiAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nKTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCB7XG4gIGJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmcpO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICMyYjM2NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC50aXRsZSB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmYzNDM4OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZC1tb2RhbCAubW9kYWwgLnRpdGxlIHtcbiAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNlbmQtbW9kYWwgLm1vZGFsIC5hY3Rpb24tYnV0dG9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kLW1vZGFsIC5tb2RhbCAuYWN0aW9uLWJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7XG4gIGNvbG9yOiAjZmVmZWZlOyB9XG5cbmFwcC1tYWluLCBhcHAtY3JlYXRlLXdhbGxldCwgYXBwLW9wZW4td2FsbGV0LCBhcHAtcmVzdG9yZS13YWxsZXQsIGFwcC1zZWVkLXBocmFzZSwgYXBwLXdhbGxldC1kZXRhaWxzLCBhcHAtYXNzaWduLWFsaWFzLCBhcHAtZWRpdC1hbGlhcywgYXBwLXRyYW5zZmVyLWFsaWFzLCBhcHAtc2V0dGluZ3MsIGFwcC1sb2dpbiB7XG4gIGZsZXg6IDEgMSBhdXRvO1xuICBwYWRkaW5nOiAzcmVtO1xuICBtaW4td2lkdGg6IDg1cmVtOyB9XG4gIGFwcC1tYWluIC5jb250ZW50LCBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1kYXJrIGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtY3JlYXRlLXdhbGxldCAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtcmVzdG9yZS13YWxsZXQgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1zZWVkLXBocmFzZSAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtYXNzaWduLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZWRpdC1hbGlhcyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQsIC50aGVtZS1ncmF5IGFwcC1sb2dpbiAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLW9wZW4td2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXJlc3RvcmUtd2FsbGV0IC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXdhbGxldC1kZXRhaWxzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWFzc2lnbi1hbGlhcyAuY29udGVudCwgLnRoZW1lLXdoaXRlIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXRyYW5zZmVyLWFsaWFzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWxvZ2luIC5jb250ZW50IHtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC41KTtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgYXBwLW1haW4gLmNvbnRlbnQgLmhlYWQsIGFwcC1jcmVhdGUtd2FsbGV0IC5jb250ZW50IC5oZWFkLCBhcHAtb3Blbi13YWxsZXQgLmNvbnRlbnQgLmhlYWQsIGFwcC1yZXN0b3JlLXdhbGxldCAuY29udGVudCAuaGVhZCwgYXBwLXNlZWQtcGhyYXNlIC5jb250ZW50IC5oZWFkLCBhcHAtd2FsbGV0LWRldGFpbHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hc3NpZ24tYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1lZGl0LWFsaWFzIC5jb250ZW50IC5oZWFkLCBhcHAtdHJhbnNmZXItYWxpYXMgLmNvbnRlbnQgLmhlYWQsIGFwcC1zZXR0aW5ncyAuY29udGVudCAuaGVhZCwgYXBwLWxvZ2luIC5jb250ZW50IC5oZWFkIHtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMDtcbiAgICAgIGxlZnQ6IDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLW1haW4gLmNvbnRlbnQgLmFkZC13YWxsZXQgLmFkZC13YWxsZXQtaGVscCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1tYWluIC5jb250ZW50IC5hZGQtd2FsbGV0IC5hZGQtd2FsbGV0LWhlbHAgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWFpbiAuY29udGVudCAuYWRkLXdhbGxldCAuYWRkLXdhbGxldC1oZWxwIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTcxZTI3O1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VlZC1waHJhc2UgLnNlZWQtcGhyYXNlLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNlZWQtcGhyYXNlIC5zZWVkLXBocmFzZS1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxNzFlMjc7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldC1kZXRhaWxzIC5zZWVkLXBocmFzZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyOTJkMzE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQtZGV0YWlscyAuc2VlZC1waHJhc2Uge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2OyB9XG5cbmFwcC1zZXR0aW5ncyAuY29udGVudCB7XG4gIGhlaWdodDogMTAwJTtcbiAgb3ZlcmZsb3cteTogYXV0bztcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogIzU1NjU3NjsgfVxuICAudGhlbWUtZ3JheSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnRoZW1lLXNlbGVjdGlvbiB7XG4gICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAudGhlbWUtc2VsZWN0aW9uIHtcbiAgICBjb2xvcjogI2EwYTVhYjsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSk7IH1cbiAgLnRoZW1lLWdyYXkgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpOyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cbiAgLnRoZW1lLWRhcmsgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2sgLmxhYmVsIHtcbiAgICBjb2xvcjogIzU2NWM2MjsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXNldHRpbmdzIC5jb250ZW50IC5zY2FsZS1zZWxlY3Rpb24gLmJ1dHRvbi1ibG9jayAubGFiZWwge1xuICAgIGNvbG9yOiAjYTBhNWFiOyB9XG4gIC50aGVtZS1kYXJrIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuICAudGhlbWUtZGFyayBhcHAtc2V0dGluZ3MgLmNvbnRlbnQgLnNjYWxlLXNlbGVjdGlvbiAuYnV0dG9uLWJsb2NrLmFjdGl2ZSAubGFiZWwge1xuICAgIGNvbG9yOiAjNGRiMWZmOyB9XG4gIC50aGVtZS1ncmF5IGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICM0MmE1ZjU7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC1zZXR0aW5ncyAuY29udGVudCAuc2NhbGUtc2VsZWN0aW9uIC5idXR0b24tYmxvY2suYWN0aXZlIC5sYWJlbCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cblxuYXBwLWxvZ2luIHtcbiAgbWluLXdpZHRoOiBpbmhlcml0OyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWYyNzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxYzFlMjE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtaGVhZGVyIGgzIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBoMyB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIgYnV0dG9uIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWhlYWRlciBidXR0b24ge1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTtcbiAgY29sb3I6ICNmZWZlZmU7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzQzZjRhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM2M2EzZTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93IC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudCAuc2lkZWJhci1hY2NvdW50LXJvdyAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQgLnNpZGViYXItYWNjb3VudC1yb3cuYWNjb3VudC1zeW5jaHJvbml6YXRpb24ge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50IC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMWU4OGU1O1xuICBjb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAudGV4dCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC50ZXh0IHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjtcbiAgY29sb3I6ICMxMTE5MjE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdyAuaW5kaWNhdG9yIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTtcbiAgY29sb3I6ICMxYTFhMWE7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzIC5zaWRlYmFyLWFjY291bnRzLWxpc3QgLnNpZGViYXItYWNjb3VudC5hY3RpdmUgLnNpZGViYXItYWNjb3VudC1yb3cgLnN3aXRjaCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDA7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93IC5zd2l0Y2gge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50LmFjdGl2ZSAuc2lkZWJhci1hY2NvdW50LXJvdy5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQuYWN0aXZlIC5zaWRlYmFyLWFjY291bnQtcm93LmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcbiAgY29sb3I6ICM5MWJhZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHMgLnNpZGViYXItYWNjb3VudHMtbGlzdCAuc2lkZWJhci1hY2NvdW50OmhvdmVyOm5vdCguYWN0aXZlKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDY5LCA4NSwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1hY2NvdW50cyAuc2lkZWJhci1hY2NvdW50cy1saXN0IC5zaWRlYmFyLWFjY291bnQ6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLWFjY291bnRzOmFmdGVyIHtcbiAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KHRvIGJvdHRvbSwgdHJhbnNwYXJlbnQgMCUsICMxNzFmMjcgMTAwJSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgIzFjMWUyMSAxMDAlKTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItYWNjb3VudHM6YWZ0ZXIge1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB0cmFuc3BhcmVudCAwJSwgd2hpdGUgMTAwJSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3Mge1xuICBib3JkZXItYm90dG9tOiAwLjJyZW0gc29saWQgIzFmMjgzMzsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjMmUzMzM3OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyB7XG4gIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCAjZWJlYmViOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXNldHRpbmdzIC53cmFwLWJ1dHRvbiBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24gYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSkgIWltcG9ydGFudDtcbiAgY29sb3I6ICNlMGUwZTAgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSAhaW1wb3J0YW50O1xuICBjb2xvcjogI2UwZTBlMCAhaW1wb3J0YW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxZTg4ZTUgIWltcG9ydGFudDtcbiAgY29sb3I6ICNmZmZmZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmYgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zZXR0aW5ncyAud3JhcC1idXR0b24uYWN0aXZlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjUgIWltcG9ydGFudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc2V0dGluZ3MgLndyYXAtYnV0dG9uLmFjdGl2ZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmICFpbXBvcnRhbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vZmZsaW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLm9mZmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5vbmxpbmU6YmVmb3JlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAub25saW5lOmJlZm9yZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5zeW5jaW5nIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnN0YXR1cy1jb250YWluZXIgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnN5bmNpbmcgLnByb2dyZXNzLWJhciAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAuc3luY2luZyAucHJvZ3Jlc3MtYmFyIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC5zdGF0dXMtY29udGFpbmVyIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5sb2FkaW5nIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAuc3RhdHVzLWNvbnRhaW5lciAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciAubG9hZGluZyB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuc3RhbmRhcmQge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5zdGFuZGFyZCB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmltcG9ydGFudCB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pbXBvcnRhbnQge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5jcml0aWNhbCB7XG4gIGNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmNyaXRpY2FsIHtcbiAgY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLnRpbWUge1xuICBjb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAudGltZSB7XG4gIGNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uc3RhbmRhcmQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLnN0YW5kYXJkIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5pbXBvcnRhbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2lkZWJhciAuc2lkZWJhci1zeW5jaHJvbml6YXRpb24tc3RhdHVzIC51cGRhdGUtY29udGFpbmVyIC5pY29uLmltcG9ydGFudCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi5jcml0aWNhbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24uY3JpdGljYWwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zaWRlYmFyIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMgLnVwZGF0ZS1jb250YWluZXIgLmljb24udGltZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXNpZGViYXIgLnNpZGViYXItc3luY2hyb25pemF0aW9uLXN0YXR1cyAudXBkYXRlLWNvbnRhaW5lciAuaWNvbi50aW1lIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNmYwMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IHtcbiAgY29sb3I6ICM0MzQ1NGI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24ge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIGJ1dHRvbiB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmhlYWRlciBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5oZWFkZXIgYnV0dG9uIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC5oZWFkZXIgLmFsaWFzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuaGVhZGVyIC5hbGlhcyAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3Mge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAuYWRkcmVzcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLmFkZHJlc3MgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC5hZGRyZXNzIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyMywgMzEsIDM5LCAwLjUpOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI4LCAzMCwgMzMsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7XG4gIGNvbG9yOiAjMTExOTIxOyB9XG5cbi50aGVtZS1ncmF5IGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWIgLmluZGljYXRvciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7XG4gIGNvbG9yOiAjMWExYTFhOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiIC5pbmRpY2F0b3Ige1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmO1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNDMsIDU0LCA2OCwgMC41KTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWhlYWRlciAudGFiLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYi5hY3RpdmUge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1oZWFkZXIgLnRhYjpob3Zlcjpub3QoLmFjdGl2ZSk6bm90KC5kaXNhYmxlZCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDU4LCA2MiwgNjYsIDAuNSk7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC13YWxsZXQgLnRhYnMgLnRhYnMtaGVhZGVyIC50YWI6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsgfVxuXG4udGhlbWUtZGFyayBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXdhbGxldCAudGFicyAudGFicy1jb250ZW50IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtd2FsbGV0IC50YWJzIC50YWJzLWNvbnRlbnQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXNlbmQgLmZvcm0tc2VuZCAuc2VuZC1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCB7XG4gIGNvbG9yOiAjNDM0NTRiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc2VuZCAuZm9ybS1zZW5kIC5zZW5kLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLnNlbmQtc2VsZWN0IC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtc2VuZCAuZm9ybS1zZW5kIC5hZGRpdGlvbmFsLWRldGFpbHMge1xuICBib3JkZXI6IDAuMnJlbSBzb2xpZCAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zZW5kIC5mb3JtLXNlbmQgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICNlYmViZWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1yZWNlaXZlIC5idG4tY29weS1hZGRyZXNzIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXJlY2VpdmUgLmJ0bi1jb3B5LWFkZHJlc3Mge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTU2NTc2OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyLmxvY2tlZC10cmFuc2FjdGlvbiB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ci5sb2NrZWQtdHJhbnNhY3Rpb24ge1xuICBjb2xvcjogI2EwYTVhYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMSkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTgyMDJhOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0bisxKSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzIpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMikge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZCg0biszKSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rMykge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0cjpudGgtY2hpbGQoNG4rNCkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKDRuKzQpIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzM0M2Y0YTsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzIC5jb25maXJtYXRpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNkY2RjOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMgLmNvbmZpcm1hdGlvbiAuZmlsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM1Y2RhOWQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ3Y2Y4ZDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnN0YXR1cyAuY29uZmlybWF0aW9uIC5maWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzQ2YzE3MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY2ZjAwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjZmMDA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWhpc3RvcnkgdGFibGUgdGJvZHkgdHIgLnVubG9jay10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC51bmxvY2stdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnNlbmQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMuc2VuZCAuc3RhdHVzLXRyYW5zYWN0aW9uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtaGlzdG9yeSB0YWJsZSB0Ym9keSB0ciAuc3RhdHVzLnJlY2VpdmVkIC5zdGF0dXMtdHJhbnNhY3Rpb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNWNkYTlkOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0N2NmOGQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1oaXN0b3J5IHRhYmxlIHRib2R5IHRyIC5zdGF0dXMucmVjZWl2ZWQgLnN0YXR1cy10cmFuc2FjdGlvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0NmMxNzI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ubmV3LCAudGhlbWUtZ3JheSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5hbGVydCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZjUyNTI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLm5ldywgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLmFsZXJ0IHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLWRhcmsgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24uc2VsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRyYWN0cyAud3JhcC10YWJsZSAuY29udHJhY3QgLmljb24ucHVyY2hhc2UsIC50aGVtZS1ncmF5IGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udHJhY3RzIC53cmFwLXRhYmxlIC5jb250cmFjdCAuaWNvbi5wdXJjaGFzZSwgLnRoZW1lLXdoaXRlIGFwcC1jb250cmFjdHMgLndyYXAtdGFibGUgLmNvbnRyYWN0IC5pY29uLnNlbGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAucHVyY2hhc2Utc2VsZWN0IHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3Qge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zZWxlY3QgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXNlbGVjdCAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5mb3JtLXB1cmNoYXNlIC5wdXJjaGFzZS1zdGF0ZXMge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLnB1cmNoYXNlLXN0YXRlcyB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgIzJiMzY0NDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLmZvcm0tcHVyY2hhc2UgLmFkZGl0aW9uYWwtZGV0YWlscyB7XG4gIGJvcmRlcjogMC4ycmVtIHNvbGlkICMyZjM0Mzg7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1wdXJjaGFzZSAuZm9ybS1wdXJjaGFzZSAuYWRkaXRpb25hbC1kZXRhaWxzIHtcbiAgYm9yZGVyOiAwLjJyZW0gc29saWQgI2ViZWJlYjsgfVxuXG4udGhlbWUtZGFyayBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzNDNmNGE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzYzYTNlOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNkY2RjZGM7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXB1cmNoYXNlIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIC5wcm9ncmVzcy1iYXIgLnByb2dyZXNzLWJhci1mdWxsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzVjZGE5ZDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDdjZjhkOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtcHVyY2hhc2UgLnByb2dyZXNzLWJhci1jb250YWluZXIgLnByb2dyZXNzLWJhciAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDZjMTcyOyB9XG5cbmFwcC1tZXNzYWdlcyB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCBzcGFuIHtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7IH1cblxuLnRoZW1lLWRhcmsgYXBwLW1lc3NhZ2VzIHRhYmxlIHRib2R5IHRyIHRkOmZpcnN0LWNoaWxkIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmNTI1MjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtbWVzc2FnZXMgdGFibGUgdGJvZHkgdHIgdGQ6Zmlyc3QtY2hpbGQgLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmY1MjUyOyB9XG5cbi50aGVtZS1kYXJrIGFwcC10eXBpbmctbWVzc2FnZSAuaGVhZCAuaW50ZXJsb2N1dG9yIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5oZWFkIC5pbnRlcmxvY3V0b3Ige1xuICBjb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmRhdGUge1xuICBjb2xvcjogIzU2NWM2MjsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5kYXRlIHtcbiAgY29sb3I6ICNhMGE1YWI7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyYTM1NDQ7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMzMDM2M2M7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYubXk6YmVmb3JlIHtcbiAgY29udGVudDogXCJcIjtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwO1xuICBsZWZ0OiAtMS4xcmVtO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzJhMzU0NDsgfVxuICAudGhlbWUtZ3JheSBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2Lm15OmJlZm9yZSB7XG4gICAgYm9yZGVyLXRvcC1jb2xvcjogIzMwMzYzYzsgfVxuICAudGhlbWUtd2hpdGUgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5teTpiZWZvcmUge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNmZmY7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMxODIwMmE7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXR5cGluZy1tZXNzYWdlIC5tZXNzYWdlcy1jb250ZW50IC5tZXNzYWdlcy1saXN0IGRpdi5idWRkeSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICMyNTI5MmQ7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHkge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWRlZGVkOyB9XG5cbmFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICBjb250ZW50OiBcIlwiO1xuICBkaXNwbGF5OiBibG9jaztcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICByaWdodDogLTEuMXJlbTtcbiAgdG9wOiAwO1xuICBib3JkZXI6IDEuMnJlbSBzb2xpZCB0cmFuc3BhcmVudDsgfVxuICAudGhlbWUtZGFyayBhcHAtdHlwaW5nLW1lc3NhZ2UgLm1lc3NhZ2VzLWNvbnRlbnQgLm1lc3NhZ2VzLWxpc3QgZGl2LmJ1ZGR5OmFmdGVyIHtcbiAgICBib3JkZXItdG9wLWNvbG9yOiAjMTgyMDJhOyB9XG4gIC50aGVtZS1ncmF5IGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICMyNTI5MmQ7IH1cbiAgLnRoZW1lLXdoaXRlIGFwcC10eXBpbmctbWVzc2FnZSAubWVzc2FnZXMtY29udGVudCAubWVzc2FnZXMtbGlzdCBkaXYuYnVkZHk6YWZ0ZXIge1xuICAgIGJvcmRlci10b3AtY29sb3I6ICNlZGVkZWQ7IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LWhlYWRlciAuZ2VuZXJhbCAubGFiZWwge1xuICBjb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjNTY1YzYyOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5sYWJlbCB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5nZW5lcmFsIC5vcHRpb25zIHtcbiAgY29sb3I6ICNlMGUwZTA7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1oZWFkZXIgLmdlbmVyYWwgLm9wdGlvbnMge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG5hcHAtc3Rha2luZyAuY2hhcnQtaGVhZGVyIC5zZWxlY3RlZCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gIGZsZXgtZ3JvdzogMTtcbiAgZm9udC1zaXplOiAxLjZyZW07IH1cblxuLnRoZW1lLWRhcmsgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NTY1NzY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLnRpdGxlIHtcbiAgY29sb3I6ICM1NjVjNjI7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC50aXRsZSB7XG4gIGNvbG9yOiAjYTBhNWFiOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmIzNjQ0OyB9XG5cbi50aGVtZS1ncmF5IGFwcC1zdGFraW5nIC5jaGFydC1vcHRpb25zIC5vcHRpb25zIGJ1dHRvbiB7XG4gIGNvbG9yOiAjZTBlMGUwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24ge1xuICBjb2xvcjogIzQzNDU0YjtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2UwZTBlMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtc3Rha2luZyAuY2hhcnQtb3B0aW9ucyAub3B0aW9ucyBidXR0b24uYWN0aXZlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzUxNTk2MDsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLXN0YWtpbmcgLmNoYXJ0LW9wdGlvbnMgLm9wdGlvbnMgYnV0dG9uLmFjdGl2ZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7IH1cblxuLmlucHV0LWJsb2NrLWFsaWFzIHtcbiAgcG9zaXRpb246IHJlbGF0aXZlOyB9XG4gIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDYuNXJlbTtcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcbiAgICBvdmVyZmxvdzogYXV0bztcbiAgICB3aWR0aDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE3MWUyNztcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLWdyYXkgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjkyZDMxO1xuICAgICAgY29sb3I6ICNlMGUwZTA7IH1cbiAgICAudGhlbWUtd2hpdGUgLmlucHV0LWJsb2NrLWFsaWFzIC5hbGlhcy1kcm9wZG93biB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTZlNmU2O1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdiB7XG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcbiAgICAgIHBhZGRpbmc6IDFyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpOyB9XG4gICAgICAudGhlbWUtZ3JheSAuaW5wdXQtYmxvY2stYWxpYXMgLmFsaWFzLWRyb3Bkb3duIGRpdjpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5pbnB1dC1ibG9jay1hbGlhcyAuYWxpYXMtZHJvcGRvd24gZGl2OmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpOyB9XG5cbmFwcC1jb250YWN0cywgYXBwLWFkZC1jb250YWN0cyxcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcbiAgZmxleDogMSAxIGF1dG87XG4gIHBhZGRpbmc6IDNyZW07XG4gIG1pbi13aWR0aDogODVyZW07IH1cbiAgYXBwLWNvbnRhY3RzIC5jb250ZW50LCBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LFxuICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHBhZGRpbmc6IDNyZW07XG4gICAgbWluLWhlaWdodDogMTAwJTsgfVxuICAgIC50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmsgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWRhcmtcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZGFyayBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXkgYXBwLWFkZC1jb250YWN0cyAuY29udGVudCwgLnRoZW1lLWdyYXlcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtZ3JheSBhcHAtZXhwb3J0LWltcG9ydCAuY29udGVudCB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDM3LCA0MCwgNDMsIDAuNSk7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmNvbnRlbnQsIC50aGVtZS13aGl0ZSBhcHAtYWRkLWNvbnRhY3RzIC5jb250ZW50LCAudGhlbWUtd2hpdGVcbiAgICBhcHAtY29udGFjdC1zZW5kIC5jb250ZW50LCAudGhlbWUtd2hpdGUgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjUpO1xuICAgICAgY29sb3I6ICM0MzQ1NGI7IH1cbiAgICBhcHAtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsIGFwcC1hZGQtY29udGFjdHMgLmNvbnRlbnQgLmhlYWQsXG4gICAgYXBwLWNvbnRhY3Qtc2VuZCAuY29udGVudCAuaGVhZCwgYXBwLWV4cG9ydC1pbXBvcnQgLmNvbnRlbnQgLmhlYWQge1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAwO1xuICAgICAgbGVmdDogMDsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIC5hbGlhcyB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgLmFsaWFzIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cblxuLnRoZW1lLWdyYXkgYXBwLWNvbnRhY3RzIHRhYmxlIGJ1dHRvbiAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gLmljb24ge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyB0YWJsZSBidXR0b24gc3BhbiB7XG4gIGNvbG9yOiAjZTBlMGUwOyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgdGFibGUgYnV0dG9uIHNwYW4ge1xuICBjb2xvcjogIzQzNDU0YjsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdHMgLmZvb3RlciB7XG4gIGNvbG9yOiAjNGRiMWZmOyB9XG5cbi50aGVtZS1ncmF5IGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLnRoZW1lLWRhcmsgYXBwLWNvbnRhY3RzIC5mb290ZXIgLmltcG9ydC1idG4ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjNDJhNWY1OyB9XG5cbi50aGVtZS13aGl0ZSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biB7XG4gIGNvbG9yOiAjMmM5NWYxOyB9XG5cbi50aGVtZS1kYXJrIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdHMgLmZvb3RlciAuaW1wb3J0LWJ0biAuaWNvbiB7XG4gIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cblxuLnRoZW1lLXdoaXRlIGFwcC1jb250YWN0cyAuZm9vdGVyIC5pbXBvcnQtYnRuIC5pY29uIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzJjOTVmMTsgfVxuXG4udGhlbWUtZGFyayBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzRkYjFmZjsgfVxuXG4udGhlbWUtZ3JheSBhcHAtY29udGFjdC1zZW5kIC53YWxsZXRzLXNlbGVjdGlvbiBidXR0b24ge1xuICBjb2xvcjogIzQyYTVmNTsgfVxuXG4udGhlbWUtd2hpdGUgYXBwLWNvbnRhY3Qtc2VuZCAud2FsbGV0cy1zZWxlY3Rpb24gYnV0dG9uIHtcbiAgY29sb3I6ICMyYzk1ZjE7IH1cblxuLmhlYWQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgZm9udC1zaXplOiAxLjNyZW07XG4gIHBhZGRpbmc6IDAgM3JlbTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogM3JlbTsgfVxuICAudGhlbWUtZGFyayAuaGVhZCB7XG4gICAgY29sb3I6ICM0ZGIxZmY7IH1cbiAgLnRoZW1lLWdyYXkgLmhlYWQge1xuICAgIGNvbG9yOiAjNDJhNWY1OyB9XG4gIC50aGVtZS13aGl0ZSAuaGVhZCB7XG4gICAgY29sb3I6ICMyYzk1ZjE7IH1cbiAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpIHtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIG1hcmdpbi1yaWdodDogMjBweDtcbiAgICBvdXRsaW5lLXN0eWxlOiBub25lOyB9XG4gICAgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMC41cmVtO1xuICAgICAgcmlnaHQ6IC0xLjVyZW07XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYXJyb3ctcmlnaHQuc3ZnKSBuby1yZXBlYXQgY2VudGVyO1xuICAgICAgbWFzay1zaXplOiBjb3ZlcjsgfVxuICAgICAgLnRoZW1lLWRhcmsgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZGFyayAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzRkYjFmZjsgfVxuICAgICAgLnRoZW1lLWdyYXkgLmhlYWQgLmJyZWFkY3J1bWJzID4gc3Bhbjpub3QoOmxhc3QtY2hpbGQpOmFmdGVyLCAudGhlbWUtZ3JheSAuaGVhZCAuYnJlYWRjcnVtYnMgYTpub3QoOmxhc3QtY2hpbGQpOmFmdGVyIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzQyYTVmNTsgfVxuICAgICAgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyA+IHNwYW46bm90KDpsYXN0LWNoaWxkKTphZnRlciwgLnRoZW1lLXdoaXRlIC5oZWFkIC5icmVhZGNydW1icyBhOm5vdCg6bGFzdC1jaGlsZCk6YWZ0ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG4gIC5oZWFkIC5iYWNrLWJ0biB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIGNvbG9yOiAjNGRiMWZmO1xuICAgIGZvbnQtc2l6ZTogaW5oZXJpdDtcbiAgICBmb250LXdlaWdodDogNDAwO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XG4gICAgcGFkZGluZzogMDtcbiAgICBoZWlnaHQ6IGF1dG87IH1cbiAgICAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XG4gICAgICBtYXNrOiB1cmwofnNyYy9hc3NldHMvaWNvbnMvYmFjay5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgICB3aWR0aDogMC45cmVtO1xuICAgICAgaGVpZ2h0OiAwLjlyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0ZGIxZmY7IH1cbiAgICAgIC50aGVtZS1ncmF5IC5oZWFkIC5iYWNrLWJ0biAuaWNvbiB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM0MmE1ZjU7IH1cbiAgICAgIC50aGVtZS13aGl0ZSAuaGVhZCAuYmFjay1idG4gLmljb24ge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMmM5NWYxOyB9XG5cbi5zY3JvbGxlZC1jb250ZW50Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBjdXJzb3I6IGRlZmF1bHQ7XG4gIHdpZHRoOiAxcmVtO1xuICBoZWlnaHQ6IDFyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRyYWNrIHtcbiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcbiAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcbiAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xuICBib3JkZXItcmFkaXVzOiAwLjVyZW07IH1cblxuLnNjcm9sbGVkLWNvbnRlbnQ6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjsgfVxuXG50YWJsZSB7XG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xuICB3aWR0aDogMTAwJTsgfVxuICB0YWJsZSB0aGVhZCB7XG4gICAgdGV4dC1hbGlnbjogbGVmdDsgfVxuICAgIC50aGVtZS1kYXJrIHRhYmxlIHRoZWFkIHtcbiAgICAgIGNvbG9yOiAjNTU2NTc2OyB9XG4gICAgLnRoZW1lLWdyYXkgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICM1NjVjNjI7IH1cbiAgICAudGhlbWUtd2hpdGUgdGFibGUgdGhlYWQge1xuICAgICAgY29sb3I6ICNhMGE1YWI7IH1cbiAgICB0YWJsZSB0aGVhZCB0ciB7XG4gICAgICBoZWlnaHQ6IDRyZW07IH1cbiAgICAgIHRhYmxlIHRoZWFkIHRyIHRoIHtcbiAgICAgICAgcGFkZGluZzogMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IGJvdHRvbTsgfVxuICAgICAgICB0YWJsZSB0aGVhZCB0ciB0aDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRoZWFkIHRyIHRoOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cbiAgdGFibGUgdGJvZHkge1xuICAgIHRleHQtYWxpZ246IGxlZnQ7IH1cbiAgICAudGhlbWUtZGFyayB0YWJsZSB0Ym9keSB7XG4gICAgICBjb2xvcjogI2UwZTBlMDsgfVxuICAgIC50aGVtZS1ncmF5IHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjZTBlMGUwOyB9XG4gICAgLnRoZW1lLXdoaXRlIHRhYmxlIHRib2R5IHtcbiAgICAgIGNvbG9yOiAjNDM0NTRiOyB9XG4gICAgdGFibGUgdGJvZHkgdHIge1xuICAgICAgaGVpZ2h0OiAzLjVyZW07IH1cbiAgICAgIC50aGVtZS1kYXJrIHRhYmxlIHRib2R5IHRyOm50aC1jaGlsZChvZGQpIHtcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzE4MjAyYTsgfVxuICAgICAgLnRoZW1lLWdyYXkgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjUyOTJkOyB9XG4gICAgICAudGhlbWUtd2hpdGUgdGFibGUgdGJvZHkgdHI6bnRoLWNoaWxkKG9kZCkge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyB9XG4gICAgICB0YWJsZSB0Ym9keSB0ciB0ZCB7XG4gICAgICAgIGxpbmUtaGVpZ2h0OiAxLjdyZW07XG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcbiAgICAgICAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTsgfVxuICAgICAgICB0YWJsZSB0Ym9keSB0ciB0ZDpmaXJzdC1jaGlsZCB7XG4gICAgICAgICAgcGFkZGluZy1sZWZ0OiAzcmVtOyB9XG4gICAgICAgIHRhYmxlIHRib2R5IHRyIHRkOmxhc3QtY2hpbGQge1xuICAgICAgICAgIHBhZGRpbmctcmlnaHQ6IDNyZW07IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtTGlnaHQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDMwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA0MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtU2VtaUJvbGQudHRmKTtcbiAgZm9udC13ZWlnaHQ6IDYwMDsgfVxuXG5AZm9udC1mYWNlIHtcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1Cb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7IH1cblxuQGZvbnQtZmFjZSB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XG4gIGZvbnQtd2VpZ2h0OiA4MDA7IH1cblxuaHRtbCB7XG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcbiAgZm9udC1zaXplOiAxMHB4OyB9XG5cbmJvZHkge1xuICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XG4gIGZvbnQtc2l6ZTogMS42cmVtO1xuICB3aWR0aDogMTAwdnc7XG4gIGhlaWdodDogMTAwdmg7IH1cbiAgYm9keS50aGVtZS1kYXJrIHtcbiAgICBiYWNrZ3JvdW5kOiAjMTMxOTIxIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS1ncmF5IHtcbiAgICBiYWNrZ3JvdW5kOiAjMTAxNDE3IHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1ncmF5LnBuZ1wiKSBuby1yZXBlYXQgY2VudGVyO1xuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7IH1cbiAgYm9keS50aGVtZS13aGl0ZSB7XG4gICAgYmFja2dyb3VuZDogI2VlZWVlZSB1cmwoXCJhc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XG4gICAgYmFja2dyb3VuZC1zaXplOiBjb3ZlcjsgfVxuICBib2R5IGFwcC1yb290IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTsgfVxuXG4udXBkYXRlLXRvb2x0aXAgLnRvb2x0aXAtaW5uZXIgLmljb24ge1xuICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7IH1cbiIsIi5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcntiYWNrZ3JvdW5kOiNmZmY7Ym9yZGVyLWNvbG9yOiNiM2IzYjMgI2NjYyAjZDlkOWQ5fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lcjpob3Zlcntib3gtc2hhZG93Om5vbmV9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy1hcnJvd3t0b3A6LTJweDtib3JkZXItY29sb3I6dHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgIzk5OTtib3JkZXItd2lkdGg6MCA1cHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW9wZW5lZD4ubmctc2VsZWN0LWNvbnRhaW5lciAubmctYXJyb3c6aG92ZXJ7Ym9yZGVyLWNvbG9yOnRyYW5zcGFyZW50IHRyYW5zcGFyZW50ICMzMzN9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC1ib3R0b20+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6MDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtb3BlbmVkLm5nLXNlbGVjdC10b3A+Lm5nLXNlbGVjdC1jb250YWluZXJ7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MDtib3JkZXItdG9wLWxlZnQtcmFkaXVzOjB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtZm9jdXNlZDpub3QoLm5nLXNlbGVjdC1vcGVuZWQpPi5uZy1zZWxlY3QtY29udGFpbmVye2JvcmRlci1jb2xvcjojMDA3ZWZmO2JveC1zaGFkb3c6aW5zZXQgMCAxcHggMXB4IHJnYmEoMCwwLDAsMC4wNzUpLDAgMCAwIDNweCByZ2JhKDAsMTI2LDI1NSwwLjEpfS5uZy1zZWxlY3Qubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0IC5uZy1oYXMtdmFsdWUgLm5nLXBsYWNlaG9sZGVye2Rpc3BsYXk6bm9uZX0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVye2JhY2tncm91bmQtY29sb3I6I2ZmZjtib3JkZXItcmFkaXVzOjRweDtib3JkZXI6MXB4IHNvbGlkICNjY2M7bWluLWhlaWdodDozNnB4O2FsaWduLWl0ZW1zOmNlbnRlcn0ubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyOmhvdmVye2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lcnthbGlnbi1pdGVtczpjZW50ZXI7cGFkZGluZy1sZWZ0OjEwcHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0IC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy1yaWdodDoxMHB4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1zaW5nbGUgLm5nLXNlbGVjdC1jb250YWluZXJ7aGVpZ2h0OjM2cHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3Qtc2luZ2xlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3RvcDo1cHg7bGVmdDowO3BhZGRpbmctbGVmdDoxMHB4O3BhZGRpbmctcmlnaHQ6NTBweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LXNpbmdsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy1pbnB1dHtwYWRkaW5nLXJpZ2h0OjEwcHg7cGFkZGluZy1sZWZ0OjUwcHh9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOTtib3JkZXI6MXB4IHNvbGlkICNlNmU2ZTZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUubmctc2VsZWN0LWRpc2FibGVkPi5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nOjAgNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXJ7cGFkZGluZy10b3A6NXB4O3BhZGRpbmctbGVmdDo3cHh9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVye3BhZGRpbmctcmlnaHQ6N3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVle2ZvbnQtc2l6ZTouOWVtO21hcmdpbi1ib3R0b206NXB4O2JhY2tncm91bmQtY29sb3I6I2ViZjVmZjtib3JkZXItcmFkaXVzOjJweDttYXJnaW4tcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWV7bWFyZ2luLXJpZ2h0OjA7bWFyZ2luLWxlZnQ6NXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVke2JhY2tncm91bmQtY29sb3I6I2Y5ZjlmOX0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZS5uZy12YWx1ZS1kaXNhYmxlZCAubmctdmFsdWUtbGFiZWx7cGFkZGluZy1sZWZ0OjVweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlLm5nLXZhbHVlLWRpc2FibGVkIC5uZy12YWx1ZS1sYWJlbHtwYWRkaW5nLWxlZnQ6MDtwYWRkaW5nLXJpZ2h0OjVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtbGFiZWx7ZGlzcGxheTppbmxpbmUtYmxvY2s7cGFkZGluZzoxcHggNXB4fS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29ue2Rpc3BsYXk6aW5saW5lLWJsb2NrO3BhZGRpbmc6MXB4IDVweH0ubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbjpob3ZlcntiYWNrZ3JvdW5kLWNvbG9yOiNkMWU4ZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ubGVmdHtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9W2Rpcj1cInJ0bFwiXSAubmctc2VsZWN0Lm5nLXNlbGVjdC1tdWx0aXBsZSAubmctc2VsZWN0LWNvbnRhaW5lciAubmctdmFsdWUtY29udGFpbmVyIC5uZy12YWx1ZSAubmctdmFsdWUtaWNvbi5sZWZ0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmO2JvcmRlci1yaWdodDpub25lfS5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXZhbHVlIC5uZy12YWx1ZS1pY29uLnJpZ2h0e2JvcmRlci1sZWZ0OjFweCBzb2xpZCAjYjhkYmZmfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctdmFsdWUgLm5nLXZhbHVlLWljb24ucmlnaHR7Ym9yZGVyLWxlZnQ6MDtib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNiOGRiZmZ9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctaW5wdXR7cGFkZGluZzowIDAgM3B4IDNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLWlucHV0e3BhZGRpbmc6MCAzcHggM3B4IDB9Lm5nLXNlbGVjdC5uZy1zZWxlY3QtbXVsdGlwbGUgLm5nLXNlbGVjdC1jb250YWluZXIgLm5nLXZhbHVlLWNvbnRhaW5lciAubmctcGxhY2Vob2xkZXJ7dG9wOjVweDtwYWRkaW5nLWJvdHRvbTo1cHg7cGFkZGluZy1sZWZ0OjNweH1bZGlyPVwicnRsXCJdIC5uZy1zZWxlY3Qubmctc2VsZWN0LW11bHRpcGxlIC5uZy1zZWxlY3QtY29udGFpbmVyIC5uZy12YWx1ZS1jb250YWluZXIgLm5nLXBsYWNlaG9sZGVye3BhZGRpbmctcmlnaHQ6M3B4O3BhZGRpbmctbGVmdDowfS5uZy1zZWxlY3QgLm5nLWNsZWFyLXdyYXBwZXJ7Y29sb3I6Izk5OX0ubmctc2VsZWN0IC5uZy1jbGVhci13cmFwcGVyOmhvdmVyIC5uZy1jbGVhcntjb2xvcjojRDAwMjFCfS5uZy1zZWxlY3QgLm5nLXNwaW5uZXItem9uZXtwYWRkaW5nOjVweCA1cHggMCAwfVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctc3Bpbm5lci16b25le3BhZGRpbmc6NXB4IDAgMCA1cHh9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcnt3aWR0aDoyNXB4O3BhZGRpbmctcmlnaHQ6NXB4fVtkaXI9XCJydGxcIl0gLm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlcntwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH0ubmctc2VsZWN0IC5uZy1hcnJvdy13cmFwcGVyOmhvdmVyIC5uZy1hcnJvd3tib3JkZXItdG9wLWNvbG9yOiM2NjZ9Lm5nLXNlbGVjdCAubmctYXJyb3ctd3JhcHBlciAubmctYXJyb3d7Ym9yZGVyLWNvbG9yOiM5OTkgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7Ym9yZGVyLXN0eWxlOnNvbGlkO2JvcmRlci13aWR0aDo1cHggNXB4IDIuNXB4fS5uZy1kcm9wZG93bi1wYW5lbHtiYWNrZ3JvdW5kLWNvbG9yOiNmZmY7Ym9yZGVyOjFweCBzb2xpZCAjY2NjO2JveC1zaGFkb3c6MCAxcHggMCByZ2JhKDAsMCwwLDAuMDYpO2xlZnQ6MH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbXt0b3A6MTAwJTtib3JkZXItYm90dG9tLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1jb2xvcjojZTZlNmU2O21hcmdpbi10b3A6LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LWJvdHRvbSAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpsYXN0LWNoaWxke2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjRweDtib3JkZXItYm90dG9tLWxlZnQtcmFkaXVzOjRweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcHtib3R0b206MTAwJTtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHg7Ym9yZGVyLWJvdHRvbS1jb2xvcjojZTZlNmU2O21hcmdpbi1ib3R0b206LTFweH0ubmctZHJvcGRvd24tcGFuZWwubmctc2VsZWN0LXRvcCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbjpmaXJzdC1jaGlsZHtib3JkZXItdG9wLXJpZ2h0LXJhZGl1czo0cHg7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czo0cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1oZWFkZXJ7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1mb290ZXJ7Ym9yZGVyLXRvcDoxcHggc29saWQgI2NjYztwYWRkaW5nOjVweCA3cHh9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXB7dXNlci1zZWxlY3Q6bm9uZTtwYWRkaW5nOjhweCAxMHB4O2ZvbnQtd2VpZ2h0OjUwMDtjb2xvcjpyZ2JhKDAsMCwwLDAuNTQpO2N1cnNvcjpwb2ludGVyfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGdyb3VwLm5nLW9wdGlvbi1kaXNhYmxlZHtjdXJzb3I6ZGVmYXVsdH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRncm91cC5uZy1vcHRpb24tc2VsZWN0ZWQsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0Z3JvdXAubmctb3B0aW9uLXNlbGVjdGVkLm5nLW9wdGlvbi1tYXJrZWR7YmFja2dyb3VuZC1jb2xvcjojZWJmNWZmO2ZvbnQtd2VpZ2h0OjYwMH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb257YmFja2dyb3VuZC1jb2xvcjojZmZmO2NvbG9yOnJnYmEoMCwwLDAsMC44Nyk7cGFkZGluZzo4cHggMTBweH0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkLC5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tc2VsZWN0ZWQubmctb3B0aW9uLW1hcmtlZHtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6I2ViZjVmZn0ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLXNlbGVjdGVkIC5uZy1vcHRpb24tbGFiZWwsLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1zZWxlY3RlZC5uZy1vcHRpb24tbWFya2VkIC5uZy1vcHRpb24tbGFiZWx7Zm9udC13ZWlnaHQ6NjAwfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tbWFya2Vke2JhY2tncm91bmQtY29sb3I6I2Y1ZmFmZjtjb2xvcjojMzMzfS5uZy1kcm9wZG93bi1wYW5lbCAubmctZHJvcGRvd24tcGFuZWwtaXRlbXMgLm5nLW9wdGlvbi5uZy1vcHRpb24tZGlzYWJsZWR7Y29sb3I6I2NjY30ubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24ubmctb3B0aW9uLWNoaWxke3BhZGRpbmctbGVmdDoyMnB4fVtkaXI9XCJydGxcIl0gLm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uLm5nLW9wdGlvbi1jaGlsZHtwYWRkaW5nLXJpZ2h0OjIycHg7cGFkZGluZy1sZWZ0OjB9Lm5nLWRyb3Bkb3duLXBhbmVsIC5uZy1kcm9wZG93bi1wYW5lbC1pdGVtcyAubmctb3B0aW9uIC5uZy10YWctbGFiZWx7Zm9udC1zaXplOjgwJTtmb250LXdlaWdodDo0MDA7cGFkZGluZy1yaWdodDo1cHh9W2Rpcj1cInJ0bFwiXSAubmctZHJvcGRvd24tcGFuZWwgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIC5uZy1vcHRpb24gLm5nLXRhZy1sYWJlbHtwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctcmlnaHQ6MH1bZGlyPVwicnRsXCJdIC5uZy1kcm9wZG93bi1wYW5lbHtkaXJlY3Rpb246cnRsO3RleHQtYWxpZ246cmlnaHR9XG4iLCIvLyogKioqKioqKiByZXNldCAmIG5vcm1hbGl6ZSAqKioqKioqICAqLy9cclxuXHJcbi8vIGJveC1zaXppbmcgdGhlIHNhbWUgZm9yIGFsbCBlbGVtZW50c1xyXG5odG1sIHtcclxuICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xyXG4gIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAtbW96LWJveC1zaXppbmc6IGJvcmRlci1ib3g7XHJcbn1cclxuKiwgKjpiZWZvcmUsICo6YWZ0ZXIge1xyXG4gIGJveC1zaXppbmc6IGluaGVyaXQ7XHJcbiAgLXdlYmtpdC1ib3gtc2l6aW5nOiBpbmhlcml0O1xyXG4gIC1tb3otYm94LXNpemluZzogaW5oZXJpdDtcclxuICBtYXJnaW46IDA7XHJcbiAgcGFkZGluZzogMDtcclxuICBAaW5jbHVkZSB1blNlbGVjdDtcclxufVxyXG5cclxuaHRtbCwgYm9keSwgZGl2LCBzcGFuLCBhcHBsZXQsIG9iamVjdCwgaWZyYW1lLFxyXG5oMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBwLCBibG9ja3F1b3RlLCBwcmUsXHJcbmEsIGFiYnIsIGFjcm9ueW0sIGFkZHJlc3MsIGJpZywgY2l0ZSwgY29kZSxcclxuZGVsLCBkZm4sIGVtLCBpbWcsIGlucywga2JkLCBxLCBzLCBzYW1wLFxyXG5zbWFsbCwgc3RyaWtlLCBzdHJvbmcsIHN1Yiwgc3VwLCB0dCwgdmFyLFxyXG5iLCB1LCBpLCBjZW50ZXIsXHJcbmRsLCBkdCwgZGQsIG9sLCB1bCwgbGksXHJcbmZpZWxkc2V0LCBmb3JtLCBsYWJlbCwgbGVnZW5kLFxyXG50YWJsZSwgY2FwdGlvbiwgdGJvZHksIHRmb290LCB0aGVhZCwgdHIsIHRoLCB0ZCxcclxuYXJ0aWNsZSwgYXNpZGUsIGNhbnZhcywgZGV0YWlscywgZW1iZWQsXHJcbmZpZ3VyZSwgZmlnY2FwdGlvbiwgZm9vdGVyLCBoZWFkZXIsIGhncm91cCxcclxubWVudSwgbmF2LCBvdXRwdXQsIHJ1YnksIHNlY3Rpb24sIHN1bW1hcnksXHJcbnRpbWUsIG1hcmssIGF1ZGlvLCB2aWRlbyB7XHJcbiAgICBib3JkZXI6IDA7XHJcbiAgICBmb250LXNpemU6IDEwMCU7XHJcbiAgICBmb250OiBpbmhlcml0O1xyXG4gICAgdmVydGljYWwtYWxpZ246IGJhc2VsaW5lO1xyXG59XHJcbmFydGljbGUsIGFzaWRlLCBkZXRhaWxzLCBmaWdjYXB0aW9uLCBmaWd1cmUsXHJcbmZvb3RlciwgaGVhZGVyLCBoZ3JvdXAsIG1lbnUsIG5hdiwgc2VjdGlvbiB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxufVxyXG5cclxuYm9keSB7XHJcbiAgIGxpbmUtaGVpZ2h0OiAxO1xyXG4gICBmb250LXN0eWxlOiBub3JtYWw7XHJcbn1cclxub2wsIHVsIHtcclxuICAgIGxpc3Qtc3R5bGU6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZSwgcSB7XHJcbiAgICBxdW90ZXM6IG5vbmU7XHJcbn1cclxuYmxvY2txdW90ZTpiZWZvcmUsIGJsb2NrcXVvdGU6YWZ0ZXIsXHJcbnE6YmVmb3JlLCBxOmFmdGVyIHtcclxuICAgIGNvbnRlbnQ6IG5vbmU7XHJcbn1cclxuXHJcbi8vdGFibGVcclxudGFibGUge1xyXG4gICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTtcclxuICAgIGJvcmRlci1zcGFjaW5nOiAwO1xyXG59XHJcbnRkLFxyXG50aCB7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5cclxuLy9mb3JtcyBlbGVtZW50XHJcbmlucHV0IHtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAmOi13ZWJraXQtYXV0b2ZpbGwge1xyXG4gICAgICAtd2Via2l0LWJveC1zaGFkb3c6IDAgMCAwIDEwMDBweCB3aGl0ZSBpbnNldDtcclxuICAgIH1cclxufVxyXG5cclxuYnV0dG9uLFxyXG5odG1sIGlucHV0W3R5cGU9XCJidXR0b25cIl0sXHJcbmlucHV0W3R5cGU9XCJyZXNldFwiXSxcclxuaW5wdXRbdHlwZT1cInN1Ym1pdFwiXSB7XHJcbiAgLXdlYmtpdC1hcHBlYXJhbmNlOiBidXR0b247XHJcbiAgY3Vyc29yOiBwb2ludGVyO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbn1cclxuYnV0dG9uW2Rpc2FibGVkXSxcclxuaHRtbCBpbnB1dFtkaXNhYmxlZF0ge1xyXG4gIGN1cnNvcjogZGVmYXVsdDtcclxufVxyXG5idXR0b246Oi1tb3otZm9jdXMtaW5uZXIsXHJcbmlucHV0OjotbW96LWZvY3VzLWlubmVyIHtcclxuICBib3JkZXI6IDA7XHJcbiAgcGFkZGluZzogMDtcclxufVxyXG5pbnB1dCB7XHJcbiAgbGluZS1oZWlnaHQ6IG5vcm1hbDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IHRleHRmaWVsZDtcclxuICBib3gtc2l6aW5nOiBjb250ZW50LWJveDtcclxufVxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1jYW5jZWwtYnV0dG9uLFxyXG5pbnB1dFt0eXBlPVwic2VhcmNoXCJdOjotd2Via2l0LXNlYXJjaC1kZWNvcmF0aW9uIHtcclxuICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XHJcbn1cclxuXHJcblxyXG4vL2xpbmtcclxuYSB7XHJcblx0dGV4dC1kZWNvcmF0aW9uOiBub25lO1xyXG5cdCY6YWN0aXZlLFxyXG5cdCY6aG92ZXIsXHJcblx0Jjpmb2N1cyB7XHJcblx0XHRvdXRsaW5lOiAwO1xyXG5cdH1cclxufVxyXG5cclxuaSB7IGZvbnQtc3R5bGU6IGl0YWxpYzsgfVxyXG5iLCBzdHJvbmcgeyBmb250LXdlaWdodDogNzAwOyAgIH1cclxuXHJcbi8vIGltYWdlc1xyXG5pbWcge1xyXG5cdHdpZHRoOiBhdXRvO1xyXG5cdG1heC13aWR0aDogMTAwJTtcclxuXHRoZWlnaHQ6IGF1dG87XHJcbiAgdmVydGljYWwtYWxpZ246IHRvcDtcclxuXHRib3JkZXI6IDA7XHJcbn1cclxuXHJcbi5oaWRkZW4ge1xyXG4gIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDtcclxufVxyXG4iLCIuYXBwLWNvbnRlbnQge1xyXG5cclxuICAucHJlbG9hZGVyIHtcclxuXHJcbiAgICAubG9hZGluZy1iYXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmJ1dHRvbiB7XHJcbiAgYm9yZGVyOiBub25lO1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNXJlbTtcclxuICBmb250LXdlaWdodDogNjAwO1xyXG4gIG91dGxpbmU6IG5vbmU7XHJcbiAgcGFkZGluZzogMCAxcmVtO1xyXG4gIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAmOmRpc2FibGVkOm5vdCgudHJhbnNwYXJlbnQtYnV0dG9uKSwgXHJcbiAgJi5ibHVlLWJ1dHRvbl9yZXNldHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhbHRlcm5hdGl2ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJjpob3ZlciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGRpc2FibGVkQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYuYmx1ZS1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Ib3ZlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICY6Zm9jdXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVCdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5ncmVlbi1idXR0b246bm90KDpkaXNhYmxlZCkge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlbkJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5CdXR0b25Gb2N1c0NvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50dXJxdW9pc2UtYnV0dG9uOm5vdCg6ZGlzYWJsZWQpIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgICY6aG92ZXIge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJjpmb2N1cyB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYudHJhbnNwYXJlbnQtYnV0dG9uIHtcclxuICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXI6IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBtYXJnaW4tcmlnaHQ6IDFyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9jb21wbGV0ZS10ZXN0d2FsbGV0LnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDEuN3JlbTtcclxuICAgICAgaGVpZ2h0OiAxLjdyZW07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxufVxyXG5cclxuLmlucHV0LWJsb2NrIHtcclxuICBkaXNwbGF5OiBmbGV4O1xyXG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XHJcbiAgbWFyZ2luLWJvdHRvbTogMC40cmVtO1xyXG5cclxuICAud3JhcC1sYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcclxuICAgIG1pbi1oZWlnaHQ6IDIuNHJlbTtcclxuICB9XHJcblxyXG4gIGxhYmVsIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbnB1dFt0eXBlPSd0ZXh0J10sIGlucHV0W3R5cGU9J3Bhc3N3b3JkJ10sIHNlbGVjdCB7XHJcbiAgICBib3JkZXI6IG5vbmU7XHJcbiAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICBwYWRkaW5nOiAwIDFyZW07XHJcbiAgICB3aWR0aDogMTAwJTtcclxuICAgIGhlaWdodDogNC4ycmVtO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi50ZXh0YXJlYSB7XHJcbiAgICBoZWlnaHQ6IGF1dG87XHJcblxyXG4gICAgdGV4dGFyZWEge1xyXG4gICAgICBmb250LWZhbWlseTogT3BlblNhbnMsIHNhbnMtc2VyaWY7XHJcbiAgICAgIGJvcmRlcjogbm9uZTtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDFyZW07XHJcbiAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICBtaW4td2lkdGg6IDEwMCU7XHJcbiAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgbWluLWhlaWdodDogNy41cmVtO1xyXG4gICAgICBtYXgtaGVpZ2h0OiA3LjVyZW07XHJcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgICByZXNpemU6IG5vbmU7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5lcnJvci1ibG9jayB7XHJcbiAgICBmb250LXNpemU6IDFyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS40cmVtO1xyXG4gICAgYWxpZ24tc2VsZjogZmxleC1lbmQ7XHJcbiAgICB0ZXh0LWFsaWduOiByaWdodDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmVycm9yLXRleHQge1xyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gIH1cclxufVxyXG5cclxuaW5wdXRbdHlwZT0ncmFkaW8nXS5zdHlsZS1yYWRpbyB7XHJcblxyXG4gICYgKyBsYWJlbCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgIGZvbnQtd2VpZ2h0OiA0MDA7XHJcbiAgICBwYWRkaW5nLWxlZnQ6IDIuNHJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgQGluY2x1ZGUgdW5TZWxlY3Q7XHJcbiAgfVxyXG5cclxuICAmOm5vdChjaGVja2VkKSB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICBvcGFjaXR5OiAwO1xyXG5cclxuICAgICYgKyBsYWJlbCB7XHJcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIH1cclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAwLjdyZW07XHJcbiAgICAgIGxlZnQ6IDA7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICBib3JkZXItcmFkaXVzOiA1MCU7XHJcbiAgICAgIHdpZHRoOiAxLjRyZW07XHJcbiAgICAgIGhlaWdodDogMS40cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjFyZW0gc29saWQgdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgY29udGVudDogJyc7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiAxcmVtO1xyXG4gICAgICBsZWZ0OiAwLjNyZW07XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcclxuICAgICAgb3BhY2l0eTogMDtcclxuICAgICAgd2lkdGg6IDAuOHJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjhyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICY6Y2hlY2tlZCB7XHJcblxyXG4gICAgJiArIGxhYmVsOmFmdGVyIHtcclxuICAgICAgb3BhY2l0eTogMTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmlucHV0W3R5cGU9J2NoZWNrYm94J10uc3R5bGUtY2hlY2tib3gge1xyXG5cclxuICAmICsgbGFiZWwge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgcGFkZGluZy1sZWZ0OiAzLjZyZW07XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIEBpbmNsdWRlIHVuU2VsZWN0O1xyXG4gIH1cclxuXHJcbiAgJjpub3QoY2hlY2tlZCkge1xyXG4gICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgdG9wOiA1MCU7XHJcbiAgICBsZWZ0OiAxLjZyZW07XHJcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICB2aXNpYmlsaXR5OiBoaWRkZW47XHJcblxyXG4gICAgJiArIGxhYmVsIHtcclxuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgfVxyXG5cclxuICAgICYgKyBsYWJlbDpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiAnJztcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IDUwJTtcclxuICAgICAgbGVmdDogMS42cmVtO1xyXG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTUwJSk7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xyXG4gICAgICB3aWR0aDogMS40cmVtO1xyXG4gICAgICBoZWlnaHQ6IDEuNHJlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4xcmVtIHNvbGlkIHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJjpjaGVja2VkIHtcclxuXHJcbiAgICAmICsgbGFiZWw6YmVmb3JlIHtcclxuICAgICAgYmFja2dyb3VuZDogdXJsKH5zcmMvYXNzZXRzL2ljb25zL2NvbXBsZXRlLXRlc3R3YWxsZXQuc3ZnKTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLnN3aXRjaCB7XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAuY2lyY2xlIHtcclxuXHJcbiAgICAmLm9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgICYub2ZmIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwIHtcclxuICBwYWRkaW5nOiAxcmVtIDJyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgYm94LXNoYWRvdzogdGhlbWVkKHRvb2x0aXBTaGFkb3cpO1xyXG4gICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gICAgbGluZS1oZWlnaHQ6IDEuOHJlbTtcclxuICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC10b3Age1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogY2FsYyg1MCUgLSAwLjVyZW0pO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wLWxlZnQge1xyXG4gICAgbWFyZ2luLXRvcDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgYm90dG9tOiAtMXJlbTtcclxuICAgICAgbGVmdDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXRvcC1yaWdodCB7XHJcbiAgICBtYXJnaW4tdG9wOiAtMXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IC0xcmVtO1xyXG4gICAgICByaWdodDogMC43cmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKSB0cmFuc3BhcmVudCB0cmFuc3BhcmVudDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1ib3R0b20tbGVmdCB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IC0xcmVtO1xyXG4gICAgICBsZWZ0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtYm90dG9tLXJpZ2h0IHtcclxuICAgIG1hcmdpbi10b3A6IDFyZW07XHJcblxyXG4gICAgJjpiZWZvcmUge1xyXG4gICAgICBjb250ZW50OiBcIlwiO1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogLTFyZW07XHJcbiAgICAgIHJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtbGVmdCB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTFyZW07XHJcblxyXG4gICAgJjphZnRlciB7XHJcbiAgICAgIGNvbnRlbnQ6IFwiXCI7XHJcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgdG9wOiBjYWxjKDUwJSAtIDAuNXJlbSk7XHJcbiAgICAgIHJpZ2h0OiAtMXJlbTtcclxuICAgICAgYm9yZGVyLXdpZHRoOiAwLjVyZW07XHJcbiAgICAgIGJvcmRlci1zdHlsZTogc29saWQ7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICB0b3A6IGNhbGMoNTAlIC0gMC41cmVtKTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbi50YWJsZS10b29sdGlwLWRpbWVuc2lvbnMge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcbiAgICBvdmVyZmxvdzogYXV0bztcclxuICAgIG1heC13aWR0aDogMjByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAxMHJlbTtcclxuICB9XHJcbn1cclxuXHJcbi5iYWxhbmNlLXRvb2x0aXAge1xyXG4gIHBhZGRpbmc6IDEuM3JlbTtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBiYWNrZ3JvdW5kOiB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcik7XHJcbiAgICBib3gtc2hhZG93OiB0aGVtZWQodG9vbHRpcFNoYWRvdyk7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XHJcbiAgICBmb250LXNpemU6IDEuM3JlbTtcclxuXHJcbiAgICAuYXZhaWxhYmxlIHtcclxuICAgICAgbWFyZ2luLWJvdHRvbTogMS43cmVtO1xyXG5cclxuICAgICAgYiB7XHJcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5sb2NrZWQge1xyXG4gICAgICBtYXJnaW4tYm90dG9tOiAwLjdyZW07XHJcblxyXG4gICAgICBiIHtcclxuICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmxpbmsge1xyXG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLm5nLXRvb2x0aXAtdG9wIHtcclxuICAgIG1hcmdpbi10b3A6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tdG9wOiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLWxlZnQge1xyXG4gICAgbWFyZ2luLWxlZnQ6IC0xcmVtO1xyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0IHtcclxuICAgIG1hcmdpbi1sZWZ0OiAxcmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmFjY291bnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7XHJcbiAgICBtYXgtd2lkdGg6IDE4cmVtO1xyXG4gIH1cclxufVxyXG5cclxuLmNvbW1lbnQtdG9vbHRpcCB7XHJcblxyXG4gIC50b29sdGlwLWlubmVyIHtcclxuICAgIG92ZXJmbG93OiBhdXRvO1xyXG4gICAgd29yZC1icmVhazogYnJlYWstd29yZDtcclxuICAgIG1heC13aWR0aDogNTByZW07XHJcbiAgICBtYXgtaGVpZ2h0OiAyNXJlbTtcclxuICB9XHJcbn1cclxuXHJcbi51cGRhdGUtdG9vbHRpcCB7XHJcbiAgcGFkZGluZzogMS41cmVtO1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgfVxyXG5cclxuICAmLmltcG9ydGFudCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgJi5uZy10b29sdGlwLWxlZnQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YWZ0ZXIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcEltcG9ydGFudEJhY2tncm91bmRDb2xvcikgdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAmLmNyaXRpY2FsIHtcclxuICAgIHBhZGRpbmc6IDIuNXJlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKHRvb2x0aXBDcml0aWNhbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC50b29sdGlwLWlubmVyIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtbGVmdC1ib3R0b20ge1xyXG5cclxuICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKSB0aGVtZWQodG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmLm5nLXRvb2x0aXAtcmlnaHQtYm90dG9tIHtcclxuXHJcbiAgICAgICY6YmVmb3JlIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBib3JkZXItY29sb3I6IHRyYW5zcGFyZW50IHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLnRvb2x0aXAtaW5uZXIge1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICBsaW5lLWhlaWdodDogMS44cmVtO1xyXG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xyXG5cclxuICAgIC5zdGFuZGFyZC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuaW1wb3J0YW50LXVwZGF0ZSB7XHJcbiAgICAgIGZvbnQtc2l6ZTogMS41cmVtO1xyXG4gICAgICBsaW5lLWhlaWdodDogMi43cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZCh0b29sdGlwSW1wb3J0YW50VGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5jcml0aWNhbC11cGRhdGUge1xyXG4gICAgICBmb250LXNpemU6IDEuNXJlbTtcclxuICAgICAgbGluZS1oZWlnaHQ6IDIuN3JlbTtcclxuICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gICAgfVxyXG5cclxuICAgIC53cm9uZy10aW1lIHtcclxuICAgICAgZm9udC1zaXplOiAxLjVyZW07XHJcbiAgICAgIGxpbmUtaGVpZ2h0OiAyLjdyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXJnaW46IDEuNXJlbSAwO1xyXG4gICAgICB3aWR0aDogNXJlbTtcclxuICAgICAgaGVpZ2h0OiA1cmVtO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRvb2x0aXBDcml0aWNhbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gICYubmctdG9vbHRpcC1sZWZ0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogLTEuNXJlbTtcclxuXHJcbiAgICAmOmFmdGVyIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgcmlnaHQ6IC0xcmVtO1xyXG4gICAgICBib3JkZXItd2lkdGg6IDAuNXJlbTtcclxuICAgICAgYm9yZGVyLXN0eWxlOiBzb2xpZDtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQgdHJhbnNwYXJlbnQgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRoZW1lZCh0b29sdGlwQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgJi5uZy10b29sdGlwLXJpZ2h0LWJvdHRvbSB7XHJcbiAgICBtYXJnaW4tbGVmdDogMS41cmVtO1xyXG5cclxuICAgICY6YmVmb3JlIHtcclxuICAgICAgY29udGVudDogXCJcIjtcclxuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICBib3R0b206IDAuNnJlbTtcclxuICAgICAgbGVmdDogLTFyZW07XHJcbiAgICAgIGJvcmRlci13aWR0aDogMC41cmVtO1xyXG4gICAgICBib3JkZXItc3R5bGU6IHNvbGlkO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudCB0aGVtZWQodG9vbHRpcEJhY2tncm91bmRDb2xvcikgdGhlbWVkKHRvb2x0aXBCYWNrZ3JvdW5kQ29sb3IpIHRyYW5zcGFyZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmd4LWNvbnRleHRtZW51IHtcclxuXHJcbiAgLmRyb3Bkb3duLW1lbnUge1xyXG4gICAgYm9yZGVyOiBub25lO1xyXG4gICAgcGFkZGluZzogMDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGJveC1zaGFkb3c6IHRoZW1lZCh0b29sdGlwU2hhZG93KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGxpIHtcclxuICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgZm9udC1mYW1pbHk6IE9wZW5TYW5zLCBzYW5zLXNlcmlmO1xyXG4gICAgZm9udC1zaXplOiAxLjNyZW07XHJcbiAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xyXG4gICAgdGV4dC1hbGlnbjogY2VudGVyO1xyXG4gIH1cclxuXHJcbiAgYSB7XHJcbiAgICBkaXNwbGF5OiBibG9jaztcclxuICAgIHBhZGRpbmc6IDAuNWVtIDFlbTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAmOmhvdmVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjaGFydE9wdGlvbnNIb3ZlckNvbG9yKTtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4ubmctc2VsZWN0IHtcclxuXHJcbiAgJi5jdXN0b20tc2VsZWN0IHtcclxuICAgIHdpZHRoOiAxMDAlO1xyXG5cclxuICAgICYubmctc2VsZWN0LXNpbmdsZSB7XHJcbiAgICAgIC5uZy1zZWxlY3QtY29udGFpbmVyIHtcclxuICAgICAgICAubmctdmFsdWUtY29udGFpbmVyIHtcclxuICAgICAgICAgIC5uZy12YWx1ZSB7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAxLjhyZW07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLXNlbGVjdC1jb250YWluZXIge1xyXG4gICAgICBib3JkZXI6IG5vbmU7XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDA7XHJcbiAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgZm9udC1zaXplOiAxLjRyZW07XHJcbiAgICAgIG91dGxpbmU6IG5vbmU7XHJcbiAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgaGVpZ2h0OiA0LjJyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoaW5wdXRCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5uZy12YWx1ZS1jb250YWluZXIge1xyXG4gICAgICAgIHBhZGRpbmc6IDA7XHJcblxyXG4gICAgICAgIC5uZy1pbnB1dCB7XHJcbiAgICAgICAgICB0b3A6IGF1dG87XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLm5nLWRyb3Bkb3duLXBhbmVsIHtcclxuICAgICAgYm9yZGVyOiBub25lO1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLm5nLWRyb3Bkb3duLXBhbmVsLWl0ZW1zIHtcclxuXHJcbiAgICAgICAgLm5nLW9wdGlvbiB7XHJcbiAgICAgICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgICAgIHBhZGRpbmc6IDFyZW07XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChpbnB1dEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tbWFya2VkIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzZWxlY3RIb3ZlckNvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJi5uZy1vcHRpb24tc2VsZWN0ZWQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdFNlbGVjdGVkQ29sb3IpO1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgY3Vyc29yOiBkZWZhdWx0O1xyXG4gICAgICAgICAgd2lkdGg6IDFyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDFyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOjotd2Via2l0LXNjcm9sbGJhci10cmFjayB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNsaXA6IHBhZGRpbmctYm94O1xyXG4gICAgICAgICAgYm9yZGVyOiAwLjI1cmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzU1NjU3NjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tb2RhbC1jb250YWluZXIsIGFwcC1jb25maXJtLW1vZGFsICB7XHJcblxyXG4gIC5tb2RhbCB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQ6IHRoZW1lZChtb2RhbEJhY2tncm91bmQpO1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5jb250ZW50IHtcclxuXHJcbiAgICAgIC5pY29uLmVycm9yIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uLnN1Y2Nlc3Mge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChncmVlblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbi5pbmZvIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmNsb3NlLWJ1dHRvbiB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNsb3NlQnV0dG9uQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXRyYW5zYWN0aW9uLWRldGFpbHMge1xyXG5cclxuICAudGFibGUge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBib3JkZXItdG9wOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC5yb3cge1xyXG5cclxuICAgICAgLmNlbGwge1xyXG5cclxuICAgICAgICAmLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYua2V5LXZhbHVlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1wcm9ncmVzcy1jb250YWluZXIge1xyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW9wZW4td2FsbGV0LW1vZGFsIHtcclxuXHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtc2VuZC1tb2RhbCB7XHJcbiAgLm1vZGFsIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZDogdGhlbWVkKG1vZGFsQmFja2dyb3VuZCk7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLnRpdGxlIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlci1ib3R0b206IDAuMnJlbSBzb2xpZCB0aGVtZWQodHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICB9XHJcblxyXG4gICAgLmFjdGlvbi1idXR0b24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYWx0ZXJuYXRpdmVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59IiwiJHRoZW1lczogKFxyXG4gIGRhcms6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICMxMzE5MjEsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjMWYyODMzLFxyXG4gICAgb25saW5lQ29sb3I6ICM1Y2RhOWQsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDQzLCA1NCwgNjgsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICM0ZGIxZmYsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzVjZGE5ZCxcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0ZGIxZmYsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzgyZDdmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjNTliNWZkLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5Y2FkYjcsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNiN2QxZTAsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzhkZmNjNixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzYyZTBiMixcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzRkZDBlMSxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM4N2Y0ZjUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjNDJkNWU4LFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogIzJiMzY0NCxcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjMTcxZTI3LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSg0MywgNTQsIDY4LCAwLjUpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDU4LCA2OSwgODUsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzU1NjU3NixcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICMxMTE5MjEsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjMDAwMDAwLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogIzRkYjFmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIzLCAzMSwgMzksIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjksIDg1LCAwLjUpLFxyXG4gICAgdGFibGVCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBtZXNzYWdlTXlCYWNrZ3JvdW5kQ29sb3I6ICMyYTM1NDQsXHJcbiAgICBtZXNzYWdlQnVkZHlCYWNrZ3JvdW5kQ29sb3I6ICMxODIwMmEsXHJcbiAgICBwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcjogIzM0M2Y0YSxcclxuICAgIHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcjogIzVjZGE5ZCxcclxuICAgIGNoYXJ0T3B0aW9uc0JhY2tncm91bmRDb2xvcjogIzJiMzY0NCxcclxuICAgIGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3I6ICM1NTY1NzYsXHJcbiAgICB0b29sdGlwQmFja2dyb3VuZENvbG9yOiAjNDI1MDVmLFxyXG4gICAgdG9vbHRpcEltcG9ydGFudFRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRCYWNrZ3JvdW5kQ29sb3I6ICM1ZjJiMTEsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICB0b29sdGlwQ3JpdGljYWxCYWNrZ3JvdW5kQ29sb3I6ICM1ZjFkMWQsXHJcbiAgICB0b29sdGlwU2hhZG93OiAwIDAgMXJlbSByZ2JhKDAsIDAsIDAsIDAuNSksXHJcbiAgICBtb2RhbEJhY2tncm91bmQ6IHVybCh+c3JjL2Fzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC1kYXJrLnBuZyksXHJcbiAgICBjbG9zZUJ1dHRvbkNvbG9yOiAjNTU2NTc2XHJcbiAgKSxcclxuICBncmF5OiAoXHJcbiAgICBib2R5QmFja2dyb3VuZENvbG9yOiAjMTAxNDE3LFxyXG4gICAgc2lkZWJhckJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAxKSxcclxuICAgIHNpZGViYXJCb3JkZXJDb2xvcjogIzJlMzMzNyxcclxuICAgIG9ubGluZUNvbG9yOiAjNDdjZjhkLFxyXG4gICAgb2ZmbGluZUNvbG9yOiAjZmY1MjUyLFxyXG4gICAgY29udGVudEJhY2tncm91bmRDb2xvcjogcmdiYSgzNywgNDAsIDQzLCAwLjUpLFxyXG4gICAgbWFpblRleHRDb2xvcjogI2UwZTBlMCxcclxuICAgIGFsdGVybmF0aXZlVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgb3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBibHVlVGV4dENvbG9yOiAjNDJhNWY1LFxyXG4gICAgZ3JlZW5UZXh0Q29sb3I6ICM0N2NmOGQsXHJcbiAgICBvcmFuZ2VUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICByZWRUZXh0Q29sb3I6ICNmZjUyNTIsXHJcbiAgICBibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNDJhNWY1LFxyXG4gICAgYmx1ZUJ1dHRvbkhvdmVyQ29sb3I6ICM4NmQ2ZmYsXHJcbiAgICBibHVlQnV0dG9uRm9jdXNDb2xvcjogIzVmYjZmYyxcclxuICAgIGRpc2FibGVkQnV0dG9uQmFja2dyb3VuZENvbG9yOiAjNzk4NDhmLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Ib3ZlckNvbG9yOiAjYTFhZWJiLFxyXG4gICAgZGlzYWJsZWRCdXR0b25Gb2N1c0NvbG9yOiAjOGE5NTlmLFxyXG4gICAgZ3JlZW5CdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBncmVlbkJ1dHRvbkhvdmVyQ29sb3I6ICM3YmY2YzYsXHJcbiAgICBncmVlbkJ1dHRvbkZvY3VzQ29sb3I6ICM1Y2RjOWUsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMzZWM1ZDcsXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Ib3ZlckNvbG9yOiAjNzJlZGZlLFxyXG4gICAgdHVycXVvaXNlQnV0dG9uRm9jdXNDb2xvcjogIzUwZDBlMSxcclxuICAgIHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3I6ICMyZjM0MzgsXHJcbiAgICBpbnB1dEJhY2tncm91bmRDb2xvcjogIzI5MmQzMSxcclxuICAgIHNlbGVjdEhvdmVyQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHNlbGVjdFNlbGVjdGVkQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIHN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoMzcsIDQwLCA0MywgMC41KSxcclxuICAgIGFjY291bnRIb3ZlckJhY2tncm91bmRDb2xvcjogcmdiYSg1OCwgNjIsIDY2LCAwLjUpLFxyXG4gICAgYWNjb3VudE1haW5UZXh0Q29sb3I6ICNlMGUwZTAsXHJcbiAgICBhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3I6ICM1NjVjNjIsXHJcbiAgICBhY2NvdW50SW5kaWNhdG9yVGV4dENvbG9yOiAjMWExYTFhLFxyXG4gICAgYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcjogIzAwMDAwMCxcclxuICAgIGFjY291bnRJbmRpY2F0b3JCYWNrZ3JvdW5kQ29sb3I6ICM0MmE1ZjUsXHJcbiAgICB0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcjogcmdiYSgyOCwgMzAsIDMzLCAwLjUpLFxyXG4gICAgdGFiSG92ZXJCYWNrZ3JvdW5kQ29sb3I6IHJnYmEoNTgsIDYyLCA2NiwgMC41KSxcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjMzAzNjNjLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjMjUyOTJkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICMzNjNhM2UsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0N2NmOGQsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICMyOTJkMzEsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjNTE1OTYwLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogIzNlNDY0YyxcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZjZmMDAsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjNTUyNDBkLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmY1MjUyLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjNGMxOTE5LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgwLCAwLCAwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtZ3JheS5wbmcpLFxyXG4gICAgY2xvc2VCdXR0b25Db2xvcjogIzUxNTk2MFxyXG4gICksXHJcbiAgd2hpdGU6IChcclxuICAgIGJvZHlCYWNrZ3JvdW5kQ29sb3I6ICNlZWVlZWUsXHJcbiAgICBzaWRlYmFyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDEpLFxyXG4gICAgc2lkZWJhckJvcmRlckNvbG9yOiAjZWJlYmViLFxyXG4gICAgb25saW5lQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBvZmZsaW5lQ29sb3I6ICNmZjUyNTIsXHJcbiAgICBjb250ZW50QmFja2dyb3VuZENvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSksXHJcbiAgICBtYWluVGV4dENvbG9yOiAjNDM0NTRiLFxyXG4gICAgYWx0ZXJuYXRpdmVUZXh0Q29sb3I6ICNmZWZlZmUsXHJcbiAgICBvcHRpb25hbFRleHRDb2xvcjogI2EwYTVhYixcclxuICAgIGJsdWVUZXh0Q29sb3I6ICMyYzk1ZjEsXHJcbiAgICBncmVlblRleHRDb2xvcjogIzQ2YzE3MixcclxuICAgIG9yYW5nZVRleHRDb2xvcjogI2ZmNmYwMCxcclxuICAgIHJlZFRleHRDb2xvcjogI2ZmNTI1MixcclxuICAgIGJsdWVCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICMyYzk1ZjEsXHJcbiAgICBibHVlQnV0dG9uSG92ZXJDb2xvcjogIzVjYjNmZixcclxuICAgIGJsdWVCdXR0b25Gb2N1c0NvbG9yOiAjMzc5ZmZhLFxyXG4gICAgZGlzYWJsZWRCdXR0b25CYWNrZ3JvdW5kQ29sb3I6ICM5MGE0YWUsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkhvdmVyQ29sb3I6ICNhZWJlYzYsXHJcbiAgICBkaXNhYmxlZEJ1dHRvbkZvY3VzQ29sb3I6ICNhN2I5YzIsXHJcbiAgICBncmVlbkJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzQ2YzE3MixcclxuICAgIGdyZWVuQnV0dG9uSG92ZXJDb2xvcjogIzVhZDU4NixcclxuICAgIGdyZWVuQnV0dG9uRm9jdXNDb2xvcjogIzUzYzc3YyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkJhY2tncm91bmRDb2xvcjogIzI2YjZjNyxcclxuICAgIHR1cnF1b2lzZUJ1dHRvbkhvdmVyQ29sb3I6ICM1MmNiZDksXHJcbiAgICB0dXJxdW9pc2VCdXR0b25Gb2N1c0NvbG9yOiAjMzFiZWNmLFxyXG4gICAgdHJhbnNwYXJlbnRCdXR0b25Cb3JkZXJDb2xvcjogI2ViZWJlYixcclxuICAgIGlucHV0QmFja2dyb3VuZENvbG9yOiAjZTZlNmU2LFxyXG4gICAgc2VsZWN0SG92ZXJDb2xvcjogcmdiYSgyNDAsIDI0MCwgMjQwLCAwLjUpLFxyXG4gICAgc2VsZWN0U2VsZWN0ZWRDb2xvcjogcmdiYSgyMjQsIDIyNCwgMjI0LCAwLjUpLFxyXG4gICAgc3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZTBlMGUwLFxyXG4gICAgYWNjb3VudEJhY2tncm91bmRDb2xvcjogcmdiYSgzMCwgMTM2LCAyMjksIDEpLFxyXG4gICAgYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yOiByZ2JhKDI0MCwgMjQwLCAyNDAsIDAuNSksXHJcbiAgICBhY2NvdW50TWFpblRleHRDb2xvcjogI2ZmZmZmZixcclxuICAgIGFjY291bnRPcHRpb25hbFRleHRDb2xvcjogIzkxYmFmMSxcclxuICAgIGFjY291bnRJbmRpY2F0b3JUZXh0Q29sb3I6ICM0MzQ1NGIsXHJcbiAgICBhY2NvdW50U3dpdGNoQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYkluYWN0aXZlQmFja2dyb3VuZENvbG9yOiByZ2JhKDIyNCwgMjI0LCAyMjQsIDAuNSksXHJcbiAgICB0YWJIb3ZlckJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRhYmxlQmFja2dyb3VuZENvbG9yOiAjZmZmZmZmLFxyXG4gICAgbWVzc2FnZU15QmFja2dyb3VuZENvbG9yOiAjZmZmLFxyXG4gICAgbWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yOiAjZWRlZGVkLFxyXG4gICAgcHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3I6ICNkY2RjZGMsXHJcbiAgICBwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3I6ICM0NmMxNzIsXHJcbiAgICBjaGFydE9wdGlvbnNCYWNrZ3JvdW5kQ29sb3I6ICNlMGUwZTAsXHJcbiAgICBjaGFydE9wdGlvbnNIb3ZlckNvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcEJhY2tncm91bmRDb2xvcjogI2ZmZmZmZixcclxuICAgIHRvb2x0aXBJbXBvcnRhbnRUZXh0Q29sb3I6ICNmZmZmZmYsXHJcbiAgICB0b29sdGlwSW1wb3J0YW50QmFja2dyb3VuZENvbG9yOiAjZWY2YzAwLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsVGV4dENvbG9yOiAjZmZmZmZmLFxyXG4gICAgdG9vbHRpcENyaXRpY2FsQmFja2dyb3VuZENvbG9yOiAjZTUzOTM1LFxyXG4gICAgdG9vbHRpcFNoYWRvdzogMCAwIDFyZW0gcmdiYSgxMjAsIDEyMCwgMTIwLCAwLjUpLFxyXG4gICAgbW9kYWxCYWNrZ3JvdW5kOiB1cmwofnNyYy9hc3NldHMvaW1hZ2VzL2JhY2tncm91bmQtd2hpdGUucG5nKSxcclxuICAgIGNsb3NlQnV0dG9uQ29sb3I6ICM0MzQ1NGJcclxuICApXHJcbik7XHJcblxyXG5cclxuXHJcblxyXG5cclxuIiwiYXBwLW1haW4sIGFwcC1jcmVhdGUtd2FsbGV0LCBhcHAtb3Blbi13YWxsZXQsIGFwcC1yZXN0b3JlLXdhbGxldCwgYXBwLXNlZWQtcGhyYXNlLCBhcHAtd2FsbGV0LWRldGFpbHMsIGFwcC1hc3NpZ24tYWxpYXMsIGFwcC1lZGl0LWFsaWFzLCBhcHAtdHJhbnNmZXItYWxpYXMsIGFwcC1zZXR0aW5ncywgYXBwLWxvZ2luIHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1tYWluIHtcclxuXHJcbiAgLmNvbnRlbnQge1xyXG5cclxuICAgIC5hZGQtd2FsbGV0IHtcclxuXHJcbiAgICAgIC5hZGQtd2FsbGV0LWhlbHAge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZWVkLXBocmFzZSB7XHJcblxyXG4gIC5zZWVkLXBocmFzZS1jb250ZW50IHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXdhbGxldC1kZXRhaWxzIHtcclxuXHJcbiAgLnNlZWQtcGhyYXNlIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1zZXR0aW5ncyB7XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIGhlaWdodDogMTAwJTtcclxuICAgIG92ZXJmbG93LXk6IGF1dG87XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuXHJcbiAgICAudGhlbWUtc2VsZWN0aW9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNjYWxlLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgICAuYnV0dG9uLWJsb2NrIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQodGFiSW5hY3RpdmVCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLmxhYmVsIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLWxvZ2luIHtcclxuICBtaW4td2lkdGg6IGluaGVyaXQ7XHJcbn1cclxuIiwiYXBwLXNpZGViYXIge1xyXG5cclxuICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChzaWRlYmFyQmFja2dyb3VuZENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLWFjY291bnRzIHtcclxuXHJcbiAgICAuc2lkZWJhci1hY2NvdW50cy1oZWFkZXIge1xyXG5cclxuICAgICAgaDMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNpZGViYXItYWNjb3VudHMtbGlzdCB7XHJcblxyXG4gICAgICAuc2lkZWJhci1hY2NvdW50IHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2lkZWJhci1hY2NvdW50LXJvdyB7XHJcblxyXG4gICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAuaW5kaWNhdG9yIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlQnV0dG9uQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKGFsdGVybmF0aXZlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5wcm9ncmVzcy1iYXItY29udGFpbmVyIHtcclxuXHJcbiAgICAgICAgICAgIC5wcm9ncmVzcy1iYXIge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmLmFjY291bnQtc3luY2hyb25pemF0aW9uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLnNpZGViYXItYWNjb3VudC1yb3cge1xyXG5cclxuICAgICAgICAgICAgLnRleHQge1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudE9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuc3dpdGNoIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudFN3aXRjaEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgJi5hY2NvdW50LXN5bmNocm9uaXphdGlvbiB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50T3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpob3Zlcjpub3QoLmFjdGl2ZSkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCh0byBib3R0b20sIHRyYW5zcGFyZW50IDAlLCB0aGVtZWQoc2lkZWJhckJhY2tncm91bmRDb2xvcikgMTAwJSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXNldHRpbmdzIHtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYm9yZGVyLWJvdHRvbTogMC4ycmVtIHNvbGlkIHRoZW1lZChzaWRlYmFyQm9yZGVyQ29sb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIC53cmFwLWJ1dHRvbiB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgYnV0dG9uIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGFjY291bnRCYWNrZ3JvdW5kQ29sb3IpIWltcG9ydGFudDtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChhY2NvdW50TWFpblRleHRDb2xvcikhaW1wb3J0YW50O1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChhY2NvdW50SW5kaWNhdG9yQmFja2dyb3VuZENvbG9yKSFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5zaWRlYmFyLXN5bmNocm9uaXphdGlvbi1zdGF0dXMge1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICAuc3RhdHVzLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAub2ZmbGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvZmZsaW5lQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9ubGluZTpiZWZvcmUge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvbmxpbmVDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgICAgIC5zeW5jaW5nIHtcclxuXHJcbiAgICAgICAgICAucHJvZ3Jlc3MtYmFyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC5maWxsIHtcclxuXHJcbiAgICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJGdWxsQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5sb2FkaW5nIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnVwZGF0ZS1jb250YWluZXIge1xyXG5cclxuICAgICAgLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmltcG9ydGFudCB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmNyaXRpY2FsIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBjb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAudGltZSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICAmLnN0YW5kYXJkIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJi5pbXBvcnRhbnQge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQob3JhbmdlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuY3JpdGljYWwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYudGltZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtd2FsbGV0IHtcclxuXHJcbiAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gIH1cclxuXHJcbiAgLmhlYWRlciB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLmFsaWFzIHtcclxuXHJcbiAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmljb24ge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAudGFicyB7XHJcblxyXG4gICAgLnRhYnMtaGVhZGVyIHtcclxuXHJcbiAgICAgIC50YWIge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZCh0YWJJbmFjdGl2ZUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5pbmRpY2F0b3Ige1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvckJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIGNvbG9yOiB0aGVtZWQoYWNjb3VudEluZGljYXRvclRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLmFjdGl2ZSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6aG92ZXI6bm90KC5hY3RpdmUpOm5vdCguZGlzYWJsZWQpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYkhvdmVyQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAudGFicy1jb250ZW50IHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChjb250ZW50QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXNlbmQge1xyXG5cclxuICAuZm9ybS1zZW5kIHtcclxuXHJcbiAgICAuc2VuZC1zZWxlY3Qge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmljb24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAuYWRkaXRpb25hbC1kZXRhaWxzIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGJvcmRlcjogMC4ycmVtIHNvbGlkIHRoZW1lZCh0cmFuc3BhcmVudEJ1dHRvbkJvcmRlckNvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXJlY2VpdmUge1xyXG5cclxuICAuYnRuLWNvcHktYWRkcmVzcyB7XHJcblxyXG4gICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1oaXN0b3J5IHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgJi5sb2NrZWQtdHJhbnNhY3Rpb24ge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBjb2xvcjogdGhlbWVkKG9wdGlvbmFsVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzEpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzIpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bnRoLWNoaWxkKDRuKzMpIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOm50aC1jaGlsZCg0bis0KSB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cyB7XHJcblxyXG4gICAgICAgICAgLmNvbmZpcm1hdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAuZmlsbCB7XHJcblxyXG4gICAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHByb2dyZXNzQmFyRnVsbEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChvcmFuZ2VUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnVubG9jay10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zdGF0dXMuc2VuZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocmVkVGV4dENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnN0YXR1cy5yZWNlaXZlZCB7XHJcblxyXG4gICAgICAgICAgLnN0YXR1cy10cmFuc2FjdGlvbiB7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoZ3JlZW5UZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtY29udHJhY3RzIHtcclxuXHJcbiAgLndyYXAtdGFibGUge1xyXG5cclxuICAgIC5jb250cmFjdCB7XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgICYubmV3LCAmLmFsZXJ0IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHJlZFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLnB1cmNoYXNlLCAmLnNlbGwge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtcHVyY2hhc2Uge1xyXG5cclxuICAuZm9ybS1wdXJjaGFzZSB7XHJcblxyXG4gICAgLnB1cmNoYXNlLXNlbGVjdCB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKG1haW5UZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuaWNvbiB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5wdXJjaGFzZS1zdGF0ZXMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC5hZGRpdGlvbmFsLWRldGFpbHMge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgYm9yZGVyOiAwLjJyZW0gc29saWQgdGhlbWVkKHRyYW5zcGFyZW50QnV0dG9uQm9yZGVyQ29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAucHJvZ3Jlc3MtYmFyLWNvbnRhaW5lciB7XHJcblxyXG4gICAgLnByb2dyZXNzLWJhciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQocHJvZ3Jlc3NCYXJCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAucHJvZ3Jlc3MtYmFyLWZ1bGwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChwcm9ncmVzc0JhckZ1bGxCYWNrZ3JvdW5kQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLW1lc3NhZ2VzIHtcclxuXHJcbiAgdGFibGUge1xyXG5cclxuICAgIHRib2R5IHtcclxuXHJcbiAgICAgIHRyIHtcclxuXHJcbiAgICAgICAgdGQ6Zmlyc3QtY2hpbGQge1xyXG5cclxuICAgICAgICAgIHNwYW4ge1xyXG4gICAgICAgICAgICBAaW5jbHVkZSB0ZXh0LXRydW5jYXRlO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC5pY29uIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChyZWRUZXh0Q29sb3IpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG5hcHAtdHlwaW5nLW1lc3NhZ2Uge1xyXG5cclxuICAuaGVhZCB7XHJcblxyXG4gICAgLmludGVybG9jdXRvciB7XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBjb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAubWVzc2FnZXMtY29udGVudCB7XHJcblxyXG4gICAgLm1lc3NhZ2VzLWxpc3Qge1xyXG5cclxuICAgICAgZGl2IHtcclxuXHJcbiAgICAgICAgJi5kYXRlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmLm15IHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgJjpiZWZvcmUge1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgICB0b3A6IDA7XHJcbiAgICAgICAgICAgIGxlZnQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIGJvcmRlcjogMS4ycmVtIHNvbGlkIHRyYW5zcGFyZW50O1xyXG5cclxuICAgICAgICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgICAgICAgYm9yZGVyLXRvcC1jb2xvcjogdGhlbWVkKG1lc3NhZ2VNeUJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYnVkZHkge1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAmOmFmdGVyIHtcclxuXHJcbiAgICAgICAgICAgIEBpbmNsdWRlIHBzZXVkbztcclxuICAgICAgICAgICAgcmlnaHQ6IC0xLjFyZW07XHJcbiAgICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgICAgYm9yZGVyOiAxLjJyZW0gc29saWQgdHJhbnNwYXJlbnQ7XHJcblxyXG4gICAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgICBib3JkZXItdG9wLWNvbG9yOiB0aGVtZWQobWVzc2FnZUJ1ZGR5QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuYXBwLXN0YWtpbmcge1xyXG5cclxuICAuY2hhcnQtaGVhZGVyIHtcclxuXHJcbiAgICAuZ2VuZXJhbCB7XHJcblxyXG4gICAgICAubGFiZWwge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQob3B0aW9uYWxUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLm9wdGlvbnMge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLnNlbGVjdGVkIHtcclxuICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcclxuICAgICAgZmxleC1ncm93OiAxO1xyXG4gICAgICBmb250LXNpemU6IDEuNnJlbTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5jaGFydC1vcHRpb25zIHtcclxuXHJcbiAgICAudGl0bGUge1xyXG5cclxuICAgICAgQGluY2x1ZGUgdGhlbWlmeSgkdGhlbWVzKSB7XHJcbiAgICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAub3B0aW9ucyB7XHJcblxyXG4gICAgICBidXR0b24ge1xyXG5cclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY2hhcnRPcHRpb25zQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYuYWN0aXZlIHtcclxuXHJcbiAgICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGNoYXJ0T3B0aW9uc0hvdmVyQ29sb3IpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLmlucHV0LWJsb2NrLWFsaWFzIHtcclxuICBwb3NpdGlvbjogcmVsYXRpdmU7XHJcblxyXG4gIC5hbGlhcy1kcm9wZG93biB7XHJcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICB0b3A6IDYuNXJlbTtcclxuICAgIG1heC1oZWlnaHQ6IDEwcmVtO1xyXG4gICAgb3ZlcmZsb3c6IGF1dG87XHJcbiAgICB3aWR0aDogMTAwJTtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGlucHV0QmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICBkaXYge1xyXG4gICAgICBmb250LXNpemU6IDEuNHJlbTtcclxuICAgICAgcGFkZGluZzogMXJlbTtcclxuXHJcbiAgICAgICY6aG92ZXIge1xyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHNlbGVjdEhvdmVyQ29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJhcHAtY29udGFjdHMsIGFwcC1hZGQtY29udGFjdHMsXHJcbmFwcC1jb250YWN0LXNlbmQsIGFwcC1leHBvcnQtaW1wb3J0IHtcclxuICBmbGV4OiAxIDEgYXV0bztcclxuICBwYWRkaW5nOiAzcmVtO1xyXG4gIG1pbi13aWR0aDogODVyZW07XHJcblxyXG4gIC5jb250ZW50IHtcclxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgIHBhZGRpbmc6IDNyZW07XHJcbiAgICBtaW4taGVpZ2h0OiAxMDAlO1xyXG5cclxuICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoY29udGVudEJhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgLmhlYWQge1xyXG4gICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgIHRvcDogMDtcclxuICAgICAgbGVmdDogMDtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmFwcC1jb250YWN0cyB7XHJcbiAgXHJcbiAgdGFibGUge1xyXG5cclxuICAgIC5hbGlhcyB7XHJcbiAgXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGJ1dHRvbiB7XHJcbiAgICBcclxuICAgICAgLmljb24ge1xyXG4gIFxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKGJsdWVUZXh0Q29sb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gIFxyXG4gICAgICBzcGFuIHtcclxuICAgICAgICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGNvbG9yOiB0aGVtZWQobWFpblRleHRDb2xvcilcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC5mb290ZXIge1xyXG4gICAgXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgIH1cclxuICBcclxuICAgIC5pbXBvcnQtYnRuIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5pY29uIHtcclxuICBcclxuICAgICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgXHJcbn1cclxuXHJcbmFwcC1jb250YWN0LXNlbmQge1xyXG4gIFxyXG4gIC53YWxsZXRzLXNlbGVjdGlvbiB7XHJcblxyXG4gICAgYnV0dG9uIHtcclxuXHJcbiAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgIGNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn0iLCIuaGVhZCB7XHJcbiAgZGlzcGxheTogZmxleDtcclxuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XHJcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gIGZvbnQtc2l6ZTogMS4zcmVtO1xyXG4gIHBhZGRpbmc6IDAgM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuICBoZWlnaHQ6IDNyZW07XHJcblxyXG4gIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgY29sb3I6IHRoZW1lZChibHVlVGV4dENvbG9yKTtcclxuICB9XHJcblxyXG4gIC5icmVhZGNydW1icyB7XHJcblxyXG4gICAgPiBzcGFuLCBhIHtcclxuXHJcbiAgICAgICY6bm90KDpsYXN0LWNoaWxkKSB7XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICBtYXJnaW4tcmlnaHQ6IDIwcHg7XHJcbiAgICAgICAgb3V0bGluZS1zdHlsZTogbm9uZTtcclxuXHJcbiAgICAgICAgJjphZnRlciB7XHJcblxyXG4gICAgICAgICAgQGluY2x1ZGUgcHNldWRvO1xyXG4gICAgICAgICAgdG9wOiAwLjVyZW07XHJcbiAgICAgICAgICByaWdodDogLTEuNXJlbTtcclxuICAgICAgICAgIHdpZHRoOiAwLjlyZW07XHJcbiAgICAgICAgICBoZWlnaHQ6IDAuOXJlbTtcclxuICAgICAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9hcnJvdy1yaWdodC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICAgICAgICBtYXNrLXNpemU6IGNvdmVyO1xyXG5cclxuICAgICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAuYmFjay1idG4ge1xyXG4gICAgZGlzcGxheTogZmxleDtcclxuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGNvbG9yOiAjNGRiMWZmO1xyXG4gICAgZm9udC1zaXplOiBpbmhlcml0O1xyXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcclxuICAgIGxpbmUtaGVpZ2h0OiAxLjNyZW07XHJcbiAgICBwYWRkaW5nOiAwO1xyXG4gICAgaGVpZ2h0OiBhdXRvO1xyXG5cclxuICAgIC5pY29uIHtcclxuICAgICAgbWFyZ2luLXJpZ2h0OiAwLjdyZW07XHJcbiAgICAgIG1hc2s6IHVybCh+c3JjL2Fzc2V0cy9pY29ucy9iYWNrLnN2Zykgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgICAgd2lkdGg6IDAuOXJlbTtcclxuICAgICAgaGVpZ2h0OiAwLjlyZW07XHJcblxyXG4gICAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0aGVtZWQoYmx1ZVRleHRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLnNjcm9sbGVkLWNvbnRlbnQge1xyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhciB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcclxuICAgIGN1cnNvcjogZGVmYXVsdDtcclxuICAgIHdpZHRoOiAxcmVtO1xyXG4gICAgaGVpZ2h0OiAxcmVtO1xyXG4gIH1cclxuXHJcbiAgJjo6LXdlYmtpdC1zY3JvbGxiYXItdHJhY2sge1xyXG4gICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XHJcbiAgfVxyXG5cclxuICAmOjotd2Via2l0LXNjcm9sbGJhci10aHVtYiB7XHJcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNTU2NTc2O1xyXG4gICAgYmFja2dyb3VuZC1jbGlwOiBwYWRkaW5nLWJveDtcclxuICAgIGJvcmRlcjogMC4yNXJlbSBzb2xpZCB0cmFuc3BhcmVudDtcclxuICAgIGJvcmRlci1yYWRpdXM6IDAuNXJlbTtcclxuICB9XHJcblxyXG4gICY6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHtcclxuICAgIGJhY2tncm91bmQtY29sb3I6ICM1NTY1NzY7XHJcbiAgfVxyXG59XHJcbiIsInRhYmxlIHtcclxuICBmb250LXNpemU6IDEuM3JlbTtcclxuICB3aWR0aDogMTAwJTtcclxuXHJcbiAgdGhlYWQge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChvcHRpb25hbFRleHRDb2xvcik7XHJcbiAgICB9XHJcblxyXG4gICAgdHIge1xyXG4gICAgICBoZWlnaHQ6IDRyZW07XHJcblxyXG4gICAgICB0aCB7XHJcbiAgICAgICAgcGFkZGluZzogMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogYm90dG9tO1xyXG5cclxuICAgICAgICAmOmZpcnN0LWNoaWxkIHtcclxuICAgICAgICAgIHBhZGRpbmctbGVmdDogM3JlbTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICY6bGFzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAzcmVtO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdGJvZHkge1xyXG4gICAgdGV4dC1hbGlnbjogbGVmdDtcclxuXHJcbiAgICBAaW5jbHVkZSB0aGVtaWZ5KCR0aGVtZXMpIHtcclxuICAgICAgY29sb3I6IHRoZW1lZChtYWluVGV4dENvbG9yKTtcclxuICAgIH1cclxuXHJcbiAgICB0ciB7XHJcbiAgICAgIGhlaWdodDogMy41cmVtO1xyXG5cclxuICAgICAgJjpudGgtY2hpbGQob2RkKSB7XHJcblxyXG4gICAgICAgIEBpbmNsdWRlIHRoZW1pZnkoJHRoZW1lcykge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogdGhlbWVkKHRhYmxlQmFja2dyb3VuZENvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHRkIHtcclxuICAgICAgICBsaW5lLWhlaWdodDogMS43cmVtO1xyXG4gICAgICAgIHBhZGRpbmc6IDAgMXJlbTtcclxuICAgICAgICB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xyXG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XHJcbiAgICAgICAgbWF4LXdpZHRoOiAyMHJlbTtcclxuXHJcbiAgICAgICAgJjpmaXJzdC1jaGlsZCB7XHJcbiAgICAgICAgICBwYWRkaW5nLWxlZnQ6IDNyZW07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAmOmxhc3QtY2hpbGQge1xyXG4gICAgICAgICAgcGFkZGluZy1yaWdodDogM3JlbTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiLy8gQkFTRVxyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL21peGlucyc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvbnVsbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2Jhc2UvdGhlbWUnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9iYXNlL2Jhc2UnO1xyXG5cclxuLy8gTEFZT1VUXHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL2xheW91dC9tYWluJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NldHRpbmdzJztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L3NpZGViYXInO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9sYXlvdXQvd2FsbGV0JztcclxuQGltcG9ydCAnYXNzZXRzL3Njc3MvbGF5b3V0L2NvbnRhY3QnO1xyXG5cclxuLy8gTU9EVUxFU1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL2hlYWQnO1xyXG5AaW1wb3J0ICdhc3NldHMvc2Nzcy9tb2R1bGVzL3Njcm9sbCc7XHJcbkBpbXBvcnQgJ2Fzc2V0cy9zY3NzL21vZHVsZXMvdGFibGUnO1xyXG5cclxuQGltcG9ydCBcIn5Abmctc2VsZWN0L25nLXNlbGVjdC90aGVtZXMvZGVmYXVsdC50aGVtZS5jc3NcIjtcclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1MaWdodC50dGYpO1xyXG4gIGZvbnQtd2VpZ2h0OiAzMDA7XHJcbn1cclxuXHJcbkBmb250LWZhY2Uge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2FucztcclxuICBzcmM6IHVybCh+c3JjL2Fzc2V0cy9mb250cy9PcGVuU2Fucy1SZWd1bGFyLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDQwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLVNlbWlCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDYwMDtcclxufVxyXG5cclxuQGZvbnQtZmFjZSB7XHJcbiAgZm9udC1mYW1pbHk6IE9wZW5TYW5zO1xyXG4gIHNyYzogdXJsKH5zcmMvYXNzZXRzL2ZvbnRzL09wZW5TYW5zLUJvbGQudHRmKTtcclxuICBmb250LXdlaWdodDogNzAwO1xyXG59XHJcblxyXG5AZm9udC1mYWNlIHtcclxuICBmb250LWZhbWlseTogT3BlblNhbnM7XHJcbiAgc3JjOiB1cmwofnNyYy9hc3NldHMvZm9udHMvT3BlblNhbnMtRXh0cmFCb2xkLnR0Zik7XHJcbiAgZm9udC13ZWlnaHQ6IDgwMDtcclxufVxyXG5cclxuXHJcbmh0bWwge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEwcHg7XHJcbn1cclxuXHJcbmJvZHkge1xyXG4gIGZvbnQtZmFtaWx5OiBPcGVuU2Fucywgc2Fucy1zZXJpZjtcclxuICBmb250LXNpemU6IDEuNnJlbTtcclxuICB3aWR0aDogMTAwdnc7XHJcbiAgaGVpZ2h0OiAxMDB2aDtcclxuXHJcbiAgJi50aGVtZS1kYXJrIHtcclxuICAgIGJhY2tncm91bmQ6ICMxMzE5MjEgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWRhcmsucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS1ncmF5IHtcclxuICAgIGJhY2tncm91bmQ6ICMxMDE0MTcgdXJsKFwiYXNzZXRzL2ltYWdlcy9iYWNrZ3JvdW5kLWdyYXkucG5nXCIpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICBiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xyXG4gIH1cclxuXHJcbiAgJi50aGVtZS13aGl0ZSB7XHJcbiAgICBiYWNrZ3JvdW5kOiAjZWVlZWVlIHVybChcImFzc2V0cy9pbWFnZXMvYmFja2dyb3VuZC13aGl0ZS5wbmdcIikgbm8tcmVwZWF0IGNlbnRlcjtcclxuICAgIGJhY2tncm91bmQtc2l6ZTogY292ZXI7XHJcbiAgfVxyXG5cclxuICBhcHAtcm9vdCB7XHJcbiAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgd2lkdGg6IDEwMCU7XHJcbiAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgfVxyXG59XHJcblxyXG4udXBkYXRlLXRvb2x0aXAge1xyXG5cclxuICAudG9vbHRpcC1pbm5lciB7XHJcblxyXG4gICAgLmljb24ge1xyXG4gICAgICBtYXNrOiB1cmwoYXNzZXRzL2ljb25zL3VwZGF0ZS1hbGVydC5zdmcpIG5vLXJlcGVhdCBjZW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ== */\", '', '']]","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n\nvar stylesInDom = {};\n\nvar\tmemoize = function (fn) {\n\tvar memo;\n\n\treturn function () {\n\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\treturn memo;\n\t};\n};\n\nvar isOldIE = memoize(function () {\n\t// Test for IE <= 9 as proposed by Browserhacks\n\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n\t// Tests for existence of standard globals is to allow style-loader\n\t// to operate correctly into non-standard environments\n\t// @see https://github.com/webpack-contrib/style-loader/issues/177\n\treturn window && document && document.all && !window.atob;\n});\n\nvar getTarget = function (target, parent) {\n if (parent){\n return parent.querySelector(target);\n }\n return document.querySelector(target);\n};\n\nvar getElement = (function (fn) {\n\tvar memo = {};\n\n\treturn function(target, parent) {\n // If passing function in options, then use it for resolve \"head\" element.\n // Useful for Shadow Root style i.e\n // {\n // insertInto: function () { return document.querySelector(\"#foo\").shadowRoot }\n // }\n if (typeof target === 'function') {\n return target();\n }\n if (typeof memo[target] === \"undefined\") {\n\t\t\tvar styleTarget = getTarget.call(this, target, parent);\n\t\t\t// Special case to return head of iframe instead of iframe itself\n\t\t\tif (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n\t\t\t\ttry {\n\t\t\t\t\t// This will throw an exception if access to iframe is blocked\n\t\t\t\t\t// due to cross-origin restrictions\n\t\t\t\t\tstyleTarget = styleTarget.contentDocument.head;\n\t\t\t\t} catch(e) {\n\t\t\t\t\tstyleTarget = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmemo[target] = styleTarget;\n\t\t}\n\t\treturn memo[target]\n\t};\n})();\n\nvar singleton = null;\nvar\tsingletonCounter = 0;\nvar\tstylesInsertedAtTop = [];\n\nvar\tfixUrls = require(\"./urls\");\n\nmodule.exports = function(list, options) {\n\tif (typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif (typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\n\toptions.attrs = typeof options.attrs === \"object\" ? options.attrs : {};\n\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of