From 3f44b7d0881470c1bb9de55af03de3494b244a5c Mon Sep 17 00:00:00 2001 From: maxshayne Date: Fri, 2 Mar 2018 22:27:13 +0700 Subject: [PATCH 001/658] part of everex tests added --- tests/everexTests.php | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/everexTests.php diff --git a/tests/everexTests.php b/tests/everexTests.php new file mode 100644 index 00000000..4a9cf793 --- /dev/null +++ b/tests/everexTests.php @@ -0,0 +1,48 @@ +_iterateTest($test); + } + + public function everexProvider() + { + return [ + // =================== + // historical tests + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical currencies with USD =', + 'compareFrom' => 'USD', + 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], + 'compareSource' => 'quandl', + 'compareSourceParam' => 'CURRFX' + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical BTC to USD =', + 'compareFrom' => 'USD', + 'compareTo' => ['BTC'], + 'compareReplace' => 'MKPRU', + 'compareSource' => 'quandl', + 'compareSourceParam' => 'BCHAIN' + ]] + ]; + } + +} \ No newline at end of file From 5c16c93855ac92f1a64052c732f6222061a8c712 Mon Sep 17 00:00:00 2001 From: maxshayne Date: Mon, 5 Mar 2018 15:51:16 +0700 Subject: [PATCH 002/658] quandl fixes --- tests/everexTests.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/everexTests.php b/tests/everexTests.php index 4a9cf793..25b0536a 100644 --- a/tests/everexTests.php +++ b/tests/everexTests.php @@ -39,9 +39,9 @@ public function everexProvider() 'compareFrom' => 'USD', 'compareTo' => ['BTC'], 'compareReplace' => 'MKPRU', - 'compareSource' => 'quandl', + 'compareSource' => 'quandl-reverse', 'compareSourceParam' => 'BCHAIN' - ]] + ]] ]; } From 43d31ccca10c932ef7ab58a856318bcbf5ee3d84 Mon Sep 17 00:00:00 2001 From: maxshayne Date: Wed, 7 Mar 2018 17:35:49 +0700 Subject: [PATCH 003/658] added more tests --- tests/everexTests.php | 107 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/tests/everexTests.php b/tests/everexTests.php index 25b0536a..aff58016 100644 --- a/tests/everexTests.php +++ b/tests/everexTests.php @@ -7,8 +7,6 @@ class everexTest extends TestCase { protected $everex_url = 'http://rates.everex.io'; - const APIKey = 'freekey'; - /** * @dataProvider everexProvider @@ -41,7 +39,110 @@ public function everexProvider() 'compareReplace' => 'MKPRU', 'compareSource' => 'quandl-reverse', 'compareSourceParam' => 'BCHAIN' - ]] + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical ETH to USD =', + 'compareFrom' => '0x0000000000000000000000000000000000000000', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcaphtml', + 'compareSourceParam' => 'ethereum' + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical token to USD =', + 'compareFrom' => '0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcaphtml', + 'compareSourceParam' => 'everex' + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical token to USD =', + 'compareFrom' => '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcaphtml', + 'compareSourceParam' => 'eos' + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyHistory', + 'description' => '= Comparing historical token to USD =', + 'compareFrom' => '0xd26114cd6ee289accf82350c8d8487fedb8a0c07', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcaphtml', + 'compareSourceParam' => 'omisego' + ]], + // =================== + // current tests + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current ETH to USD =', + 'compareFrom' => '0x0000000000000000000000000000000000000000', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcapapi', + 'compareSourceParam' => 'ethereum', + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current token to USD =', + 'compareFrom' => '0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcapapi', + 'compareSourceParam' => 'everex', + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current token to USD =', + 'compareFrom' => '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcapapi', + 'compareSourceParam' => 'eos', + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current token to USD =', + 'compareFrom' => '0xd26114cd6ee289accf82350c8d8487fedb8a0c07', + 'compareTo' => ['USD'], + 'compareSource' => 'coinmarketcapapi', + 'compareSourceParam' => 'omisego', + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current currencies with USD =', + 'compareFrom' => 'USD', + 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], + 'compareSource' => 'openexchangerates', + ]], + [[ + 'type' => 'everex', + 'method' => 'getBTCPrice', + 'description' => '= Comparing current BTC with USD =', + 'compareFrom' => 'USD', // + 'compareTo' => ['USD'], + 'compareSource' => 'bitstamp', + ]], + [[ + 'type' => 'everex', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current THBEX with USD =', + 'compareFrom' => '0xff71cb760666ab06aa73f34995b42dd4b85ea07b', + 'compareTo' => ['USD'], + 'compareSource' => 'openexchangerates-reverse', + 'compareTags' => ['THB'] + ]] ]; } From a0a2b635e33412bf465d4f5688aea9f21721699e Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 8 Mar 2018 18:06:27 +0700 Subject: [PATCH 004/658] Cache locks. --- service/lib/cache.php | 184 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 159 insertions(+), 25 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 136c2dcd..b2f7e72e 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -27,7 +27,22 @@ class evxCache { /** * Seconds in 30 days */ - const MONTH = 2592000; + const MONTH = 2592000; // 30 * 24 * 3600 + + /** + * Cache locks ttl in seconds + */ + const LOCK_TTL = 120; + + /** + * Waiting time for checking cache data in seconds + */ + const LOCK_WAITING_TIME = 3; + + /** + * Repeats number for checking cache data + */ + const LOCK_WAITING_REPEATS = 20; /** * Cache storage. @@ -121,23 +136,29 @@ public function save($entryName, $data){ switch($this->driver){ case 'memcached': $lifetime = isset($this->aLifetime[$entryName]) ? (int)$this->aLifetime[$entryName] : 0; - if($lifetime > evxCache::MONTH){ + /*if($lifetime > evxCache::MONTH){ $lifetime = time() + $cacheLifetime; - } + }*/ if(!$lifetime){ // 365 days if cache lifetime is not set - $lifetime = time() + 12 * evxCache::MONTH + 5; + $lifetime = time() + 12 * evxCache::MONTH + 5 * 24 * evxCache::HOUR; + }else{ + $lifetime = time() + $lifetime; } - $saveRes = $this->oDriver->set($entryName, $data, $lifetime); + //$saveRes = $this->oDriver->set($entryName, $data, $lifetime); + $aMemcachedData = array('lifetime' => $lifetime, 'data' => $data); + $saveRes = $this->oDriver->set($entryName, $aMemcachedData); if(!in_array($entryName, array('tokens', 'rates')) && (0 !== strpos($entryName, 'rates-history-'))){ break; } case 'file': $filename = $this->path . '/' . $entryName . ".tmp"; + @unlink($filename); $json = json_encode($data, JSON_PRETTY_PRINT); $saveRes = !!file_put_contents($filename, $json); break; } + $this->deleteLock($entryName); return $saveRes; } @@ -151,6 +172,102 @@ public function exists($entryName){ return isset($this->aData[$entryName]); } + /** + * Returns true if cache lock file created. + * + * @param string $file File name + * @return boolean + */ + public function isLockFileExists($file){ + if(file_exists($file)){ + $lockFileTime = filemtime($file); + if((time() - $lockFileTime) <= evxCache::LOCK_TTL){ + return TRUE; + } + } + + return FALSE; + } + + /** + * Adds cache lock. + * + * @param string $entryName Cache entry name + * @return boolean + */ + public function addLock($entryName){ + if('memcached' === $this->driver){ + return $this->oDriver->add($entryName . '-lock', TRUE, evxCache::LOCK_TTL); + }else{ + $lockFilename = $this->path . '/' . $entryName . "-lock.tmp"; + + if($this->isLockFileExists($lockFilename)) return FALSE; + + @unlink($lockFilename); + $saveLockRes = !!file_put_contents($lockFilename, '1'); + return $saveLockRes; + } + } + + /** + * Deletes cache lock. + * + * @param string $entryName Cache entry name + * @return boolean + */ + public function deleteLock($entryName){ + if('memcached' === $this->driver){ + return $this->oDriver->delete($entryName . '-lock'); + }else{ + return @unlink($this->path . '/' . $entryName . '-lock.tmp'); + } + } + + /** + * Returns cached data by entry name. + * + * @param string $entryName + * @param mixed $default + * @param boolean $loadIfNeeded + * @return mixed + */ + public function loadCachedData($entryName, $default = NULL, $cacheLifetime = FALSE){ + $result = array('data' => $default, 'expired' => FALSE); + $file = ('file' === $this->driver); + if('memcached' === $this->driver){ + $memcachedData = $this->oDriver->get($entryName); + if($memcachedData && isset($memcachedData['lifetime']) && isset($memcachedData['data'])){ + $result['data'] = $memcachedData['data']; + if($memcachedData['lifetime'] < time()){ + $result['expired'] = TRUE; + } + } + // @todo: move hardcode to controller + if(!$result['data'] || $result['expired'] || (in_array($entryName, array('tokens', 'rates')) || (0 === strpos($entryName, 'rates-history-')))){ + $file = TRUE; + } + } + if($file){ + $filename = $this->path . '/' . $entryName . ".tmp"; + if(file_exists($filename)){ + $isFileExpired = FALSE; + if(FALSE !== $cacheLifetime){ + $fileTime = filemtime($filename); + $gmtZero = gmmktime(0, 0, 0); + if((($gmtZero > $fileTime) && ($cacheLifetime > evxCache::HOUR)) || ((time() - $fileTime) > $cacheLifetime)){ + $isFileExpired = TRUE; + } + } + if(!$isFileExpired || !$result['data'] || $result['expired']){ + $contents = @file_get_contents($filename); + $result['data'] = json_decode($contents, TRUE); + $result['expired'] = $isFileExpired; + } + } + } + return $result; + } + /** * Returns cached data by entry name. * @@ -161,36 +278,53 @@ public function exists($entryName){ */ public function get($entryName, $default = NULL, $loadIfNeeded = FALSE, $cacheLifetime = FALSE){ $result = $default; - $file = ('file' === $this->driver); + $isExpired = FALSE; if(FALSE !== $cacheLifetime){ $this->aLifetime[$entryName] = $cacheLifetime; } if($this->exists($entryName)){ $result = $this->aData[$entryName]; }elseif($loadIfNeeded){ - if('memcached' === $this->driver){ - $result = $this->oDriver->get($entryName); - // @todo: move hardcode to controller - if(!$result || (in_array($entryName, array('tokens', 'rates')) || (0 === strpos($entryName, 'rates-history-')))){ - $file = TRUE; + $aCachedData = $this->loadCachedData($entryName, $default, $cacheLifetime); + $result = $aCachedData['data']; + $isExpired = $aCachedData['expired']; + } + + if($result && !$isExpired){ + return $result; + }else{ + // try to create cache lock + if($this->addLock($entryName)){ + return FALSE; + }else{ + // return any cached data if exist + if($result){ + return $result; } - } - if($file){ - $filename = $this->path . '/' . $entryName . ".tmp"; - if(file_exists($filename)){ - if(FALSE !== $cacheLifetime){ - $fileTime = filemtime($filename); - $gmtZero = gmmktime(0, 0, 0); - if((($gmtZero > $fileTime) && ($cacheLifetime > evxCache::HOUR)) || ((time() - $fileTime) > $cacheLifetime)){ - @unlink($filename); - return $result; - } + // waiting when other process creates cache data + for($i = 0; $i < evxCache::LOCK_WAITING_REPEATS; $i++){ + set_time_limit(20); + sleep(evxCache::LOCK_WAITING_TIME); + $aCachedData = $this->loadCachedData($entryName, $default, $cacheLifetime); + if($aCachedData['data']){ + return $aCachedData['data']; } - $contents = @file_get_contents($filename); - $result = json_decode($contents, TRUE); } } } - return $result; + + $this->send503Header(180); + die(); + } + + /** + * Sends HTTP error code 503. + * + * @param int $timeout Retry timeout + */ + protected function send503Header($timeout){ + header((isset($_SERVER["SERVER_PROTOCOL"]) ? $_SERVER["SERVER_PROTOCOL"] : '') . ' 503 Service Temporarily Unavailable'); + header('Status: 503 Service Temporarily Unavailable'); + header('Retry-After: ' . $timeout); } } \ No newline at end of file From 848e55d9f347619d36748c48eeaf69880f3a37c9 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 9 Mar 2018 21:18:22 +0700 Subject: [PATCH 005/658] Cache locks. --- service/lib/cache.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index b2f7e72e..5851d92c 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -288,6 +288,8 @@ public function get($entryName, $default = NULL, $loadIfNeeded = FALSE, $cacheLi $aCachedData = $this->loadCachedData($entryName, $default, $cacheLifetime); $result = $aCachedData['data']; $isExpired = $aCachedData['expired']; + }else{ + return $result; } if($result && !$isExpired){ From 876421667be4d4eee7d488ec1a58a1b686689323 Mon Sep 17 00:00:00 2001 From: maxshayne Date: Tue, 13 Mar 2018 22:24:55 +0700 Subject: [PATCH 006/658] added callbacks to tests --- tests/everexTests.php | 227 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 184 insertions(+), 43 deletions(-) diff --git a/tests/everexTests.php b/tests/everexTests.php index aff58016..31b8e023 100644 --- a/tests/everexTests.php +++ b/tests/everexTests.php @@ -2,11 +2,12 @@ namespace apiTests; require "vendor/autoload.php"; +use DOMDocument; use EverexIO\PHPUnitIterator\TestCase; class everexTest extends TestCase { - protected $everex_url = 'http://rates.everex.io'; + protected $url = 'http://rates.everex.io'; /** * @dataProvider everexProvider @@ -22,128 +23,268 @@ public function everexProvider() // =================== // historical tests [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical currencies with USD =', 'compareFrom' => 'USD', 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], - 'compareSource' => 'quandl', - 'compareSourceParam' => 'CURRFX' + 'compareType' => 'normal', + 'compareSourceParam' => 'CURRFX', + 'compareTime' => 'historic', + 'callback' => function($database, $dataset){ + $apiKey = 'SS1Kj9CAzyj9bGssEQz9'; + $url = 'https://www.quandl.com/api/v1/datasets/'.$database. + '/'.$dataset.'.json?auth_token='.$apiKey.'&trim_start=2015-04-01'; + $json = file_get_contents($url); + $result = json_decode($json, TRUE); + return $result['data']; + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical BTC to USD =', 'compareFrom' => 'USD', 'compareTo' => ['BTC'], 'compareReplace' => 'MKPRU', - 'compareSource' => 'quandl-reverse', - 'compareSourceParam' => 'BCHAIN' + 'compareType' => 'reverse', + 'compareSourceParam' => 'BCHAIN', + 'compareTime' => 'historic', + 'callback' => function($database, $dataset){ + $apiKey = 'SS1Kj9CAzyj9bGssEQz9'; + $url = 'https://www.quandl.com/api/v1/datasets/'.$database. + '/'.$dataset.'.json?auth_token='.$apiKey.'&trim_start=2015-04-01'; + $json = file_get_contents($url); + $result = json_decode($json, TRUE); + return $result['data']; + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical ETH to USD =', 'compareFrom' => '0x0000000000000000000000000000000000000000', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcaphtml', - 'compareSourceParam' => 'ethereum' + 'compareType' => 'cycle', + 'compareSourceParam' => 'ethereum', + 'compareTime' => 'historic', + 'callback' => function($currency){ + return $this->getHtmlData($currency); + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical token to USD =', 'compareFrom' => '0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcaphtml', - 'compareSourceParam' => 'everex' + 'compareType' => 'cycle', + 'compareSourceParam' => 'everex', + 'compareTime' => 'historic', + 'callback' => function($currency){ + return $this->getHtmlData($currency); + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical token to USD =', 'compareFrom' => '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcaphtml', - 'compareSourceParam' => 'eos' + 'compareType' => 'cycle', + 'compareSourceParam' => 'eos', + 'compareTime' => 'historic', + 'callback' => function($currency) { + return $this->getHtmlData($currency); + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyHistory', 'description' => '= Comparing historical token to USD =', 'compareFrom' => '0xd26114cd6ee289accf82350c8d8487fedb8a0c07', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcaphtml', - 'compareSourceParam' => 'omisego' + 'compareType' => 'cycle', + 'compareSourceParam' => 'omisego', + 'compareTime' => 'historic', + 'callback' => function($currency){ + return $this->getHtmlData($currency); + } ]], // =================== // current tests [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyCurrent', 'description' => '= Comparing current ETH to USD =', 'compareFrom' => '0x0000000000000000000000000000000000000000', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcapapi', + 'compareType' => 'cycle', 'compareSourceParam' => 'ethereum', - 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']], + 'compareTime' => 'current', + 'callback' => function($currency){ + $url = 'https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=0'; + $data = json_decode(file_get_contents($url), true); + foreach ($data as $item) + { + if ($item['id'] == $currency) + return $item; + } + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyCurrent', 'description' => '= Comparing current token to USD =', 'compareFrom' => '0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcapapi', + 'compareType' => 'cycle', 'compareSourceParam' => 'everex', - 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']], + 'compareTime' => 'current', + 'callback' => function($currency){ + $url = 'https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=0'; + $data = json_decode(file_get_contents($url), true); + foreach ($data as $item) + { + if ($item['id'] == $currency) + return $item; + } + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyCurrent', 'description' => '= Comparing current token to USD =', 'compareFrom' => '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcapapi', + 'compareType' => 'cycle', 'compareSourceParam' => 'eos', - 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']], + 'compareTime' => 'current', + 'callback' => function($currency){ + $url = 'https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=0'; + $data = json_decode(file_get_contents($url), true); + foreach ($data as $item) + { + if ($item['id'] == $currency) + return $item; + } + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyCurrent', 'description' => '= Comparing current token to USD =', 'compareFrom' => '0xd26114cd6ee289accf82350c8d8487fedb8a0c07', 'compareTo' => ['USD'], - 'compareSource' => 'coinmarketcapapi', + 'compareType' => 'cycle', 'compareSourceParam' => 'omisego', - 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']] + 'compareTags' => [['availableSupply', 'available_supply'], ['marketCapUsd', 'market_cap_usd']], + 'compareTime' => 'current', + 'callback' => function($currency){ + $url = 'https://api.coinmarketcap.com/v1/ticker/?convert=USD&limit=0'; + $data = json_decode(file_get_contents($url), true); + foreach ($data as $item) + { + if ($item['id'] == $currency) + return $item; + } + } ]], - [[ - 'type' => 'everex', - 'method' => 'getCurrencyCurrent', - 'description' => '= Comparing current currencies with USD =', - 'compareFrom' => 'USD', - 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], - 'compareSource' => 'openexchangerates', + [[ + 'type' => 'compare', + 'method' => 'getCurrencyCurrent', + 'description' => '= Comparing current currencies with USD =', + 'compareFrom' => 'USD', + 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], + 'compareType' => 'key', + 'compareTime' => 'current', + 'callback' => function(){ + $apiKey = '56373b75d3204d008efa8b62e0589743'; + $url = 'https://openexchangerates.org/api/latest.json?app_id='.$apiKey; + $json = file_get_contents($url); + $result = json_decode($json, TRUE); + return $result['rates']; + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getBTCPrice', 'description' => '= Comparing current BTC with USD =', 'compareFrom' => 'USD', // 'compareTo' => ['USD'], - 'compareSource' => 'bitstamp', + 'compareType' => 'cycle-key', + 'compareTime' => 'current', + 'callback' => function(){ + $url = 'http://www.bitstamp.net/api/ticker/'; + $json = file_get_contents($url); + $result = json_decode($json, TRUE); + return $result; + } ]], [[ - 'type' => 'everex', + 'type' => 'compare', 'method' => 'getCurrencyCurrent', 'description' => '= Comparing current THBEX with USD =', 'compareFrom' => '0xff71cb760666ab06aa73f34995b42dd4b85ea07b', 'compareTo' => ['USD'], - 'compareSource' => 'openexchangerates-reverse', - 'compareTags' => ['THB'] + 'compareTags' => ['THB'], + 'compareType' => 'key-reverse', + 'compareTime' => 'current', + 'callback' => function(){ + $apiKey = '56373b75d3204d008efa8b62e0589743'; + $url = 'https://openexchangerates.org/api/latest.json?app_id='.$apiKey; + $json = file_get_contents($url); + $result = json_decode($json, TRUE); + return $result['rates']; + } ]] ]; } + private function getDataFromHtml($html) + { + $DOM = new DOMDocument; + libxml_use_internal_errors(true); + $DOM->loadHTML($html); + libxml_clear_errors(); + $data = $DOM->getElementsByTagName('tr'); + return $data; + } + + private function getHtmlData($currency) + { + $url = 'https://coinmarketcap.com/currencies/'.$currency.'/historical-data/?start=20130428&end=20180122'; + $html = file_get_contents($url); + $data = $this->getDataFromHtml($html); + $result = array(); + foreach($data as $key => $node) + { //first node is header node, so we skip it + if ($key == 0) continue; + $nodeValue = $node->nodeValue; + $values = explode("\n", $nodeValue); + $values = $this->remove_empty($values); + $array_elem = array(); + foreach ($values as $innerkey => $val) + { + if ($innerkey == 1){ + $val = date('Y-m-d', strtotime($val)); + } else { + $val = str_replace( ',', '', $val ); + $val = floatval($val); + } + array_push($array_elem, $val); + } + array_push($result, $array_elem); + } + return $result; + } + + function remove_empty($array) { + return array_filter($array, function($value) { + return !empty($value) || $value === 0; + }); + } } \ No newline at end of file From 2d021bf0338a26ea3142464755efbe421d22d02f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 14 Mar 2018 02:08:07 +0700 Subject: [PATCH 007/658] Bug fixed. --- api/widget.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index b21c27cc..a900912e 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1642,7 +1642,11 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te var currentDate = new Date(); var currentDatePriceKey = currentDate.getFullYear() + '-' + (currentDate.getMonth() < 9 ? '0' : '') + (currentDate.getMonth() + 1) + '-' + (currentDate.getDate() < 10 ? '0' : '') + currentDate.getDate(); - if(widgetPriceData[widgetPriceData.length - 1].date != currentDatePriceKey){ + var prevDate = new Date(); + prevDate.setDate(currentDate.getDate() - 1); + var prevDatePriceKey = prevDate.getFullYear() + '-' + (prevDate.getMonth() < 9 ? '0' : '') + (prevDate.getMonth() + 1) + '-' + (prevDate.getDate() < 10 ? '0' : '') + prevDate.getDate(); + + if(widgetPriceData[widgetPriceData.length - 1].date != currentDatePriceKey && widgetPriceData[widgetPriceData.length - 1].date == prevDatePriceKey){ if(currentPrice.rate && (currentPrice.rate > 0) && currentPrice.volume24h && currentPrice.ts){ var diff = ethplorerWidget.Utils.pdiff(currentPrice.rate, widgetPriceData[widgetPriceData.length - 1].close, true); if('x' === diff){ From 51862b782a4d998db87d822693c00dfddc0a92ff Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 14 Mar 2018 16:22:16 +0700 Subject: [PATCH 008/658] Menu updated --- css/ethplorer.css | 11 + index.php | 3 +- widgets.html | 671 ---------------------------------------------- widgets.php | 5 +- 4 files changed, 15 insertions(+), 675 deletions(-) delete mode 100644 widgets.html diff --git a/css/ethplorer.css b/css/ethplorer.css index 21088f35..89a152d8 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -966,6 +966,17 @@ li.ui-menu-item.have-more { white-space: nowrap; } +.new-mark { + color: #f71e1e; + font-size: 10px; + font-family: 'Open Sans'; + line-height: 1.55; + font-weight: 700; + position: absolute; + right: 5px; + top: 5px; +} + @media screen and (max-width: 1199px) { .footer-donation { font-size:12.8px; diff --git a/index.php b/index.php index 1fd7cfd9..d2dd3472 100644 --- a/index.php +++ b/index.php @@ -162,7 +162,8 @@ @@ -629,7 +629,6 @@ function getWidgetCode(ta) { From 528fa5d606a15b96a67c8822f5bc59e3a149f0b0 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 14 Mar 2018 16:29:32 +0700 Subject: [PATCH 009/658] gAds updated --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index d2dd3472..3260a956 100644 --- a/index.php +++ b/index.php @@ -177,7 +177,7 @@
- + From 40699ba50f3cdb044bfd59f4a254e684343e93e3 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 14 Mar 2018 16:32:18 +0700 Subject: [PATCH 010/658] codeVersion updated --- index.php | 2 +- widgets.php | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/index.php b/index.php index 3260a956..950af37b 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "180"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "209"; $error = TRUE; $header = ""; diff --git a/widgets.php b/widgets.php index 8c0f4221..9a0e95f8 100644 --- a/widgets.php +++ b/widgets.php @@ -16,6 +16,9 @@ */ $aConfig = require dirname(__FILE__) . '/service/config.php'; + +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "209"; + ?> @@ -23,7 +26,7 @@ - + @@ -36,9 +39,9 @@ - - - + + + Show Ethereum transfers: 0 ? 'checked="checked"' : '') + ' name="showEth" value="1" style="vertical-align: text-bottom;margin-right:5px;">'); + } if(!data.transfers || !data.transfers.length){ $('#' + tableId).find('.total-records').empty(); $('#' + tableId).find('.table').append('No transfers found'); @@ -1077,9 +1085,13 @@ Ethplorer = { for(var i=0; i'); var tdDate = $('').addClass('hide-small'); var tdData = $(''); @@ -1159,6 +1171,15 @@ Ethplorer = { $('#' + tableId).show(); }, + showEthTransfers: function(switcher){ + Ethplorer.Nav.del('transfers'); + Ethplorer.showEth = switcher.checked ? 1 : 0; + Ethplorer.Storage.set('showEth', Ethplorer.showEth); + Ethplorer.Nav.set('showEth', Ethplorer.showEth); + var tab = Ethplorer.getActiveTab(); + Ethplorer.reloadTab(tab); + }, + drawIssuances: function(address, issuancesData){ $('#filter_list').attr('disabled', false); $('#address-issuances .table').empty(); diff --git a/service/service.php b/service/service.php index 06475de7..9851d143 100644 --- a/service/service.php +++ b/service/service.php @@ -40,6 +40,7 @@ if(strlen($search) || (false !== $data)){ $es = Ethplorer::db($aConfig); + //$es->setShowEth(true); if(strlen($search)){ $result = $es->searchToken($search); @@ -64,7 +65,8 @@ $es->setFilter($aPageParams[1]); break; case 'showEth': - $es->setShowEth($aPageParams[1]); + $showEth = (intval($aPageParams[1]) > 0) ? TRUE : FALSE; + $es->setShowEth($showEth); break; } } From 158aa05da641a680b3b053ce5a9b7d0894fde74e Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 22 Mar 2018 18:38:43 +0700 Subject: [PATCH 036/658] Cache bug fixed. --- bin/cache_tokens_full_history.php | 1 + service/lib/ethplorer.php | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index b4fe4b99..cede7f38 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -23,3 +23,4 @@ $es->getTokenFullHistoryGrouped(); $es->getTokenCapHistory(0, TRUE); +$es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 52f71ecf..5d6fd383 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1703,10 +1703,10 @@ protected function _sortByTxCount($a, $b){ * @param string $address Address * @return array */ - public function getTokenHistoryGrouped($period = 30, $address = FALSE, $type = 'daily', $cacheLifetime = 1800, $showEth = FALSE){ + public function getTokenHistoryGrouped($period = 30, $address = FALSE, $type = 'daily', $cacheLifetime = 1800, $showEth = FALSE, $updateCache = FALSE){ $cache = 'token_history_grouped-' . ($address ? ($address . '-') : '') . $period . (($type == 'hourly') ? '-hourly' : '') . ($showEth ? '-eth' : ''); - $result = $this->oCache->get($cache, false, true, $cacheLifetime); - if(FALSE === $result){ + $result = $address ? $this->oCache->get($cache, false, true, $cacheLifetime) : $this->oCache->get($cache, false, true); + if(FALSE === $result || $updateCache){ // Chainy if($address && ($address == self::ADDRESS_CHAINY)){ return $this->getChainyTokenHistoryGrouped($period); From f3854cbea85c2304cbafef80a5f9603dc5c9d842 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 22 Mar 2018 18:42:12 +0700 Subject: [PATCH 037/658] Cache bug fixed. --- bin/cache_tokens_full_history.php | 1 - bin/cache_tokens_history.php | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 bin/cache_tokens_history.php diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index cede7f38..b4fe4b99 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -23,4 +23,3 @@ $es->getTokenFullHistoryGrouped(); $es->getTokenCapHistory(0, TRUE); -$es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); diff --git a/bin/cache_tokens_history.php b/bin/cache_tokens_history.php new file mode 100644 index 00000000..9aa539ca --- /dev/null +++ b/bin/cache_tokens_history.php @@ -0,0 +1,24 @@ +createProcessLock('tokens.history.lock'); + +$es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); From 5eff78207362948d5842f29e3af869f906c34286 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 23 Mar 2018 15:51:45 +0700 Subject: [PATCH 038/658] Test with eth operations. --- service/lib/mongo_scanner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/mongo_scanner.php b/service/lib/mongo_scanner.php index 12ac50b7..b747483b 100644 --- a/service/lib/mongo_scanner.php +++ b/service/lib/mongo_scanner.php @@ -54,7 +54,7 @@ protected function __construct(array $aSettings){ 'blocks' => $oDB->blocks, 'contracts' => $oDB->contracts, 'tokens' => $oDB->tokens, - 'operations' => $oDB->tokenOperations, + 'operations' => $oDB->tokenOperations2, 'balances' => $oDB->tokenBalances, 'addressCache' => $oDB->cacheAddressData ); @@ -67,7 +67,7 @@ protected function __construct(array $aSettings){ 'blocks' => "blocks", 'contracts' => "contracts", 'tokens' => "tokens", - 'operations' => "tokenOperations", + 'operations' => "tokenOperations2", 'balances' => "tokenBalances", 'addressCache' => "cacheAddressData" ); From fba85dad407af5d271a042c67b1e23c6f361b593 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 23 Mar 2018 16:02:49 +0700 Subject: [PATCH 039/658] Revert "Test with eth operations." This reverts commit 5eff78207362948d5842f29e3af869f906c34286. --- service/lib/mongo_scanner.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/mongo_scanner.php b/service/lib/mongo_scanner.php index b747483b..12ac50b7 100644 --- a/service/lib/mongo_scanner.php +++ b/service/lib/mongo_scanner.php @@ -54,7 +54,7 @@ protected function __construct(array $aSettings){ 'blocks' => $oDB->blocks, 'contracts' => $oDB->contracts, 'tokens' => $oDB->tokens, - 'operations' => $oDB->tokenOperations2, + 'operations' => $oDB->tokenOperations, 'balances' => $oDB->tokenBalances, 'addressCache' => $oDB->cacheAddressData ); @@ -67,7 +67,7 @@ protected function __construct(array $aSettings){ 'blocks' => "blocks", 'contracts' => "contracts", 'tokens' => "tokens", - 'operations' => "tokenOperations2", + 'operations' => "tokenOperations", 'balances' => "tokenBalances", 'addressCache' => "cacheAddressData" ); From eeedb3554a2cf3c5ffa873851fa59729b1913530 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 23 Mar 2018 17:02:35 +0700 Subject: [PATCH 040/658] Profiler updated --- service/lib/mongo.php | 2 +- service/service.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index ee7803a0..4b722055 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -172,7 +172,7 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi $finish = microtime(true); $qTime = $finish - $start; if($qTime > 1){ - $this->log('(' . ($qTime) . 's) Find ' . $this->dbName . '.' . $this->aDBs[$collection] . ' > ' . json_encode($aSearch)); + $this->log('(' . ($qTime) . 's) Find ' . $this->dbName . '.' . $this->aDBs[$collection] . ' > ' . json_encode($aSearch) . ' [' . json_encode($aOptions) . ']'); } return $aResult; } diff --git a/service/service.php b/service/service.php index 00409a3e..6b65cc83 100644 --- a/service/service.php +++ b/service/service.php @@ -14,6 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +if(file_exists("_service.php")){ + require "_service.php"; +} require dirname(__FILE__) . '/lib/ethplorer.php'; From 3767bd2eabe07dd605ada9691b4d96b524217201 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Fri, 23 Mar 2018 19:07:56 +0700 Subject: [PATCH 041/658] on insert check and correct --- api/widget.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/api/widget.js b/api/widget.js index c97b01a4..6f15694d 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1947,8 +1947,9 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te } } }; + var color = '#989795' if(this.options['theme'] == 'dark'){ - def.options.colors = noPrice ? ['#FCEC0F']: ['#999999', '#FCEC0F', '#DEDEDE']; + def.options.colors = noPrice ? ['#FCEC0F']: [color, '#FCEC0F', '#DEDEDE']; def.options.titleTextStyle = {color: '#DEDEDE'}; def.options.backgroundColor = {fill: 'transparent'}; @@ -1963,21 +1964,18 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te def.options = $.extend(true, def.options, this.options['options']); var chart = new google.visualization.ChartWrapper(def); - /*if(!noPrice){ + if(!noPrice){ + var $chartEl = $("#chart") + $("#chart").bind("DOMNodeInserted",function(){ + // console.log('DOMNodeInserted') + $chartEl.find('rect[width="2"][fill="'+color+'"]') + .attr("width", 1) + }); google.visualization.events.addListener(chart, 'ready', function(){ - var svgElements = document.getElementsByTagNameNS("http://www.w3.org/2000/svg", "svg"); - for(var i=0; i<1; i++){ - var svgElement = svgElements.item(i); - var allRects = svgElement.getElementsByTagName("rect"); - for(var i=0; i Date: Mon, 26 Mar 2018 18:42:09 +0700 Subject: [PATCH 042/658] correct x coordinate and adaptive width --- api/widget.js | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/api/widget.js b/api/widget.js index 6f15694d..b6218b44 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1968,15 +1968,34 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te var $chartEl = $("#chart") $("#chart").bind("DOMNodeInserted",function(){ // console.log('DOMNodeInserted') - $chartEl.find('rect[width="2"][fill="'+color+'"]') - .attr("width", 1) + $chartEl.find('[width="2"][fill="' + color + '"]') + .each(function (index, item) { + var sibling = $(item).siblings()[0]; + if (sibling) { + var width = $(sibling).attr('width'); + var w = width > 27 ? 2 : (width > 2 ? 1 : + width / 2); + var x = +$(sibling).attr('x') + (width - w) / 2; + $(item) + .attr('width', w) + .attr('x', x) + } + }) }); google.visualization.events.addListener(chart, 'ready', function(){ // console.log('ready') - $chartEl.find('rect[width="2"][fill="'+color+'"]').attr("width", 1) + $chartEl.find('[width="2"][fill="'+color+'"]').each(function (index, item) { + var sibling = $(item).siblings()[0]; + if (sibling) { + var width = $(sibling).attr('width'); + var w = width > 27 ? 2 : (width > 2 ? 1 : + width / 2); + var x = +$(sibling).attr('x') + (width - w) / 2; + $(item) + .attr('width', w) + .attr('x', x) + } + }) }); } - // draw chart dashboard.bind(control, chart); dashboard.draw(data); From 48e19089a4f2c5673a77216ab88162e784031f40 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 27 Mar 2018 14:48:32 +0700 Subject: [PATCH 043/658] Bug fixed. --- service/lib/ethplorer.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 5d6fd383..db7d3daa 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1515,10 +1515,17 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } // get total cap for previous day - if((1 == $period) && !$isEth && !$previousTokenCapAdded && isset($aToken['cap'])){ + /*if((1 == $period) && !$isEth && !$previousTokenCapAdded && isset($aToken['cap'])){ $aTotals['capPrevious'] += $aToken['cap']; $previousTokenCapAdded = true; - } + }*/ + } + + // get total cap for previous day + $prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']) && ($aRecord['hour'] = $curHour); + if(!$isEth && $prevCapPeriod && (1 == $period) && !$previousTokenCapAdded && isset($aToken['cap'])){ + $aTotals['capPrevious'] += $aToken['cap']; + $previousTokenCapAdded = true; } } } From d350acd90d8c9d92f68663a0e55ca267cd4c621f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 27 Mar 2018 19:05:59 +0700 Subject: [PATCH 044/658] Bug fixed. --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index db7d3daa..b1ba7da0 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1522,9 +1522,9 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } // get total cap for previous day - $prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']) && ($aRecord['hour'] = $curHour); + $prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']) && ($aRecord['hour'] == $curHour); if(!$isEth && $prevCapPeriod && (1 == $period) && !$previousTokenCapAdded && isset($aToken['cap'])){ - $aTotals['capPrevious'] += $aToken['cap']; + $aTotals['capPrevious'] += $aRecord['cap']; $previousTokenCapAdded = true; } } From 8ff45ea84d7bd394cb6e18569b14513096c39180 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 27 Mar 2018 20:54:42 +0700 Subject: [PATCH 045/658] Cache locks. --- service/lib/cache.php | 9 +++++++-- service/lib/ethplorer.php | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 5851d92c..b7f960a1 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -79,13 +79,15 @@ class evxCache { */ protected $aLifetime = array(); + protected $useLocks = FALSE; + /** * Constructor. * * @param string $path Cache files path * @todo params to config */ - public function __construct($path = __DIR__, $driver = FALSE){ + public function __construct($path = __DIR__, $driver = FALSE, $useLocks = FALSE){ $path = realpath($path); if(file_exists($path) && is_dir($path)){ $this->path = $path; @@ -93,6 +95,7 @@ public function __construct($path = __DIR__, $driver = FALSE){ if(FALSE !== $driver){ $this->driver = $driver; } + $this->useLocks = $useLocks; if('memcached' === $this->driver){ if(class_exists('Memcached')){ @@ -158,7 +161,7 @@ public function save($entryName, $data){ $saveRes = !!file_put_contents($filename, $json); break; } - $this->deleteLock($entryName); + if($this->useLocks) $this->deleteLock($entryName); return $saveRes; } @@ -295,6 +298,8 @@ public function get($entryName, $default = NULL, $loadIfNeeded = FALSE, $cacheLi if($result && !$isExpired){ return $result; }else{ + if(!$this->useLocks) return FALSE; + // try to create cache lock if($this->addLock($entryName)){ return FALSE; diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index b15af8b5..afe0afa1 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -118,7 +118,8 @@ protected function __construct(array $aConfig){ "locksDir" => dirname(__FILE__) . "/../lock/", ); $cacheDriver = isset($this->aSettings['cacheDriver']) ? $this->aSettings['cacheDriver'] : 'file'; - $this->oCache = new evxCache($this->aSettings['cacheDir'], $cacheDriver); + $useLocks = isset($this->aSettings['useLocks']) ? $this->aSettings['useLocks'] : FALSE; + $this->oCache = new evxCache($this->aSettings['cacheDir'], $cacheDriver, $useLocks); if(isset($this->aSettings['mongo']) && is_array($this->aSettings['mongo'])){ evxMongoScanner::init($this->aSettings['mongo']); $this->oMongo = evxMongoScanner::getInstance(); From 738a3afd8a395799c18e432b469aad1280428bb1 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 27 Mar 2018 22:10:45 +0700 Subject: [PATCH 046/658] Cache locks: tmp flag added. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index b7f960a1..a829a61e 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -149,7 +149,7 @@ public function save($entryName, $data){ $lifetime = time() + $lifetime; } //$saveRes = $this->oDriver->set($entryName, $data, $lifetime); - $aMemcachedData = array('lifetime' => $lifetime, 'data' => $data); + $aMemcachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); $saveRes = $this->oDriver->set($entryName, $aMemcachedData); if(!in_array($entryName, array('tokens', 'rates')) && (0 !== strpos($entryName, 'rates-history-'))){ break; From ffab059c9df7ebbdf80fa87038cf470f62e25685 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 27 Mar 2018 22:15:42 +0700 Subject: [PATCH 047/658] Checking cache lock flag added. --- service/lib/cache.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index 136c2dcd..6f4dc2c8 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -170,6 +170,9 @@ public function get($entryName, $default = NULL, $loadIfNeeded = FALSE, $cacheLi }elseif($loadIfNeeded){ if('memcached' === $this->driver){ $result = $this->oDriver->get($entryName); + if(isset($result['lock'])){ + $result = FALSE; + } // @todo: move hardcode to controller if(!$result || (in_array($entryName, array('tokens', 'rates')) || (0 === strpos($entryName, 'rates-history-')))){ $file = TRUE; From fa8516d690f2788b37ff37cae74fc59c13edddb5 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 28 Mar 2018 16:07:45 +0700 Subject: [PATCH 048/658] Checking cache lock flag added. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 6f4dc2c8..5aec242d 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -170,7 +170,7 @@ public function get($entryName, $default = NULL, $loadIfNeeded = FALSE, $cacheLi }elseif($loadIfNeeded){ if('memcached' === $this->driver){ $result = $this->oDriver->get($entryName); - if(isset($result['lock'])){ + if(is_array($result) && isset($result['lock'])){ $result = FALSE; } // @todo: move hardcode to controller From 947a3dfc4fcc32bcba244d536b526989c219d2d5 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 28 Mar 2018 16:27:52 +0700 Subject: [PATCH 049/658] Cache locks. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index a829a61e..10d02f5b 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -156,7 +156,7 @@ public function save($entryName, $data){ } case 'file': $filename = $this->path . '/' . $entryName . ".tmp"; - @unlink($filename); + //@unlink($filename); $json = json_encode($data, JSON_PRETTY_PRINT); $saveRes = !!file_put_contents($filename, $json); break; From 2901f57df75b179963a456ce0d62334fcd04c648 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 14:51:59 +0700 Subject: [PATCH 050/658] Timestamp added. --- service/lib/ethplorer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index dbe1e2c1..c2de4a52 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1576,6 +1576,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } } //$result = $res; + $aTotals['ts'] = time(); $result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); $this->oCache->save('top_tokens_totals', $result['totals']); From c2e0ee4e4791d2db6e26a20bd13e9eca859fad31 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 17:39:01 +0700 Subject: [PATCH 051/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c2de4a52..90c7b3f3 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1524,7 +1524,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa // get total cap for previous day $prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']) && ($aRecord['hour'] == $curHour); - if(!$isEth && $prevCapPeriod && (1 == $period) && !$previousTokenCapAdded && isset($aToken['cap'])){ + if(!$isEth && $prevCapPeriod && (1 == $period) && !$previousTokenCapAdded && isset($aRecord['cap'])){ $aTotals['capPrevious'] += $aRecord['cap']; $previousTokenCapAdded = true; } From fa55fdc544a07b7bb12a649791199ce753abfbb2 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 18:06:48 +0700 Subject: [PATCH 052/658] Saving cap history into file. --- bin/cache_top.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/bin/cache_top.php b/bin/cache_top.php index db240f0c..c68ecf9a 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -20,7 +20,27 @@ $es = Ethplorer::db($aConfig); $es->createProcessLock('topTokens.lock'); -$aCriteries = array('trade', 'cap', 'count'); +$aCriteries = array('cap', 'trade', 'count'); +$aTotals = null; foreach($aCriteries as $criteria){ - $es->getTokensTop(100, $criteria, TRUE); + $res = $es->getTokensTop(100, $criteria, TRUE); + if(!$aTotals && isset($res['totals'])){ + $aTotals = $res['totals']; + } } + +// save cap history into file +if($aTotals){ + $aTotals['date'] = date("Y-m-d H:i", time()); + + $data = array(); + $historyFile = './cap_history.json'; + if(file_exists($historyFile)){ + $history = @file_get_contents($historyFile); + $data = json_decode($history, TRUE); + } + $data[] = $aTotals; + $json = json_encode($data, JSON_PRETTY_PRINT); + @file_put_contents($historyFile, $json); +} + From 954c81b1bb5d0443e205271f48fc74d452827082 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 18:10:57 +0700 Subject: [PATCH 053/658] Saving cap history into file. --- bin/cache_top.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/cache_top.php b/bin/cache_top.php index c68ecf9a..7f2ca44a 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -31,7 +31,7 @@ // save cap history into file if($aTotals){ - $aTotals['date'] = date("Y-m-d H:i", time()); + $aTotals['date'] = gmdate("Y-m-d H:i", time()); $data = array(); $historyFile = './cap_history.json'; @@ -40,7 +40,7 @@ $data = json_decode($history, TRUE); } $data[] = $aTotals; - $json = json_encode($data, JSON_PRETTY_PRINT); + $json = json_encode($data); @file_put_contents($historyFile, $json); } From dec35b68608c879e175b1f8793bf0cce04b30d2a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 19:26:00 +0700 Subject: [PATCH 054/658] Saving cap history into file. --- bin/cache_top.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cache_top.php b/bin/cache_top.php index 7f2ca44a..951e67db 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -34,7 +34,7 @@ $aTotals['date'] = gmdate("Y-m-d H:i", time()); $data = array(); - $historyFile = './cap_history.json'; + $historyFile = dirname(__FILE__) . '/cap_history.json'; if(file_exists($historyFile)){ $history = @file_get_contents($historyFile); $data = json_decode($history, TRUE); From 7f6426d4dd150e14c5550b1ac943628c1fe28944 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 20:42:20 +0700 Subject: [PATCH 055/658] Bug fixed. --- service/lib/ethplorer.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 90c7b3f3..2c622684 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1576,10 +1576,16 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } } //$result = $res; - $aTotals['ts'] = time(); - $result = array('tokens' => $res, 'totals' => $aTotals); + $result = array('tokens' => $res); + if($criteria == 'cap'){ + $aTotals['ts'] = time(); + $result['totals'] = $aTotals; + $this->oCache->save('top_tokens_totals', $aTotals); + }else{ + $result['totals'] = $this->getTokensTopTotals(); + } + //$result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); - $this->oCache->save('top_tokens_totals', $result['totals']); } $res = []; From 282b88231fe8031f8cf1e0190793e05458b44952 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 21:57:54 +0700 Subject: [PATCH 056/658] Bug fixed. --- service/lib/ethplorer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2c622684..40791f72 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1463,7 +1463,8 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa }else{ $aPrice = $this->getTokenPrice($address); } - if($aPrice && ($isEth || $aToken['totalSupply'])){ + //if($aPrice && ($isEth || $aToken['totalSupply'])){ + if($isEth || ($aPrice && isset($aPrice['rate']) && isset($aPrice['marketCapUsd']) && $aPrice['marketCapUsd'])){ if(!$isEth) $aTotals['tokensWithPrice'] += 1; if(!$isEth && isset($aPrice['marketCapUsd'])){ $aTotals['cap'] += $aPrice['marketCapUsd']; From e003b8e8a6e612fd0d0386ecfd5266dbbd727521 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 22:16:21 +0700 Subject: [PATCH 057/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 40791f72..3d0da892 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1464,7 +1464,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $aPrice = $this->getTokenPrice($address); } //if($aPrice && ($isEth || $aToken['totalSupply'])){ - if($isEth || ($aPrice && isset($aPrice['rate']) && isset($aPrice['marketCapUsd']) && $aPrice['marketCapUsd'])){ + if($isEth || ($aPrice && isset($aPrice['rate']))){ if(!$isEth) $aTotals['tokensWithPrice'] += 1; if(!$isEth && isset($aPrice['marketCapUsd'])){ $aTotals['cap'] += $aPrice['marketCapUsd']; From 28973ac624d4d43bca7e7549343651c34c3879d1 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 29 Mar 2018 22:48:36 +0700 Subject: [PATCH 058/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 3d0da892..288f3144 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2105,7 +2105,7 @@ public function getTokenPrice($address, $updateCache = FALSE){ $method = 'getCurrencyCurrent'; $params = array($address, 'USD'); $result = $this->_jsonrpcall($this->aSettings['currency'], $method, $params); - if($result){ + if($result && isset($result['rate'])){ unset($result['code_from']); unset($result['code_to']); unset($result['bid']); From 6c69e5ac5d69092453234565e10c9e6ec7bf9a70 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 30 Mar 2018 17:50:11 +0700 Subject: [PATCH 059/658] Cap value for previous day fix. --- service/lib/ethplorer.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 288f3144..1bc67406 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1494,7 +1494,9 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } $aHistory = $this->getTokenPriceHistory($address, 60, 'hourly'); if(is_array($aHistory)){ - $previousTokenCapAdded = false; + //$previousTokenCapAdded = false; + $prevDayCap = null; + $prevPrevDayCap = null; foreach($aHistory as $aRecord){ foreach($aPeriods as $aPeriod){ $period = $aPeriod['period']; @@ -1515,22 +1517,27 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $aToken['cap-' . $period . 'd-previous'] = $aRecord['volumeConverted'] / $aRecord['volume']; } } - - // get total cap for previous day - /*if((1 == $period) && !$isEth && !$previousTokenCapAdded && isset($aToken['cap'])){ - $aTotals['capPrevious'] += $aToken['cap']; - $previousTokenCapAdded = true; - }*/ } // get total cap for previous day - $prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']) && ($aRecord['hour'] == $curHour); + /*$prevCapPeriod = ($aRecord['date'] == $aPeriod['currentPeriodStart']); if(!$isEth && $prevCapPeriod && (1 == $period) && !$previousTokenCapAdded && isset($aRecord['cap'])){ $aTotals['capPrevious'] += $aRecord['cap']; $previousTokenCapAdded = true; + }*/ + if(!$isEth && (1 == $period)){ + if(($aRecord['date'] == $aPeriod['currentPeriodStart']) && isset($aRecord['cap'])) $prevDayCap = $aRecord['cap']; + if(($aRecord['date'] == $aPeriod['previousPeriodStart']) && isset($aRecord['cap'])) $prevPrevDayCap = $aRecord['cap']; } } } + + // get total cap for previous day + if(!$isEth){ + if($prevDayCap) $aTotals['capPrevious'] += $prevDayCap; + else if($prevPrevDayCap) $aTotals['capPrevious'] += $prevPrevDayCap; + } + // get total volume for previous day if(!$isEth){ $aTotals['volumePrevious'] += $aToken['volume-1d-previous']; @@ -1576,17 +1583,10 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $res[] = $item; } } - //$result = $res; - $result = array('tokens' => $res); - if($criteria == 'cap'){ - $aTotals['ts'] = time(); - $result['totals'] = $aTotals; - $this->oCache->save('top_tokens_totals', $aTotals); - }else{ - $result['totals'] = $this->getTokensTopTotals(); - } - //$result = array('tokens' => $res, 'totals' => $aTotals); + $aTotals['ts'] = time(); + $result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); + $this->oCache->save('top_tokens_totals', $aTotals); } $res = []; From ec697df79a99621e73a7d67a23f9002695b7afb7 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 30 Mar 2018 20:35:51 +0700 Subject: [PATCH 060/658] Save json in pretty mode. --- bin/cache_top.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cache_top.php b/bin/cache_top.php index 951e67db..1feaeb30 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -40,7 +40,7 @@ $data = json_decode($history, TRUE); } $data[] = $aTotals; - $json = json_encode($data); + $json = json_encode($data, JSON_PRETTY_PRINT); @file_put_contents($historyFile, $json); } From b2c4105915a37f8ae0dadecf1fceff92412161ca Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 2 Apr 2018 17:06:10 +0700 Subject: [PATCH 061/658] Calc. tokens with prices fixed. --- service/lib/ethplorer.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1bc67406..8e4e0df4 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1586,6 +1586,13 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $aTotals['ts'] = time(); $result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); + + $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); + $prevTokensNum = 0; + if(FALSE !== $aPrevTotals){ + $prevTokensNum = $aPrevTotals['tokensWithPrice']; + } + if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; $this->oCache->save('top_tokens_totals', $aTotals); } From 2d133b937474d42875425146cd7d61b58730fdbb Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 2 Apr 2018 18:31:01 +0700 Subject: [PATCH 062/658] Bug fixed. --- service/lib/ethplorer.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 8e4e0df4..a9ca3738 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1584,15 +1584,14 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa } } $aTotals['ts'] = time(); - $result = array('tokens' => $res, 'totals' => $aTotals); - $this->oCache->save($cache, $result); - $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); $prevTokensNum = 0; if(FALSE !== $aPrevTotals){ $prevTokensNum = $aPrevTotals['tokensWithPrice']; } if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; + $result = array('tokens' => $res, 'totals' => $aTotals); + $this->oCache->save($cache, $result); $this->oCache->save('top_tokens_totals', $aTotals); } From cf9e10b40279d73575da74ab048016b3f2513ca2 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 3 Apr 2018 18:40:45 +0700 Subject: [PATCH 063/658] Allowing use hints in mongo queries. --- service/lib/mongo.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index 4b722055..a484a73e 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -117,7 +117,7 @@ public function toDate($timestamp = 0){ * @param int $skip * @return array */ - public function find($collection, array $aSearch = array(), $sort = false, $limit = false, $skip = false, $fields = false){ + public function find($collection, array $aSearch = array(), $sort = false, $limit = false, $skip = false, $fields = false, $hint = false){ $aResult = false; $start = microtime(true); switch($this->driver){ @@ -136,6 +136,9 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi if(false !== $limit){ $cursor = $cursor->limit($limit); } + if(false !== $hint){ + $cursor = $cursor->hint($hint); + } $aResult = $cursor; break; @@ -156,6 +159,9 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi $aOptions['projection'][$field] = 1; } } + if(false !== $hint){ + $aOptions['hint'] = $hint; + } $query = new MongoDB\Driver\Query($aSearch, $aOptions); $cursor = $this->oMongo->executeQuery($this->dbName . '.' . $this->aDBs[$collection], $query); From 3d6521ddb886afbf72c0e4c316051cb712ce9579 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 4 Apr 2018 15:44:46 +0700 Subject: [PATCH 064/658] Query optimizations. --- service/lib/ethplorer.php | 20 ++++++++++++++++---- service/lib/mongo_scanner.php | 2 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index a9ca3738..0c96136e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1198,7 +1198,17 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr $result = array(); $search = array('addresses' => $address); - if(!$showEth) $search['contract'] = array('$ne' => 'ETH'); + if($aTypes && is_array($aTypes) && count($aTypes)){ + if(1 == count($aTypes)){ + $search['type'] = $aTypes[0]; + }else{ + $search['type'] = array('$in' => $aTypes); + } + } + //if(!$showEth) $search['contract'] = array('$ne' => 'ETH'); + if(!$showEth){ + $search['isEth'] = false; + } // @todo: remove $or, use special field with from-to-address-txHash concatination maybe if($this->filter){ @@ -1215,11 +1225,13 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr ); } - if($aTypes && is_array($aTypes) && count($aTypes)){ + /*if($aTypes && is_array($aTypes) && count($aTypes)){ $search['type'] = array('$in' => $aTypes); - } + }*/ - $cursor = $this->oMongo->find('operations', $search, array("timestamp" => -1), $limit, $offset); + $hint = 'addresses_1_type_1_timestamp_1_isEth_1'; + + $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); foreach($cursor as $transfer){ if(is_null($aTypes) || in_array($transfer['type'], $aTypes)){ unset($transfer["_id"]); diff --git a/service/lib/mongo_scanner.php b/service/lib/mongo_scanner.php index 12ac50b7..7d6ad6fc 100644 --- a/service/lib/mongo_scanner.php +++ b/service/lib/mongo_scanner.php @@ -55,6 +55,7 @@ protected function __construct(array $aSettings){ 'contracts' => $oDB->contracts, 'tokens' => $oDB->tokens, 'operations' => $oDB->tokenOperations, + 'operations2' => $oDB->tokenOperations2, 'balances' => $oDB->tokenBalances, 'addressCache' => $oDB->cacheAddressData ); @@ -68,6 +69,7 @@ protected function __construct(array $aSettings){ 'contracts' => "contracts", 'tokens' => "tokens", 'operations' => "tokenOperations", + 'operations2' => "tokenOperations2", 'balances' => "tokenBalances", 'addressCache' => "cacheAddressData" ); From 4efc44bd05cb033d741efc669ad24d95a61a2b6c Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 4 Apr 2018 15:58:57 +0700 Subject: [PATCH 065/658] freekey workaround --- api/controller.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/controller.php b/api/controller.php index 5d912341..4ae6e6d6 100644 --- a/api/controller.php +++ b/api/controller.php @@ -111,16 +111,19 @@ public function run(){ $key = in_array($command, $this->apiCommands) ? $this->getRequest('apiKey', FALSE) : $this->getPostRequest('apiKey', FALSE); if(!$key || !$this->db->checkAPIkey($key)){ $this->sendError(1, 'Invalid API key'); - } + } $this->defaults = $this->db->getAPIKeyDefaults($key, $command); if(in_array($command, $this->apiPostCommands)){ + // @todo: Temporary solution, special key property will be used later + if($key == "freekey"){ + $this->sendError(1, 'Invalid API key'); + } $result = call_user_func(array($this, $command)); return $result; } $timestamp = $this->getRequest('timestamp', FALSE); - if(FALSE !== $timestamp){ $cacheId = 'API-' . $command . '-' . md5($_SERVER["REQUEST_URI"]); $oCache = $this->db->getCache(); From b3ee26a3b9ab8cb8148ba701a98ac0605718122d Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 4 Apr 2018 16:25:46 +0700 Subject: [PATCH 066/658] var_export -> json_encode --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 0c96136e..deaa2310 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1903,7 +1903,7 @@ public function getAPIKeyDefaults($key, $option = FALSE){ * @return array */ protected function getContractOperationCount($type, $address, $useFilter = TRUE){ - evxProfiler::checkpoint('getContractOperationCount', 'START', 'address=' . $address . ', type=' . (is_array($type) ? var_export($type, TRUE) : $type) . ', useFilter=' . (int)$useFilter); + evxProfiler::checkpoint('getContractOperationCount', 'START', 'address=' . $address . ', type=' . (is_array($type) ? json_encode($type) : $type) . ', useFilter=' . (int)$useFilter); $search = array("contract" => $address, 'type' => $type); $result = 0; if($useFilter && $this->filter){ @@ -1930,7 +1930,7 @@ protected function getContractOperationCount($type, $address, $useFilter = TRUE) * @return array */ protected function getContractOperation($type, $address, $limit, $offset = FALSE){ - evxProfiler::checkpoint('getContractOperation', 'START', 'type=' . (is_array($type) ? var_export($type, TRUE) : $type) . ', address=' . $address . ', limit=' . $limit . ', offset=' . (int)$offset); + evxProfiler::checkpoint('getContractOperation', 'START', 'type=' . (is_array($type) ? json_encode($type) : $type) . ', address=' . $address . ', limit=' . $limit . ', offset=' . (int)$offset); $search = array("contract" => $address, 'type' => $type); if($this->filter){ $search['$or'] = array( From 1712c6954d440c43f783148ee266b185da3149c9 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 13:12:31 +0700 Subject: [PATCH 067/658] Query rollback --- service/lib/ethplorer.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index deaa2310..4659c6e9 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1205,7 +1205,6 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr $search['type'] = array('$in' => $aTypes); } } - //if(!$showEth) $search['contract'] = array('$ne' => 'ETH'); if(!$showEth){ $search['isEth'] = false; } @@ -1225,13 +1224,11 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr ); } - /*if($aTypes && is_array($aTypes) && count($aTypes)){ - $search['type'] = array('$in' => $aTypes); - }*/ + $cursor = $this->oMongo->find('operations', $search, array("timestamp" => -1), $limit, $offset); - $hint = 'addresses_1_type_1_timestamp_1_isEth_1'; + // $hint = 'addresses_1_type_1_timestamp_1_isEth_1'; + // $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); - $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); foreach($cursor as $transfer){ if(is_null($aTypes) || in_array($transfer['type'], $aTypes)){ unset($transfer["_id"]); From 37516208e44bc946c0d11bb95bb77f69042ef71f Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:09:54 +0700 Subject: [PATCH 068/658] Some debug data added --- service/lib/ethplorer.php | 12 +++++++++ service/lib/mongo.php | 55 ++++++++++++++++++++++++++++++--------- service/service.php | 4 +++ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 4659c6e9..542ba10f 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -168,6 +168,18 @@ public function getCache(){ return $this->oCache; } + /** + * Returns some debug data + * + * @return array + */ + public function getDebugData(){ + return array( + 'phpTime' => evxProfiler::getTotalTime(), + 'queries' => $this->oMongo->getQueryProfileData() + ); + } + /** * Singleton getter. * diff --git a/service/lib/mongo.php b/service/lib/mongo.php index a484a73e..c062e340 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -62,6 +62,13 @@ class evxMongo { */ protected $logFile; + /** + * Mongo profiler + * + * @var array + */ + protected $aProfile = array(); + /** * Constructor. * @@ -175,11 +182,16 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi */ break; } - $finish = microtime(true); - $qTime = $finish - $start; - if($qTime > 1){ - $this->log('(' . ($qTime) . 's) Find ' . $this->dbName . '.' . $this->aDBs[$collection] . ' > ' . json_encode($aSearch) . ' [' . json_encode($aOptions) . ']'); + $aQuery = [ + 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'find' => $aSearch, + 'opts' => $aOptions, + 'time' => round(microtime(true) - $start, 4) + ]; + if($aQuery['time'] > 1){ + $this->log('(' . ($aQuery['time']) . 's) ' . $aQuery['collection'] . '.find(' . json_encode($aQuery['find']) . ', ' . json_encode($aQuery['opts']) . ')'); } + $this->aProfile[] = $aQuery; return $aResult; } @@ -223,11 +235,16 @@ public function count($collection, array $aSearch = array(), $limit = FALSE){ */ break; } - $finish = microtime(true); - $qTime = $finish - $start; - if($qTime > 1){ - $this->log('(' . ($qTime) . 's) Count ' . $this->dbName . '.' . $this->aDBs[$collection] . ' > ' . json_encode($aSearch)); + $aQuery = [ + 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'count' => $aSearch, + 'opts' => $aOptions, + 'time' => round(microtime(true) - $start, 4) + ]; + if($aQuery['time'] > 1){ + $this->log('(' . ($aQuery['time']) . 's) ' . $aQuery['collection'] . '.count(' . json_encode($aQuery['count']) . ', ' . json_encode($aQuery['opts']) . ')'); } + $this->aProfile[] = $aQuery; return $result; } @@ -270,14 +287,28 @@ public function aggregate($collection, array $aSearch = array()){ } break; } - $finish = microtime(true); - $qTime = $finish - $start; - if($qTime > 1){ - $this->log('(' . ($qTime) . 's) Aggregate ' . $this->dbName . '.' . $this->aDBs[$collection] . ' > ' . json_encode($aSearch)); + $aQuery = [ + 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'aggregate' => $aSearch, + 'opts' => $aOptions, + 'time' => round(microtime(true) - $start, 4) + ]; + if($aQuery['time'] > 1){ + $this->log('(' . ($aQuery['time']) . 's) ' . $aQuery['collection'] . '.aggregate(' . json_encode($aQuery['aggregate']) . ')'); } + $this->aProfile[] = $aQuery; return $aResult; } + /** + * Returns query profiler. + * + * @return array + */ + public function getQueryProfileData(){ + return $this->aProfile; + } + /** * Singleton implementation. * diff --git a/service/service.php b/service/service.php index f80133c6..b0f6e022 100644 --- a/service/service.php +++ b/service/service.php @@ -100,4 +100,8 @@ $result = Ethplorer::db($aConfig)->getActiveNotes(); } +if($debugId){ + $result['debug'] = $es->getDebugData(); +} + echo json_encode($result); From 28943847d7dc12b2bcca70445fabdaa484d29a7d Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:13:59 +0700 Subject: [PATCH 069/658] Notice fixed --- service/lib/mongo.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index c062e340..9d626300 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -127,6 +127,7 @@ public function toDate($timestamp = 0){ public function find($collection, array $aSearch = array(), $sort = false, $limit = false, $skip = false, $fields = false, $hint = false){ $aResult = false; $start = microtime(true); + $aOptions = array(); switch($this->driver){ case 'fake': $aResult = array(); @@ -150,7 +151,6 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi break; case 'mongodb': - $aOptions = array(); if(is_array($sort)){ $aOptions['sort'] = $sort; } @@ -183,7 +183,7 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi break; } $aQuery = [ - 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'collection' => $this->aDBs[$collection], 'find' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) @@ -236,7 +236,7 @@ public function count($collection, array $aSearch = array(), $limit = FALSE){ break; } $aQuery = [ - 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'collection' => $this->aDBs[$collection], 'count' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) @@ -288,7 +288,7 @@ public function aggregate($collection, array $aSearch = array()){ break; } $aQuery = [ - 'collection' => $this->dbName . '.' . $this->aDBs[$collection], + 'collection' => $this->aDBs[$collection], 'aggregate' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) From b4caa05f61c47954478a9ad3d0bc7bc1281d9392 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:19:33 +0700 Subject: [PATCH 070/658] Collection name fixed --- service/lib/mongo.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index 9d626300..3f0f44f4 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -183,7 +183,7 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi break; } $aQuery = [ - 'collection' => $this->aDBs[$collection], + 'collection' => (string)$this->aDBs[$collection], 'find' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) @@ -236,7 +236,7 @@ public function count($collection, array $aSearch = array(), $limit = FALSE){ break; } $aQuery = [ - 'collection' => $this->aDBs[$collection], + 'collection' => (string)$this->aDBs[$collection], 'count' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) @@ -288,7 +288,7 @@ public function aggregate($collection, array $aSearch = array()){ break; } $aQuery = [ - 'collection' => $this->aDBs[$collection], + 'collection' => (string)$this->aDBs[$collection], 'aggregate' => $aSearch, 'opts' => $aOptions, 'time' => round(microtime(true) - $start, 4) From 16a058469b349d246cb8cb763ec341f1b5fe504e Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:29:46 +0700 Subject: [PATCH 071/658] Notice fixed --- service/lib/mongo.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index 3f0f44f4..1e41c2ea 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -261,6 +261,7 @@ public function count($collection, array $aSearch = array(), $limit = FALSE){ public function aggregate($collection, array $aSearch = array()){ $aResult = false; $start = microtime(true); + $aOptions = array(); switch($this->driver){ case 'fake': $aResult = array(); From 9dd9b47ac9c8e2931b1fa55b13c9a87957fc4a91 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:37:12 +0700 Subject: [PATCH 072/658] Rollback --- service/lib/ethplorer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 542ba10f..3a4f05a3 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1218,7 +1218,8 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr } } if(!$showEth){ - $search['isEth'] = false; + $search['contract'] = array('$ne' => 'ETH'); + // $search['isEth'] = false; } // @todo: remove $or, use special field with from-to-address-txHash concatination maybe From a0d1b9f3396e55dfe36b64c02fc7d0530c607cb6 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 14:49:45 +0700 Subject: [PATCH 073/658] Notice fixed --- service/lib/ethplorer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 3a4f05a3..132ad9be 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -738,6 +738,7 @@ public function getTokens($updateCache = false){ $aResult = $this->oCache->get('tokens', false, true); if($updateCache || (false === $aResult)){ evxProfiler::checkpoint('getTokens', 'START'); + $aPrevTokens = array(); if($updateCache){ $aPrevTokens = $aResult; if(!is_array($aPrevTokens)){ From e6900d55f89f449af3fbab2692d95d9ef3763e0d Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 5 Apr 2018 19:44:05 +0700 Subject: [PATCH 074/658] Store request debug --- js/ethplorer.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index 22c79a81..b65fbd5e 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -299,6 +299,9 @@ Ethplorer = { } $.getJSON(Ethplorer.service, requestData, function(_txHash){ return function(data){ + if(data.debug){ + Ethplorer.requestDebug = data.debug; + } if(data.ethPrice){ Ethplorer.ethPrice = data.ethPrice; } @@ -700,6 +703,9 @@ Ethplorer = { } $.getJSON(Ethplorer.service, data, function(_address){ return function(data){ + if(data.debug){ + Ethplorer.requestDebug = data.debug; + } if(data.ethPrice){ Ethplorer.ethPrice = data.ethPrice; } @@ -1580,6 +1586,9 @@ Ethplorer = { data.debugId = Ethplorer.debugId; } $.getJSON(Ethplorer.service, data, function(data){ + if(data.debug){ + Ethplorer.requestDebug = data.debug; + } var empty = !(data && data.results && data.total); if(!empty){ document.location.href = '/address/' + data.results[0][2]; From 0c681c330aa40674b1ac14a8b3305c800f26e246 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Apr 2018 16:19:49 +0700 Subject: [PATCH 075/658] Widgets customizations. --- api/widget.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/api/widget.js b/api/widget.js index b6218b44..c922b2d5 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1000,7 +1000,7 @@ ethplorerWidget.Type['top'] = function(element, options, templates){ } var totalsHtml = ''; if(data.totals){ - var cap = data.totals.cap ? (ethplorerWidget.Utils.formatNum(data.totals.cap / 1000000000, true, 0, true)) : '?'; + var cap = data.totals.cap ? (ethplorerWidget.Utils.formatNum(data.totals.cap / 1000000000, true, 1, true)) : '?'; var volume24h = data.totals.volume24h ? (ethplorerWidget.Utils.formatNum(data.totals.volume24h, true, 0, true, true, 99999999)) : '?'; var ivdiff = ethplorerWidget.Utils.pdiff(data.totals.cap, data.totals.capPrevious, true); @@ -1215,7 +1215,8 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat pattern: "#,### K" }); var currencyFormatter = new google.visualization.NumberFormat({ - pattern: '$ #,### B' + //pattern: '$ #,### B' + pattern: '$ #,##0.0 B' }); var tooltip = '
'; tooltip += '' + tooltipDateFormatter.formatValue(date) + '
' + @@ -1229,7 +1230,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat var totalsHtml = ''; if(this.options.total && aTotals && aTotals.cap){ - var cap = aTotals.cap ? (ethplorerWidget.Utils.formatNum(aTotals.cap / 1000000000, true, 0, true)) : '?'; + var cap = aTotals.cap ? (ethplorerWidget.Utils.formatNum(aTotals.cap / 1000000000, true, 1, true)) : '?'; var volume24h = aTotals.volume24h ? (ethplorerWidget.Utils.formatNum(aTotals.volume24h, true, 0, true, true, 99999999)) : '?'; var ivdiff = ethplorerWidget.Utils.pdiff(aTotals.cap, aTotals.capPrevious, true); var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; @@ -1306,7 +1307,8 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat var capKey = stDate.getFullYear() + '-' + capKeyMonth + '-' + capKeyDay; var cap = ('undefined' !== typeof(aCap[capKey])) ? aCap[capKey] : 0; if(cap <= 1000000000 && firstDate) skipDate = true; - cap = Math.round(cap / 1000000000); + //cap = Math.round(cap / 1000000000); + cap = parseFloat(ethplorerWidget.Utils.formatNum(cap / 1000000000, true, 1, true)); var tooltip = this.getTooltip(new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt, cap); if(!skipDate) aData.push([new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt, tooltip, cap, tooltip]); }else{ @@ -1399,7 +1401,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat title: 'Token operations', format: '#,### K', viewWindow: { - max: 700 + max: 1000 }, }, 1: { From 58521cee141f0236126c26b79ebc95432eaaf501 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Apr 2018 17:08:27 +0700 Subject: [PATCH 076/658] Widgets customizations. --- api/widget.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/widget.js b/api/widget.js index c922b2d5..af623831 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1221,7 +1221,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat var tooltip = '
'; tooltip += '' + tooltipDateFormatter.formatValue(date) + '
' + 'Token operations: ' + ((cnt < 1) ? '<1 K' : numFormatter.formatValue(cnt)) + '
' + - 'Tokens Cap: ' + ((cap < 1) ? '<1 B' : currencyFormatter.formatValue(cap)) + '' + + 'Tokens Cap: ' + ((cap < 0.1) ? '<0.1 B' : currencyFormatter.formatValue(cap)) + '' + '
'; return tooltip; } @@ -1370,7 +1370,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat pointSize: 5, }; if(this.options['theme'] == 'dark'){ - defOptions.colors = this.options.cap ? ['#FCEC0F', '#47C2FF'] : ['#47C2FF', '#FCEC0F']; + defOptions.colors = this.options.cap ? ['#B5A81B', '#47C2FF'] : ['#47C2FF', '#FCEC0F']; defOptions.titleTextStyle = {color: '#DEDEDE'}; defOptions.backgroundColor = {fill: 'transparent'}; @@ -1389,6 +1389,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat type: 'steppedArea', targetAxisIndex: 0, lineWidth: 1, + //areaOpacity: 0 }, 1: { type: 'line', From 51fd0907622e5511ace61804516cce70ee80c188 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 10 Apr 2018 17:15:32 +0700 Subject: [PATCH 077/658] Website updated --- index.php | 2 +- widgets.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 950af37b..45691185 100644 --- a/index.php +++ b/index.php @@ -696,7 +696,7 @@
-
© 2016-2018 Everex +
© 2016-2018 Everex
Privacy & Terms
diff --git a/widgets.php b/widgets.php index 9a0e95f8..287ae1e2 100644 --- a/widgets.php +++ b/widgets.php @@ -631,7 +631,7 @@ function getWidgetCode(ta) {
-
© 2016-2018 Everex +
© 2016-2018 Everex
Privacy & Terms
From 97b86ec057200d0ae9f08d32b90f12dc3a6ee768 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Apr 2018 17:45:51 +0700 Subject: [PATCH 078/658] Redis support. --- service/lib/cache.php | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 10d02f5b..bc0bbdad 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -107,9 +107,17 @@ public function __construct($path = __DIR__, $driver = FALSE, $useLocks = FALSE) } $this->oDriver = $mc; }else{ - die('Memcached calss not found, use filecache instead'); + die('Memcached class not found, use filecache instead'); $this->driver = 'file'; } + }else if('redis' === $this->driver){ + if(class_exists('Redis')){ + $rc = new Redis(); + $rc->connect('localhost', 6379); + $this->oDriver = $rc; + }else{ + die('Redis class not found'); + } } } @@ -137,6 +145,7 @@ public function save($entryName, $data){ $saveRes = false; $this->store($entryName, $data); switch($this->driver){ + case 'redis': case 'memcached': $lifetime = isset($this->aLifetime[$entryName]) ? (int)$this->aLifetime[$entryName] : 0; /*if($lifetime > evxCache::MONTH){ @@ -149,9 +158,9 @@ public function save($entryName, $data){ $lifetime = time() + $lifetime; } //$saveRes = $this->oDriver->set($entryName, $data, $lifetime); - $aMemcachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); - $saveRes = $this->oDriver->set($entryName, $aMemcachedData); - if(!in_array($entryName, array('tokens', 'rates')) && (0 !== strpos($entryName, 'rates-history-'))){ + $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); + $saveRes = $this->oDriver->set($entryName, ('redis' == $this->driver) ? json_encode($aCachedData) : $aCachedData); + if(('redis' == $this->driver) || (!in_array($entryName, array('tokens', 'rates')) && (0 !== strpos($entryName, 'rates-history-')))){ break; } case 'file': @@ -201,6 +210,8 @@ public function isLockFileExists($file){ public function addLock($entryName){ if('memcached' === $this->driver){ return $this->oDriver->add($entryName . '-lock', TRUE, evxCache::LOCK_TTL); + }else if('redis' === $this->driver){ + return $this->oDriver->set($entryName . '-lock', 'true', array('nx', 'ex' => evxCache::LOCK_TTL)); }else{ $lockFilename = $this->path . '/' . $entryName . "-lock.tmp"; @@ -219,7 +230,7 @@ public function addLock($entryName){ * @return boolean */ public function deleteLock($entryName){ - if('memcached' === $this->driver){ + if('memcached' === $this->driver || 'redis' === $this->driver){ return $this->oDriver->delete($entryName . '-lock'); }else{ return @unlink($this->path . '/' . $entryName . '-lock.tmp'); @@ -237,8 +248,8 @@ public function deleteLock($entryName){ public function loadCachedData($entryName, $default = NULL, $cacheLifetime = FALSE){ $result = array('data' => $default, 'expired' => FALSE); $file = ('file' === $this->driver); - if('memcached' === $this->driver){ - $memcachedData = $this->oDriver->get($entryName); + if('memcached' === $this->driver || 'redis' === $this->driver){ + $memcachedData = ('redis' == $this->driver) ? json_decode($this->oDriver->get($entryName), TRUE) : $this->oDriver->get($entryName); if($memcachedData && isset($memcachedData['lifetime']) && isset($memcachedData['data'])){ $result['data'] = $memcachedData['data']; if($memcachedData['lifetime'] < time()){ @@ -249,6 +260,9 @@ public function loadCachedData($entryName, $default = NULL, $cacheLifetime = FAL if(!$result['data'] || $result['expired'] || (in_array($entryName, array('tokens', 'rates')) || (0 === strpos($entryName, 'rates-history-')))){ $file = TRUE; } + if('redis' === $this->driver){ + $file = FALSE; + } } if($file){ $filename = $this->path . '/' . $entryName . ".tmp"; From a9f928b504f5245652af6947567fa2b1086297fb Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Apr 2018 19:56:28 +0700 Subject: [PATCH 079/658] Redis support. --- service/lib/cache.php | 5 +++-- service/lib/ethplorer.php | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index bc0bbdad..a498c346 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -87,7 +87,8 @@ class evxCache { * @param string $path Cache files path * @todo params to config */ - public function __construct($path = __DIR__, $driver = FALSE, $useLocks = FALSE){ + public function __construct(array $aConfig, $driver = FALSE, $useLocks = FALSE){ + $path = $aConfig['cacheDir']; $path = realpath($path); if(file_exists($path) && is_dir($path)){ $this->path = $path; @@ -113,7 +114,7 @@ public function __construct($path = __DIR__, $driver = FALSE, $useLocks = FALSE) }else if('redis' === $this->driver){ if(class_exists('Redis')){ $rc = new Redis(); - $rc->connect('localhost', 6379); + $rc->connect($aConfig['redis']['server'], $aConfig['redis']['port']); $this->oDriver = $rc; }else{ die('Redis class not found'); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 132ad9be..1406538e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -125,7 +125,7 @@ protected function __construct(array $aConfig){ ); $cacheDriver = isset($this->aSettings['cacheDriver']) ? $this->aSettings['cacheDriver'] : 'file'; $useLocks = isset($this->aSettings['useLocks']) ? $this->aSettings['useLocks'] : FALSE; - $this->oCache = new evxCache($this->aSettings['cacheDir'], $cacheDriver, $useLocks); + $this->oCache = new evxCache($this->aSettings, $cacheDriver, $useLocks); if(isset($this->aSettings['mongo']) && is_array($this->aSettings['mongo'])){ evxMongoScanner::init($this->aSettings['mongo']); $this->oMongo = evxMongoScanner::getInstance(); From 01feadad3f9f06992167ee08a3418532184117da Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Apr 2018 20:18:43 +0700 Subject: [PATCH 080/658] Redis support. --- service/lib/cache.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index a498c346..cd6b2d0f 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -98,6 +98,8 @@ public function __construct(array $aConfig, $driver = FALSE, $useLocks = FALSE){ } $this->useLocks = $useLocks; + if(class_exists('Redis') && (php_sapi_name() === 'cli') && isset($aConfig['redis'])) $this->driver = 'redis'; + if('memcached' === $this->driver){ if(class_exists('Memcached')){ $mc = new Memcached('ethplorer'); From 60bad7c6d4bf43db2be3e39c5dbf82dae475c60a Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 16:56:37 +0700 Subject: [PATCH 081/658] Connect to mongo only on actual query --- service/lib/mongo.php | 13 +++++++++++++ service/lib/mongo_pools.php | 13 +++++-------- service/lib/mongo_scanner.php | 13 +++++-------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/service/lib/mongo.php b/service/lib/mongo.php index 1e41c2ea..500e6311 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -68,7 +68,11 @@ class evxMongo { * @var array */ protected $aProfile = array(); + + protected $aSettings = array(); + protected $isConnected = false; + /** * Constructor. * @@ -85,6 +89,8 @@ protected function __construct(array $aSettings){ 'dbName' => 'ethplorer', 'prefix' => 'everex.' ); + + $this->aSettings = $aSettings; $this->dbName = $aSettings['dbName']; $this->driver = $aSettings['driver']; } @@ -125,6 +131,7 @@ public function toDate($timestamp = 0){ * @return array */ public function find($collection, array $aSearch = array(), $sort = false, $limit = false, $skip = false, $fields = false, $hint = false){ + $this->connectDb(); $aResult = false; $start = microtime(true); $aOptions = array(); @@ -203,6 +210,7 @@ public function find($collection, array $aSearch = array(), $sort = false, $limi * @return int */ public function count($collection, array $aSearch = array(), $limit = FALSE){ + $this->connectDb(); $result = false; $start = microtime(true); $aOptions = array(); @@ -259,6 +267,7 @@ public function count($collection, array $aSearch = array(), $limit = FALSE){ * @return array */ public function aggregate($collection, array $aSearch = array()){ + $this->connectDb(); $aResult = false; $start = microtime(true); $aOptions = array(); @@ -328,4 +337,8 @@ protected function log($message){ $logString = '[' . date('Y-m-d H:i:s') . '] - ' . $message . "\n"; file_put_contents($this->logFile, $logString, FILE_APPEND); } + + protected function connectDb(){ + + } } diff --git a/service/lib/mongo_pools.php b/service/lib/mongo_pools.php index 669ee13c..4634e837 100644 --- a/service/lib/mongo_pools.php +++ b/service/lib/mongo_pools.php @@ -29,15 +29,10 @@ public static function init(array $aSettings = array()){ self::$oInstance = new evxMongoPools($aSettings); } - /** - * Constructor. - * - * @param array $aSettings - * @throws \Exception - */ - protected function __construct(array $aSettings){ + protected function connectDb(){ + if($this->isConnected) return; - parent::__construct($aSettings); + $aSettings = $this->aSettings; $start = microtime(true); switch($aSettings['driver']){ @@ -72,5 +67,7 @@ protected function __construct(array $aSettings){ if($qTime > 0.1){ $this->log('(' . ($qTime) . 's) Connection to ' . $aSettings['server']); } + + $this->isConnected = true; } } diff --git a/service/lib/mongo_scanner.php b/service/lib/mongo_scanner.php index 7d6ad6fc..72654ec9 100644 --- a/service/lib/mongo_scanner.php +++ b/service/lib/mongo_scanner.php @@ -29,15 +29,10 @@ public static function init(array $aSettings = array()){ self::$oInstance = new evxMongoScanner($aSettings); } - /** - * Constructor. - * - * @param array $aSettings - * @throws \Exception - */ - protected function __construct(array $aSettings){ + protected function connectDb(){ + if($this->isConnected) return; - parent::__construct($aSettings); + $aSettings = $this->aSettings; $start = microtime(true); switch($aSettings['driver']){ @@ -82,5 +77,7 @@ protected function __construct(array $aSettings){ if($qTime > 0.1){ $this->log('(' . ($qTime) . 's) Connection to ' . $aSettings['server']); } + $this->isConnected = true; } + } From 9a7fca1aa8c14fb3de6642e06cf61f1ca2be82e6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 11 Apr 2018 17:03:58 +0700 Subject: [PATCH 082/658] Test --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b2c98c31..5665306d 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,4 @@ Make sure your web server supports .htaccess and mod_rewrite. # Configure Copy `service/config.sample.php` to `service/config.php` and specify service addresses. + From a1183a18d62d9c41e5c1c2876497c16e57abf571 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 17:41:10 +0700 Subject: [PATCH 083/658] Query debug --- api/controller.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/controller.php b/api/controller.php index 9db68124..4a637bb6 100644 --- a/api/controller.php +++ b/api/controller.php @@ -85,6 +85,9 @@ public function getPostRequest($name, $default = NULL){ } public function sendResult(array $result){ + if($this->getRequest('debugId')){ + $result['debug'] = $es->getDebugData(); + } echo json_encode($result, JSON_UNESCAPED_SLASHES); die(); } From a3c62b8de0a64d400e585271c15c311bc3658b46 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 17:46:09 +0700 Subject: [PATCH 084/658] Mistype fixed --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 4a637bb6..8dccb311 100644 --- a/api/controller.php +++ b/api/controller.php @@ -86,7 +86,7 @@ public function getPostRequest($name, $default = NULL){ public function sendResult(array $result){ if($this->getRequest('debugId')){ - $result['debug'] = $es->getDebugData(); + $result['debug'] = $this->db->getDebugData(); } echo json_encode($result, JSON_UNESCAPED_SLASHES); die(); From b130979218ecd0bce5c1f23720af1a9105ce011c Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 18:08:03 +0700 Subject: [PATCH 085/658] Debug info --- service/lib/ethplorer.php | 3 ++- service/lib/mongo.php | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1406538e..1b689ae4 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -175,7 +175,8 @@ public function getCache(){ */ public function getDebugData(){ return array( - 'phpTime' => evxProfiler::getTotalTime(), + 'totalTime' => evxProfiler::getTotalTime(), + 'dbConnected' => $this->oMongo->dbConnected(), 'queries' => $this->oMongo->getQueryProfileData() ); } diff --git a/service/lib/mongo.php b/service/lib/mongo.php index 500e6311..9cadfb6b 100644 --- a/service/lib/mongo.php +++ b/service/lib/mongo.php @@ -318,6 +318,10 @@ public function aggregate($collection, array $aSearch = array()){ public function getQueryProfileData(){ return $this->aProfile; } + + public function dbConnected(){ + return $this->isConnected; + } /** * Singleton implementation. @@ -339,6 +343,6 @@ protected function log($message){ } protected function connectDb(){ - + // @todo: throw an exception } } From 37150aef70cd84253f32c5971bd6162001704c0e Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 11 Apr 2018 19:19:41 +0700 Subject: [PATCH 086/658] Use new index. --- service/lib/ethplorer.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1b689ae4..34f6406e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1220,8 +1220,8 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr } } if(!$showEth){ - $search['contract'] = array('$ne' => 'ETH'); - // $search['isEth'] = false; + //$search['contract'] = array('$ne' => 'ETH'); + $search['isEth'] = false; } // @todo: remove $or, use special field with from-to-address-txHash concatination maybe @@ -1239,10 +1239,12 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr ); } - $cursor = $this->oMongo->find('operations', $search, array("timestamp" => -1), $limit, $offset); - - // $hint = 'addresses_1_type_1_timestamp_1_isEth_1'; - // $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); + if(!$showEth){ + $hint = 'addresses_1_isEth_1_timestamp_1'; + $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); + }else{ + $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset); + } foreach($cursor as $transfer){ if(is_null($aTypes) || in_array($transfer['type'], $aTypes)){ From be190dbcf596c17b4dd001ebe0dd0d8ee5d71518 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 19:39:26 +0700 Subject: [PATCH 087/658] getAddressTransactions sort fixed --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 34f6406e..1ba4d013 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -511,8 +511,8 @@ public function getTransactions($address, $limit = 10, $showZero = FALSE){ ); } } - usort($result, function($a, $b){ - return ($a['timestamp'] > $b['timestamp']) ? 1 : (($a['timestamp'] < $b['timestamp']) ? -1 : 0); + usort($result, function($a, $b){ + return ($a['timestamp'] > $b['timestamp']) ? -1 : (($a['timestamp'] < $b['timestamp']) ? 1 : 0); }); if(count($result) > $limit){ From dbdf2244e0bde13ee0298917920eaae897f448fc Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Apr 2018 19:47:44 +0700 Subject: [PATCH 088/658] Cache added --- service/lib/ethplorer.php | 82 ++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1ba4d013..fc3a1895 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -480,50 +480,54 @@ public function getEtherTotalOut($address, $updateCache = FALSE){ * @return array */ public function getTransactions($address, $limit = 10, $showZero = FALSE){ - $result = array(); - $fields = ['from', 'to']; - foreach($fields as $field){ - $search = array(); - $search[$field] = $address; - if(!$showZero){ - $search['value'] = array('$gt' => 0); - } - $cursor = $this->oMongo->find('transactions', $search, array("timestamp" => -1), $limit); - foreach($cursor as $tx){ - $receipt = isset($tx['receipt']) ? $tx['receipt'] : false; - $tx['gasLimit'] = $tx['gas']; - $tx['gasUsed'] = isset($tx['gasUsed']) ? $tx['gasUsed'] : ($receipt ? $receipt['gasUsed'] : 0); - // @todo: research - // $toContract = !!$tx['input']; - // $toContract = !!$this->getContract($tx['to']); // <-- too slow - - $success = ((21000 == $tx['gasUsed']) || /*!$toContract ||*/ ($tx['gasUsed'] < $tx['gasLimit']) || ($receipt && !empty($receipt['logs']))); - $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; + $cache = 'transactions-' . $address . '-' . $limit . '-' . ($showZero ? '1' : '0'); + $result = $this->oCache->get($cache, FALSE, TRUE, 15); + if(!$result){ + $result = array(); + $fields = ['from', 'to']; + foreach($fields as $field){ + $search = array(); + $search[$field] = $address; + if(!$showZero){ + $search['value'] = array('$gt' => 0); + } + $cursor = $this->oMongo->find('transactions', $search, array("timestamp" => -1), $limit); + foreach($cursor as $tx){ + $receipt = isset($tx['receipt']) ? $tx['receipt'] : false; + $tx['gasLimit'] = $tx['gas']; + $tx['gasUsed'] = isset($tx['gasUsed']) ? $tx['gasUsed'] : ($receipt ? $receipt['gasUsed'] : 0); + // @todo: research + // $toContract = !!$tx['input']; + // $toContract = !!$this->getContract($tx['to']); // <-- too slow + + $success = ((21000 == $tx['gasUsed']) || /*!$toContract ||*/ ($tx['gasUsed'] < $tx['gasLimit']) || ($receipt && !empty($receipt['logs']))); + $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; - $result[] = array( - 'timestamp' => $tx['timestamp'], - 'from' => $tx['from'], - 'to' => $tx['to'], - 'hash' => $tx['hash'], - 'value' => $tx['value'], - 'input' => $tx['input'], - 'success' => $success - ); + $result[] = array( + 'timestamp' => $tx['timestamp'], + 'from' => $tx['from'], + 'to' => $tx['to'], + 'hash' => $tx['hash'], + 'value' => $tx['value'], + 'input' => $tx['input'], + 'success' => $success + ); + } } - } - usort($result, function($a, $b){ - return ($a['timestamp'] > $b['timestamp']) ? -1 : (($a['timestamp'] < $b['timestamp']) ? 1 : 0); - }); + usort($result, function($a, $b){ + return ($a['timestamp'] > $b['timestamp']) ? -1 : (($a['timestamp'] < $b['timestamp']) ? 1 : 0); + }); - if(count($result) > $limit){ - $limitedResult = []; - foreach($result as $index => $record){ - if($index == $limit) break; - $limitedResult[] = $record; + if(count($result) > $limit){ + $limitedResult = []; + foreach($result as $index => $record){ + if($index == $limit) break; + $limitedResult[] = $record; + } + $result = $limitedResult; } - $result = $limitedResult; + $this->oCache->save($cache, $result); } - return $result; } From dac74584f59ada1adeb4176045a2bd589cfb9935 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 12 Apr 2018 16:20:09 +0700 Subject: [PATCH 089/658] Redis support. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index cd6b2d0f..f3b860e1 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -98,7 +98,7 @@ public function __construct(array $aConfig, $driver = FALSE, $useLocks = FALSE){ } $this->useLocks = $useLocks; - if(class_exists('Redis') && (php_sapi_name() === 'cli') && isset($aConfig['redis'])) $this->driver = 'redis'; + //if(class_exists('Redis') && (php_sapi_name() === 'cli') && isset($aConfig['redis'])) $this->driver = 'redis'; if('memcached' === $this->driver){ if(class_exists('Memcached')){ From 3db91837918f3091875e4e2a646ddfa17e13946c Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Apr 2018 23:42:21 +0700 Subject: [PATCH 090/658] Cache updated --- api/controller.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/controller.php b/api/controller.php index 8dccb311..9131a7f0 100644 --- a/api/controller.php +++ b/api/controller.php @@ -123,15 +123,16 @@ public function run(){ } $timestamp = $this->getRequest('timestamp', FALSE); + $needCache = (FALSE !== $timestamp) || ($command === 'getAddressHistory'); - if(FALSE !== $timestamp){ + if($needCache){ $cacheId = 'API-' . $command . '-' . md5($_SERVER["REQUEST_URI"]); $oCache = $this->db->getCache(); $result = $oCache->get($cacheId, FALSE, TRUE, 15); } if(!$result){ $result = call_user_func(array($this, $command)); - if((FALSE !== $timestamp) && $cacheId && (FALSE !== $result)){ + if($needCache && $cacheId && (FALSE !== $result)){ $oCache->save($cacheId, $result); } } From e3a4bc7fe3b6715e1ac51e866207284426ea1495 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Apr 2018 23:48:11 +0700 Subject: [PATCH 091/658] Suspend keys --- api/controller.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/controller.php b/api/controller.php index 9131a7f0..4acb492a 100644 --- a/api/controller.php +++ b/api/controller.php @@ -117,6 +117,10 @@ public function run(){ } $this->defaults = $this->db->getAPIKeyDefaults($key, $command); + if(isset($this->aSettings['apiKeys'][$key]['suspended']) && $this->aSettings['apiKeys'][$key]['suspended']){ + $this->sendError(133, 'API key temporary suspended. Contact support.'); + } + if(in_array($command, $this->apiPostCommands)){ $result = call_user_func(array($this, $command)); return $result; From dc1f4ffdeb5cc5215b9f30f700939131261a581a Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Apr 2018 23:53:47 +0700 Subject: [PATCH 092/658] Suspend keys --- api/controller.php | 2 +- service/lib/ethplorer.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 4acb492a..04108b56 100644 --- a/api/controller.php +++ b/api/controller.php @@ -117,7 +117,7 @@ public function run(){ } $this->defaults = $this->db->getAPIKeyDefaults($key, $command); - if(isset($this->aSettings['apiKeys'][$key]['suspended']) && $this->aSettings['apiKeys'][$key]['suspended']){ + if($this->db->isSuspendedAPIKey($key)){ $this->sendError(133, 'API key temporary suspended. Contact support.'); } diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index fc3a1895..69a31ffa 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1899,6 +1899,10 @@ public function checkAPIKey($key){ return isset($this->aSettings['apiKeys']) && isset($this->aSettings['apiKeys'][$key]); } + public function isSuspendedAPIKey($key){ + return (isset($this->aSettings['apiKeys'][$key]['suspended']) && $this->aSettings['apiKeys'][$key]['suspended']); + } + public function getAPIKeyDefaults($key, $option = FALSE){ $res = FALSE; if($this->checkAPIKey($key)){ From d4ac162aa8e3be20ba4c60a11e65fbc6af7f6b55 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 16 Apr 2018 17:43:20 +0700 Subject: [PATCH 093/658] Widgets customizations. --- api/widget.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/widget.js b/api/widget.js index af623831..cf61223e 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1307,6 +1307,10 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat var capKey = stDate.getFullYear() + '-' + capKeyMonth + '-' + capKeyDay; var cap = ('undefined' !== typeof(aCap[capKey])) ? aCap[capKey] : 0; if(cap <= 1000000000 && firstDate) skipDate = true; + if(aTotals && aTotals.cap && firstDate){ + var capdiff = ethplorerWidget.Utils.pdiff(cap, aTotals.cap); + if(Math.abs(capdiff) >= 30) skipDate = true; + } //cap = Math.round(cap / 1000000000); cap = parseFloat(ethplorerWidget.Utils.formatNum(cap / 1000000000, true, 1, true)); var tooltip = this.getTooltip(new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt, cap); From 1729db83b99993d957066139adc9a148ec190ccd Mon Sep 17 00:00:00 2001 From: Ilya S Date: Mon, 16 Apr 2018 17:44:36 +0700 Subject: [PATCH 094/658] show historical price if enabled in session --- css/ethplorer.css | 37 +++++++++++- index.php | 10 +++- js/ethplorer.js | 141 ++++++++++++++++++++++++++-------------------- 3 files changed, 124 insertions(+), 64 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 93532128..50230bbf 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -175,6 +175,28 @@ tr.paginationFooter td ul.pagination { padding: 8px 8px 8px 28px; } +table.table.limit-width td:first-child, +table.table.limit-width td:nth-child(2) { + word-wrap: break-word; + max-width: 100px; +} + + +@media screen and (min-width: 500px) { + table.table.limit-width td:first-child{ + max-width: 200px; + } + table.table.limit-width td:nth-child(2) { + max-width: 200px; + } +} +@media screen and (min-width: 922px) { + table.table.limit-width td:first-child, + table.table.limit-width td:nth-child(2) { + max-width: 270px; /*tr width max 540px*/ + } +} + #address-chainy-tx .table tr:nth-child(even), #token-transfers-tab .table tr:nth-child(even), #token-issuances-tab .table tr:nth-child(even), @@ -1227,7 +1249,8 @@ a.token-update { } .multiop tr td:nth-child(3), - .multiop tr td:nth-child(4) + .multiop tr td:nth-child(4), + .multiop tr td:nth-child(5) { display: none; } @@ -1345,3 +1368,15 @@ a.token-update { 0%{transform:rotate(0deg)} 100%{transform:rotate(360deg)} } + +.scrollable{ + max-height: 400px; + overflow-y: auto; +} + +.historical-price { + /*font-size: 0.7em;*/ + font-size: 0.8em; + /*opacity: 0.5;*/ + color: rgba(255, 255, 255, 0.6); +} \ No newline at end of file diff --git a/index.php b/index.php index 45691185..d04feb8f 100644 --- a/index.php +++ b/index.php @@ -263,8 +263,10 @@

Internal operations

- -
+
+ +
+
@@ -314,6 +316,10 @@ Date + + Value @ tx date + + From diff --git a/js/ethplorer.js b/js/ethplorer.js index b65fbd5e..c231994c 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -32,6 +32,7 @@ Ethplorer = { Ethplorer.Config = ethplorerConfig; } Ethplorer.isProd = ('ethplorer.io' === document.location.host); + Ethplorer.showHistoricalPrice = sessionStorage.getItem("enableHistoricalPrice") === 'true'; BigNumber.config({ ERRORS: false }); Ethplorer.Nav.init(); Ethplorer.Storage.init(); @@ -53,7 +54,7 @@ Ethplorer = { $('#filter_list').val(Ethplorer.filter); $('#filter_list').addClass('filled'); }else{ - Ethplorer.Nav.del('filter'); + Ethplorer.Nav.del('filter'); } } } @@ -141,7 +142,7 @@ Ethplorer = { Ethplorer.filter = filter; Ethplorer.showTableLoader(); $('#filter_list').attr('disabled', true) - + // Reload active tab, set other tabs as need to reload Ethplorer.reloadTab(false, true); } @@ -309,10 +310,8 @@ Ethplorer = { } }(txHash)); }, - knownContracts: [], dataFields: {}, - showOpDetails: function(oTx, op){ var titleAdd = ''; var oToken = Ethplorer.prepareToken(op.token); @@ -321,7 +320,7 @@ Ethplorer = { $('.token-name:eq(0)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, tokenName, false)); $('.token-name:eq(1)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, oToken.name , false)); var txData = {tx: oTx, operation: op, token: oToken}; - + $('.token-related td.list-field').empty(); Ethplorer.fillValues('transaction', txData, ['token', 'token.timestamp', 'token.contract', 'token.symbol', 'token.price', 'token.decimals', 'token.owner']); var totalSupply = oToken.totalSupply; @@ -373,15 +372,13 @@ Ethplorer = { Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); if(oTx.blockNumber){ $('#txTokenStatus')[oOperation.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); + $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); $('#txTokenStatus').html(oOperation.success ? 'Success' : 'Failed' + (oOperation.failedReason ? (': ' + Ethplorer.getTxErrorReason(oOperation.failedReason)) : '')); $('#operation-status').addClass(oOperation.success ? 'green' : 'red'); } document.title = 'Ethplorer: ' + (titleAdd ? (titleAdd + ' -') : ''); Ethplorer.Utils.hideEmptyFields(); }, - - showTxDetails: function(txHash, txData){ // $('#ethplorer-path').html('

Transaction hash: ' + txHash + '

'); $('#ethplorer-path').show(); @@ -480,7 +477,7 @@ Ethplorer = { } } if(txData.tx.gasPrice){ - txData.tx.gasPrice = parseFloat(Ethplorer.Utils.toBig(txData.tx.gasPrice).toString()); + txData.tx.gasPrice = parseFloat(Ethplorer.Utils.toBig(txData.tx.gasPrice).toString()); txData.tx.cost = txData.tx.gasUsed ? txData.tx.gasPrice * txData.tx.gasUsed : 0; } Ethplorer.fillValues('transaction', txData, ['tx', 'tx.from', 'tx.to', 'tx.creates', 'tx.value', 'tx.timestamp', 'tx.gasLimit', 'tx.gasUsed', 'tx.gasPrice', 'tx.fee', 'tx.nonce', 'tx.blockNumber', 'tx.confirmations', 'tx.input', 'tx.cost', 'tx.method']); @@ -491,15 +488,15 @@ Ethplorer = { titleAdd += (tokenName + ' '); $('.token-name:eq(0)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, tokenName, false)); $('.token-name:eq(1)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, oToken.name , false)); - + if(oToken.image){ var img = Ethplorer.Utils.getEthplorerLink(oToken.address, '##IMG##', false); $('.token-related:eq(1) .block-header').find('img').remove(); $('.token-related:eq(1) .block-header').prepend( img.replace('##IMG##', '') ); - } - + } + txData.token = oToken; Ethplorer.fillValues('transaction', txData, ['token', 'token.timestamp', 'token.contract', 'token.symbol', 'token.price', 'token.decimals', 'token.owner', 'token.totalSupply']); @@ -556,11 +553,11 @@ Ethplorer = { } if(multiop){ var row = $( - '' + + '' + 'Details' + '' + op.type.toString().toUpperCase() + ' ' + op.value + ' ' + op.symbol + '' + - '
' + opParties + '
' + + '
' + opParties + '' + '' + op.value + '' + '' + op.symbol + '' + '' + @@ -614,7 +611,7 @@ Ethplorer = { if(oTx.blockNumber){ $('#txTokenStatus')[oOperation.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); + $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); $('#txTokenStatus').html(oOperation.success ? 'Success' : 'Failed' + (oOperation.failedReason ? (': ' + Ethplorer.getTxErrorReason(oOperation.failedReason)) : '')); $('#operation-status').addClass(oOperation.success ? 'green' : 'red'); } @@ -634,7 +631,7 @@ Ethplorer = { } if(oTx.blockNumber){ $('#txTokenStatus')[oTx.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[oTx.success ? 'addClass' : 'removeClass']('text-success'); + $('#txTokenStatus')[oTx.success ? 'addClass' : 'removeClass']('text-success'); $('#txTokenStatus').html(oTx.success ? 'Success' : 'Failed' + (oTx.failedReason ? (': ' + Ethplorer.getTxErrorReason(oTx.failedReason)) : '')); $('#operation-status').addClass(oTx.success ? 'green' : 'red'); } @@ -642,13 +639,30 @@ Ethplorer = { if(!oTx.blockNumber){ $('#txTokenStatus').removeClass('text-danger text-success'); $('#txTokenStatus').html('Pending'); - } + } Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); }else{ $('#tx-details-block').show(); $('.tx-details-close').hide(); } + var usdPrice = ''; + if(oTx.usdPrice && Ethplorer.showHistoricalPrice){ + + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(oTx.usdPrice, oToken.price.rate), 2); + var hint = 'estimated at tx date'; + + var cls = (diff > 0 ? 'diff-up' : 'diff-down') + if(diff > 0){ + diff = '+' + Ethplorer.Utils.round(diff, 2); + } + var historyPrice = Ethplorer.Utils.formatNum(Ethplorer.Utils.round(oTx.usdPrice, 2), true, 2, true); + + usdPrice = '~$' + historyPrice + + ' (' + diff + '%)' + } + $('#historical-price').html(usdPrice); + document.title = 'Ethplorer'; document.title += (': ' + (titleAdd ? (titleAdd + ' -') : '')); document.title += (' hash ' + txHash); @@ -677,7 +691,6 @@ Ethplorer = { $("table").find("tr:visible:even").addClass("even"); $("table").find("tr:visible:last").addClass("last"); }, - getAddressDetails: function(address){ // Check Address format first address = address.toLowerCase(); @@ -687,7 +700,6 @@ Ethplorer = { } Ethplorer.loadAddressData(address, Ethplorer.showAddressDetails); }, - loadAddressData: function(address, data, callback){ if('function' === typeof(data)){ callback = data; @@ -705,7 +717,7 @@ Ethplorer = { return function(data){ if(data.debug){ Ethplorer.requestDebug = data.debug; - } + } if(data.ethPrice){ Ethplorer.ethPrice = data.ethPrice; } @@ -713,7 +725,6 @@ Ethplorer = { } }(address)); }, - showAddressDetails: function(address, data){ var srcAddress = address; address = Ethplorer.Utils.toChecksumAddress(address); @@ -805,7 +816,7 @@ Ethplorer = { } if(oToken.image){ - $('#address-token-details .block-header').find('img').remove(); + $('#address-token-details .block-header').find('img').remove(); $('#address-token-details .block-header').prepend(''); } $('.address-token-name').html(oToken.name); @@ -837,10 +848,10 @@ Ethplorer = { 'token', 'token.name', 'token.price', 'token.description', 'token.owner', 'token.totalSupply', 'token.totalIn', 'token.totalOut', 'token.decimals', 'token.symbol', 'token.txsCount', 'token.transfersCount', 'token.issuancesCount', 'token.holdersCount', 'token.createdAt', 'token.createdTx' ]; - + $('#tab-issuances').show(); $('#tab-holders').show(); - + Ethplorer.fillValues('address', data, fields); var totalSupply = oToken.totalSupply; @@ -892,7 +903,7 @@ Ethplorer = { return -1; return 0; }); - + // Show $('#address-token-balances table').empty(); for(var k=0; k🔥 Burn' : value + '
⚒ Issuance'; } - if(txToken.price && txToken.price.rate){ - var pf = parseFloat(value.replace(/\,/g,'').split(' ')[0]); - if(pf){ - pf = Ethplorer.Utils.round(pf * txToken.price.rate, 2); - var usdval = Ethplorer.Utils.formatNum(Math.abs(pf), true, 2, true); - value = value + '
$ ' + usdval + ''; + var pf = parseFloat(value.replace(/\,/g,'').split(' ')[0]); + var usdPrice = ''; + if(pf){ + if(txToken.price && txToken.price.rate){ + var usdval = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf * txToken.price.rate, 2)), true, 2, true); + value = value + '
$ ' + usdval + ''; + } + if (tx.usdPrice && Ethplorer.showHistoricalPrice){ + + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(tx.usdPrice, txToken.price.rate), 2); + var hint = 'estimated at tx date'; + + var cls = (diff > 0 ? 'diff-up' : 'diff-down') + if(diff > 0){ + diff = '+' + Ethplorer.Utils.round(diff, 2); + } + var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); + + usdPrice = '
$' + historyPrice + + ' (' + diff + '%)' } } + value += usdPrice; divData.html( 'Date: ' + date + '
' + (!data.token ? ('Token: ' + token + '
') : '') + - 'Value: ' + value + '
' + + 'Value: ' + value + '
' + 'Tx: ' + Ethplorer.Utils.getEthplorerLink(tx.transactionHash) + '
' + (from ? ('From: ' + from + '
To: ' + to) : ('Address: ' + _address)) ); @@ -1176,7 +1199,6 @@ Ethplorer = { $('#' + tableId).show(); }, - showEthTransfers: function(switcher){ Ethplorer.Nav.del('transfers'); Ethplorer.showEth = switcher.checked ? 1 : 0; @@ -1185,7 +1207,6 @@ Ethplorer = { var tab = Ethplorer.getActiveTab(); Ethplorer.reloadTab(tab); }, - drawIssuances: function(address, issuancesData){ $('#filter_list').attr('disabled', false); $('#address-issuances .table').empty(); @@ -1227,7 +1248,7 @@ Ethplorer = { var usdval = Ethplorer.Utils.formatNum(Math.abs(pf), true, 2, true); value = value + '
$ ' + usdval + ''; } - } + } tdQty.html(value); row.append(tdDate, tdHash, tdOpType, tdQty); $('#address-issuances .table').append(row); @@ -1243,7 +1264,6 @@ Ethplorer = { Ethplorer.hideTableLoader(); $('#address-issuances').show(); }, - drawHolders: function(address, holdersData){ $('#filter_list').attr('disabled', false); $('#address-token-holders .table').empty(); @@ -1316,7 +1336,6 @@ Ethplorer = { Ethplorer.hideTableLoader(); $('#address-token-holders').show(); }, - drawChainy: function(address, chainyData){ $('#filter_list').attr('disabled', false); $('#address-chainy-tx .table').empty(); @@ -1358,7 +1377,7 @@ Ethplorer = { var row = $(''); var tdDate = $(''); var tdHash = $('').addClass('list-field table-hash-field'); - var tdOpType = $('').addClass('text-center table-type-field'); + var tdOpType = $('').addClass('text-center table-type-field'); var tdLink = $(''); tdDate.html(Ethplorer.Utils.getEthplorerLink(tx.hash, Ethplorer.Utils.ts2date(tx.timestamp, false), false)); tdDate.find('a').attr('title', Ethplorer.Utils.ts2date(tx.timestamp, true)); @@ -1390,7 +1409,7 @@ Ethplorer = { Ethplorer.hideTableLoader(); $('#address-chainy-tx').show(); }, - drawPager: function(container, pageData){ + drawPager: function(container, pageData){ var currentPage = pageData.page, recordsCount = pageData.records, totalCount = pageData.total; @@ -1445,7 +1464,7 @@ Ethplorer = { } } }(container, recordsCount, totalCount), 100); - + container.empty(); if(recordsCount){ @@ -1454,7 +1473,7 @@ Ethplorer = { for(var i=1; i<=pages; i++){ if((i <= 1) || ((i <= 5) &&(currentPage <= 4)) || ((i >= (pages - 4)) &&(currentPage >= (pages - 3))) || (i >= (pages)) || ((i >= (currentPage - 1)) && (i <= (currentPage + 1)))){ var page = $('
  • '); - page.addClass('page-item'); + page.addClass('page-item'); var link = $(''); link.html(i); if(i === currentPage){ @@ -1490,7 +1509,6 @@ Ethplorer = { container.append(pager); } }, - prepareToken: function(oToken){ if(!oToken){ oToken = {address: '', name: '', decimals: 0, symbol: '', totalSupply: 0}; @@ -1555,7 +1573,6 @@ Ethplorer = { oToken.prepared = true; return oToken; }, - convert: function(id, switcher){ switcher = $(switcher); var pre = $('#' + id); @@ -1570,7 +1587,6 @@ Ethplorer = { switcher.text('HEX'); } }, - search: function(value, fromInput){ value = value.replace(/^\s+/, '').replace(/\s+$/, ''); if(value.length){ @@ -1588,7 +1604,7 @@ Ethplorer = { $.getJSON(Ethplorer.service, data, function(data){ if(data.debug){ Ethplorer.requestDebug = data.debug; - } + } var empty = !(data && data.results && data.total); if(!empty){ document.location.href = '/address/' + data.results[0][2]; @@ -1603,7 +1619,6 @@ Ethplorer = { Ethplorer.error('Nothing found'); } }, - fillValues: function(prefix, data, keys){ for(var key in data){ if(keys.indexOf(key) >= 0){ @@ -1619,7 +1634,6 @@ Ethplorer = { } } }, - fillValue: function(id, value){ var type = $('#' + id).attr('data-type') || 'none'; var options = $('#' + id).attr('data-options') ? $('#' + id).attr('data-options').split('|') : []; @@ -1654,7 +1668,7 @@ Ethplorer = { case 'ether-full': if(value < 0){ value = "N/A"; - }else{ + }else{ var res = Ethplorer.Utils.formatNum(value, true, 18, true) + ' ETHER'; if(value){ var price = Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * value, true, 4, true); @@ -1677,7 +1691,7 @@ Ethplorer = { }else{ value = ""; } - break; + break; case 'etherscan': value = Ethplorer.Utils.getEtherscanLink(value, value, (options.indexOf('no-contract') < 0) ? Ethplorer.knownContracts.indexOf(value) >= 0 : false); break; @@ -1707,7 +1721,7 @@ Ethplorer = { Ethplorer.loaderTimeout = setTimeout(function(){ $('#loader').show(); }, 1000); - }, + }, hideLoader: function(){ $('#loader').hide(); if(Ethplorer.loaderTimeout){ @@ -1877,7 +1891,7 @@ Ethplorer = { cutZeroes = !!cutZeroes; withDecimals = !!withDecimals; decimals = ('undefined' !== typeof(decimals)) ? decimals : 2; - + if((num.toString().indexOf("e+") > 0)){ if(noE){ var parts = num.toString().split('e+'); @@ -1942,7 +1956,7 @@ Ethplorer = { return res; }, /** - * + * * @returns {String} */ getEtherscanAddress: function(){ @@ -1963,7 +1977,7 @@ Ethplorer = { var res = text; if(isContract){ res = 'Contract ' + res; - } + } return res; }, @@ -1982,7 +1996,7 @@ Ethplorer = { res += ('/' + data + '" class="local-link">' + text + ''); if(isContract){ res = 'Contract ' + res; - } + } return res; }, @@ -1992,7 +2006,7 @@ Ethplorer = { ts *= 1000; function padZero(s){ return (s < 10) ? '0' + s : s.toString(); - } + } var res = ''; var dt = new Date(ts); res += (dt.getFullYear() + '-' + padZero((dt.getMonth() + 1)) + '-' + padZero(dt.getDate())); @@ -2024,8 +2038,8 @@ Ethplorer = { ascii2hex: function(text){ var res = []; for (var i=0; i Date: Mon, 16 Apr 2018 22:39:47 +0700 Subject: [PATCH 095/658] scrollable and correct value @ tx date --- index.php | 2 +- js/ethplorer.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.php b/index.php index d04feb8f..d7ae4e7c 100644 --- a/index.php +++ b/index.php @@ -519,7 +519,7 @@
  • -
    +
    diff --git a/js/ethplorer.js b/js/ethplorer.js index c231994c..a92e9201 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -327,7 +327,7 @@ Ethplorer = { if(oToken.price && oToken.price.rate){ var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); + pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); // не надо так totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#transaction-token-totalSupply').html(totalSupply); } @@ -514,6 +514,7 @@ Ethplorer = { $('#transaction-token-decimals').append(' (estimated)'); } + //WAT? if($('#transaction-tx-message').html()){ $('#transfer-tx-message').html($('#transaction-tx-message').html()); $('#transaction-tx-message').html('') @@ -647,8 +648,7 @@ Ethplorer = { } var usdPrice = ''; - if(oTx.usdPrice && Ethplorer.showHistoricalPrice){ - + if(oTx.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(oTx.usdPrice, oToken.price.rate), 2); var hint = 'estimated at tx date'; @@ -656,7 +656,7 @@ Ethplorer = { if(diff > 0){ diff = '+' + Ethplorer.Utils.round(diff, 2); } - var historyPrice = Ethplorer.Utils.formatNum(Ethplorer.Utils.round(oTx.usdPrice, 2), true, 2, true); + var historyPrice = Ethplorer.Utils.formatNum(oTx.usdPrice * valFloat, true, 2, true, true); usdPrice = '~$' + historyPrice + ' (' + diff + '%)' From 9f8e70248d5bb218d64bc67f65b1df8214ec2ff0 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Tue, 17 Apr 2018 17:23:18 +0700 Subject: [PATCH 096/658] fix desapeared value on tx page --- css/ethplorer.css | 3 ++- js/ethplorer.js | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 50230bbf..6e723659 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -328,6 +328,7 @@ a.local-link, a.local-link:visited, a.local-link:hover { position: absolute; width: 100%; bottom: 0px; + overflow-x: auto; } .footer .small-link { @@ -1379,4 +1380,4 @@ a.token-update { font-size: 0.8em; /*opacity: 0.5;*/ color: rgba(255, 255, 255, 0.6); -} \ No newline at end of file +} diff --git a/js/ethplorer.js b/js/ethplorer.js index a92e9201..c10a1d5c 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -661,8 +661,6 @@ Ethplorer = { usdPrice = '~$' + historyPrice + ' (' + diff + '%)' } - $('#historical-price').html(usdPrice); - document.title = 'Ethplorer'; document.title += (': ' + (titleAdd ? (titleAdd + ' -') : '')); document.title += (' hash ' + txHash); @@ -681,6 +679,7 @@ Ethplorer = { }else if(multiop){ Ethplorer.showOpDetails(oTx, txData.operations[0]); } + $('#historical-price').html(usdPrice); Ethplorer.Events.fire('ethp_showTxDetails_finish', txData); Ethplorer.Utils.hideEmptyFields(); From 232c8fd4b9c08db7e71b8a80ed30af39f8d2ffc7 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Tue, 17 Apr 2018 19:10:37 +0700 Subject: [PATCH 097/658] UX scrollable --- css/ethplorer.css | 65 ++++++++++++++++++++++++++++++++++++++++------- index.php | 7 ++--- js/ethplorer.js | 61 ++++++++++++++++++++++++++++++-------------- 3 files changed, 100 insertions(+), 33 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 6e723659..55de2467 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -637,11 +637,14 @@ a.dashed { font-size: 0.8em; } -.hash-from-to { +.hash-from-to, .cut-long-text { max-width: 40vw; overflow: hidden; text-overflow: ellipsis } +.cut-long-text { + max-width: 17vw; +} #address-token-transfers small, #address-transfers small, @@ -1057,7 +1060,7 @@ li.ui-menu-item.have-more { } @media screen and (min-width: 400px) and (max-width: 991px) { - .hash-from-to { + .hash-from-to, .cut-long-text { padding-left: 20px; max-width: 38vw; } @@ -1075,6 +1078,9 @@ li.ui-menu-item.have-more { .hash-from-to { max-width: 56vw; } + .cut-long-text { + max-width: 32vw; + } td.table-hash-field { display: none; @@ -1269,7 +1275,7 @@ a.token-update { font-size: 20px; } - .hash-from-to { + .hash-from-to{ max-width: 75vw !important; } @@ -1369,15 +1375,56 @@ a.token-update { 0%{transform:rotate(0deg)} 100%{transform:rotate(360deg)} } - -.scrollable{ - max-height: 400px; - overflow-y: auto; -} - .historical-price { /*font-size: 0.7em;*/ font-size: 0.8em; /*opacity: 0.5;*/ color: rgba(255, 255, 255, 0.6); } +/* Scrollable */ +.scrollable{ + position: relative; +} +.scrollwrapper{ + max-height: 400px; + overflow-y: auto; +} +.scrollwrapper:before, .scrollwrapper:after{ + content: ""; + position: absolute; + display: block; + left: 0px; + width: 100%; + height: 10px; +} +.scrollwrapper.hide-top-gr:before{ + display: none; +} +.scrollwrapper.hide-bottom-gr:after{ + display: none; +} +.scrollwrapper:before{ + content: ''; + top: 0; + background: rgba(226,226,226,1);/* Old Browsers */ + background: -moz-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* FF3.6+ */ + background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(226,226,226,1)), color-stop(53%, rgba(241,241,241,0)), color-stop(100%, rgba(254,254,254,0)));/* Chrome, Safari4+ */ + background: -webkit-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* IE 10+ */ + background: linear-gradient(to bottom, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%);/* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e2e2e2', endColorstr='#fefefe', GradientType=0 );/* IE6-9 */ +} +.scrollwrapper:after{ + content: ''; + bottom: 0; + background: rgba(254,254,254,0);/* Old Browsers */ + background: -moz-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(254,254,254,0)), color-stop(47%, rgba(241,241,241,0)), color-stop(100%, rgba(226,226,226,1)));/* Chrome, Safari4+ */ + background: -webkit-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* IE 10+ */ + background: linear-gradient(to bottom, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%);/* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fefefe', endColorstr='#e2e2e2', GradientType=0 );/* IE6-9 */ +} +/* ^^^ Scrollable ^^^ */ \ No newline at end of file diff --git a/index.php b/index.php index d7ae4e7c..645d6d06 100644 --- a/index.php +++ b/index.php @@ -263,10 +263,7 @@

    Internal operations

    -
    - -
    -
    +
    @@ -519,7 +516,7 @@
    -
    +
    diff --git a/js/ethplorer.js b/js/ethplorer.js index c10a1d5c..507cad45 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -220,6 +220,7 @@ Ethplorer = { window.open("data:" + mimetype + "," + encodeURIComponent(data), '_blank', ''); }; }*/ + this.Utils.initScrollable(); }, getActiveTab: function(){ var tab = ($('.nav-tabs:visible li.active').length) ? $('.nav-tabs:visible li.active').attr('id').replace('tab-', '') : false; @@ -658,7 +659,7 @@ Ethplorer = { } var historyPrice = Ethplorer.Utils.formatNum(oTx.usdPrice * valFloat, true, 2, true, true); - usdPrice = '~$' + historyPrice + + usdPrice = '~$ ' + historyPrice + ' (' + diff + '%)' } document.title = 'Ethplorer'; @@ -945,8 +946,8 @@ Ethplorer = { value += ('
    Total In: ' + Ethplorer.Utils.formatNum(totalIn, true, oToken.decimals, true) + '
    '); value += ('Total Out: ' + Ethplorer.Utils.formatNum(totalOut, true, oToken.decimals, true) + '
    '); } - row.append('' + Ethplorer.Utils.getEthplorerLink(balance.contract, oToken.name, false) + ''); - row.append('' + value + ''); + row.append('' + Ethplorer.Utils.getEthplorerLink(balance.contract, oToken.name, false) + ''); + row.append('' + value + ''); row.find('td:eq(1)').addClass('text-right'); $('#address-token-balances table').append(row); } @@ -1152,7 +1153,7 @@ Ethplorer = { } var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); - usdPrice = '
    $' + historyPrice + + usdPrice = '
    ~$ ' + historyPrice + ' (' + diff + '%)' } } @@ -1935,7 +1936,6 @@ Ethplorer = { } return res; }, - /** * Parses URL path * @returns {string} @@ -1979,7 +1979,6 @@ Ethplorer = { } return res; }, - getEthplorerLink: function(data, text, isContract){ text = text || data; if(!/^0x/.test(data)){ @@ -1992,13 +1991,12 @@ Ethplorer = { } var res = '' + text + ''); + res += ('/' + data + '" class="local-link" title="' + text + '">' + text + ''); if(isContract){ res = 'Contract ' + res; } return res; }, - // Date with fixed GMT to local date ts2date: function(ts, withGMT){ withGMT = 'undefined' !== typeof(withGMT) ? withGMT : true; @@ -2016,12 +2014,10 @@ Ethplorer = { } return res; }, - getTZOffset: function(){ var offset = -Math.round(new Date().getTimezoneOffset() / 60); return 'GMT' + (offset > 0 ? '+' : '-') + offset; }, - hideEmptyFields: function(){ $('.list-field').parents('TR').show(); $('.list-field:empty').parents('TR').hide(); @@ -2033,7 +2029,6 @@ Ethplorer = { } */ }, - ascii2hex: function(text){ var res = []; for (var i=0; i .scrollwrapper > + * + */ + initScrollable: function () { + function checkPosition(el){ + var $el = $(el); + var $child = $el.children() + + $el + .removeClass('hide-bottom-gr') + .removeClass('hide-top-gr'); + + if ($child.outerHeight(true) - $el.outerHeight(true) + $child.position().top === 0){ + //bottom + $el.addClass('hide-bottom-gr') + } + if ($child.position().top === 0){ + //top + $el.addClass('hide-top-gr') + } + + } + var timer = null; + $('.scrollwrapper').on( 'scroll', function(e){ + + if (timer) clearTimeout(timer); + timer = setTimeout(function(){ + checkPosition(e.target) + }, 100); + }); + } }, enableHistoricalPrice: function(bool){ From 08409658999d2b795bb15b2b75ee3486e4376fda Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 18 Apr 2018 17:22:33 +0700 Subject: [PATCH 098/658] Tocken page diff 7d --- js/ethplorer.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index c10a1d5c..7b643c89 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -755,6 +755,7 @@ Ethplorer = { $('#address-token-details').show(); var oToken = Ethplorer.prepareToken(data.token); // oToken.address = oToken.address; + // QUESTION: WHAT? WHY? var ttype = (address.toLowerCase() !== "0x55d34b686aa8c04921397c5807db9ecedba00a4c") ? 'Token ' : 'Contract '; $('#ethplorer-path').html(qrIcon + ttype + oToken.name + '
    ' + Ethplorer.Utils.toChecksumAddress(oToken.address) + ''); titleAdd = ttype + oToken.name + (oToken.symbol ? (' [' + oToken.symbol + ']') : '' ) + ' Information'; @@ -1647,11 +1648,19 @@ Ethplorer = { value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true); if(rate.diff){ var cls = rate.diff > 0 ? 'diff-up' : 'diff-down'; - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); + var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 24 hour period'; if(rate.diff > 0){ rate.diff = '+' + rate.diff; } - value = value + ' (' + Ethplorer.Utils.round(rate.diff, 2) + '%)' + value = value + ' (24h ' + Ethplorer.Utils.round(rate.diff, 2) + '%)' + } + if(rate.diff7d){ + var cls = rate.diff7d > 0 ? 'diff-up' : 'diff-down'; + var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 7 days period'; + if(rate.diff7d > 0){ + rate.diff7d = '+' + rate.diff7d; + } + value = value + ' (7d ' + Ethplorer.Utils.round(rate.diff7d, 2) + '%)' } }else{ value = ''; @@ -1935,7 +1944,6 @@ Ethplorer = { } return res; }, - /** * Parses URL path * @returns {string} @@ -1979,7 +1987,6 @@ Ethplorer = { } return res; }, - getEthplorerLink: function(data, text, isContract){ text = text || data; if(!/^0x/.test(data)){ @@ -1998,7 +2005,6 @@ Ethplorer = { } return res; }, - // Date with fixed GMT to local date ts2date: function(ts, withGMT){ withGMT = 'undefined' !== typeof(withGMT) ? withGMT : true; @@ -2016,12 +2022,10 @@ Ethplorer = { } return res; }, - getTZOffset: function(){ var offset = -Math.round(new Date().getTimezoneOffset() / 60); return 'GMT' + (offset > 0 ? '+' : '-') + offset; }, - hideEmptyFields: function(){ $('.list-field').parents('TR').show(); $('.list-field:empty').parents('TR').hide(); @@ -2033,7 +2037,6 @@ Ethplorer = { } */ }, - ascii2hex: function(text){ var res = []; for (var i=0; i Date: Mon, 23 Apr 2018 17:16:32 +0700 Subject: [PATCH 099/658] run once right after data fill the table --- js/ethplorer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 507cad45..76fee69c 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2163,12 +2163,14 @@ Ethplorer = { } var timer = null; - $('.scrollwrapper').on( 'scroll', function(e){ + $('.scrollwrapper').on('scroll', function(e){ if (timer) clearTimeout(timer); timer = setTimeout(function(){ checkPosition(e.target) }, 100); + }).one("DOMSubtreeModified", function(event){ + checkPosition(event.target.parentElement) }); } From 4100ba9557aa7a5217bf56f1f51bb4844463880a Mon Sep 17 00:00:00 2001 From: Ilya S Date: Mon, 23 Apr 2018 17:29:48 +0700 Subject: [PATCH 100/658] remove comments --- js/ethplorer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 76fee69c..b1429a24 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -328,7 +328,7 @@ Ethplorer = { if(oToken.price && oToken.price.rate){ var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); // не надо так + pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#transaction-token-totalSupply').html(totalSupply); } @@ -515,7 +515,6 @@ Ethplorer = { $('#transaction-token-decimals').append(' (estimated)'); } - //WAT? if($('#transaction-tx-message').html()){ $('#transfer-tx-message').html($('#transaction-tx-message').html()); $('#transaction-tx-message').html('') From a13b12ef024500a17ec663960442cea83762547a Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Apr 2018 18:01:35 +0700 Subject: [PATCH 101/658] Use operations2 for addressHistory --- service/lib/ethplorer.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 69a31ffa..95914d47 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1180,11 +1180,11 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ if(isset($options['address']) && isset($options['history'])){ $search['addresses'] = $options['address']; } - if(isset($options['token']) && isset($options['history'])){ $search['contract'] = $options['token']; - }elseif(!$showEth){ - $search['contract'] = array('$ne' => 'ETH'); + } + if(!$showEth){ + $search['isEth'] = false; } $sort = array("timestamp" => -1); @@ -1192,8 +1192,9 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ $search['timestamp'] = array('$gt' => $options['timestamp']); } + $limit = isset($options['limit']) ? (int)$options['limit'] : false; - $cursor = $this->oMongo->find('operations', $search, $sort, $limit); + $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); $result = array(); foreach($cursor as $transfer){ From ee981c95b7140fa3d45a1eb0e94e7da7b6b19392 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Mon, 23 Apr 2018 18:31:22 +0700 Subject: [PATCH 102/658] remove comments --- js/ethplorer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 7b643c89..6afcaf18 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -417,6 +417,7 @@ Ethplorer = { }; var obj = Ethplorer.Utils.parseJData(oTx.input); var isChainy = false; + // QUESTION: need explanation if(oTx.to && ('0xf3763c30dd6986b53402d41a8552b8f7f6a6089b' === oTx.to)){ var input = Ethplorer.Utils.hex2ascii(oTx.input.substring(136).replace(/0+$/, '')); try { @@ -755,7 +756,7 @@ Ethplorer = { $('#address-token-details').show(); var oToken = Ethplorer.prepareToken(data.token); // oToken.address = oToken.address; - // QUESTION: WHAT? WHY? + // QUESTION: need explanation var ttype = (address.toLowerCase() !== "0x55d34b686aa8c04921397c5807db9ecedba00a4c") ? 'Token ' : 'Contract '; $('#ethplorer-path').html(qrIcon + ttype + oToken.name + '
    ' + Ethplorer.Utils.toChecksumAddress(oToken.address) + ''); titleAdd = ttype + oToken.name + (oToken.symbol ? (' [' + oToken.symbol + ']') : '' ) + ' Information'; From e795340843caf1e511405a1bb04e98a3e128c1c4 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Apr 2018 19:42:41 +0700 Subject: [PATCH 103/658] fast option for getToken --- service/lib/ethplorer.php | 41 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 95914d47..8da1963c 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -880,7 +880,7 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ * @param string $address Token contract address * @return array */ - public function getToken($address){ + public function getToken($address, $fast = FALSE){ // evxProfiler::checkpoint('getToken', 'START', 'address=' . $address); $cache = 'token-' . $address; $result = $this->oCache->get($cache, false, true, 30); @@ -898,17 +898,19 @@ public function getToken($address){ } } - // Ask DB for fresh counts - $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); - $token = false; - if($cursor){ - foreach($cursor as $token){ - break; + if(!$fast){ + // Ask DB for fresh counts + $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); + $token = false; + if($cursor){ + foreach($cursor as $token){ + break; + } + } + if($token){ + $result['txsCount'] = $token['txsCount']; + $result['transfersCount'] = $token['transfersCount']; } - } - if($token){ - $result['txsCount'] = $token['txsCount']; - $result['transfersCount'] = $token['transfersCount']; } $result['txsCount'] = (int)$result['txsCount'] + 1; // Contract creation tx @@ -1167,13 +1169,6 @@ public function getAddressBalances($address, $withZero = true){ */ public function getLastTransfers(array $options = array(), $showEth = FALSE){ $search = array(); - if(!isset($options['type'])){ - $search['type'] = 'transfer'; - }else{ - if(FALSE !== $options['type']){ - $search['type'] = $options['type']; - } - } if(isset($options['address']) && !isset($options['history'])){ $search['contract'] = $options['address']; } @@ -1186,7 +1181,13 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ if(!$showEth){ $search['isEth'] = false; } - + if(!isset($options['type'])){ + $search['type'] = 'transfer'; + }else{ + if(FALSE !== $options['type']){ + $search['type'] = $options['type']; + } + } $sort = array("timestamp" => -1); if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ @@ -1198,7 +1199,7 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ $result = array(); foreach($cursor as $transfer){ - $transfer['token'] = $this->getToken($transfer['contract']); + $transfer['token'] = $this->getToken($transfer['contract'], true); unset($transfer["_id"]); $result[] = $transfer; } From f1314e1331483d4503e4e7f1951bd54c9bc390e6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 23 Apr 2018 19:59:22 +0700 Subject: [PATCH 104/658] Bug fixed. --- api/widget.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/api/widget.js b/api/widget.js index cf61223e..eb3ae2b6 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1694,11 +1694,9 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te var strLastPriceDate = widgetPriceData[widgetPriceData.length - 1].date + 'T00:00:00Z'; var strFirstDate = strLastPriceDate; }else{ - var firstMonth = aTxData[0]._id.month, - firstDay = aTxData[0]._id.day; - if(firstMonth < 10) firstMonth = '0' + firstMonth; - if(firstDay < 10) firstDay = '0' + firstDay; - var strFirstDate = aTxData[0]._id.year + '-' + firstMonth + '-' + firstDay + 'T00:00:00Z'; + var currentDate = new Date(); + var currentDateKey = currentDate.getFullYear() + '-' + (currentDate.getMonth() < 9 ? '0' : '') + (currentDate.getMonth() + 1) + '-' + (currentDate.getDate() < 10 ? '0' : '') + currentDate.getDate(); + var strFirstDate = currentDateKey + 'T00:00:00Z'; } /*if(widgetPriceData && widgetPriceData.length){ From 3488e993f34b82fcbab91d27cf1487eee0b3bfe6 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Mon, 23 Apr 2018 20:09:12 +0700 Subject: [PATCH 105/658] remove top gradient remove scroll event css fixes update gradient --- css/ethplorer.css | 50 +++++++++++++++++++++-------------------------- js/ethplorer.js | 29 +++++++++++++++------------ 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 55de2467..e0eaf8bd 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1389,42 +1389,36 @@ a.token-update { max-height: 400px; overflow-y: auto; } -.scrollwrapper:before, .scrollwrapper:after{ +.scrollwrapper:after{ content: ""; position: absolute; display: block; left: 0px; width: 100%; - height: 10px; -} -.scrollwrapper.hide-top-gr:before{ - display: none; + height: 15px; } .scrollwrapper.hide-bottom-gr:after{ display: none; } -.scrollwrapper:before{ - content: ''; - top: 0; - background: rgba(226,226,226,1);/* Old Browsers */ - background: -moz-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* FF3.6+ */ - background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(226,226,226,1)), color-stop(53%, rgba(241,241,241,0)), color-stop(100%, rgba(254,254,254,0)));/* Chrome, Safari4+ */ - background: -webkit-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%); /* IE 10+ */ - background: linear-gradient(to bottom, rgba(226,226,226,1) 0%, rgba(241,241,241,0) 53%, rgba(254,254,254,0) 100%);/* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e2e2e2', endColorstr='#fefefe', GradientType=0 );/* IE6-9 */ -} .scrollwrapper:after{ - content: ''; bottom: 0; - background: rgba(254,254,254,0);/* Old Browsers */ - background: -moz-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(254,254,254,0)), color-stop(47%, rgba(241,241,241,0)), color-stop(100%, rgba(226,226,226,1)));/* Chrome, Safari4+ */ - background: -webkit-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%); /* IE 10+ */ - background: linear-gradient(to bottom, rgba(254,254,254,0) 0%, rgba(241,241,241,0) 47%, rgba(226,226,226,1) 100%);/* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fefefe', endColorstr='#e2e2e2', GradientType=0 );/* IE6-9 */ -} -/* ^^^ Scrollable ^^^ */ \ No newline at end of file + content: ''; + background: rgba(252,252,252,0.7); + background: -moz-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); + background: -webkit-gradient(left bottom, left top, color-stop(0%, rgba(252,252,252,0.7)), color-stop(100%, rgba(242,242,242,0))); + background: -webkit-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); + background: -o-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); + background: -ms-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); + background: linear-gradient(to top, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfcfc', endColorstr='#f2f2f2', GradientType=0 ); +} +/* ^^^ Scrollable ^^^ */ + +#address-token-balances, .multiop { + margin-bottom: 20px; +} + +#address-token-balances table, .multiop table{ + margin-bottom: 0; +} + diff --git a/js/ethplorer.js b/js/ethplorer.js index a543c1a8..dd5491f7 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1662,6 +1662,15 @@ Ethplorer = { } value = value + ' (7d ' + Ethplorer.Utils.round(rate.diff7d, 2) + '%)' } + if(rate.diff && rate.diff7d){ + var cls = rate.diff7d > 0 ? 'diff-up' : 'diff-down'; + var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 30 days period'; + var diff30d = 123456.789; + if(rate.diff7d > 0){ + diff30d = '+' + diff30d; + } + value = value + ' (30d ' + Ethplorer.Utils.round(diff30d, 2) + '%)' + } }else{ value = ''; } @@ -2160,25 +2169,21 @@ Ethplorer = { .removeClass('hide-bottom-gr') .removeClass('hide-top-gr'); - if ($child.outerHeight(true) - $el.outerHeight(true) + $child.position().top === 0){ + console.log($child.outerHeight(true) , $el.outerHeight(true) ) + if ($child.outerHeight(true) < $el.outerHeight(true) || $child.outerHeight(true) - $el.outerHeight(true) + $child.position().top === 0){ //bottom $el.addClass('hide-bottom-gr') } - if ($child.position().top === 0){ + /*if ($child.position().top === 0){ //top $el.addClass('hide-top-gr') - } + }*/ } - var timer = null; - $('.scrollwrapper').on('scroll', function(e){ - - if (timer) clearTimeout(timer); - timer = setTimeout(function(){ - checkPosition(e.target) - }, 100); - }).one("DOMSubtreeModified", function(event){ - checkPosition(event.target.parentElement) + $('.scrollwrapper').one("DOMSubtreeModified", function(event){ + setTimeout(() => { + checkPosition(event.target.parentElement) + },100) }); } From 8ae35047d65f5f5105f8598ef1482e04944838e1 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Mon, 23 Apr 2018 20:11:26 +0700 Subject: [PATCH 106/658] chery pic --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index dd5491f7..558033f8 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -755,7 +755,7 @@ Ethplorer = { $('#address-token-details').show(); var oToken = Ethplorer.prepareToken(data.token); // oToken.address = oToken.address; - // QUESTION: WHAT? WHY? + // QUESTION: need explanation var ttype = (address.toLowerCase() !== "0x55d34b686aa8c04921397c5807db9ecedba00a4c") ? 'Token ' : 'Contract '; $('#ethplorer-path').html(qrIcon + ttype + oToken.name + '
    ' + Ethplorer.Utils.toChecksumAddress(oToken.address) + ''); titleAdd = ttype + oToken.name + (oToken.symbol ? (' [' + oToken.symbol + ']') : '' ) + ' Information'; From 0868eeb34c35426db02a1c605d69847eb2a2dbf6 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Apr 2018 20:24:24 +0700 Subject: [PATCH 107/658] getToken fast mode updated --- service/lib/ethplorer.php | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 8da1963c..5368b167 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -883,6 +883,14 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ public function getToken($address, $fast = FALSE){ // evxProfiler::checkpoint('getToken', 'START', 'address=' . $address); $cache = 'token-' . $address; + if($fast){ + $aTokens = $this->getTokens(); + $result = isset($aTokens[$address]) ? $aTokens[$address] : false; + if($result){ + unset($result["_id"]); + } + return $result; + } $result = $this->oCache->get($cache, false, true, 30); if(FALSE === $result){ $aTokens = $this->getTokens(); @@ -898,20 +906,18 @@ public function getToken($address, $fast = FALSE){ } } - if(!$fast){ - // Ask DB for fresh counts - $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); - $token = false; - if($cursor){ - foreach($cursor as $token){ - break; - } - } - if($token){ - $result['txsCount'] = $token['txsCount']; - $result['transfersCount'] = $token['transfersCount']; + // Ask DB for fresh counts + $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); + $token = false; + if($cursor){ + foreach($cursor as $token){ + break; } } + if($token){ + $result['txsCount'] = $token['txsCount']; + $result['transfersCount'] = $token['transfersCount']; + } $result['txsCount'] = (int)$result['txsCount'] + 1; // Contract creation tx From b9de23cb012cc6a0238e98cf8762a877cb62b69f Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Apr 2018 21:49:09 +0700 Subject: [PATCH 108/658] Memory limit increased --- bin/cache_tokens.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 4aaf32d5..27c5545f 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -15,6 +15,8 @@ * limitations under the License. */ +ini_set('memory_limit', '512M'); + require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; From 6d268cc7a7a1d800c9248bbbdb3787422d1aa4cc Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 18:36:39 +0700 Subject: [PATCH 109/658] Price diff for 30d added. --- service/lib/ethplorer.php | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 69a31ffa..11eed62e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2125,6 +2125,20 @@ public function getBlockTransactions($block, $showZero = false){ return $transactions; } + public function getTokenPrice30d($address){ + $result = FALSE; + $aTokensTop = $this->getTokensTop(100, 'cap'); + if(is_array($aTokensTop) && isset($aTokensTop['tokens'])){ + foreach($aTokensTop['tokens'] as $aToken){ + if(($aToken['address'] == $address) && isset($aToken['cap-30d-previous']) && $aToken['cap-30d-previous'] > 0){ + $result = $aToken['cap-30d-previous']; + break; + } + } + } + return $result; + } + public function getTokenPrice($address, $updateCache = FALSE){ // evxProfiler::checkpoint('getTokenPrice', 'START', 'address=' . $address . ', updateCache=' . ($updateCache ? 'TRUE' : 'FALSE')); $result = FALSE; @@ -2155,6 +2169,13 @@ public function getTokenPrice($address, $updateCache = FALSE){ $result = 1 / (float)$result['rate']; } } + $price30d = $this->getTokenPrice30d($address); + if($price30d && $result['rate']){ + $pdiff = _getPDiff($result['rate'], $price30d); + if($pdiff){ + $result['diff30d'] = $pdiff; + } + } $rates[$address] = $result; $this->oCache->save($cache, $rates); } @@ -2671,6 +2692,26 @@ protected function _getRateByDate($address, $date){ return $result; } + protected function _getPDiff($a, $b){ + var $res = 100; + if(!$b){ + return ($a > 0) ? FALSE : 0; + } + if($a !== $b){ + if($a && $b){ + $res = ($a / $b) * 100 - 100; + }else{ + $res *= (($a - $b) < 0) ? -1 : 1; + } + }else{ + $res = 0; + } + if((abs($res) > 10000) && ($b < 10)){ + $res = FALSE; + } + return $res; + } + /** * JSON RPC request implementation. * From f74843c6f52b71a56f2473556d603ab9baa3d1d8 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 18:38:06 +0700 Subject: [PATCH 110/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 11eed62e..be4faed5 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2693,7 +2693,7 @@ protected function _getRateByDate($address, $date){ } protected function _getPDiff($a, $b){ - var $res = 100; + $res = 100; if(!$b){ return ($a > 0) ? FALSE : 0; } From 8c7ad25f54afce90c28d8a9e3e7b4734b9bd1cdb Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 18:38:51 +0700 Subject: [PATCH 111/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index be4faed5..e533fb5c 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2171,7 +2171,7 @@ public function getTokenPrice($address, $updateCache = FALSE){ } $price30d = $this->getTokenPrice30d($address); if($price30d && $result['rate']){ - $pdiff = _getPDiff($result['rate'], $price30d); + $pdiff = $this->_getPDiff($result['rate'], $price30d); if($pdiff){ $result['diff30d'] = $pdiff; } From 71f2d2636ac3a5a1ed85f9f5c782d183e8697a1a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 18:36:39 +0700 Subject: [PATCH 112/658] Price diff for 30d added. --- service/lib/ethplorer.php | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 5368b167..6cbeb1f7 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2133,6 +2133,20 @@ public function getBlockTransactions($block, $showZero = false){ return $transactions; } + public function getTokenPrice30d($address){ + $result = FALSE; + $aTokensTop = $this->getTokensTop(100, 'cap'); + if(is_array($aTokensTop) && isset($aTokensTop['tokens'])){ + foreach($aTokensTop['tokens'] as $aToken){ + if(($aToken['address'] == $address) && isset($aToken['cap-30d-previous']) && $aToken['cap-30d-previous'] > 0){ + $result = $aToken['cap-30d-previous']; + break; + } + } + } + return $result; + } + public function getTokenPrice($address, $updateCache = FALSE){ // evxProfiler::checkpoint('getTokenPrice', 'START', 'address=' . $address . ', updateCache=' . ($updateCache ? 'TRUE' : 'FALSE')); $result = FALSE; @@ -2163,6 +2177,13 @@ public function getTokenPrice($address, $updateCache = FALSE){ $result = 1 / (float)$result['rate']; } } + $price30d = $this->getTokenPrice30d($address); + if($price30d && $result['rate']){ + $pdiff = $this->_getPDiff($result['rate'], $price30d); + if($pdiff){ + $result['diff30d'] = $pdiff; + } + } $rates[$address] = $result; $this->oCache->save($cache, $rates); } @@ -2679,6 +2700,26 @@ protected function _getRateByDate($address, $date){ return $result; } + protected function _getPDiff($a, $b){ + $res = 100; + if(!$b){ + return ($a > 0) ? FALSE : 0; + } + if($a !== $b){ + if($a && $b){ + $res = ($a / $b) * 100 - 100; + }else{ + $res *= (($a - $b) < 0) ? -1 : 1; + } + }else{ + $res = 0; + } + if((abs($res) > 10000) && ($b < 10)){ + $res = FALSE; + } + return $res; + } + /** * JSON RPC request implementation. * From 0238cbbd9f33007aa7b75ed73f55293a569c4f29 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Tue, 24 Apr 2018 21:16:28 +0700 Subject: [PATCH 113/658] merge formater from widget + some fixes --- css/ethplorer.css | 16 +++- js/ethplorer.js | 183 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 154 insertions(+), 45 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index e0eaf8bd..10fcb870 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1376,10 +1376,8 @@ a.token-update { 100%{transform:rotate(360deg)} } .historical-price { - /*font-size: 0.7em;*/ - font-size: 0.8em; - /*opacity: 0.5;*/ - color: rgba(255, 255, 255, 0.6); + font-size: 0.7em; + color: rgba(255, 255, 255, 0.5); } /* Scrollable */ .scrollable{ @@ -1422,3 +1420,13 @@ a.token-update { margin-bottom: 0; } +.diff-span { + padding-right: 10px; + color: rgba(255, 255, 255, 0.6); +} +.diff-span span { + padding-left: 4px; +} +.diff-zero{ + color: rgba(255, 255, 255, 0.6); +} \ No newline at end of file diff --git a/js/ethplorer.js b/js/ethplorer.js index a504ed58..d44187f3 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -368,6 +368,23 @@ Ethplorer = { } $('#transfer-operation-value').html(value); + var usdPrice = ''; + if(op.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(op.usdPrice, oToken.price.rate), 2); + var hint = 'estimated at tx date'; + + var cls = getDiffClass(diff); + if(diff > 0){ + diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; + } + var historyPrice = Ethplorer.Utils.formatNum(op.usdPrice * valFloat, true, 2, true, true); + + usdPrice = '~$ ' + historyPrice + + ' ' + diff + '%' + } + $('#historical-price').html(usdPrice); + + titleAdd += oOperation.type; $('.token-operation-type').text(oOperation['type']); Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); @@ -609,6 +626,21 @@ Ethplorer = { value = value + '
    ($ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ')'; } $('#transfer-operation-value').html(value); + var usdPrice = ''; + if(oOperation.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(oOperation.usdPrice, oToken.price.rate), 2); + var hint = 'estimated at tx date'; + + var cls = getDiffClass(diff); + if(diff > 0){ + diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; + } + var historyPrice = Ethplorer.Utils.formatNum(oOperation.usdPrice * valFloat, true, 2, true, true); + + usdPrice = '~$ ' + historyPrice + + ' (' + diff + '%)' + } + $('#historical-price').html(usdPrice); } if(oTx.blockNumber){ @@ -648,20 +680,6 @@ Ethplorer = { $('.tx-details-close').hide(); } - var usdPrice = ''; - if(oTx.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ - var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(oTx.usdPrice, oToken.price.rate), 2); - var hint = 'estimated at tx date'; - - var cls = (diff > 0 ? 'diff-up' : 'diff-down') - if(diff > 0){ - diff = '+' + Ethplorer.Utils.round(diff, 2); - } - var historyPrice = Ethplorer.Utils.formatNum(oTx.usdPrice * valFloat, true, 2, true, true); - - usdPrice = '~$ ' + historyPrice + - ' (' + diff + '%)' - } document.title = 'Ethplorer'; document.title += (': ' + (titleAdd ? (titleAdd + ' -') : '')); document.title += (' hash ' + txHash); @@ -680,7 +698,6 @@ Ethplorer = { }else if(multiop){ Ethplorer.showOpDetails(oTx, txData.operations[0]); } - $('#historical-price').html(usdPrice); Ethplorer.Events.fire('ethp_showTxDetails_finish', txData); Ethplorer.Utils.hideEmptyFields(); @@ -922,7 +939,7 @@ Ethplorer = { var price = balances[k].balanceUSD; value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true) + ' '); if(rate.diff){ - var cls = rate.diff > 0 ? 'diff-up' : 'diff-down'; + var cls = getDiffClass(rate.diff); var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); if(rate.diff > 0){ rate.diff = '+' + rate.diff; @@ -955,7 +972,7 @@ Ethplorer = { if(totalPrice){ var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); if(totalDiff){ - var cls = totalDiff > 0 ? 'diff-up' : 'diff-down'; + var cls = getDiffClass(totalDiff); if(totalDiff > 0){ totalDiff = '+' + totalDiff; } @@ -1143,12 +1160,16 @@ Ethplorer = { var usdval = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf * txToken.price.rate, 2)), true, 2, true); value = value + '
    $ ' + usdval + ''; } + // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts + if (!tx.usdPrice && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ + tx.usdPrice = txToken.price.rate; + } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(tx.usdPrice, txToken.price.rate), 2); var hint = 'estimated at tx date'; - var cls = (diff > 0 ? 'diff-up' : 'diff-down') + var cls = getDiffClass(diff); if(diff > 0){ diff = '+' + Ethplorer.Utils.round(diff, 2); } @@ -1646,31 +1667,21 @@ Ethplorer = { case 'price': if(value && value.rate){ var rate = value; - value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true); - if(rate.diff){ - var cls = rate.diff > 0 ? 'diff-up' : 'diff-down'; - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 24 hour period'; - if(rate.diff > 0){ - rate.diff = '+' + rate.diff; - } - value = value + ' (24h ' + Ethplorer.Utils.round(rate.diff, 2) + '%)' + var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); + + value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true) + '
    '; + if('undefined' !== typeof rate.diff){ + value = value + '24h' + + getDiffString(rate.diff) +'' } - if(rate.diff7d){ - var cls = rate.diff7d > 0 ? 'diff-up' : 'diff-down'; - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 7 days period'; - if(rate.diff7d > 0){ - rate.diff7d = '+' + rate.diff7d; - } - value = value + ' (7d ' + Ethplorer.Utils.round(rate.diff7d, 2) + '%)' + if('undefined' !== typeof rate.diff7d){ + value = value + '7d' + + getDiffString(rate.diff7d) +'' } - if(rate.diff && rate.diff7d){ - var cls = rate.diff7d > 0 ? 'diff-up' : 'diff-down'; - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true) + ' in 30 days period'; - var diff30d = 123456.789; - if(rate.diff7d > 0){ - diff30d = '+' + diff30d; - } - value = value + ' (30d ' + Ethplorer.Utils.round(diff30d, 2) + '%)' + if('undefined' !== typeof rate.diff && 'undefined' !== typeof rate.diff7d || 'undefined' !== typeof rate.diff30d){ + var diff30d = rate.diff30d || 123456.789; + value = value + '30d' + + getDiffString(diff30d) +'' } }else{ value = ''; @@ -1954,6 +1965,77 @@ Ethplorer = { } return res; }, + + /** + * Number formatter (separates thousands with comma, adds zeroes to decimal part). + * + * @param {int} num + * @param {bool} withDecimals + * @param {int} decimals + * @param {bool} cutZeroes + * @returns {string} + */ + formatNumWidget: function(num, withDecimals /* = false */, decimals /* = 2 */, cutZeroes /* = false */, withPostfix /* = false */, numLimitPostfix /* = 999999 */){ + var postfix = ''; + if(withPostfix){ + if(!numLimitPostfix) numLimitPostfix = 999999; + if(num > 999 && num <= numLimitPostfix){ + num = num / 1000; + postfix = ' K'; + }else if(num > numLimitPostfix){ + num = num / 1000000; + postfix = ' M'; + } + } + function math(command, val, decimals){ + var k = Math.pow(10, decimals ? parseInt(decimals) : 0); + return Math[command](val * k) / k; + } + function padZero(s, len){ + while(s.length < len) s += '0'; + return s; + } + if(('object' === typeof(num)) && ('undefined' !== typeof(num.c))){ + num = parseFloat(Ethplorer.Utils.toBig(num).toString()); + } + cutZeroes = !!cutZeroes; + withDecimals = !!withDecimals; +// decimals = decimals || (cutZeroes ? 0 : 2); + + if((num.toString().indexOf("e+") > 0)){ + return num.toString(); + } + + if((num.toString().indexOf("e-") > 0) && withDecimals){ + var parts = num.toString().split("e-"); + var res = parts[0].replace('.', ''); + for(var i=1; i 1){ + res += '.'; + var tail = parts[1].substring(0, decimals); + if(tail.length < zeroCount){ + tail = padZero(tail, zeroCount); + } + res += tail; + }else{ + res += padZero('.', parseInt(zeroCount) + 1); + } + } + res = res.replace(/\.$/, ''); + return res + postfix; + }, /** * Parses URL path * @returns {string} @@ -2092,6 +2174,9 @@ Ethplorer = { }, toBig: function(obj){ var res = new BigNumber(0); + if (obj && 'string' === typeof(obj)) { + obj = obj.replace(/,/g, ''); + } if(obj && 'undefined' !== typeof(obj.c)){ res.c = obj.c; res.e = obj.e; @@ -2195,3 +2280,19 @@ Ethplorer = { location.reload(); } }; + +function getDiffClass(value) { + if (value === 0) { + return 'diff-zero' + } + return value > 0 ? 'diff-up' : 'diff-down'; +} + +function getDiffString(diff){ + if (diff === 0) { + return '--'; + } + var str = (diff > 0 ? '+' : ''); + str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + '%'; + return str; +} \ No newline at end of file From bb75b21e6f5b987e911bf86dfc60b60042e5cb86 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 21:25:19 +0700 Subject: [PATCH 114/658] Price diff for 30d added. --- service/lib/ethplorer.php | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 6cbeb1f7..55a2de43 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1424,7 +1424,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa 'volumePrevious' => 0 ); $result = $this->oCache->get($cache, false, true); - if($updateCache || (FALSE === $result)){ + if($updateCache){ $aTokens = $this->getTokens(); $result = array(); $total = 0; @@ -1592,11 +1592,21 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa if($criteria == 'count') $sortMethod = '_sortByTxCount'; usort($result, array($this, $sortMethod)); + $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); + $prevTokensNum = 0; + if(FALSE !== $aPrevTotals){ + $prevTokensNum = $aPrevTotals['tokensWithPrice']; + } + if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; + if(($criteria != 'count') && ($aTotals['tokensWithPrice'] > $topLimit)){ + $tokensLimit = $aTotals['tokensWithPrice']; + }else{ + $tokensLimit = $topLimit; + } + $res = []; foreach($result as $i => $item){ - if($i < $topLimit){ - // $item['percentage'] = round(($item['volume'] / $total) * 100); - + if($i < $tokensLimit){ // get tx's other trends if(($item['address'] != self::ADDRESS_ETH) && $criteria == 'count'){ unset($aPeriods[0]); @@ -1621,20 +1631,18 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $res[] = $item; } } + $aTotals['ts'] = time(); - $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); - $prevTokensNum = 0; - if(FALSE !== $aPrevTotals){ - $prevTokensNum = $aPrevTotals['tokensWithPrice']; - } - if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; $result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); $this->oCache->save('top_tokens_totals', $aTotals); } + if(FALSE === $result){ + $result = array('tokens' => array()); + } $res = []; - if($limit < $topLimit){ + if($limit > 0 && $limit < $topLimit){ foreach($result['tokens'] as $i => $item){ if($i < $limit){ $res[] = $item; @@ -2135,7 +2143,7 @@ public function getBlockTransactions($block, $showZero = false){ public function getTokenPrice30d($address){ $result = FALSE; - $aTokensTop = $this->getTokensTop(100, 'cap'); + $aTokensTop = $this->getTokensTop(-1, 'cap'); if(is_array($aTokensTop) && isset($aTokensTop['tokens'])){ foreach($aTokensTop['tokens'] as $aToken){ if(($aToken['address'] == $address) && isset($aToken['cap-30d-previous']) && $aToken['cap-30d-previous'] > 0){ From 2e29898cff4363dab913f2502dc3d4cc4265bd1c Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 24 Apr 2018 21:25:19 +0700 Subject: [PATCH 115/658] Price diff for 30d added. --- service/lib/ethplorer.php | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index e533fb5c..870e766b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1416,7 +1416,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa 'volumePrevious' => 0 ); $result = $this->oCache->get($cache, false, true); - if($updateCache || (FALSE === $result)){ + if($updateCache){ $aTokens = $this->getTokens(); $result = array(); $total = 0; @@ -1584,11 +1584,21 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa if($criteria == 'count') $sortMethod = '_sortByTxCount'; usort($result, array($this, $sortMethod)); + $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); + $prevTokensNum = 0; + if(FALSE !== $aPrevTotals){ + $prevTokensNum = $aPrevTotals['tokensWithPrice']; + } + if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; + if(($criteria != 'count') && ($aTotals['tokensWithPrice'] > $topLimit)){ + $tokensLimit = $aTotals['tokensWithPrice']; + }else{ + $tokensLimit = $topLimit; + } + $res = []; foreach($result as $i => $item){ - if($i < $topLimit){ - // $item['percentage'] = round(($item['volume'] / $total) * 100); - + if($i < $tokensLimit){ // get tx's other trends if(($item['address'] != self::ADDRESS_ETH) && $criteria == 'count'){ unset($aPeriods[0]); @@ -1613,20 +1623,18 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $res[] = $item; } } + $aTotals['ts'] = time(); - $aPrevTotals = $this->oCache->get('top_tokens_totals', FALSE, TRUE); - $prevTokensNum = 0; - if(FALSE !== $aPrevTotals){ - $prevTokensNum = $aPrevTotals['tokensWithPrice']; - } - if($aTotals['tokensWithPrice'] < $prevTokensNum) $aTotals['tokensWithPrice'] = $prevTokensNum; $result = array('tokens' => $res, 'totals' => $aTotals); $this->oCache->save($cache, $result); $this->oCache->save('top_tokens_totals', $aTotals); } + if(FALSE === $result){ + $result = array('tokens' => array()); + } $res = []; - if($limit < $topLimit){ + if($limit > 0 && $limit < $topLimit){ foreach($result['tokens'] as $i => $item){ if($i < $limit){ $res[] = $item; @@ -2127,7 +2135,7 @@ public function getBlockTransactions($block, $showZero = false){ public function getTokenPrice30d($address){ $result = FALSE; - $aTokensTop = $this->getTokensTop(100, 'cap'); + $aTokensTop = $this->getTokensTop(-1, 'cap'); if(is_array($aTokensTop) && isset($aTokensTop['tokens'])){ foreach($aTokensTop['tokens'] as $aToken){ if(($aToken['address'] == $address) && isset($aToken['cap-30d-previous']) && $aToken['cap-30d-previous'] > 0){ From f385477806dc71669bcf2df28fead0b430ce83e0 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 25 Apr 2018 12:33:13 +0700 Subject: [PATCH 116/658] fix scrollbar --- css/ethplorer.css | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 10fcb870..fb81262b 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1393,22 +1393,21 @@ a.token-update { display: block; left: 0px; width: 100%; - height: 15px; + height: 60px; } .scrollwrapper.hide-bottom-gr:after{ display: none; } .scrollwrapper:after{ bottom: 0; + pointer-events: none; content: ''; - background: rgba(252,252,252,0.7); - background: -moz-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); - background: -webkit-gradient(left bottom, left top, color-stop(0%, rgba(252,252,252,0.7)), color-stop(100%, rgba(242,242,242,0))); - background: -webkit-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); - background: -o-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); - background: -ms-linear-gradient(bottom, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); - background: linear-gradient(to top, rgba(252,252,252,0.7) 0%, rgba(242,242,242,0) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfcfc', endColorstr='#f2f2f2', GradientType=0 ); + background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); + background: -webkit-gradient(left bottom, left top, color-stop(0%, rgba(0,0,0,0)), color-stop(100%, rgba(0,0,0,9))); + background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); + background: -o-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); + background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); + background: linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); } /* ^^^ Scrollable ^^^ */ From 1667076cfe59c63e169942fedc2f3ac7a2ee37bb Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 25 Apr 2018 13:56:49 +0700 Subject: [PATCH 117/658] correct diff % padding and fix Op price --- css/ethplorer.css | 6 +++--- js/ethplorer.js | 46 ++++++++++++++++------------------------------ 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index fb81262b..7112daa7 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1391,7 +1391,7 @@ a.token-update { content: ""; position: absolute; display: block; - left: 0px; + left: 0; width: 100%; height: 60px; } @@ -1420,11 +1420,11 @@ a.token-update { } .diff-span { - padding-right: 10px; + padding-right: 20px; color: rgba(255, 255, 255, 0.6); } .diff-span span { - padding-left: 4px; + padding-left: 6px; } .diff-zero{ color: rgba(255, 255, 255, 0.6); diff --git a/js/ethplorer.js b/js/ethplorer.js index d44187f3..08251f0e 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -351,7 +351,6 @@ Ethplorer = { } var valFloat = parseFloat(Ethplorer.Utils.toBig(oOperation.value).toString()); - valFloat = valFloat / Math.pow(10, oToken.decimals) if('undefined' !== typeof(oOperation.formatted)){ if(Ethplorer.Utils.isSafari()){ oOperation.value = valFloat; @@ -693,7 +692,7 @@ Ethplorer = { $('.multiop .blue').removeClass('blue'); el.addClass('blue'); el.removeClass('selectable'); - Ethplorer.showOpDetails(txData.tx, el[0].operation); + Ethplorer.showOpDetails(oTx, el[0].operation); } }else if(multiop){ Ethplorer.showOpDetails(oTx, txData.operations[0]); @@ -1670,19 +1669,13 @@ Ethplorer = { var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true) + '
    '; - if('undefined' !== typeof rate.diff){ - value = value + '24h' - + getDiffString(rate.diff) +'' - } - if('undefined' !== typeof rate.diff7d){ - value = value + '7d' - + getDiffString(rate.diff7d) +'' - } - if('undefined' !== typeof rate.diff && 'undefined' !== typeof rate.diff7d || 'undefined' !== typeof rate.diff30d){ - var diff30d = rate.diff30d || 123456.789; - value = value + '30d' - + getDiffString(diff30d) +'' - } + + value = value + '24h' + + getDiffString(rate.diff) +'' + value = value + '7d' + + getDiffString(rate.diff7d) +'' + value = value + '30d' + + getDiffString(rate.diff30d) +'' }else{ value = ''; } @@ -1979,10 +1972,10 @@ Ethplorer = { var postfix = ''; if(withPostfix){ if(!numLimitPostfix) numLimitPostfix = 999999; - if(num > 999 && num <= numLimitPostfix){ + if(Math.abs(num) > 999 && Math.abs(num) <= numLimitPostfix){ num = num / 1000; postfix = ' K'; - }else if(num > numLimitPostfix){ + } else if(Math.abs(num) > numLimitPostfix){ num = num / 1000000; postfix = ' M'; } @@ -2249,21 +2242,14 @@ Ethplorer = { initScrollable: function () { function checkPosition(el){ var $el = $(el); - var $child = $el.children() + var $child = $el.children(); - $el - .removeClass('hide-bottom-gr') - .removeClass('hide-top-gr'); + $el.removeClass('hide-bottom-gr'); - console.log($child.outerHeight(true) , $el.outerHeight(true) ) if ($child.outerHeight(true) < $el.outerHeight(true) || $child.outerHeight(true) - $el.outerHeight(true) + $child.position().top === 0){ //bottom $el.addClass('hide-bottom-gr') } - /*if ($child.position().top === 0){ - //top - $el.addClass('hide-top-gr') - }*/ } $('.scrollwrapper').one("DOMSubtreeModified", function(event){ @@ -2282,17 +2268,17 @@ Ethplorer = { }; function getDiffClass(value) { - if (value === 0) { + if (value === 0 || 'undefined' === typeof value) { return 'diff-zero' } return value > 0 ? 'diff-up' : 'diff-down'; } function getDiffString(diff){ - if (diff === 0) { + if ('undefined' === typeof diff) { return '--'; } - var str = (diff > 0 ? '+' : ''); - str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + '%'; + var str = ''; //(diff > 0 ? '+' : ''); + str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + ' %'; return str; } \ No newline at end of file From 54a1888d20a38361f8fb5ddcf0ffefe0234f6f80 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 25 Apr 2018 16:45:19 +0700 Subject: [PATCH 118/658] extract to method --- js/ethplorer.js | 49 +++++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 08251f0e..11dac024 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -367,21 +367,7 @@ Ethplorer = { } $('#transfer-operation-value').html(value); - var usdPrice = ''; - if(op.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ - var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(op.usdPrice, oToken.price.rate), 2); - var hint = 'estimated at tx date'; - - var cls = getDiffClass(diff); - if(diff > 0){ - diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; - } - var historyPrice = Ethplorer.Utils.formatNum(op.usdPrice * valFloat, true, 2, true, true); - - usdPrice = '~$ ' + historyPrice + - ' ' + diff + '%' - } - $('#historical-price').html(usdPrice); + $('#historical-price').html(getHistUsdPriceString(op.usdPrice, oToken.price.rate, valFloat)); titleAdd += oOperation.type; @@ -625,21 +611,7 @@ Ethplorer = { value = value + '
    ($ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ')'; } $('#transfer-operation-value').html(value); - var usdPrice = ''; - if(oOperation.usdPrice && Ethplorer.showHistoricalPrice && valFloat){ - var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(oOperation.usdPrice, oToken.price.rate), 2); - var hint = 'estimated at tx date'; - - var cls = getDiffClass(diff); - if(diff > 0){ - diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; - } - var historyPrice = Ethplorer.Utils.formatNum(oOperation.usdPrice * valFloat, true, 2, true, true); - - usdPrice = '~$ ' + historyPrice + - ' (' + diff + '%)' - } - $('#historical-price').html(usdPrice); + $('#historical-price').html(getHistUsdPriceString(oOperation.usdPrice, oToken.price.rate, valFloat)); } if(oTx.blockNumber){ @@ -2281,4 +2253,21 @@ function getDiffString(diff){ var str = ''; //(diff > 0 ? '+' : ''); str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + ' %'; return str; +} +function getHistUsdPriceString(histPrice, currPrice, valFloat){ + var usdPrice = ''; + if(histPrice && Ethplorer.showHistoricalPrice && valFloat){ + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(histPrice, currPrice), 2); + var hint = 'estimated at tx date'; + + var cls = getDiffClass(diff); + if(diff > 0){ + diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; + } + var historyPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); + + usdPrice = '~$ ' + historyPrice + + ' ' + diff + '%' + } + return usdPrice; } \ No newline at end of file From 1ffbee4f90d009a788cf563adb64e2470b4d1527 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 25 Apr 2018 18:50:01 +0700 Subject: [PATCH 119/658] updated requirements --- css/ethplorer.css | 17 +++++++++++++++- js/ethplorer.js | 52 +++++++++++++++++++++++------------------------ 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 7112daa7..a407db72 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -597,6 +597,18 @@ a.dashed { color: #ae2525 !important; } +#transfer-operation-value .diff-up{ + color: #2de72d !important; + padding-left: 6px; + font-size: 0.9em; +} + +#transfer-operation-value .diff-down{ + color: #e43434 !important; + padding-left: 6px; + font-size: 0.9em; +} + .tx-value-price { font-size: 0.9em; color: white; @@ -636,6 +648,9 @@ a.dashed { color: rgba(255, 255, 255, 0.6); font-size: 0.8em; } +.transfer-usd span{ + padding-left: 6px; +} .hash-from-to, .cut-long-text { max-width: 40vw; @@ -1377,7 +1392,7 @@ a.token-update { } .historical-price { font-size: 0.7em; - color: rgba(255, 255, 255, 0.5); + color: rgba(255, 255, 255, 0.4); } /* Scrollable */ .scrollable{ diff --git a/js/ethplorer.js b/js/ethplorer.js index 11dac024..4ca042e0 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -363,11 +363,12 @@ Ethplorer = { } var value = oOperation.value; if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    ($ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ')'; + value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; + value += getHistDiffPriceString(op.usdPrice, oToken.price.rate); } $('#transfer-operation-value').html(value); - $('#historical-price').html(getHistUsdPriceString(op.usdPrice, oToken.price.rate, valFloat)); + $('#historical-price').html(getHistUsdPriceString(op.usdPrice, valFloat)); titleAdd += oOperation.type; @@ -608,10 +609,11 @@ Ethplorer = { if(oOperation.value){ var value = oOperation.value; if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    ($ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ')'; + value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; + value += getHistDiffPriceString(oOperation.usdPrice, oToken.price.rate); } $('#transfer-operation-value').html(value); - $('#historical-price').html(getHistUsdPriceString(oOperation.usdPrice, oToken.price.rate, valFloat)); + $('#historical-price').html(getHistUsdPriceString(oOperation.usdPrice, valFloat)); } if(oTx.blockNumber){ @@ -665,6 +667,9 @@ Ethplorer = { el.addClass('blue'); el.removeClass('selectable'); Ethplorer.showOpDetails(oTx, el[0].operation); + setTimeout(function(){ + el[0].scrollIntoView() + }, 0) } }else if(multiop){ Ethplorer.showOpDetails(oTx, txData.operations[0]); @@ -1129,25 +1134,17 @@ Ethplorer = { if(pf){ if(txToken.price && txToken.price.rate){ var usdval = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf * txToken.price.rate, 2)), true, 2, true); - value = value + '
    $ ' + usdval + ''; + value = value + '
    $ ' + usdval + + getHistDiffPriceString(tx.usdPrice, txToken.price.rate) + ''; } // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts if (!tx.usdPrice && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ tx.usdPrice = txToken.price.rate; } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ - - var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(tx.usdPrice, txToken.price.rate), 2); var hint = 'estimated at tx date'; - - var cls = getDiffClass(diff); - if(diff > 0){ - diff = '+' + Ethplorer.Utils.round(diff, 2); - } var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); - - usdPrice = '
    ~$ ' + historyPrice + - ' (' + diff + '%)' + usdPrice = '
    ~$ ' + historyPrice +'' } } value += usdPrice; @@ -1638,7 +1635,7 @@ Ethplorer = { case 'price': if(value && value.rate){ var rate = value; - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); + var hint = '$' +rate.rate + ' : Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true) + '
    '; @@ -2254,20 +2251,23 @@ function getDiffString(diff){ str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + ' %'; return str; } -function getHistUsdPriceString(histPrice, currPrice, valFloat){ +function getHistDiffPriceString(histPrice, currPrice){ + var diffTag = ''; + if(histPrice && Ethplorer.showHistoricalPrice){ + var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(currPrice, histPrice), 2); + var cls = getDiffClass(diff); + diff = Ethplorer.Utils.formatNum(diff, true, 2, true, true); + diffTag = '(' + diff + '%)' + } + return diffTag; +} + +function getHistUsdPriceString(histPrice, valFloat){ var usdPrice = ''; if(histPrice && Ethplorer.showHistoricalPrice && valFloat){ - var diff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(histPrice, currPrice), 2); var hint = 'estimated at tx date'; - - var cls = getDiffClass(diff); - if(diff > 0){ - diff = '+' + Ethplorer.Utils.formatNum(diff, true, 2, true, true);; - } var historyPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); - - usdPrice = '~$ ' + historyPrice + - ' ' + diff + '%' + usdPrice = '~$ ' + historyPrice +'' } return usdPrice; } \ No newline at end of file From 3286ea3038cce41393eec79e6e8b21219dbfdd29 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Wed, 25 Apr 2018 19:58:48 +0700 Subject: [PATCH 120/658] max-h 0% colors --- css/ethplorer.css | 9 ++++++--- js/ethplorer.js | 14 ++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index a407db72..9a931127 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -598,13 +598,13 @@ a.dashed { } #transfer-operation-value .diff-up{ - color: #2de72d !important; + color: #28d028 !important; padding-left: 6px; font-size: 0.9em; } #transfer-operation-value .diff-down{ - color: #e43434 !important; + color: #a92626 !important; padding-left: 6px; font-size: 0.9em; } @@ -1399,9 +1399,12 @@ a.token-update { position: relative; } .scrollwrapper{ - max-height: 400px; + max-height: 280px; overflow-y: auto; } +#address-token-balances .scrollwrapper{ + max-height: 350px; +} .scrollwrapper:after{ content: ""; position: absolute; diff --git a/js/ethplorer.js b/js/ethplorer.js index 4ca042e0..fcccd1e4 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -668,7 +668,7 @@ Ethplorer = { el.removeClass('selectable'); Ethplorer.showOpDetails(oTx, el[0].operation); setTimeout(function(){ - el[0].scrollIntoView() + el[0].scrollIntoView({behavior: "instant", inline: "center"}) }, 0) } }else if(multiop){ @@ -1132,15 +1132,17 @@ Ethplorer = { var pf = parseFloat(value.replace(/\,/g,'').split(' ')[0]); var usdPrice = ''; if(pf){ + + // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts + if (!tx.usdPrice && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ + tx.usdPrice = txToken.price.rate; + } + if(txToken.price && txToken.price.rate){ var usdval = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf * txToken.price.rate, 2)), true, 2, true); value = value + '
    $ ' + usdval + getHistDiffPriceString(tx.usdPrice, txToken.price.rate) + ''; } - // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts - if (!tx.usdPrice && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ - tx.usdPrice = txToken.price.rate; - } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ var hint = 'estimated at tx date'; var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); @@ -2248,7 +2250,7 @@ function getDiffString(diff){ return '--'; } var str = ''; //(diff > 0 ? '+' : ''); - str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + ' %'; + str += Ethplorer.Utils.formatNumWidget(diff, true, 2, true, true) + '%'; return str; } function getHistDiffPriceString(histPrice, currPrice){ From 7099e2dc9f16b53bb495c063381bbbf0d9d7a0e0 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 26 Apr 2018 12:54:18 +0700 Subject: [PATCH 121/658] loading infinity fix --- js/ethplorer.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index fcccd1e4..327cc56e 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1144,7 +1144,7 @@ Ethplorer = { getHistDiffPriceString(tx.usdPrice, txToken.price.rate) + ''; } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ - var hint = 'estimated at tx date'; + var hint = 'estimtable-loadingated at tx date'; var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); usdPrice = '
    ~$ ' + historyPrice +'' } @@ -1701,9 +1701,7 @@ Ethplorer = { showTableLoader: function(){ $('.filter-box').addClass('processing'); $('.paginationFooter, .notFoundRow').parents('.table').addClass('unclickable'); - setTimeout(function(){ - $('.total-records:visible').html(''); - }, 500); + $('.total-records:visible').html(''); $('.nav-tabs').addClass('unclickable'); }, hideTableLoader: function(){ From 801bd02851c4d44b17db6c02943c8aeb96299f35 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 26 Apr 2018 16:43:56 +0700 Subject: [PATCH 122/658] expand/collapse and history price for unit --- css/ethplorer.css | 34 +++++++++++++++++++++++++++++++++- index.php | 3 +++ js/ethplorer.js | 37 +++++++++++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 9a931127..9ed468b6 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1427,6 +1427,38 @@ a.token-update { background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); background: linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); } + +.expand-btn{ + display: none; + font-size: 16px; + color: white !important; + opacity: 0.6; + cursor: pointer; + border-bottom: 1px dashed white; + /*text-transform:capitalize;*/ +} +.shift-up{ + position: relative; + top: -15px; +} + +.expand-btn, +.expand-btn:hover, +.expand-btn:visited, +.expand-btn:active { + text-decoration: none; +} + + +.expanded .scrollwrapper, +#address-token-balances .expanded .scrollwrapper { + max-height: none; +} + +.expanded .scrollwrapper:after{ + display: none; +} + /* ^^^ Scrollable ^^^ */ #address-token-balances, .multiop { @@ -1446,4 +1478,4 @@ a.token-update { } .diff-zero{ color: rgba(255, 255, 255, 0.6); -} \ No newline at end of file +} diff --git a/index.php b/index.php index 645d6d06..83682581 100644 --- a/index.php +++ b/index.php @@ -517,6 +517,9 @@
    +
    + Expand +
    diff --git a/js/ethplorer.js b/js/ethplorer.js index 327cc56e..62b0d6fb 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1144,9 +1144,9 @@ Ethplorer = { getHistDiffPriceString(tx.usdPrice, txToken.price.rate) + ''; } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ - var hint = 'estimtable-loadingated at tx date'; + var hint = 'estimated at tx date'; var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); - usdPrice = '
    ~$ ' + historyPrice +'' + usdPrice = '
    ~$ ' + historyPrice +'  @ '+Ethplorer.Utils.formatNum(tx.usdPrice, true, 2, true)+'' } } value += usdPrice; @@ -2220,6 +2220,33 @@ Ethplorer = { $el.addClass('hide-bottom-gr') } + // expand-btn now only for Token Balances block + // to extend functionality need to update storage keys depends on block + var $expand = $el.closest('.block').find('.expand-btn'); + if ($expand.length && $el.outerHeight(true) < $el.children().outerHeight(true)) { + $expand.show(); + var text = Ethplorer.Storage.get('expand-address-token-balances', 'expand'); + $expand + .html(text + (text === 'collapse' ? '↑': '↓')) + .toggleClass('shift-up', text.indexOf('expand') !== -1) + .parent() + .siblings('.scrollable') + .toggleClass('expanded', text.indexOf('collapse') !== -1) + $(document).on('click', '.expand-btn', function(e){ + var $btn = $(e.target); + var $scrollable = $btn.parent().siblings('.scrollable'); + var bool = $btn.text().indexOf('expand') !== -1; + $scrollable.toggleClass('expanded', bool); + text = bool ? 'collapse' : 'expand'; + $btn + .toggleClass('shift-up', text === 'expand') + .html(text + (bool ? '↑': '↓')) + Ethplorer.Storage.set('expand-address-token-balances', text); + if (!bool){ + $('#address-balances-total')[0].scrollIntoView({behavior: "instant", block: "start"}) + } + }) + } } $('.scrollwrapper').one("DOMSubtreeModified", function(event){ setTimeout(() => { @@ -2266,8 +2293,10 @@ function getHistUsdPriceString(histPrice, valFloat){ var usdPrice = ''; if(histPrice && Ethplorer.showHistoricalPrice && valFloat){ var hint = 'estimated at tx date'; - var historyPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); - usdPrice = '~$ ' + historyPrice +'' + var historyPrice = Ethplorer.Utils.formatNum(histPrice, true, 2, true, true); + var totalHistoryPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); + + usdPrice = '~$ ' + totalHistoryPrice +'  @ '+ historyPrice +'' } return usdPrice; } \ No newline at end of file From f75d7057e12d7f4cccbc62a7c95f9b5145b145ad Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 26 Apr 2018 16:54:25 +0700 Subject: [PATCH 123/658] enable historical price by default --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 62b0d6fb..910ae9fe 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -32,7 +32,7 @@ Ethplorer = { Ethplorer.Config = ethplorerConfig; } Ethplorer.isProd = ('ethplorer.io' === document.location.host); - Ethplorer.showHistoricalPrice = sessionStorage.getItem("enableHistoricalPrice") === 'true'; + Ethplorer.showHistoricalPrice = true; // sessionStorage.getItem("enableHistoricalPrice") === 'true'; BigNumber.config({ ERRORS: false }); Ethplorer.Nav.init(); Ethplorer.Storage.init(); From 506b6430cd7d47673034d8f23a4877cc8d537ce7 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 26 Apr 2018 17:38:03 +0700 Subject: [PATCH 124/658] 2 space into margin-left --- css/ethplorer.css | 3 +++ js/ethplorer.js | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 9ed468b6..7b18ab6a 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1394,6 +1394,9 @@ a.token-update { font-size: 0.7em; color: rgba(255, 255, 255, 0.4); } +.mrgnl-10 { + margin-left: 10px; +} /* Scrollable */ .scrollable{ position: relative; diff --git a/js/ethplorer.js b/js/ethplorer.js index 910ae9fe..1202de69 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1145,8 +1145,10 @@ Ethplorer = { } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ var hint = 'estimated at tx date'; - var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); - usdPrice = '
    ~$ ' + historyPrice +'  @ '+Ethplorer.Utils.formatNum(tx.usdPrice, true, 2, true)+'' + var totalHistoryPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); + var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(tx.usdPrice, 2)), true, 2, true); + usdPrice = '
    ~$ ' + + totalHistoryPrice +'@ '+ historyPrice +'' } } value += usdPrice; @@ -2296,7 +2298,7 @@ function getHistUsdPriceString(histPrice, valFloat){ var historyPrice = Ethplorer.Utils.formatNum(histPrice, true, 2, true, true); var totalHistoryPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); - usdPrice = '~$ ' + totalHistoryPrice +'  @ '+ historyPrice +'' + usdPrice = '~$ ' + totalHistoryPrice +'@ '+ historyPrice +'' } return usdPrice; } \ No newline at end of file From bee2677a300ab08781bd3ea8fd73de60589f2e48 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 26 Apr 2018 19:40:21 +0700 Subject: [PATCH 125/658]   , >0.00 and media fixes --- css/ethplorer.css | 13 +++++++++++-- js/ethplorer.js | 40 ++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 7b18ab6a..e8fdf986 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -596,16 +596,19 @@ a.dashed { .diff-down { color: #ae2525 !important; } +#transfer-operation-value .diff-up, +#transfer-operation-value .diff-zero, +#transfer-operation-value .diff-down{ + padding-left: 6px; +} #transfer-operation-value .diff-up{ color: #28d028 !important; - padding-left: 6px; font-size: 0.9em; } #transfer-operation-value .diff-down{ color: #a92626 !important; - padding-left: 6px; font-size: 0.9em; } @@ -651,6 +654,11 @@ a.dashed { .transfer-usd span{ padding-left: 6px; } +@media screen and (max-width: 1199px) and (min-width: 767px) { + .transfer-usd span{ + display: block; + } +} .hash-from-to, .cut-long-text { max-width: 40vw; @@ -1391,6 +1399,7 @@ a.token-update { 100%{transform:rotate(360deg)} } .historical-price { + display: block; font-size: 0.7em; color: rgba(255, 255, 255, 0.4); } diff --git a/js/ethplorer.js b/js/ethplorer.js index 1202de69..f8fc524b 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -329,7 +329,7 @@ Ethplorer = { var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#transaction-token-totalSupply').html(totalSupply); } } @@ -363,7 +363,7 @@ Ethplorer = { } var value = oOperation.value; if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; + value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; value += getHistDiffPriceString(op.usdPrice, oToken.price.rate); } $('#transfer-operation-value').html(value); @@ -510,7 +510,7 @@ Ethplorer = { var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#transaction-token-totalSupply').html(totalSupply); } } @@ -609,7 +609,7 @@ Ethplorer = { if(oOperation.value){ var value = oOperation.value; if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; + value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; value += getHistDiffPriceString(oOperation.usdPrice, oToken.price.rate); } $('#transfer-operation-value').html(value); @@ -853,7 +853,7 @@ Ethplorer = { var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#address-token-totalSupply').html(totalSupply); } } @@ -913,7 +913,7 @@ Ethplorer = { if(balances[k].price){ var rate = oToken.price; var price = balances[k].balanceUSD; - value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true) + ' '); + value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true) + ' '); if(rate.diff){ var cls = getDiffClass(rate.diff); var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); @@ -946,7 +946,7 @@ Ethplorer = { $('#address-token-balances table').append(row); } if(totalPrice){ - var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); + var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); if(totalDiff){ var cls = getDiffClass(totalDiff); if(totalDiff > 0){ @@ -1130,7 +1130,7 @@ Ethplorer = { value = (tx.type && ('burn' === tx.type)) ? '-' + value + '
    🔥 Burn' : value + '
    ⚒ Issuance'; } var pf = parseFloat(value.replace(/\,/g,'').split(' ')[0]); - var usdPrice = ''; + var usdPrice = '
    '; if(pf){ // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts @@ -1140,14 +1140,17 @@ Ethplorer = { if(txToken.price && txToken.price.rate){ var usdval = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf * txToken.price.rate, 2)), true, 2, true); - value = value + '
    $ ' + usdval + + value = value + '
    $ ' + usdval + getHistDiffPriceString(tx.usdPrice, txToken.price.rate) + ''; } if (tx.usdPrice && Ethplorer.showHistoricalPrice){ var hint = 'estimated at tx date'; var totalHistoryPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(pf*tx.usdPrice, 2)), true, 2, true); var historyPrice = Ethplorer.Utils.formatNum(Math.abs(Ethplorer.Utils.round(tx.usdPrice, 2)), true, 2, true); - usdPrice = '
    ~$ ' + if (historyPrice === '0.00') { + historyPrice = '>0.00'; + } + usdPrice = '~$ ' + totalHistoryPrice +'@ '+ historyPrice +'' } } @@ -1155,7 +1158,7 @@ Ethplorer = { divData.html( 'Date: ' + date + '
    ' + (!data.token ? ('Token: ' + token + '
    ') : '') + - 'Value: ' + value + '
    ' + + 'Value: ' + value + '' + 'Tx: ' + Ethplorer.Utils.getEthplorerLink(tx.transactionHash) + '
    ' + (from ? ('From: ' + from + '
    To: ' + to) : ('Address: ' + _address)) ); @@ -1240,7 +1243,7 @@ Ethplorer = { if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); var usdval = Ethplorer.Utils.formatNum(Math.abs(pf), true, 2, true); - value = value + '
    $ ' + usdval + ''; + value = value + '
    $ ' + usdval + ''; } } tdQty.html(value); @@ -1289,7 +1292,7 @@ Ethplorer = { if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); var usdval = Ethplorer.Utils.formatNum(Math.abs(pf), true, 2, true); - balance = balance + '
    $ ' + usdval + ''; + balance = balance + '
    $ ' + usdval + ''; } } @@ -1639,9 +1642,10 @@ Ethplorer = { case 'price': if(value && value.rate){ var rate = value; - var hint = '$' +rate.rate + ' : Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); + var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); + var price = rate.rate < 0.01 ? rate.rate : Ethplorer.Utils.formatNum(rate.rate, true, 2, true); - value = '$ ' + Ethplorer.Utils.formatNum(rate.rate, true, 2, true) + '
    '; + value = '$ ' + price + '
    '; value = value + '24h' + getDiffString(rate.diff) +'' @@ -1672,7 +1676,7 @@ Ethplorer = { var cls = change > 0 ? 'diff-up' : 'diff-down'; var diff = ""; // var diff = change ? (' (' + Ethplorer.Utils.round(change, 2) + '%)') : ''; - res = res + '
    $ ' + price + diff + ''; + res = res + '
    $ ' + price + diff + ''; } } value = res; @@ -2295,10 +2299,10 @@ function getHistUsdPriceString(histPrice, valFloat){ var usdPrice = ''; if(histPrice && Ethplorer.showHistoricalPrice && valFloat){ var hint = 'estimated at tx date'; - var historyPrice = Ethplorer.Utils.formatNum(histPrice, true, 2, true, true); + // var historyPrice = Ethplorer.Utils.formatNum(histPrice, true, 2, true, true); var totalHistoryPrice = Ethplorer.Utils.formatNum(histPrice * valFloat, true, 2, true, true); - usdPrice = '~$ ' + totalHistoryPrice +'@ '+ historyPrice +'' + usdPrice = '~$ ' + totalHistoryPrice +'@ '+ histPrice +'' } return usdPrice; } \ No newline at end of file From ea23f1f2580d8d4ca8ddfb44853c7a309dec0822 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Apr 2018 20:26:40 +0700 Subject: [PATCH 126/658] Cache driver for cron tasks. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index f3b860e1..93dcb44f 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -98,7 +98,7 @@ public function __construct(array $aConfig, $driver = FALSE, $useLocks = FALSE){ } $this->useLocks = $useLocks; - //if(class_exists('Redis') && (php_sapi_name() === 'cli') && isset($aConfig['redis'])) $this->driver = 'redis'; + if(isset($aConfig['cliCacheDriver']) && (php_sapi_name() === 'cli')) $this->driver = $aConfig['cliCacheDriver']; if('memcached' === $this->driver){ if(class_exists('Memcached')){ From 5ffc41d8018699c705d6bac2f1ee07b96a1e60bf Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 27 Apr 2018 18:01:29 +0700 Subject: [PATCH 127/658] Cache ttl changed. --- service/lib/cache.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 93dcb44f..bf256761 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -154,15 +154,20 @@ public function save($entryName, $data){ /*if($lifetime > evxCache::MONTH){ $lifetime = time() + $cacheLifetime; }*/ + $ttl = evxCache::MONTH; if(!$lifetime){ - // 365 days if cache lifetime is not set - $lifetime = time() + 12 * evxCache::MONTH + 5 * 24 * evxCache::HOUR; + // 1 month if cache lifetime is not set + $lifetime = time() + evxCache::MONTH; }else{ + $ttl = $lifetime; $lifetime = time() + $lifetime; } - //$saveRes = $this->oDriver->set($entryName, $data, $lifetime); $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); - $saveRes = $this->oDriver->set($entryName, ('redis' == $this->driver) ? json_encode($aCachedData) : $aCachedData); + if('redis' == $this->driver){ + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), array('ex' => $ttl)); + }else{ + $saveRes = $this->oDriver->set($entryName, $aCachedData); + } if(('redis' == $this->driver) || (!in_array($entryName, array('tokens', 'rates')) && (0 !== strpos($entryName, 'rates-history-')))){ break; } From 808ae8ff549d259f10af37f9c14b5856b639c3c1 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:07:30 +0700 Subject: [PATCH 128/658] Retreive issuance information from tx input hex --- js/ethplorer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index f8fc524b..aafb3b09 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2138,6 +2138,9 @@ Ethplorer = { res = JSON.parse(rrr); } } + if(!res && str.indexOf("Issuance")){ + res = {description: str.substr(str.indexOf("Issuance"))}; + } return res; }, toBig: function(obj){ From 966ab76de773421a75bff426f21041d0136152a0 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Fri, 27 Apr 2018 18:13:45 +0700 Subject: [PATCH 129/658] lost image fix --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index aafb3b09..94aae2e7 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2059,7 +2059,7 @@ Ethplorer = { } var res = '' + text + ''); + res += ('/' + data + '" class="local-link">' + text + ''); if(isContract){ res = 'Contract ' + res; } From db270b9531da301f7ea12167f2056f010d977115 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:14:12 +0700 Subject: [PATCH 130/658] Parse fix --- js/ethplorer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index aafb3b09..41394e9d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2138,8 +2138,9 @@ Ethplorer = { res = JSON.parse(rrr); } } - if(!res && str.indexOf("Issuance")){ - res = {description: str.substr(str.indexOf("Issuance"))}; + var fullStr = Ethplorer.Utils.hex2ascii(hex); + if(!res && fullStr.indexOf("Issuance")){ + res = {description: fullStr.substr(fullStr.indexOf("Issuance"))}; } return res; }, From ed1cb7d886e792f4f4b2634e4e3e7ad8a3531751 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:19:17 +0700 Subject: [PATCH 131/658] Parse fixed --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 41394e9d..5071ae2a 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2140,7 +2140,7 @@ Ethplorer = { } var fullStr = Ethplorer.Utils.hex2ascii(hex); if(!res && fullStr.indexOf("Issuance")){ - res = {description: fullStr.substr(fullStr.indexOf("Issuance"))}; + res = JSON.parse("{\"description\": \"" + fullStr.substr(fullStr.indexOf("Issuance")) + "\"}"); } return res; }, From b08e38cfeefc328db937f7e3e2c64f67f3e5f743 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:24:54 +0700 Subject: [PATCH 132/658] Reverted and fixed --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 5071ae2a..25b78e2c 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2140,7 +2140,7 @@ Ethplorer = { } var fullStr = Ethplorer.Utils.hex2ascii(hex); if(!res && fullStr.indexOf("Issuance")){ - res = JSON.parse("{\"description\": \"" + fullStr.substr(fullStr.indexOf("Issuance")) + "\"}"); + res = {description: fullStr.substr(fullStr.indexOf("Issuance")).replace("\\n", "\n").replace("\\u0000", "")}; } return res; }, From 2be656ee31a430ae03495b49dfe5a94e4a4766ec Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:32:02 +0700 Subject: [PATCH 133/658] Regexp fixed --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index dc6f0080..23648c52 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2140,7 +2140,7 @@ Ethplorer = { } var fullStr = Ethplorer.Utils.hex2ascii(hex); if(!res && fullStr.indexOf("Issuance")){ - res = {description: fullStr.substr(fullStr.indexOf("Issuance")).replace("\\n", "\n").replace("\\u0000", "")}; + res = {description: fullStr.substr(fullStr.indexOf("Issuance")).replace(/\\n/g, "\n").replace(/\\u0000/g, "")}; } return res; }, From af83de9e00d4ca761dee23e275082f6e1a4e5b0c Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Apr 2018 18:35:56 +0700 Subject: [PATCH 134/658] IndexOf fixed --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 23648c52..5deac734 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2139,7 +2139,7 @@ Ethplorer = { } } var fullStr = Ethplorer.Utils.hex2ascii(hex); - if(!res && fullStr.indexOf("Issuance")){ + if(!res && (fullStr.indexOf("Issuance") > 0)){ res = {description: fullStr.substr(fullStr.indexOf("Issuance")).replace(/\\n/g, "\n").replace(/\\u0000/g, "")}; } return res; From d09af73692e884b1fb56be0b9df50ec90c75aff7 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 30 Apr 2018 21:07:01 +0700 Subject: [PATCH 135/658] Getting price history optimized. --- service/lib/ethplorer.php | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 55a2de43..d64f5361 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2219,10 +2219,31 @@ public function getTokenPriceHistory($address, $period = 0, $type = 'hourly', $u $cache = 'rates-history-' . /*($period > 0 ? ('period-' . $period . '-') : '' ) . ($type != 'hourly' ? $type . '-' : '') .*/ $address; $result = $this->oCache->get($cache, false, true); if($updateCache || (FALSE === $result)){ - if(isset($this->aSettings['currency'])){ + $lastTS = 0; + $lastDate = FALSE; + $skipGetHistory = FALSE; + if(FALSE !== $result){ + for($i = 0; $i < count($result); $i++){ + if($result[$i]['ts'] > $lastTS){ + $lastTS = $result[$i]['ts']; + $lastDate = $result[$i]['date']; + } + } + $prevDate = gmdate("Y-m-d", time() - (24 * 60 * 60)); + if($lastDate && ($lastDate === $prevDate)){ + $skipGetHistory = TRUE; + } + } + if(isset($this->aSettings['currency']) && !$skipGetHistory){ $method = 'getCurrencyHistory'; $params = array($address, 'USD'); - $result = $this->_jsonrpcall($this->aSettings['currency'], $method, $params); + if($lastTS) $params[] = $lastTS + 1; + $res = $this->_jsonrpcall($this->aSettings['currency'], $method, $params); + if(FALSE !== $result){ + $result = array_merge($result, $res); + }else{ + $result = $res; + } if($result){ $aToken = $this->getToken($address); $tokenStartAt = false; From a8fdc890d20ab0c2812ce0d583d0d7308fc5a6ba Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 30 Apr 2018 21:35:42 +0700 Subject: [PATCH 136/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index d64f5361..8286ff7b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2237,7 +2237,7 @@ public function getTokenPriceHistory($address, $period = 0, $type = 'hourly', $u if(isset($this->aSettings['currency']) && !$skipGetHistory){ $method = 'getCurrencyHistory'; $params = array($address, 'USD'); - if($lastTS) $params[] = $lastTS + 1; + if($lastTS) $params[] = $lastTS; $res = $this->_jsonrpcall($this->aSettings['currency'], $method, $params); if(FALSE !== $result){ $result = array_merge($result, $res); From ca8570f0e92f077ae732fa11656d67ada2800857 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 30 Apr 2018 21:47:17 +0700 Subject: [PATCH 137/658] Revert "Bug fixed." This reverts commit a8fdc890d20ab0c2812ce0d583d0d7308fc5a6ba. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 8286ff7b..d64f5361 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2237,7 +2237,7 @@ public function getTokenPriceHistory($address, $period = 0, $type = 'hourly', $u if(isset($this->aSettings['currency']) && !$skipGetHistory){ $method = 'getCurrencyHistory'; $params = array($address, 'USD'); - if($lastTS) $params[] = $lastTS; + if($lastTS) $params[] = $lastTS + 1; $res = $this->_jsonrpcall($this->aSettings['currency'], $method, $params); if(FALSE !== $result){ $result = array_merge($result, $res); From 5259426d0147bef96dc76ed2c36ebf8af5ea5283 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 1 May 2018 17:24:18 +0700 Subject: [PATCH 138/658] Common limits for non-free keys added. --- service/lib/ethplorer.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index d64f5361..58bcc63c 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1927,6 +1927,18 @@ public function getAPIKeyDefaults($key, $option = FALSE){ $res = $this->aSettings['apiKeys'][$key]; }else if(isset($this->aSettings['apiKeys'][$key][$option])){ $res = $this->aSettings['apiKeys'][$key][$option]; + + if($key != 'freekey' && isset($this->aSettings['personalLimits'])){ + foreach($this->aSettings['personalLimits'] as $cmd => $aLimits){ + if($cmd == $option){ + foreach($aLimits as $opt => $limit){ + if(!isset($res[$opt]) || ($res[$opt] < $limit)){ + $res[$opt] = $limit; + } + } + } + } + } } } } From aa5dd8f019f6d261edb0644c49c76e121f3c8b18 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 1 May 2018 18:31:16 +0700 Subject: [PATCH 139/658] Page size selection removed. --- js/ethplorer.js | 8 ++++---- service/service.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 5deac734..0eef58f4 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -36,13 +36,13 @@ Ethplorer = { BigNumber.config({ ERRORS: false }); Ethplorer.Nav.init(); Ethplorer.Storage.init(); - Ethplorer.pageSize = Ethplorer.Storage.get('pageSize', 10); + Ethplorer.pageSize = 10; // Ethplorer.Storage.get('pageSize', 10); if(Ethplorer.pageSize > 10){ Ethplorer.Nav.set('pageSize', Ethplorer.pageSize); } - if(Ethplorer.Nav.get('pageSize')){ + /*if(Ethplorer.Nav.get('pageSize')){ Ethplorer.pageSize = Ethplorer.Nav.get('pageSize'); - } + }*/ if(Ethplorer.Nav.get('filter')){ var filter = Ethplorer.Nav.get('filter'); if(filter){ @@ -1502,7 +1502,7 @@ Ethplorer = { } pager.append(page); } - container.append(pageSizeSelect); + //container.append(pageSizeSelect); container.append(pager); } }, diff --git a/service/service.php b/service/service.php index b0f6e022..dd40673c 100644 --- a/service/service.php +++ b/service/service.php @@ -56,7 +56,7 @@ if(2 === count($aPageParams)){ switch($aPageParams[0]){ case 'pageSize': - $pageSize = intval($aPageParams[1]); + //$pageSize = intval($aPageParams[1]); break; case 'transfers': case 'issuances': From 2083ed78fc134062694e08464be22f4f3d33a558 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 1 May 2018 18:56:53 +0700 Subject: [PATCH 140/658] Disable last page clicking. --- js/ethplorer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 0eef58f4..9d03ab49 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1465,6 +1465,7 @@ Ethplorer = { container.empty(); if(recordsCount){ + var maxPageClick = 200000; var pages = Math.ceil(recordsCount / Ethplorer.pageSize); var lastPage = true; for(var i=1; i<=pages; i++){ @@ -1475,7 +1476,7 @@ Ethplorer = { link.html(i); if(i === currentPage){ page.addClass('active'); - }else{ + }else if (i != pages || pages <= maxPageClick){ link.attr('href', '#'); link.click(function(_container, _page, _pageData){ return function(e){ @@ -1489,6 +1490,9 @@ Ethplorer = { }; }(container, i, pageData)); } + if(i == pages && pages > maxPageClick){ + page.addClass('disabled'); + } page.html(link); lastPage = true; }else if(lastPage){ From cfee0ffe2a372eb8a4cc48380e2f13d442774b12 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 2 May 2018 14:50:45 +0700 Subject: [PATCH 141/658] Check token value removed from transfers list because there're token transfers with zero value (Kick) --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 9d03ab49..1bd81c86 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1093,7 +1093,7 @@ Ethplorer = { for(var i=0; i Date: Wed, 2 May 2018 17:19:39 +0700 Subject: [PATCH 142/658] Query offset optimized. --- service/lib/ethplorer.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 58bcc63c..0ecb3c24 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -251,6 +251,12 @@ public function getOffset($section){ return (1 === $this->getPager($section)) ? FALSE : ($this->getPager($section) - 1) * $limit; } + public function getOffsetReverse($section, $total){ + $limit = $this->pageSize; + $numPages = ceil($total / $limit); + return (intval($numPages) === $this->getPager($section)) ? FALSE : ($total - ($this->getPager($section) * $this->pageSize)); + } + /** * Returns true if provided string is a valid ethereum address. * @@ -390,7 +396,6 @@ public function getAddressDetails($address, $limit = 50){ $result["balances"] = $aBalances; $showEth = FALSE; if((isset($_GET['showEth']) && $_GET['showEth']) || $this->showEth) $showEth = TRUE; - $result["transfers"] = $this->getAddressOperations($address, $limit, $this->getOffset('transfers'), array('transfer'), $showEth); $countOperations = $this->countOperations($address, TRUE, $showEth); $totalOperations = $this->filter ? $this->countOperations($address, FALSE, $showEth) : $countOperations; $result['pager']['transfers'] = array( @@ -398,6 +403,8 @@ public function getAddressDetails($address, $limit = 50){ 'records' => $countOperations, 'total' => $totalOperations, ); + $aOffsets = [$this->getOffset('transfers'), $this->getOffsetReverse('transfers', $countOperations)]; + $result["transfers"] = $this->getAddressOperations($address, $limit, $aOffsets, array('transfer'), $showEth); } if(!$refresh){ $result['balance'] = $this->getBalance($address); @@ -1220,7 +1227,7 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ * @return array */ public function getAddressOperations($address, $limit = 10, $offset = FALSE, array $aTypes = NULL, $showEth = FALSE){ - evxProfiler::checkpoint('getAddressOperations', 'START', 'address=' . $address . ', limit=' . $limit . ', offset=' . (int)$offset); + evxProfiler::checkpoint('getAddressOperations', 'START', 'address=' . $address . ', limit=' . $limit . ', offset=' . (is_array($offset) ? print_r($offset, TRUE) : (int)$offset)); $result = array(); $search = array('addresses' => $address); @@ -1250,12 +1257,19 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr ) ); } - + $reverseOffset = FALSE; + $skip = is_array($offset) ? $offset[0] : $offset; if(!$showEth){ $hint = 'addresses_1_isEth_1_timestamp_1'; - $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset, false, $hint); + $sortOrder = -1; + if(is_array($offset) && ($offset[0] > 100000) && ($offset[0] > $offset[1])){ + $reverseOffset = TRUE; + $sortOrder = 1; + $skip = $offset[1]; + } + $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => $sortOrder), $limit, $skip, false, $hint); }else{ - $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $offset); + $cursor = $this->oMongo->find('operations2', $search, array("timestamp" => -1), $limit, $skip); } foreach($cursor as $transfer){ @@ -1264,6 +1278,9 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr $result[] = $transfer; } } + if($reverseOffset){ + $result = array_reverse($result); + } evxProfiler::checkpoint('getAddressOperations', 'FINISH'); return $result; } From cc2fbf0babca91d4fc9fc630c2d087c335759a10 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 17:20:23 +0700 Subject: [PATCH 143/658] Revert "Disable last page clicking." This reverts commit 2083ed78fc134062694e08464be22f4f3d33a558. --- js/ethplorer.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 1bd81c86..c63f2143 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1465,7 +1465,6 @@ Ethplorer = { container.empty(); if(recordsCount){ - var maxPageClick = 200000; var pages = Math.ceil(recordsCount / Ethplorer.pageSize); var lastPage = true; for(var i=1; i<=pages; i++){ @@ -1476,7 +1475,7 @@ Ethplorer = { link.html(i); if(i === currentPage){ page.addClass('active'); - }else if (i != pages || pages <= maxPageClick){ + }else{ link.attr('href', '#'); link.click(function(_container, _page, _pageData){ return function(e){ @@ -1490,9 +1489,6 @@ Ethplorer = { }; }(container, i, pageData)); } - if(i == pages && pages > maxPageClick){ - page.addClass('disabled'); - } page.html(link); lastPage = true; }else if(lastPage){ From 15fd483987bd7407cad61f6b8dcee029914ced58 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 18:36:45 +0700 Subject: [PATCH 144/658] Query offset optimized. --- service/lib/ethplorer.php | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 0ecb3c24..b079ea4f 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -37,6 +37,8 @@ class Ethplorer { */ const ADDRESS_ETH = '0x0000000000000000000000000000000000000000'; + const MAX_OFFSET = 100000; + /** * Settings * @@ -334,10 +336,12 @@ public function getAddressDetails($address, $limit = 50){ if(!$refresh || ($type === $refresh)){ $page = $this->getPager($type); $offset = $this->getOffset($type); + $offsetReverse = FALSE; switch($type){ case 'transfers': $count = $this->getContractOperationCount('transfer', $address); $total = $this->filter ? $this->getContractOperationCount('transfer', $address, FALSE) : $count; + $offsetReverse = $this->getOffsetReverse('transfers', $count); $cmd = 'getContractTransfers'; break; case 'issuances': @@ -355,7 +359,7 @@ public function getAddressDetails($address, $limit = 50){ $offset = 0; $page = 1; } - $result[$type] = $this->{$cmd}($address, $limit, $offset);; + $result[$type] = $this->{$cmd}($address, $limit, (($offsetReverse === FALSE) ? $offset : array($offset, $offsetReverse))); $result['pager'][$type] = array( 'page' => $page, 'records' => $count, @@ -1262,7 +1266,7 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr if(!$showEth){ $hint = 'addresses_1_isEth_1_timestamp_1'; $sortOrder = -1; - if(is_array($offset) && ($offset[0] > 100000) && ($offset[0] > $offset[1])){ + if(is_array($offset) && ($offset[0] > self::MAX_OFFSET) && ($offset[0] > $offset[1])){ $reverseOffset = TRUE; $sortOrder = 1; $skip = $offset[1]; @@ -1997,7 +2001,7 @@ protected function getContractOperationCount($type, $address, $useFilter = TRUE) * @return array */ protected function getContractOperation($type, $address, $limit, $offset = FALSE){ - evxProfiler::checkpoint('getContractOperation', 'START', 'type=' . (is_array($type) ? json_encode($type) : $type) . ', address=' . $address . ', limit=' . $limit . ', offset=' . (int)$offset); + evxProfiler::checkpoint('getContractOperation', 'START', 'type=' . (is_array($type) ? json_encode($type) : $type) . ', address=' . $address . ', limit=' . $limit . ', offset=' . (is_array($offset) ? print_r($offset, TRUE) : (int)$offset)); $search = array("contract" => $address, 'type' => $type); if($this->filter){ $search['$or'] = array( @@ -2007,7 +2011,16 @@ protected function getContractOperation($type, $address, $limit, $offset = FALSE array('transactionHash' => array('$regex' => $this->filter)) ); } - $cursor = $this->oMongo->find('operations', $search, array("timestamp" => -1), $limit, $offset); + + $reverseOffset = FALSE; + $skip = is_array($offset) ? $offset[0] : $offset; + $sortOrder = -1; + if(is_array($offset) && ($offset[0] > self::MAX_OFFSET) && ($offset[0] > $offset[1])){ + $reverseOffset = TRUE; + $sortOrder = 1; + $skip = $offset[1]; + } + $cursor = $this->oMongo->find('operations', $search, array("timestamp" => $sortOrder), $limit, $skip); $result = array(); $fetches = 0; @@ -2016,6 +2029,9 @@ protected function getContractOperation($type, $address, $limit, $offset = FALSE $result[] = $transfer; $fetches++; } + if($reverseOffset){ + $result = array_reverse($result); + } evxProfiler::checkpoint('getContractOperation', 'FINISH'); return $result; } From d4fdf34cad2d9e83154b8eefd0f27f5947283978 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 20:25:13 +0700 Subject: [PATCH 145/658] Hide filter for big lists. --- js/ethplorer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index c63f2143..fdef0667 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1503,6 +1503,8 @@ Ethplorer = { pager.append(page); } //container.append(pageSizeSelect); + if(recordsCount > 100000) $('.filter-form').hide(); + else $('.filter-form').show(); container.append(pager); } }, From caa0c46de491aa959ec2a3b56c1656fbe510b3f2 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 20:29:05 +0700 Subject: [PATCH 146/658] Hide filter for big lists. --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index fdef0667..86d5dd64 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1503,10 +1503,10 @@ Ethplorer = { pager.append(page); } //container.append(pageSizeSelect); - if(recordsCount > 100000) $('.filter-form').hide(); - else $('.filter-form').show(); container.append(pager); } + if(recordsCount && recordsCount > 100000) $('.filter-form').hide(); + else $('.filter-form').show(); }, prepareToken: function(oToken){ if(!oToken){ From 02fcdc7e29191bf619e966157c12be71edfc0d0d Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 21:26:30 +0700 Subject: [PATCH 147/658] Reverted: Hide filter for big lists. --- js/ethplorer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 86d5dd64..c63f2143 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1505,8 +1505,6 @@ Ethplorer = { //container.append(pageSizeSelect); container.append(pager); } - if(recordsCount && recordsCount > 100000) $('.filter-form').hide(); - else $('.filter-form').show(); }, prepareToken: function(oToken){ if(!oToken){ From c2e1b4ce92501307fbce00f4ffd0ec26de0f240d Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 2 May 2018 22:07:30 +0700 Subject: [PATCH 148/658] Hide filter for big lists. --- js/ethplorer.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index c63f2143..b4c196ce 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -88,6 +88,7 @@ Ethplorer = { }); $(document).on('click', '[data-toggle="tab"]', function(){ Ethplorer.Nav.set('tab', $(this).parent().attr('id')); + if(Ethplorer.data) Ethplorer.showFilter(Ethplorer.data); }); $('.download').click(function(){ var date = new Date(); @@ -1005,6 +1006,17 @@ Ethplorer = { } Ethplorer.showAddressWidget(data); + Ethplorer.showFilter(data); + }, + showFilter: function(data){ + var activeTab = Ethplorer.getActiveTab(); + if(activeTab && data.pager && data.pager[activeTab]){ + if(data.pager[activeTab].records > 100000){ + $('.filter-form').hide(); + }else{ + $('.filter-form').show(); + } + } }, showAddressWidget: function(data){ //console.log('testWidget = ' + testWidget); From 7642bd01144461d32c9af649237a179276f96f97 Mon Sep 17 00:00:00 2001 From: Ilya S Date: Thu, 3 May 2018 14:32:32 +0700 Subject: [PATCH 149/658] rate-fix --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index b4c196ce..021930ee 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1146,7 +1146,7 @@ Ethplorer = { if(pf){ // Fill the tx.usdPrice if tx age less 10 minutes, because of delay price update scripts - if (!tx.usdPrice && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ + if (!tx.usdPrice && txToken.price && txToken.price.rate && ((new Date().getTime()/1000 - tx.timestamp ) / 60 < 10)){ tx.usdPrice = txToken.price.rate; } From dbd22120ec3cfc708cda86ad29bab68e4316f5b9 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 3 May 2018 15:30:47 +0700 Subject: [PATCH 150/658] google analytics related --- extensions/CryptoKitties/js/cryptokitties.js | 4 +--- js/ethplorer.js | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/extensions/CryptoKitties/js/cryptokitties.js b/extensions/CryptoKitties/js/cryptokitties.js index 9dfa7576..ffc39d69 100644 --- a/extensions/CryptoKitties/js/cryptokitties.js +++ b/extensions/CryptoKitties/js/cryptokitties.js @@ -8,9 +8,7 @@ Ethplorer.Extensions.CryptoKitties = { Ethplorer.Events.addHandler("ethp_showAddressDetails_finish", Ethplorer.Extensions.CryptoKitties.onAddressDetails); }, gaSendEvent: function(action){ - if(Ethplorer.Config.ga && ('undefined' !== typeof(ga))){ - ga('send', 'event', 'CryptoKitties', action); - } + Ethplorer.gaSendEvent('CryptoKitties', action); }, onAddressDetails: function(addrData){ if(!addrData.cryptokitties) return; diff --git a/js/ethplorer.js b/js/ethplorer.js index 021930ee..93cb5377 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -293,6 +293,7 @@ Ethplorer = { // Check TX hash format first txHash = txHash.toLowerCase(); if(!/^0x[0-9a-f]{64}$/i.test(txHash)){ + Ethplorer.gaSendEvent('TxState', 'tx-invalid-hash'); Ethplorer.error('Invalid transaction hash'); return; } @@ -395,6 +396,7 @@ Ethplorer = { var oTx = txData.tx; if(false === oTx){ + Ethplorer.gaSendEvent('TxState', 'tx-not-found'); Ethplorer.error('Transaction not found'); return; } @@ -684,6 +686,8 @@ Ethplorer = { $("table").find("tr:visible:odd").addClass("odd"); $("table").find("tr:visible:even").addClass("even"); $("table").find("tr:visible:last").addClass("last"); + + Ethplorer.gaSendEvent('TxState', 'tx-ok'); }, getAddressDetails: function(address){ // Check Address format first @@ -2282,6 +2286,11 @@ Ethplorer = { bool = bool === undefined; sessionStorage.setItem("enableHistoricalPrice", bool); location.reload(); + }, + gaSendEvent: function(category, action){ + if(Ethplorer.Config.ga && ('undefined' !== typeof(ga))){ + ga('send', 'event', category, action); + } } }; From af6d1515955e399a816b42d52186221b67f5770f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 16:34:49 +0700 Subject: [PATCH 151/658] Timestamp param added. --- api/controller.php | 19 +++++++++++++++---- service/lib/ethplorer.php | 16 +++++++++++++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/api/controller.php b/api/controller.php index 73326cc0..fa1d5f6c 100644 --- a/api/controller.php +++ b/api/controller.php @@ -348,8 +348,9 @@ public function getAddressTransactions(){ $maxLimit = is_array($this->defaults) && isset($this->defaults['limit']) ? $this->defaults['limit'] : 50; $limit = max(min(abs((int)$this->getRequest('limit', 10)), $maxLimit), 1); + $timestamp = $this->_getTimestampParam(); $showZeroValues = !!$this->getRequest('showZeroValues', FALSE); - $result = $this->db->getTransactions($address, $limit, $showZeroValues); + $result = $this->db->getTransactions($address, $limit, $timestamp, $showZeroValues); $this->sendResult($result); } @@ -629,13 +630,11 @@ protected function _getHistory($addressHistoryMode = FALSE){ $options = array( 'type' => $this->getRequest('type', FALSE), 'limit' => max(min(abs((int)$this->getRequest('limit', 10)), $maxLimit), 1), + 'timestamp' => $this->_getTimestampParam() ); if(FALSE !== $address){ $options['address'] = $address; } - if(FALSE !== $this->getRequest('timestamp', FALSE)){ - $options['timestamp'] = (int)$this->getRequest('timestamp'); - } if($addressHistoryMode){ $token = $this->getRequest('token', FALSE); if(FALSE !== $token){ @@ -674,6 +673,18 @@ protected function _getHistory($addressHistoryMode = FALSE){ return $result; } + protected function _getTimestampParam(){ + $timestamp = (int)$this->getRequest('timestamp', 0); + if($timestamp > 0){ + $maxPeriod = is_array($this->defaults) && isset($this->defaults['maxPeriod']) ? $this->defaults['maxPeriod'] : 2592000; + if((time() - $timestamp) > $maxPeriod){ + $this->sendError(108, 'Invalid timestamp'); + } + return $timestamp; + } + return 0; + } + /** * Converts JavaScript bignumber format to a float. * diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index b079ea4f..26ab506b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -490,8 +490,8 @@ public function getEtherTotalOut($address, $updateCache = FALSE){ * @param int $limit * @return array */ - public function getTransactions($address, $limit = 10, $showZero = FALSE){ - $cache = 'transactions-' . $address . '-' . $limit . '-' . ($showZero ? '1' : '0'); + public function getTransactions($address, $limit = 10, $timestamp = 0, $showZero = FALSE){ + $cache = 'transactions-' . $address . '-' . $limit . '-' . ($timestamp ? ($timestamp . '-') : '') . ($showZero ? '1' : '0'); $result = $this->oCache->get($cache, FALSE, TRUE, 15); if(!$result){ $result = array(); @@ -499,6 +499,9 @@ public function getTransactions($address, $limit = 10, $showZero = FALSE){ foreach($fields as $field){ $search = array(); $search[$field] = $address; + if($timestamp > 0){ + $search['timestamp'] = array('$lte' => $timestamp); + } if(!$showZero){ $search['value'] = array('$gt' => 0); } @@ -1208,7 +1211,7 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ $sort = array("timestamp" => -1); if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ - $search['timestamp'] = array('$gt' => $options['timestamp']); + $search['timestamp'] = array('$lte' => $options['timestamp']); } $limit = isset($options['limit']) ? (int)$options['limit'] : false; @@ -1962,6 +1965,13 @@ public function getAPIKeyDefaults($key, $option = FALSE){ } } } + if(in_array($option, array('getTokenHistory', 'getAddressHistory', 'getAddressTransactions')){ + if($key == 'freekey'){ + $res['maxPeriod'] = 30 * 24 * 3600; + }else{ + $res['maxPeriod'] = 365 * 24 * 3600; + } + } } return $res; } From beaa511e10645638086b70a92c62cb1b850e0a27 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 16:36:39 +0700 Subject: [PATCH 152/658] Error fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 26ab506b..c8060d70 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1965,7 +1965,7 @@ public function getAPIKeyDefaults($key, $option = FALSE){ } } } - if(in_array($option, array('getTokenHistory', 'getAddressHistory', 'getAddressTransactions')){ + if(in_array($option, array('getTokenHistory', 'getAddressHistory', 'getAddressTransactions'))){ if($key == 'freekey'){ $res['maxPeriod'] = 30 * 24 * 3600; }else{ From 090154721ff96d72faf138a58afb9f1c10d592c5 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 16:58:51 +0700 Subject: [PATCH 153/658] Moved limits to config. --- service/lib/ethplorer.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c8060d70..39e5a310 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1965,13 +1965,6 @@ public function getAPIKeyDefaults($key, $option = FALSE){ } } } - if(in_array($option, array('getTokenHistory', 'getAddressHistory', 'getAddressTransactions'))){ - if($key == 'freekey'){ - $res['maxPeriod'] = 30 * 24 * 3600; - }else{ - $res['maxPeriod'] = 365 * 24 * 3600; - } - } } return $res; } From f3f5ffedbb5999f4abb54e18a003d3a93a3e9b2d Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 17:06:17 +0700 Subject: [PATCH 154/658] Cache ttl increased. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 39e5a310..306a68e0 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -492,7 +492,7 @@ public function getEtherTotalOut($address, $updateCache = FALSE){ */ public function getTransactions($address, $limit = 10, $timestamp = 0, $showZero = FALSE){ $cache = 'transactions-' . $address . '-' . $limit . '-' . ($timestamp ? ($timestamp . '-') : '') . ($showZero ? '1' : '0'); - $result = $this->oCache->get($cache, FALSE, TRUE, 15); + $result = $this->oCache->get($cache, FALSE, TRUE, 30); if(!$result){ $result = array(); $fields = ['from', 'to']; From e50291d270c934702f783162fc8824880055a4e1 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 20:31:26 +0700 Subject: [PATCH 155/658] Bug fixed. --- service/lib/ethplorer.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 306a68e0..42378af7 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1949,8 +1949,10 @@ public function getAPIKeyDefaults($key, $option = FALSE){ if(is_array($this->aSettings['apiKeys'][$key])){ if(FALSE === $option){ $res = $this->aSettings['apiKeys'][$key]; - }else if(isset($this->aSettings['apiKeys'][$key][$option])){ - $res = $this->aSettings['apiKeys'][$key][$option]; + }else{ + if(isset($this->aSettings['apiKeys'][$key][$option])){ + $res = $this->aSettings['apiKeys'][$key][$option]; + } if($key != 'freekey' && isset($this->aSettings['personalLimits'])){ foreach($this->aSettings['personalLimits'] as $cmd => $aLimits){ From 689dce8f96562bc3af9232f6b1e7bb6e879de65b Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 3 May 2018 23:48:53 +0700 Subject: [PATCH 156/658] Param name changed. --- api/controller.php | 2 +- api/widget.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/controller.php b/api/controller.php index fa1d5f6c..caea3019 100644 --- a/api/controller.php +++ b/api/controller.php @@ -130,7 +130,7 @@ public function run(){ return $result; } - $timestamp = $this->getRequest('timestamp', FALSE); + $timestamp = $this->getRequest('ts', FALSE); $needCache = (FALSE !== $timestamp) || ($command === 'getAddressHistory'); if($needCache){ diff --git a/api/widget.js b/api/widget.js index eb3ae2b6..3521f4da 100644 --- a/api/widget.js +++ b/api/widget.js @@ -468,7 +468,7 @@ ethplorerWidget.Type['tokenHistory'] = function(element, options, templates){ this.refresh = function(obj){ return function(){ - $.getJSON(obj.api, obj.getRequestParams(obj.ts ? {timestamp: obj.ts} : false), obj.refreshWidget); + $.getJSON(obj.api, obj.getRequestParams(obj.ts ? {ts: obj.ts} : false), obj.refreshWidget); } }(this); @@ -486,7 +486,7 @@ ethplorerWidget.Type['tokenHistory'] = function(element, options, templates){ }; this.getRequestParams = function(additionalParams){ - var requestOptions = ['limit', 'address', 'timestamp', 'showEth']; + var requestOptions = ['limit', 'address', 'ts', 'showEth']; var params = { apiKey: 'ethplorer.widget', type: 'transfer' From 90c99e76f6f1f12bb05a5e5221bc55cb7dca146b Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 4 May 2018 18:37:02 +0700 Subject: [PATCH 157/658] Predis client support. --- service/lib/cache.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index bf256761..97c813e5 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -15,6 +15,8 @@ * limitations under the License. */ +require_once __DIR__ . '/../../vendor/autoload.php'; + /** * Cache class. */ @@ -114,12 +116,11 @@ public function __construct(array $aConfig, $driver = FALSE, $useLocks = FALSE){ $this->driver = 'file'; } }else if('redis' === $this->driver){ - if(class_exists('Redis')){ - $rc = new Redis(); - $rc->connect($aConfig['redis']['server'], $aConfig['redis']['port']); + try{ + $rc = new Predis\Client($aConfig['redis']['servers'], $aConfig['redis']['options']); $this->oDriver = $rc; - }else{ - die('Redis class not found'); + }catch(\Exception $e){ + die($e->getMessage()); } } } @@ -164,7 +165,7 @@ public function save($entryName, $data){ } $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ - $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), array('ex' => $ttl)); + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } @@ -219,7 +220,7 @@ public function addLock($entryName){ if('memcached' === $this->driver){ return $this->oDriver->add($entryName . '-lock', TRUE, evxCache::LOCK_TTL); }else if('redis' === $this->driver){ - return $this->oDriver->set($entryName . '-lock', 'true', array('nx', 'ex' => evxCache::LOCK_TTL)); + return $this->oDriver->set($entryName . '-lock', 'true', 'nx', 'ex', evxCache::LOCK_TTL); }else{ $lockFilename = $this->path . '/' . $entryName . "-lock.tmp"; @@ -238,7 +239,9 @@ public function addLock($entryName){ * @return boolean */ public function deleteLock($entryName){ - if('memcached' === $this->driver || 'redis' === $this->driver){ + if('redis' === $this->driver){ + return $this->oDriver->del($entryName . '-lock'); + }elseif('memcached' === $this->driver){ return $this->oDriver->delete($entryName . '-lock'); }else{ return @unlink($this->path . '/' . $entryName . '-lock.tmp'); From 1686ae09fd4447ae276e9b059ea4c8766282ec9d Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 4 May 2018 20:17:48 +0700 Subject: [PATCH 158/658] Switch to slave after set command added. --- service/lib/cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index 97c813e5..eb59d801 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -166,6 +166,7 @@ public function save($entryName, $data){ $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); + $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } From 558dc2da6b71914b78b5672f657172503b4b0870 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 4 May 2018 20:23:09 +0700 Subject: [PATCH 159/658] Revert "Switch to slave after set command added." This reverts commit 1686ae09fd4447ae276e9b059ea4c8766282ec9d. --- service/lib/cache.php | 1 - 1 file changed, 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index eb59d801..97c813e5 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -166,7 +166,6 @@ public function save($entryName, $data){ $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); - $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } From 73fabba92a141008f06cbf01d014840880a15e45 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 4 May 2018 21:04:36 +0700 Subject: [PATCH 160/658] key updated --- api/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/widget.js b/api/widget.js index eb3ae2b6..70756aa5 100644 --- a/api/widget.js +++ b/api/widget.js @@ -721,7 +721,7 @@ ethplorerWidget.Type['topTokens'] = function(element, options, templates){ this.getRequestParams = function(additionalParams){ var requestOptions = ['limit', 'period', 'criteria']; var params = { - apiKey: 'freekey' + apiKey: 'ethplorer.widget' }; if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; @@ -970,7 +970,7 @@ ethplorerWidget.Type['top'] = function(element, options, templates){ this.getRequestParams = function(additionalParams){ var requestOptions = ['limit', 'period', 'criteria']; var params = { - apiKey: 'freekey' + apiKey: 'ethplorer.widget' }; if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; @@ -1473,7 +1473,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat this.getRequestParams = function(additionalParams){ var requestOptions = ['period', 'address', 'type', 'theme', 'cap', 'full']; var params = { - apiKey: 'freekey' + apiKey: 'ethplorer.widget' }; if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; @@ -2016,7 +2016,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te this.getRequestParams = function(additionalParams){ var requestOptions = ['period', 'address', 'type', 'theme']; var params = { - apiKey: 'freekey' + apiKey: 'ethplorer.widget' }; if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; From afede122d81932b70d9deda338efb18405c724bd Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 4 May 2018 21:26:03 +0700 Subject: [PATCH 161/658] Add domain param. --- api/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 3521f4da..b35c6c87 100644 --- a/api/widget.js +++ b/api/widget.js @@ -972,7 +972,7 @@ ethplorerWidget.Type['top'] = function(element, options, templates){ var params = { apiKey: 'freekey' }; - if('undefined' === typeof(this.pathReported)){ + if(true || 'undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; } From ce48805ccd14ca3d1b7594f79e4a08a5151fce46 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 4 May 2018 22:00:48 +0700 Subject: [PATCH 162/658] Revert: Add domain param. --- api/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 0d548346..81e43468 100644 --- a/api/widget.js +++ b/api/widget.js @@ -972,7 +972,7 @@ ethplorerWidget.Type['top'] = function(element, options, templates){ var params = { apiKey: 'ethplorer.widget' }; - if(true || 'undefined' === typeof(this.pathReported)){ + if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; } From f257c6f001a91dbf438a280a8d2c5bad5fc8a402 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 7 May 2018 16:39:20 +0700 Subject: [PATCH 163/658] Switch to slave after set command added. --- service/lib/cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index 97c813e5..eb59d801 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -166,6 +166,7 @@ public function save($entryName, $data){ $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); + $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } From 3b0aa213a472583029f067c63160ecdfc8e7a048 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 7 May 2018 16:42:09 +0700 Subject: [PATCH 164/658] Sentry client added --- service/lib/ethplorer.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 42378af7..1da24cac 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -111,6 +111,15 @@ class Ethplorer { * @var array */ protected $aTokens = FALSE; + + /** + * Sentry client object + * composer require "sentry/sentry" + * + * @var Raven_Client + */ + protected $sentryClient; + /** * Constructor. * @@ -136,6 +145,10 @@ protected function __construct(array $aConfig){ evxMongoPools::init($this->aSettings['bundles']); $this->oMongoPools = evxMongoPools::getInstance(); } + if(isset($this->aSettings['sentry']) && class_exists('Raven_Client')){ + $this->sentryClient = new Raven_Client($this->aSettings['sentry']); + $this->sentryClient->install(); + } } public function __destruct(){ From 120350bd533d1cea9fb30db0c6ef22497de27d74 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 7 May 2018 17:08:37 +0700 Subject: [PATCH 165/658] Sentry initialization check --- service/lib/ethplorer.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1da24cac..48026132 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -134,6 +134,14 @@ protected function __construct(array $aConfig){ "logsDir" => dirname(__FILE__) . "/../log/", "locksDir" => dirname(__FILE__) . "/../lock/", ); + if(isset($this->aSettings['sentry']) && class_exists('Raven_Client')){ + try { + $this->sentryClient = new Raven_Client($this->aSettings['sentry']); + $this->sentryClient->install(); + }catch(\Exception $e){ + error_log("Sentry initialization failed: " . $e->getMessage()); + } + } $cacheDriver = isset($this->aSettings['cacheDriver']) ? $this->aSettings['cacheDriver'] : 'file'; $useLocks = isset($this->aSettings['useLocks']) ? $this->aSettings['useLocks'] : FALSE; $this->oCache = new evxCache($this->aSettings, $cacheDriver, $useLocks); @@ -145,10 +153,6 @@ protected function __construct(array $aConfig){ evxMongoPools::init($this->aSettings['bundles']); $this->oMongoPools = evxMongoPools::getInstance(); } - if(isset($this->aSettings['sentry']) && class_exists('Raven_Client')){ - $this->sentryClient = new Raven_Client($this->aSettings['sentry']); - $this->sentryClient->install(); - } } public function __destruct(){ From 3c0a0576836e3e67516e6c4db55d7f7fb8cbf4a8 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 7 May 2018 20:09:43 +0700 Subject: [PATCH 166/658] Logs added. --- bin/cache_prices.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 4a71ce7f..315e00c1 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -18,9 +18,15 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('prices.lock'); foreach($aConfig['updateRates'] as $address){ $es->getCache()->clearLocalCache(); $es->getTokenPrice($address, TRUE); } + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; From cd35d047c0bd5f4b00f39525c4d204e5cced8a7a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 7 May 2018 20:19:26 +0700 Subject: [PATCH 167/658] Logs added. --- bin/cache_eth_out.php | 6 ++++++ bin/cache_last_block.php | 6 ++++++ bin/cache_price_history.php | 6 ++++++ bin/cache_tokens.php | 8 +++++++- bin/cache_tokens_full_history.php | 6 ++++++ bin/cache_tokens_history.php | 6 ++++++ bin/cache_tokens_with_prices.php | 6 ++++++ 7 files changed, 43 insertions(+), 1 deletion(-) diff --git a/bin/cache_eth_out.php b/bin/cache_eth_out.php index c2b0ab45..d4e5b39d 100644 --- a/bin/cache_eth_out.php +++ b/bin/cache_eth_out.php @@ -18,7 +18,13 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('ethOut.lock'); $aHolders = $es->getAllHolders(); var_dump(count($aHolders)); + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_last_block.php b/bin/cache_last_block.php index d6519b4b..19b6e090 100644 --- a/bin/cache_last_block.php +++ b/bin/cache_last_block.php @@ -18,6 +18,12 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('lastBlock.lock'); $es->getLastBlock(true); + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_price_history.php b/bin/cache_price_history.php index 7988dc2a..6b9fe1b9 100644 --- a/bin/cache_price_history.php +++ b/bin/cache_price_history.php @@ -18,9 +18,15 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('priceHistory.lock'); foreach($aConfig['updateRates'] as $address){ $es->getCache()->clearLocalCache(); $es->getTokenPriceHistory($address, 0, 'hourly', TRUE); } + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 27c5545f..205cda94 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -20,9 +20,15 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.lock'); $es->getTokens(true); $es->getTopTokens(10, 90); -$es->getTopTokens(50, 90); \ No newline at end of file +$es->getTopTokens(50, 90); + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index b4fe4b99..ba63e543 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -18,8 +18,14 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.full.history.lock'); $es->getTokenFullHistoryGrouped(); $es->getTokenCapHistory(0, TRUE); + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_history.php b/bin/cache_tokens_history.php index 9aa539ca..1e7e514b 100644 --- a/bin/cache_tokens_history.php +++ b/bin/cache_tokens_history.php @@ -18,7 +18,13 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.history.lock'); $es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_with_prices.php b/bin/cache_tokens_with_prices.php index 4205e711..a2e4b670 100644 --- a/bin/cache_tokens_with_prices.php +++ b/bin/cache_tokens_with_prices.php @@ -17,6 +17,9 @@ define("MIN_TOKENS_NUM", 350); +$startTime = microtime(TRUE); +echo "[".date("Y-m-d H:i")."], Started."; + $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $jsonRequest = json_encode(array( @@ -58,3 +61,6 @@ var_dump($e); } } + +$ms = round(microtime(TRUE) - $startTime, 4); +echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; From cfa59703cfb6499d959701afd25cfe30c70c4aa9 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 7 May 2018 20:24:46 +0700 Subject: [PATCH 168/658] Logs added. --- bin/cache_eth_out.php | 4 ++-- bin/cache_last_block.php | 4 ++-- bin/cache_price_history.php | 4 ++-- bin/cache_prices.php | 4 ++-- bin/cache_tokens.php | 4 ++-- bin/cache_tokens_full_history.php | 4 ++-- bin/cache_tokens_history.php | 4 ++-- bin/cache_tokens_with_prices.php | 4 ++-- bin/cache_top.php | 5 +++++ 9 files changed, 21 insertions(+), 16 deletions(-) diff --git a/bin/cache_eth_out.php b/bin/cache_eth_out.php index d4e5b39d..9fb7905c 100644 --- a/bin/cache_eth_out.php +++ b/bin/cache_eth_out.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('ethOut.lock'); @@ -27,4 +27,4 @@ var_dump(count($aHolders)); $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_last_block.php b/bin/cache_last_block.php index 19b6e090..659f4e8d 100644 --- a/bin/cache_last_block.php +++ b/bin/cache_last_block.php @@ -19,11 +19,11 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('lastBlock.lock'); $es->getLastBlock(true); $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_price_history.php b/bin/cache_price_history.php index 6b9fe1b9..b76237b1 100644 --- a/bin/cache_price_history.php +++ b/bin/cache_price_history.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('priceHistory.lock'); @@ -29,4 +29,4 @@ } $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 315e00c1..875519bb 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('prices.lock'); @@ -29,4 +29,4 @@ } $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 205cda94..663d7314 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -21,7 +21,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.lock'); @@ -31,4 +31,4 @@ $es->getTopTokens(50, 90); $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index ba63e543..21f97763 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.full.history.lock'); @@ -28,4 +28,4 @@ $es->getTokenCapHistory(0, TRUE); $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_history.php b/bin/cache_tokens_history.php index 1e7e514b..43500b1b 100644 --- a/bin/cache_tokens_history.php +++ b/bin/cache_tokens_history.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.history.lock'); @@ -27,4 +27,4 @@ $es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_with_prices.php b/bin/cache_tokens_with_prices.php index a2e4b670..efa96948 100644 --- a/bin/cache_tokens_with_prices.php +++ b/bin/cache_tokens_with_prices.php @@ -18,7 +18,7 @@ define("MIN_TOKENS_NUM", 350); $startTime = microtime(TRUE); -echo "[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i")."], Started."; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; @@ -63,4 +63,4 @@ } $ms = round(microtime(TRUE) - $startTime, 4); -echo "[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_top.php b/bin/cache_top.php index 1feaeb30..aab82309 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -18,6 +18,9 @@ require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; +$startTime = microtime(TRUE); +echo "\n[".date("Y-m-d H:i")."], Started."; + $es = Ethplorer::db($aConfig); $es->createProcessLock('topTokens.lock'); $aCriteries = array('cap', 'trade', 'count'); @@ -44,3 +47,5 @@ @file_put_contents($historyFile, $json); } +$ms = round(microtime(TRUE) - $startTime, 4); +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; From 0461c70160cb0cc35b0cb761a6fe89b54eac94e0 Mon Sep 17 00:00:00 2001 From: Egor Vasilyev Date: Mon, 7 May 2018 18:30:39 +0300 Subject: [PATCH 169/658] Update version of phpunit --- tests/composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/composer.json b/tests/composer.json index 5c4253d4..a9e50a13 100644 --- a/tests/composer.json +++ b/tests/composer.json @@ -7,9 +7,9 @@ ], "require": { "php": ">=5.3.3", - "phpunit/phpunit": "3.7.*", + "phpunit/phpunit": "5.6.0", "EverexIO/phpunit-iterator": "dev-develop" }, "minimum-stability": "dev", "prefer-stable" : false -} \ No newline at end of file +} From 4a10c585f3fd7ac392a4df93c4cc27c64b8d5872 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 7 May 2018 23:46:27 +0700 Subject: [PATCH 170/658] Param for locks ttl aded. --- bin/cache_top.php | 2 +- service/lib/ethplorer.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/cache_top.php b/bin/cache_top.php index aab82309..5aa65b50 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -22,7 +22,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('topTokens.lock'); +$es->createProcessLock('topTokens.lock', 600); $aCriteries = array('cap', 'trade', 'count'); $aTotals = null; foreach($aCriteries as $criteria){ diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 48026132..ed851302 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -173,8 +173,8 @@ public function __destruct(){ * * @return evxProcessLock */ - public function createProcessLock($name){ - $this->oProcessLock = new evxProcessLock($this->aSettings['locksDir'] . $name, $this->aSettings['lockTTL'], TRUE); + public function createProcessLock($name, $lockTTL = 0){ + $this->oProcessLock = new evxProcessLock($this->aSettings['locksDir'] . $name, $lockTTL ? $lockTTL : $this->aSettings['lockTTL'], TRUE); return $this->oProcessLock; } From a87d9683773196e362ad7e53eaef54dcf8ca7667 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 8 May 2018 00:15:25 +0700 Subject: [PATCH 171/658] Logs added. --- bin/cache_prices.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 875519bb..9dc8858d 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -21,12 +21,19 @@ $startTime = microtime(TRUE); echo "\n[".date("Y-m-d H:i")."], Started."; +$numPrices = 0; +$maxTimeGetPrice = 0; + $es = Ethplorer::db($aConfig); $es->createProcessLock('prices.lock'); foreach($aConfig['updateRates'] as $address){ + $startGetPrice = microtime(TRUE); $es->getCache()->clearLocalCache(); $es->getTokenPrice($address, TRUE); + $numPrices++; + $timeGetPrice = round(microtime(TRUE) - $startGetPrice, 4); + if($timeGetPrice > $maxTimeGetPrice) $maxTimeGetPrice = $timeGetPrice; } $ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; +echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s. Total prices: " . $numPrices . " Max. time : " . $maxTimeGetPrice; From 385de9214a58d81a84078193b473425908fdb080 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 8 May 2018 15:20:31 +0700 Subject: [PATCH 172/658] Logs added. --- bin/cache_prices.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 9dc8858d..642835e8 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -19,7 +19,7 @@ $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; $startTime = microtime(TRUE); -echo "\n[".date("Y-m-d H:i")."], Started."; +echo "\n[".date("Y-m-d H:i:s")."], Started."; $numPrices = 0; $maxTimeGetPrice = 0; @@ -30,10 +30,12 @@ $startGetPrice = microtime(TRUE); $es->getCache()->clearLocalCache(); $es->getTokenPrice($address, TRUE); - $numPrices++; $timeGetPrice = round(microtime(TRUE) - $startGetPrice, 4); + echo "\n[".date("Y-m-d H:i:s")."], Get price for address: " . $address . " Time : " . $timeGetPrice; + + $numPrices++; if($timeGetPrice > $maxTimeGetPrice) $maxTimeGetPrice = $timeGetPrice; } $ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s. Total prices: " . $numPrices . " Max. time : " . $maxTimeGetPrice; +echo "\n[".date("Y-m-d H:i:s")."], Finished, {$ms} s. Total prices: " . $numPrices . " Max. time : " . $maxTimeGetPrice; From 363dbc5ccce24e07d92ea2cbc64954a2204e73c6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 8 May 2018 15:24:20 +0700 Subject: [PATCH 173/658] File lock ttl decreased. --- bin/cache_prices.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 642835e8..d25f5caa 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -25,7 +25,7 @@ $maxTimeGetPrice = 0; $es = Ethplorer::db($aConfig); -$es->createProcessLock('prices.lock'); +$es->createProcessLock('prices.lock', 600); foreach($aConfig['updateRates'] as $address){ $startGetPrice = microtime(TRUE); $es->getCache()->clearLocalCache(); From 5ad49273790e2a6da7dc3ec8cd003af568c3a0af Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 8 May 2018 15:51:41 +0700 Subject: [PATCH 174/658] lastBlock tests updated --- tests/apiTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index ab441fec..b0ce9779 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -559,7 +559,7 @@ public function provider() 'method' => 'getTokenHistory', 'GET_params' => ['apiKey' => apiTest::APIKey,], 'asserts' => [ - ['type' => 'checkLastBlock', 'fields' => ['operations'], 'time' => 30], + ['type' => 'checkLastBlock', 'fields' => ['operations'], 'time' => 90], ] ]], // request with "period" field @@ -677,7 +677,7 @@ public function provider() 'method' => 'getLastBlock', 'GET_params' => ['apiKey' => apiTest::APIKey], 'asserts' => [ - ['type' => 'timeCheck', 'fields' => ['time' => 30]] + ['type' => 'timeCheck', 'fields' => ['time' => 90]] ] ]], //Errors From 37bc4b0d59b59ec71c1b9cdd531ac861509ef4fe Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 8 May 2018 17:11:37 +0700 Subject: [PATCH 175/658] Bug fixed. --- service/lib/ethplorer.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ed851302..c1824f43 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1517,13 +1517,17 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa $aHistoryCount = $this->getTokenHistoryGrouped(2, $address, 'hourly', 3600); if(is_array($aHistoryCount)){ foreach($aHistoryCount as $aRecord){ - if(!is_object($aRecord['_id'])){ + $aRec = $aRecord['_id']; + if(is_object($aRecord['_id'])){ + $aRec = json_decode($aRecord['_id'], JSON_OBJECT_AS_ARRAY); + } + if(!is_array($aRec)){ continue; } $aPeriod = $aPeriods[0]; $aRecordDate = date("Y-m-d", $aRecord['ts']); - $inCurrentPeriod = ($aRecordDate > $aPeriod['currentPeriodStart']) || (($aRecordDate == $aPeriod['currentPeriodStart']) && ($aRecord['_id']->hour >= $curHour)); - $inPreviousPeriod = !$inCurrentPeriod && (($aRecordDate > $aPeriod['previousPeriodStart']) || (($aRecordDate == $aPeriod['previousPeriodStart']) && ($aRecord['_id']->hour >= $curHour))); + $inCurrentPeriod = ($aRecordDate > $aPeriod['currentPeriodStart']) || (($aRecordDate == $aPeriod['currentPeriodStart']) && ($aRec['hour'] >= $curHour)); + $inPreviousPeriod = !$inCurrentPeriod && (($aRecordDate > $aPeriod['previousPeriodStart']) || (($aRecordDate == $aPeriod['previousPeriodStart']) && ($aRec['hour'] >= $curHour))); if($inCurrentPeriod){ $aToken['txsCount-1d-current'] += $aRecord['cnt']; }else if($inPreviousPeriod){ From 135ba493a784d3f92c94fe738034ded1fcef1574 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 8 May 2018 17:15:58 +0700 Subject: [PATCH 176/658] Bug fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c1824f43..5a179421 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1519,7 +1519,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa foreach($aHistoryCount as $aRecord){ $aRec = $aRecord['_id']; if(is_object($aRecord['_id'])){ - $aRec = json_decode($aRecord['_id'], JSON_OBJECT_AS_ARRAY); + $aRec = json_decode(json_encode($aRecord['_id']), JSON_OBJECT_AS_ARRAY); } if(!is_array($aRec)){ continue; From 6a739905ddc107063161eac6dbc02029e498147e Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 8 May 2018 19:53:00 +0700 Subject: [PATCH 177/658] Sentry configuration updated --- service/lib/ethplorer.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ed851302..d3460789 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -134,10 +134,19 @@ protected function __construct(array $aConfig){ "logsDir" => dirname(__FILE__) . "/../log/", "locksDir" => dirname(__FILE__) . "/../lock/", ); - if(isset($this->aSettings['sentry']) && class_exists('Raven_Client')){ + if(isset($this->aSettings['sentry']) && is_array($this->aSettings['sentry']) && class_exists('Raven_Client')){ try { - $this->sentryClient = new Raven_Client($this->aSettings['sentry']); - $this->sentryClient->install(); + $aSentry = $this->aSettings['sentry']; + $url = isset($aSentry['url']) ? $aSentry['url'] : false; + $key = isset($aSentry['key']) ? $aSentry['key'] : false; + $secret = isset($aSentry['secret']) ? $aSentry['secret'] : false; + $id = isset($aSentry['id']) ? $aSentry['id'] : false; + if($url && $key && $secret && $id){ + $this->sentryClient = new Raven_Client("http://" . $key . ":" . $secret . "@" . $url . "/" . $id); + $this->sentryClient->install(); + }else{ + throw new \Exception("Invalid configuration: one of mandatory fields missing"); + } }catch(\Exception $e){ error_log("Sentry initialization failed: " . $e->getMessage()); } From 944b709b76d564b5a64c665aeabd74e8df769b08 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 8 May 2018 20:03:58 +0700 Subject: [PATCH 178/658] Sentry configuration updated --- service/lib/ethplorer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 076358f3..d4716b29 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -141,11 +141,11 @@ protected function __construct(array $aConfig){ $key = isset($aSentry['key']) ? $aSentry['key'] : false; $secret = isset($aSentry['secret']) ? $aSentry['secret'] : false; $id = isset($aSentry['id']) ? $aSentry['id'] : false; - if($url && $key && $secret && $id){ - $this->sentryClient = new Raven_Client("http://" . $key . ":" . $secret . "@" . $url . "/" . $id); + if($url && $key){ + $this->sentryClient = new Raven_Client("http://" . $key . ($secret ? (":" . $secret) : "") . "@" . $url . ($id ? ("/" . $id) : "")); $this->sentryClient->install(); }else{ - throw new \Exception("Invalid configuration: one of mandatory fields missing"); + throw new \Exception("Invalid configuration: one of mandatory field [" . ($url ? "key" : "url") . "] is missing"); } }catch(\Exception $e){ error_log("Sentry initialization failed: " . $e->getMessage()); From baf173aa936d7aa523368220e08b6a0645b49fd6 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 8 May 2018 20:25:11 +0700 Subject: [PATCH 179/658] Sentry client-side --- index.php | 19 +++++++++++++++++++ js/raven.min.js | 3 +++ 2 files changed, 22 insertions(+) create mode 100644 js/raven.min.js diff --git a/index.php b/index.php index 83682581..117dd08f 100644 --- a/index.php +++ b/index.php @@ -69,6 +69,15 @@ $hasNotes = isset($aConfig['adv']) && count($aConfig['adv']); +$sentryURL = false; +if(isset($aConfig['sentry']) && is_array($aConfig['sentry']) && class_exists('Raven_Client')){ + $url = isset($aSentry['url']) ? $aSentry['url'] : false; + $key = isset($aSentry['key']) ? $aSentry['key'] : false; + if($url && $key){ + $sentryURL = "http://" . $key . "@" . $url; + } +} + $csvExport = ''; if(is_array($rParts) && isset($rParts[2])){ $csvExport = ' Export...Export as CSV'; @@ -105,6 +114,7 @@ + @@ -735,6 +745,15 @@



    diff --git a/js/ethplorer.js b/js/ethplorer.js index 3f17e397..5a205d19 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1117,6 +1117,7 @@ Ethplorer = { getCode: true, address: address, period: 730, + withEth: Ethplorer.Storage.get('withEth', false), //options: {title: widgetTitle} } ); From d9475c59b7427ba2a07ad859861083400e0c4d36 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 25 Jun 2018 16:40:31 +0700 Subject: [PATCH 308/658] ether with gwei added --- index.php | 2 +- js/ethplorer.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 2f5aff4c..4c7956d1 100644 --- a/index.php +++ b/index.php @@ -448,7 +448,7 @@ Gas Price - + Tx Cost diff --git a/js/ethplorer.js b/js/ethplorer.js index e6351d33..3e2eea97 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1757,6 +1757,13 @@ Ethplorer = { value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH'; } break; + case 'ether-gwei': + if(value < 0){ + value = "N/A"; + }else{ + value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + (Ethplorer.Utils.formatNum(value, false) * 10**9) + ' Gwei)'; + } + break; case 'ether-full': if(value < 0){ value = "N/A"; From 2ba17bb722d2f79f6c52d509703b8ded7dd4056a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 17:35:39 +0700 Subject: [PATCH 309/658] Allow eth transfers in address widget. --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 28809c90..aff5cba7 100644 --- a/api/controller.php +++ b/api/controller.php @@ -507,7 +507,7 @@ public function getAddressPriceHistoryGrouped(){ $this->sendError(104, 'Invalid address format'); } } - $withEth = !!$this->getRequest('withEth', FALSE); + $withEth = $this->getRequest('withEth', FALSE); $result = array('history' => $this->db->getAddressPriceHistoryGrouped($address, FALSE, $withEth)); if(isset($result['history']['cache'])) $this->cacheState = $result['history']['cache']; else $this->cacheState = ''; From a8b02ffe37ee0a078ef9804a3e61355f92ad0bc0 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 18:00:39 +0700 Subject: [PATCH 310/658] Allow eth transfers in address widget. --- api/widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index aa796189..71a343d6 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2100,7 +2100,6 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, this.options = { period: 365, - withEth: false, type: 'area', theme: 'light', options: {}, From 16fad427f911210d55a35c549f5780255ead9a19 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 18:06:03 +0700 Subject: [PATCH 311/658] Allow eth transfers in address widget. --- api/controller.php | 2 +- index.php | 2 +- js/ethplorer.js | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/api/controller.php b/api/controller.php index aff5cba7..8ef99b8f 100644 --- a/api/controller.php +++ b/api/controller.php @@ -507,7 +507,7 @@ public function getAddressPriceHistoryGrouped(){ $this->sendError(104, 'Invalid address format'); } } - $withEth = $this->getRequest('withEth', FALSE); + $withEth = (isset($_GET["withEth"]) && $_GET["withEth"]) ? TRUE : FALSE; $result = array('history' => $this->db->getAddressPriceHistoryGrouped($address, FALSE, $withEth)); if(isset($result['history']['cache'])) $this->cacheState = $result['history']['cache']; else $this->cacheState = ''; diff --git a/index.php b/index.php index 3b6a20aa..c77f2ac3 100644 --- a/index.php +++ b/index.php @@ -158,7 +158,7 @@ method: "getPriceHistoryGrouped", options: { address: '', - withEth: '' + } } ]; diff --git a/js/ethplorer.js b/js/ethplorer.js index 5a205d19..a725ea66 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1109,17 +1109,18 @@ Ethplorer = { $('#widget-block').hide(); $('#token-price-history-grouped-widget').hide(); } - ethplorerWidget.init( - '#token-price-history-grouped-widget', - 'addressPriceHistoryGrouped', + var opt = { theme: 'dark', getCode: true, address: address, period: 730, - withEth: Ethplorer.Storage.get('withEth', false), - //options: {title: widgetTitle} - } + }; + if(Ethplorer.Storage.get('withEth', false)) opt['withEth'] = true; + ethplorerWidget.init( + '#token-price-history-grouped-widget', + 'addressPriceHistoryGrouped', + opt ); //ethplorerWidget.loadScript("https://www.google.com/jsapi", ethplorerWidget.loadGoogleControlCharts); ethplorerWidget.loadGoogleControlCharts(); From 754dd3a0348a811b04c6f687f17914a3657a524c Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 18:46:24 +0700 Subject: [PATCH 312/658] Show eth transfers. --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index a725ea66..05714477 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1143,7 +1143,7 @@ Ethplorer = { var tableId = data.token ? 'address-token-transfers' : 'address-transfers'; $('#' + tableId).find('.table').empty(); if(Ethplorer.showTx && !$('#showTxEth').length){ - var showTxChecks = ' ' + ' '; + var showTxChecks = ' ' + ' '; if(!data.token){ $('.filter-form').prepend('' + showTxChecks); From d824000d588767f1f6a3cc202053fef042372da6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 18:53:21 +0700 Subject: [PATCH 313/658] Show eth transfers. --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 05714477..4c84623f 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1143,12 +1143,12 @@ Ethplorer = { var tableId = data.token ? 'address-token-transfers' : 'address-transfers'; $('#' + tableId).find('.table').empty(); if(Ethplorer.showTx && !$('#showTxEth').length){ - var showTxChecks = ' ' + ' '; + var showTxChecks = ' ' + ' '; if(!data.token){ $('.filter-form').prepend('' + showTxChecks); }else{ - $('.filter-box').prepend('' + showTxChecks); + $('.filter-box').prepend('' + showTxChecks); } } if(!data.transfers || !data.transfers.length){ From e08197097537bae01bd6f0cb7f99ec86eda1e7f0 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 18:57:27 +0700 Subject: [PATCH 314/658] Show eth transfers. --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 4c84623f..1c850248 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1148,7 +1148,7 @@ Ethplorer = { if(!data.token){ $('.filter-form').prepend('' + showTxChecks); }else{ - $('.filter-box').prepend('' + showTxChecks); + $('.filter-box').prepend('' + showTxChecks); } } if(!data.transfers || !data.transfers.length){ From dfec91489ddb4367bef3f28c0544d22a7a69baaa Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 19:00:18 +0700 Subject: [PATCH 315/658] Show eth transfers. --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 1c850248..d3142c30 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1146,7 +1146,7 @@ Ethplorer = { var showTxChecks = ' ' + ' '; if(!data.token){ - $('.filter-form').prepend('' + showTxChecks); + $('.filter-form').prepend('' + showTxChecks); }else{ $('.filter-box').prepend('' + showTxChecks); } From ee0036774ed88ac773544618fdbbbb144ff9a760 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 25 Jun 2018 19:05:09 +0700 Subject: [PATCH 316/658] Show eth transfers. --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index d3142c30..31cbb73e 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1148,7 +1148,7 @@ Ethplorer = { if(!data.token){ $('.filter-form').prepend('' + showTxChecks); }else{ - $('.filter-box').prepend('' + showTxChecks); + $('.filter-box').prepend('' + showTxChecks); } } if(!data.transfers || !data.transfers.length){ From 0a8b8781609f2ed5633a8a69c90dfd94608b4372 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 25 Jun 2018 19:29:28 +0700 Subject: [PATCH 317/658] fixes --- js/ethplorer.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 3e2eea97..e02617bb 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -416,7 +416,9 @@ Ethplorer = { showTxDetails: function(txHash, txData){ // $('#ethplorer-path').html('

    Transaction hash: ' + txHash + '

    '); $('#ethplorer-path').show(); - if (txData.pending) { + if (txData.pending && txData.tx && txData.tx.blockNumber) { + $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Processing transation  

    ') + } else if (txData.pending) { $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Pending transation  

    ') } @@ -442,7 +444,10 @@ Ethplorer = { $('#txEthStatus')[oTx.success ? 'addClass' : 'removeClass']('text-success'); $('#txEthStatus').html(oTx.success ? 'Success' : 'Failed' + (oTx.failedReason ? (': ' + Ethplorer.getTxErrorReason(oTx.failedReason)) : '')); $('#tx-status').addClass(oTx.success ? 'green' : 'red'); - }else{ + } else if (oTx.blockNumber && txData.pending) { + $('#txEthStatus').removeClass('text-danger text-success'); + $('#txEthStatus').html('Processing'); + } else { $('#txEthStatus').removeClass('text-danger text-success'); $('#txEthStatus').html('Pending'); } From 1537d198c7bc8d86c2e257248211dfa85c119fa7 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 25 Jun 2018 20:05:35 +0700 Subject: [PATCH 318/658] refactoring --- service/lib/ethplorer.php | 66 ++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 015c12dc..2e24d458 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -688,31 +688,27 @@ public function getTransactionDetails($hash){ if (isset($transaction['to'])) { $token = $this->getToken($transaction['to']); - if ($token) { - $result['token'] = $token; - if (isset($transaction['input'])) { - preg_match('/^(?.{10})(?.{64})(?.{64})(?.*)?$/', $transaction['input'], $operation); - if (strtoupper($operation['code']) === '0XA9059CBB') { - $value = hexdec($operation['value']); - $result['operations'] = [ - [ - 'transactionHash' => $transaction['hash'], - 'blockNumber' => null, - 'contract' => $operation['from'], - 'value' => $value, - 'intValue' => (int)$value, - 'type' => 'Transfer', - 'isEth' => false, - 'priority' => 0, - 'from' => $transaction['from'], - 'to' => $transaction['to'], - 'addresses' => '', - 'success' => false, - 'pending' => true, - 'token' => $token - ] - ]; - } + if ($token && isset($transaction['input'])) { + $operation = $this->getTokenOperationData($transaction['input'], $token['decimals']); + if ($operation && strtoupper($operation['code']) === '0XA9059CBB') { + $result['operations'] = [ + [ + 'transactionHash' => $transaction['hash'], + 'blockNumber' => null, + 'contract' => $operation['from'], + 'value' => $operation['value'], + 'intValue' => (int)$operation['value'], + 'type' => 'Transfer', + 'isEth' => false, + 'priority' => 0, + 'from' => $transaction['from'], + 'to' => $transaction['to'], + 'addresses' => '', + 'success' => false, + 'pending' => true, + 'token' => $token + ] + ]; } } } @@ -795,6 +791,26 @@ public function getTransactionDetails($hash){ return $result; } + /** + * Return operation details + * @param String $input Transaction input raw data + * @param Int $division + * @return Array|null Operation data + */ + private function getTokenOperationData($input, $division = 18) { + preg_match('/^(?.{10})(?.{64})(?.{64})(?.*)?$/', $input, $operation); + if ($operation) { + $ten = Decimal::create(10); + $dec = Decimal::create($token['decimals']);; + $value = Decimal::create(hexdec($operation['value'])); + $operation['value'] = '' . $value->div($ten->pow($dec), 4); + + return $operation; + } + + return null; + } + /** * Returns a list of transactions currently in the queue of Parity * @param String $hash Transaction hash From 4fd6c74f08a169d564915dd8291d617b09ff202f Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 13:27:16 +0700 Subject: [PATCH 319/658] status of ETH transfer transaction --- js/ethplorer.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index e02617bb..e09d6c64 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -703,6 +703,32 @@ Ethplorer = { } Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); }else{ + if ( + (!txData.tx.operations || !txData.tx.operations.length) && + txData.tx.success && txData.tx.value > 0 + ) { + $('#token-operation-block').show(); + $('#token-operation-block .token-name:eq(0)').html('ETH'); + $('.token-operation-type').text('Transfer'); + txData.operation = { + from: txData.tx.from, + to: txData.tx.to, + success: txData.tx.success + } + Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); + if(oTx.blockNumber && !txData.pending){ + $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); + $('#txTokenStatus')[txData.operation.success ? 'addClass' : 'removeClass']('text-success'); + $('#txTokenStatus').html(txData.operation.success ? 'Success' : 'Failed'); + $('#operation-status').addClass(txData.operation.success ? 'green' : 'red'); + } else if (oTx.blockNumber && txData.pending) { + $('#operation-status').removeClass('text-danger text-success'); + $('#operation-status').html('Processing'); + } else { + $('#operation-status').removeClass('text-danger text-success'); + $('#operation-status').html('Pending'); + } + } $('#tx-details-block').show(); $('.tx-details-close').hide(); } From cb27c46b71134ca6ce3c0e2e42f0d286a42bb107 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 14:19:52 +0700 Subject: [PATCH 320/658] cookie agree button --- .gitignore | 6 ++++++ css/ethplorer.css | 10 +++++++++- index.php | 25 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c8c7cd6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +vendor +service/config.php +service/log +composer.lock +docker-compose.yaml +Dockerfile \ No newline at end of file diff --git a/css/ethplorer.css b/css/ethplorer.css index e0c64e77..90b02fdc 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -296,7 +296,7 @@ pre.list-field { padding-left: 36px; } -a { +a:not(.btn) { text-decoration: underline; } @@ -1547,4 +1547,12 @@ a.token-update { #page-create { min-height: 650px; +} + +#cookie-notification { + position: fixed; + width: 100%; + bottom: 0; + padding: 10px 0; + background: #eaeaea; } \ No newline at end of file diff --git a/index.php b/index.php index 2f5aff4c..cb4304ac 100644 --- a/index.php +++ b/index.php @@ -800,5 +800,30 @@ fbq('track', 'PageView'); } + + From c37d679ae6411858fd14c4c1c19f76d5a66ce190 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 14:24:54 +0700 Subject: [PATCH 321/658] fix --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index cb4304ac..0e370bc4 100644 --- a/index.php +++ b/index.php @@ -818,7 +818,7 @@ $('#cookie-notification').removeClass('hidden'); $('.agree-using-cookies').on('click', function() { var date = new Date(); - date.setFullYear(date.getFullYear + 2); // + 2 years + date.setFullYear(date.getFullYear() + 2); // + 2 years document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); $('#cookie-notification').addClass('hide'); return false; From c0831f4c7eda817482d6166a993379d378448198 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 14:42:11 +0700 Subject: [PATCH 322/658] improve --- css/ethplorer.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/css/ethplorer.css b/css/ethplorer.css index 90b02fdc..4253e592 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1555,4 +1555,9 @@ a.token-update { bottom: 0; padding: 10px 0; background: #eaeaea; +} + +#cookie-notification span { + padding-bottom: 7px; + display: inline-block; } \ No newline at end of file From 01c720f240ff8d1178ab1c54a873c38201237c2b Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 14:53:05 +0700 Subject: [PATCH 323/658] fix --- css/ethplorer.css | 1 + 1 file changed, 1 insertion(+) diff --git a/css/ethplorer.css b/css/ethplorer.css index 4253e592..8728a156 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1560,4 +1560,5 @@ a.token-update { #cookie-notification span { padding-bottom: 7px; display: inline-block; + margin-right: 10px; } \ No newline at end of file From f02dac5703ed912029a8316ceb4e0e37068a8ddd Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 15:25:41 +0700 Subject: [PATCH 324/658] gwei and eth transfer fixes --- js/ethplorer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index e09d6c64..d4215019 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -704,6 +704,7 @@ Ethplorer = { Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); }else{ if ( + (Ethplorer.Storage.get('showTx') == 'all' || Ethplorer.Storage.get('showTx') == 'eth') && (!txData.tx.operations || !txData.tx.operations.length) && txData.tx.success && txData.tx.value > 0 ) { @@ -1792,7 +1793,7 @@ Ethplorer = { if(value < 0){ value = "N/A"; }else{ - value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + (Ethplorer.Utils.formatNum(value, false) * 10**9) + ' Gwei)'; + value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + (Ethplorer.Utils.formatNum(value, true, 18, true) * 10**9) + ' Gwei)'; } break; case 'ether-full': From 1b0c452b21bdcbeadfeb79fd41ff4f6a4b99563a Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 26 Jun 2018 16:08:12 +0700 Subject: [PATCH 325/658] Cache bug fixed --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 5bf9fe31..ec4e99cf 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -959,9 +959,9 @@ public function getTokens($updateCache = false){ $aResult[$address]['symbol'] = htmlspecialchars($aResult[$address]['symbol']); } - $cursor = $this->oMongo->find('addressCache', array("address" => $address)); + $cursor2 = $this->oMongo->find('addressCache', array("address" => $address)); $aCachedData = false; - foreach($cursor as $aCachedData) break; + foreach($cursor2 as $aCachedData) break; if(false !== $aCachedData){ $aResult[$address]['txsCount'] = $aCachedData['txsCount']; if(isset($aCachedData['ethTransfersCount'])) $aResult[$address]['ethTransfersCount'] = $aCachedData['ethTransfersCount']; From 076e29906a05b580d324c2918fbfd5b23031fc3a Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 16:56:46 +0700 Subject: [PATCH 326/658] fixes --- index.php | 4 ++++ js/ethplorer.js | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 4c7956d1..cbbca576 100644 --- a/index.php +++ b/index.php @@ -329,6 +329,10 @@ Value + + Value + + Date diff --git a/js/ethplorer.js b/js/ethplorer.js index d4215019..93e76a82 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -714,9 +714,12 @@ Ethplorer = { txData.operation = { from: txData.tx.from, to: txData.tx.to, + valueEth: txData.tx.value, success: txData.tx.success } - Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); + + Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to', 'operation.valueEth']); + Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); if(oTx.blockNumber && !txData.pending){ $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); $('#txTokenStatus')[txData.operation.success ? 'addClass' : 'removeClass']('text-success'); @@ -1757,6 +1760,7 @@ Ethplorer = { } }, fillValue: function(id, value){ + console.log(id, value); var type = $('#' + id).attr('data-type') || 'none'; var options = $('#' + id).attr('data-options') ? $('#' + id).attr('data-options').split('|') : []; switch(type){ From f68317e1d9d1e2cb7722e94e2b9a024d9b536069 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 16:58:07 +0700 Subject: [PATCH 327/658] remove console.log --- js/ethplorer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 93e76a82..9fbd5971 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1760,7 +1760,6 @@ Ethplorer = { } }, fillValue: function(id, value){ - console.log(id, value); var type = $('#' + id).attr('data-type') || 'none'; var options = $('#' + id).attr('data-options') ? $('#' + id).attr('data-options').split('|') : []; switch(type){ From d080861da1f8d9e57edddf760896a3a973e057e5 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 17:17:47 +0700 Subject: [PATCH 328/658] fix --- service/lib/ethplorer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2e24d458..00c2d19e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -685,12 +685,12 @@ public function getTransactionDetails($hash){ // transaction is pending if has no blockHash $result['pending'] = true; $result['tx'] = $transaction ?: false; - if (isset($transaction['to'])) { $token = $this->getToken($transaction['to']); if ($token && isset($transaction['input'])) { $operation = $this->getTokenOperationData($transaction['input'], $token['decimals']); if ($operation && strtoupper($operation['code']) === '0XA9059CBB') { + $result['token'] = $token; $result['operations'] = [ [ 'transactionHash' => $transaction['hash'], @@ -794,14 +794,14 @@ public function getTransactionDetails($hash){ /** * Return operation details * @param String $input Transaction input raw data - * @param Int $division + * @param Int $decimals * @return Array|null Operation data */ - private function getTokenOperationData($input, $division = 18) { + private function getTokenOperationData($input, $decimals = 18) { preg_match('/^(?.{10})(?.{64})(?.{64})(?.*)?$/', $input, $operation); if ($operation) { $ten = Decimal::create(10); - $dec = Decimal::create($token['decimals']);; + $dec = Decimal::create($decimals); $value = Decimal::create(hexdec($operation['value'])); $operation['value'] = '' . $value->div($ten->pow($dec), 4); From 49c9bc8af33ac95c5efd7668ee61f73bcfdca58d Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 18:55:34 +0700 Subject: [PATCH 329/658] gwei fix --- js/ethplorer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 9fbd5971..4c89c26d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1796,7 +1796,8 @@ Ethplorer = { if(value < 0){ value = "N/A"; }else{ - value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + (Ethplorer.Utils.formatNum(value, true, 18, true) * 10**9) + ' Gwei)'; + var gwei = Ethplorer.Utils.toBig(value).mul(Math.pow(10, 9)).toString(); + value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + Ethplorer.Utils.formatNum(gwei, true, 3, true).toString().replace(/[0.]*$/, '', 'g') + ' Gwei)'; } break; case 'ether-full': From 55d4b016344a02380e9786ac7cb1e7e13c5c7ac0 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 19:01:22 +0700 Subject: [PATCH 330/658] small fixes --- js/ethplorer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 4c89c26d..79bb3c4a 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -704,7 +704,7 @@ Ethplorer = { Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); }else{ if ( - (Ethplorer.Storage.get('showTx') == 'all' || Ethplorer.Storage.get('showTx') == 'eth') && + (Ethplorer.Storage.get('showTx') === 'all' || Ethplorer.Storage.get('showTx') === 'eth') && (!txData.tx.operations || !txData.tx.operations.length) && txData.tx.success && txData.tx.value > 0 ) { @@ -727,10 +727,10 @@ Ethplorer = { $('#operation-status').addClass(txData.operation.success ? 'green' : 'red'); } else if (oTx.blockNumber && txData.pending) { $('#operation-status').removeClass('text-danger text-success'); - $('#operation-status').html('Processing'); + $('#txTokenStatus').html('Processing'); } else { $('#operation-status').removeClass('text-danger text-success'); - $('#operation-status').html('Pending'); + $('#txTokenStatus').html('Pending'); } } $('#tx-details-block').show(); From 9d6978f6ff7ca7b5c9f66e4eb6bfae2e2221c4f8 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 20:09:11 +0700 Subject: [PATCH 331/658] show price of ETH in value field --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index caecc94c..12d0be6b 100644 --- a/index.php +++ b/index.php @@ -345,7 +345,7 @@ Value - + Date From 84e6dab8e7384a5f8906ee347a677c77d136fe40 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 26 Jun 2018 21:06:30 +0700 Subject: [PATCH 332/658] only 2 decimals for price in usd --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 3bfb1728..0451c582 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1819,13 +1819,13 @@ Ethplorer = { }else{ var res = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH'; if(value){ - var price = Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * value, true, 4, true); + var price = Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * value, true, 2, true); if(true || ('0.00' != price)){ var change = Ethplorer.ethPrice.diff; var cls = change > 0 ? 'diff-up' : 'diff-down'; var diff = ""; // var diff = change ? (' (' + Ethplorer.Utils.round(change, 2) + '%)') : ''; - res = res + '
    $ ' + price + diff + ''; + res = res + '
    $ ' + price + diff + ''; } } value = res; From ef4541d8af9ff7842cff497be69cd75e548efc72 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 26 Jun 2018 21:19:02 +0700 Subject: [PATCH 333/658] ETH balance fix --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ec4e99cf..808970c2 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -794,7 +794,7 @@ public function getBalance($address){ $result = false; $cursor = $this->oMongo->find('ethBalances', array('address' => $address)); foreach($cursor as $result) break; - if($result && isset($result['balance'])){ + if($result && isset($result['balance']) && ((time() * 1000 - (int)$result['lastUpdated']) < 3600000 * 24)){ $balance = $result['balance']; }else{ $balance = $this->_callRPC('eth_getBalance', array($address, 'latest')); From 046284135d25779ba471157fc34e132f6ae2b71a Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 14:09:46 +0700 Subject: [PATCH 334/658] add history data for ethereum --- css/ethplorer.css | 1 + js/ethplorer.js | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 65b5271e..bd03df0c 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -637,6 +637,7 @@ a.dashed { } .tx-value-price { + font-weight: bold; font-size: 0.9em; color: white; opacity: 0.6; diff --git a/js/ethplorer.js b/js/ethplorer.js index 0451c582..7bc5317d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -716,11 +716,22 @@ Ethplorer = { from: txData.tx.from, to: txData.tx.to, valueEth: txData.tx.value, - success: txData.tx.success + success: txData.tx.success, + usdPrice: txData.tx.usdPrice } - Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to', 'operation.valueEth']); + Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); + + // Custom price value + if(txData.tx.value && txData.tx.usdPrice && Ethplorer.ethPrice.rate) { + value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; + value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); + } + $('#transfer-operation-value').html(value); + // Price of eth on transaction exceute + $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); + if(oTx.blockNumber && !txData.pending){ $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); $('#txTokenStatus')[txData.operation.success ? 'addClass' : 'removeClass']('text-success'); From 8539fa6b1b30ff34a3bf3c3aabebcbbc5a5145de Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 16:19:30 +0700 Subject: [PATCH 335/658] fix --- js/ethplorer.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 7bc5317d..77814c9d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -724,13 +724,14 @@ Ethplorer = { Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); // Custom price value + var value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH'; if(txData.tx.value && txData.tx.usdPrice && Ethplorer.ethPrice.rate) { - value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; + value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); + // Price of eth on transaction exceute + $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); } $('#transfer-operation-value').html(value); - // Price of eth on transaction exceute - $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); if(oTx.blockNumber && !txData.pending){ $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); From c9d11e9fd58c03d549a82f347aa13f683833d80d Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 16:22:08 +0700 Subject: [PATCH 336/658] fix --- js/ethplorer.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 77814c9d..d0a346b6 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -725,11 +725,13 @@ Ethplorer = { // Custom price value var value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH'; - if(txData.tx.value && txData.tx.usdPrice && Ethplorer.ethPrice.rate) { - value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; - value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); - // Price of eth on transaction exceute - $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); + if(txData.tx.value && Ethplorer.ethPrice.rate) { + value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; + if (txData.tx.usdPrice) { + value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); + // Price of eth on transaction exceute + $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); + } } $('#transfer-operation-value').html(value); From 638c90422cc40a716606d4799317d5cd69c437b8 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 16:26:16 +0700 Subject: [PATCH 337/658] fix styles --- css/ethplorer.css | 1 - js/ethplorer.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index bd03df0c..65b5271e 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -637,7 +637,6 @@ a.dashed { } .tx-value-price { - font-weight: bold; font-size: 0.9em; color: white; opacity: 0.6; diff --git a/js/ethplorer.js b/js/ethplorer.js index d0a346b6..277c2c56 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1839,7 +1839,7 @@ Ethplorer = { var cls = change > 0 ? 'diff-up' : 'diff-down'; var diff = ""; // var diff = change ? (' (' + Ethplorer.Utils.round(change, 2) + '%)') : ''; - res = res + '
    $ ' + price + diff + ''; + res = res + '
    $ ' + price + diff + ''; } } value = res; From 77c30cb6ebb46bd84dfec9abb87088546e241b5c Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 18:19:29 +0700 Subject: [PATCH 338/658] fixes decimals --- js/ethplorer.js | 2 +- service/lib/ethplorer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 277c2c56..253de540 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2069,7 +2069,7 @@ Ethplorer = { for(var i=1; i Date: Wed, 27 Jun 2018 18:22:12 +0700 Subject: [PATCH 339/658] checking blockNumber --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c5b8ae25..67ee9e70 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -761,7 +761,7 @@ public function getTransactionDetails($hash){ $result['tx']['confirmations'] = $confirmations; } else { // if transaction in pending status - $result['tx']['confirmations'] = $result['tx']['blockNumber'] !== null ? 1 : 0; + $result['tx']['confirmations'] = !empty($result['tx']['blockNumber']) ? 1 : 0; } // Temporary From e81f1664812d65d20c7d8d45e522218905bf3ece Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 19:23:11 +0700 Subject: [PATCH 340/658] fixes for pending refresh and ga --- js/ethplorer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 253de540..629b2236 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -328,7 +328,7 @@ Ethplorer = { location.reload(); } // is transaction is pending - if(data.pending && stopCheckingPendingAt < Date.now()){ + if(data.pending && stopCheckingPendingAt > Date.now()){ setTimeout(function() { loadTxDetails(false); }, 30000); // every 30 seconds @@ -433,7 +433,7 @@ Ethplorer = { Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-not-found'); Ethplorer.error( 'Transaction not found', - 'If transaction was created recently, it may not have reached mempool yet.
    Wait a minute and try to refresh the page.' + 'If transaction was created recently, it may not have reached mempool yet.
    Wait a minute and try to refresh the page.' ); return; } @@ -2069,7 +2069,7 @@ Ethplorer = { for(var i=1; i Date: Wed, 27 Jun 2018 19:30:43 +0700 Subject: [PATCH 341/658] fix z-index --- css/ethplorer.css | 1 + 1 file changed, 1 insertion(+) diff --git a/css/ethplorer.css b/css/ethplorer.css index f744d9fd..3e43d7f5 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1578,6 +1578,7 @@ a.token-update { #cookie-notification { position: fixed; + z-index: 1000; width: 100%; bottom: 0; padding: 10px 0; From eb70e75b0fd8e198ae93ecd9d66874d922133f77 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 27 Jun 2018 20:55:13 +0700 Subject: [PATCH 342/658] 403 error code --- api/controller.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/controller.php b/api/controller.php index 8ef99b8f..a11d9607 100644 --- a/api/controller.php +++ b/api/controller.php @@ -113,17 +113,20 @@ public function run(){ if($command && (in_array($command, $this->apiCommands) || in_array($command, $this->apiPostCommands)) && method_exists($this, $command)){ $key = in_array($command, $this->apiCommands) ? $this->getRequest('apiKey', FALSE) : $this->getPostRequest('apiKey', FALSE); if(!$key || !$this->db->checkAPIkey($key)){ + header('HTTP/1.1 403 Forbidden'); $this->sendError(1, 'Invalid API key'); } $this->defaults = $this->db->getAPIKeyDefaults($key, $command); if($this->db->isSuspendedAPIKey($key)){ + header('HTTP/1.1 403 Forbidden'); $this->sendError(133, 'API key temporary suspended. Contact support.'); } if(in_array($command, $this->apiPostCommands)){ // @todo: Temporary solution, special key property will be used later if($key == "freekey"){ + header('HTTP/1.1 403 Forbidden'); $this->sendError(1, 'Invalid API key'); } $result = call_user_func(array($this, $command)); From 0419261933c537cc3eccebb71acef5a3b8e598ba Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 21:02:37 +0700 Subject: [PATCH 343/658] balance to fixed --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 629b2236..e759a1a0 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1022,7 +1022,7 @@ Ethplorer = { if(balances[k].price){ var rate = oToken.price; var price = balances[k].balanceUSD; - value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true) + ' '); + value += ('
    $ ' + Ethplorer.Utils.toBig(price).toFixed(2) + ' '); if(rate.diff){ var cls = getDiffClass(rate.diff); var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); @@ -1055,7 +1055,7 @@ Ethplorer = { $('#address-token-balances table').append(row); } if(totalPrice){ - var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); + var value = '~ $ ' + Ethplorer.Utils.toBig(totalPrice).toFixed(2); if(totalDiff){ var cls = getDiffClass(totalDiff); if(totalDiff > 0){ From 3da1c6ab8a82b800f9487edb0db1a57e8cf158b7 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 27 Jun 2018 21:19:28 +0700 Subject: [PATCH 344/658] fix styles --- css/ethplorer.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/css/ethplorer.css b/css/ethplorer.css index 3e43d7f5..f4f1f877 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -665,6 +665,10 @@ a.dashed { #address-balances-total-inner { max-width: 250px; display: inline-block; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 1em; + overflow-x: hidden; } .total-supply-usd { From 2981c8a73b4a19d0a73b6a129497d87948d55a5e Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 27 Jun 2018 21:31:31 +0700 Subject: [PATCH 345/658] Disable eth transfers in address widget. --- service/lib/ethplorer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 67ee9e70..0ebfc67d 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2771,6 +2771,7 @@ public function getTokenPriceHistoryGrouped($address, $period = 365, $type = 'da } public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $withEth = FALSE){ + $withEth = FALSE; evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'START', 'address=' . $address . ', withEth=' . ($withEth ? 'TRUE' : 'FALSE')); $cache = 'address_operations_history-' . $address . ($withEth ? '-eth' : ''); From 718fb43b22dc6588c491316b1ebb634c6052c211 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 27 Jun 2018 23:12:20 +0700 Subject: [PATCH 346/658] Fix format --- js/ethplorer.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index e759a1a0..24f077c7 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1022,7 +1022,7 @@ Ethplorer = { if(balances[k].price){ var rate = oToken.price; var price = balances[k].balanceUSD; - value += ('
    $ ' + Ethplorer.Utils.toBig(price).toFixed(2) + ' '); + value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true, true) + ' '); if(rate.diff){ var cls = getDiffClass(rate.diff); var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); @@ -1055,7 +1055,7 @@ Ethplorer = { $('#address-token-balances table').append(row); } if(totalPrice){ - var value = '~ $ ' + Ethplorer.Utils.toBig(totalPrice).toFixed(2); + var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); if(totalDiff){ var cls = getDiffClass(totalDiff); if(totalDiff > 0){ @@ -2064,12 +2064,15 @@ Ethplorer = { return num.toString(); } if((num.toString().indexOf("e-") > 0) && withDecimals){ + return Ethplorer.Utils.toBig(num).toFixed(decimals); + /* var parts = num.toString().split("e-"); var res = parts[0].replace('.', ''); for(var i=1; i Date: Thu, 28 Jun 2018 13:54:57 +0700 Subject: [PATCH 347/658] change text of notification --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 6754baa2..ec525605 100644 --- a/index.php +++ b/index.php @@ -822,7 +822,7 @@
    - This website uses cookies to ensure you get the best experience on our website. + We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies. Find out more in Privacy Policy. Got it
    From 4bff805263ef3153dd45abe33a2abc367e6934e7 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 14:01:45 +0700 Subject: [PATCH 348/658] balance total css fixes --- css/ethplorer.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index f4f1f877..b57d8faf 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -668,7 +668,9 @@ a.dashed { white-space: nowrap; text-overflow: ellipsis; line-height: 1em; - overflow-x: hidden; + overflow: hidden; + position: relative; + top: 2px; } .total-supply-usd { From 9f9d9920e0a500814c52260e2c317ca2355490c9 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 28 Jun 2018 14:48:35 +0700 Subject: [PATCH 349/658] Allow eth transfers in address widget. --- api/controller.php | 2 +- api/widget.js | 2 +- index.php | 2 +- service/lib/ethplorer.php | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/api/controller.php b/api/controller.php index a11d9607..fee7a8fc 100644 --- a/api/controller.php +++ b/api/controller.php @@ -510,7 +510,7 @@ public function getAddressPriceHistoryGrouped(){ $this->sendError(104, 'Invalid address format'); } } - $withEth = (isset($_GET["withEth"]) && $_GET["withEth"]) ? TRUE : FALSE; + $withEth = (isset($_GET["withEth"]) && (bool)$_GET["withEth"]) ? TRUE : FALSE; $result = array('history' => $this->db->getAddressPriceHistoryGrouped($address, FALSE, $withEth)); if(isset($result['history']['cache'])) $this->cacheState = $result['history']['cache']; else $this->cacheState = ''; diff --git a/api/widget.js b/api/widget.js index 71a343d6..5258f238 100644 --- a/api/widget.js +++ b/api/widget.js @@ -161,7 +161,7 @@ ethplorerWidget = { apiKey: 'ethplorer.widget', domain: document.location.href, period: 730, - withEth: preloadMethod.options.withEth ? preloadMethod.options.withEth : false, + withEth: preloadMethod.options.withEth ? preloadMethod.options.withEth : '', }; $.getJSON(api, params, function(_address){ diff --git a/index.php b/index.php index 6754baa2..4659957a 100644 --- a/index.php +++ b/index.php @@ -68,7 +68,7 @@ } $withEth = false; -if(isset($_GET['withEth']) && $_GET['withEth']){ +if(isset($_GET['withEth']) && (bool)$_GET['withEth']){ $withEth = $_GET['withEth']; } diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 0ebfc67d..67ee9e70 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2771,7 +2771,6 @@ public function getTokenPriceHistoryGrouped($address, $period = 365, $type = 'da } public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $withEth = FALSE){ - $withEth = FALSE; evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'START', 'address=' . $address . ', withEth=' . ($withEth ? 'TRUE' : 'FALSE')); $cache = 'address_operations_history-' . $address . ($withEth ? '-eth' : ''); From 40d365cd3ab20e254b84fac39d53c693efb748a6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 28 Jun 2018 15:08:04 +0700 Subject: [PATCH 350/658] Allow eth transfers in address widget. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 4659957a..fcbe492f 100644 --- a/index.php +++ b/index.php @@ -68,7 +68,7 @@ } $withEth = false; -if(isset($_GET['withEth']) && (bool)$_GET['withEth']){ +if((isset($_GET['withEth']) && (bool)$_GET['withEth']) || (isset($_GET['witheth']) && (bool)$_GET['witheth'])){ $withEth = $_GET['withEth']; } From 7f9519710bfc537edfbe6baceba6aa3132fe75c0 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 28 Jun 2018 15:13:14 +0700 Subject: [PATCH 351/658] Allow eth transfers in address widget. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index fcbe492f..2a9e13fb 100644 --- a/index.php +++ b/index.php @@ -69,7 +69,7 @@ $withEth = false; if((isset($_GET['withEth']) && (bool)$_GET['withEth']) || (isset($_GET['witheth']) && (bool)$_GET['witheth'])){ - $withEth = $_GET['withEth']; + $withEth = true; } $hasNotes = isset($aConfig['adv']) && count($aConfig['adv']); From 1f849d3627595ba31270fdabedb86c83219464e0 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 16:09:33 +0700 Subject: [PATCH 352/658] cookie notification js --- css/cookie-notify.css | 123 ++++++++++++++++++++++++++++++++++++++++++ index.php | 26 +-------- js/cookie-notify.js | 25 +++++++++ 3 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 css/cookie-notify.css create mode 100644 js/cookie-notify.js diff --git a/css/cookie-notify.css b/css/cookie-notify.css new file mode 100644 index 00000000..d8fce801 --- /dev/null +++ b/css/cookie-notify.css @@ -0,0 +1,123 @@ +#cookie-notification { + font-family: 'Open Sans', sans-serif; + font-size: 13px; + position: fixed; + z-index: 1000; + width: 100%; + bottom: 0; + padding: 10px 0; + background: #eaeaea; +} + +#cookie-notification span span { + white-space: nowrap; +} + +#cookie-notification span:first-child { + padding-bottom: 7px; + display: inline-block; + margin-right: 10px; +} + +@media (min-width: 992px) { + #cookie-notification .cn-container { + width: 970px; + } +} + +@media (min-width: 768px) { + #cookie-notification .cn-container { + width: 750px; + } +} + +@media (min-width: 992px) { + #cookie-notification .cn-container { + width: 970px; + } +} + +@media (min-width: 1200px) { + #cookie-notification .cn-container { + width: 1170px; + } +} + +#cookie-notification .cn-container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +#cookie-notification .text-center { + text-align: center; +} + +#cookie-notification .cn-btn-group-lg > .cn-btn, #cookie-notification .cn-btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} + +#cookie-notification .cn-btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} + +#cookie-notification .cn-btn-primary:hover { + color: #fff; + background-color: #2c679b; + border-color: #2e6da4; +} + +#cookie-notification .cn-btn-block { + display: block; +} + +#cookie-notification .cn-btn { + display: inline-block; + text-decoration: none; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: 400; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} + +#cookie-notification .visible-xs-inline-block { + display: none !important; +} + +@media (max-width: 767px) { + #cookie-notification .hidden-xs { + display: none !important; + } + + #cookie-notification .visible-xs-inline-block { + display: inline-block !important; + } + + #cookie-notification .cn-btn-block { + display: block !important; + } +} + +#cookie-notification a:not(.cn-btn) { + color: #47C2FF !important; + display: inline-block; +} \ No newline at end of file diff --git a/index.php b/index.php index ec525605..671c37a7 100644 --- a/index.php +++ b/index.php @@ -818,30 +818,6 @@ fbq('track', 'PageView'); } - - + diff --git a/js/cookie-notify.js b/js/cookie-notify.js new file mode 100644 index 00000000..b7f0743a --- /dev/null +++ b/js/cookie-notify.js @@ -0,0 +1,25 @@ +$('head').append(''); +$(document).ready(function() { + var template = $(''); + + // checking cookie + var matches = document.cookie.match(new RegExp("(?:^|; )agree_to_use=([^;]*)")); + var agreeToUseCookie = matches && decodeURIComponent(matches[1]); + if (!agreeToUseCookie) { + $('body').append(template); + template.hide().fadeIn(300); + $('.agree-using-cookies').on('click', function() { + var date = new Date(); + date.setFullYear(date.getFullYear() + 2); // + 2 years + document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); + $('#cookie-notification').fadeOut(500); + return false; + }); + } +}); \ No newline at end of file From 181d1c966bd9316e6c339fd8177870a2d51cb782 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 19:11:41 +0700 Subject: [PATCH 353/658] hide panel fix --- js/cookie-notify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/cookie-notify.js b/js/cookie-notify.js index b7f0743a..5bfed6a7 100644 --- a/js/cookie-notify.js +++ b/js/cookie-notify.js @@ -18,7 +18,7 @@ $(document).ready(function() { var date = new Date(); date.setFullYear(date.getFullYear() + 2); // + 2 years document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); - $('#cookie-notification').fadeOut(500); + $('#cookie-notification').fadeOut(500).hide(); return false; }); } From ff0bc12fbaa08442d7574760aa815b85cc329573 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 19:17:34 +0700 Subject: [PATCH 354/658] remove fade effect --- js/cookie-notify.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/cookie-notify.js b/js/cookie-notify.js index 5bfed6a7..87c23707 100644 --- a/js/cookie-notify.js +++ b/js/cookie-notify.js @@ -13,12 +13,11 @@ $(document).ready(function() { var agreeToUseCookie = matches && decodeURIComponent(matches[1]); if (!agreeToUseCookie) { $('body').append(template); - template.hide().fadeIn(300); $('.agree-using-cookies').on('click', function() { var date = new Date(); date.setFullYear(date.getFullYear() + 2); // + 2 years document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); - $('#cookie-notification').fadeOut(500).hide(); + $('#cookie-notification').hide(); return false; }); } From 35e5e29986f3049f46a96acb2f5de17aa29adad5 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 19:20:16 +0700 Subject: [PATCH 355/658] add pause for css waiting --- js/cookie-notify.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/js/cookie-notify.js b/js/cookie-notify.js index 87c23707..358cfd96 100644 --- a/js/cookie-notify.js +++ b/js/cookie-notify.js @@ -12,13 +12,15 @@ $(document).ready(function() { var matches = document.cookie.match(new RegExp("(?:^|; )agree_to_use=([^;]*)")); var agreeToUseCookie = matches && decodeURIComponent(matches[1]); if (!agreeToUseCookie) { - $('body').append(template); - $('.agree-using-cookies').on('click', function() { - var date = new Date(); - date.setFullYear(date.getFullYear() + 2); // + 2 years - document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); - $('#cookie-notification').hide(); - return false; - }); + setTimeout(function() { + $('body').append(template); + $('.agree-using-cookies').on('click', function() { + var date = new Date(); + date.setFullYear(date.getFullYear() + 2); // + 2 years + document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); + $('#cookie-notification').hide(); + return false; + }); + }, 200); } }); \ No newline at end of file From 94177ccab55f80dac65c885ab65819dd70386c9d Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 20:42:38 +0700 Subject: [PATCH 356/658] typo fix --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 24f077c7..80267a54 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -418,9 +418,9 @@ Ethplorer = { // $('#ethplorer-path').html('

    Transaction hash: ' + txHash + '

    '); $('#ethplorer-path').show(); if (txData.pending && txData.tx && txData.tx.blockNumber) { - $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Processing transation  

    ') + $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Processing transaction  

    ') } else if (txData.pending) { - $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Pending transation  

    ') + $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Pending transaction  

    ') } $('.list-field').empty(); From 92fbde4f7cea66b9af8d3dfae6497cd089369eb3 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 28 Jun 2018 21:25:49 +0700 Subject: [PATCH 357/658] show details for ethereum transaction in pending status --- js/ethplorer.js | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 80267a54..efb590c8 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -707,7 +707,7 @@ Ethplorer = { if ( (Ethplorer.Storage.get('showTx') === 'all' || Ethplorer.Storage.get('showTx') === 'eth') && (!txData.tx.operations || !txData.tx.operations.length) && - txData.tx.success && txData.tx.value > 0 + txData.tx.value > 0 ) { $('#token-operation-block').show(); $('#token-operation-block .token-name:eq(0)').html('ETH'); @@ -719,21 +719,27 @@ Ethplorer = { success: txData.tx.success, usdPrice: txData.tx.usdPrice } - - Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); - Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); - // Custom price value + var operationFields = ['operation', 'operation.from', 'operation.to']; var value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH'; - if(txData.tx.value && Ethplorer.ethPrice.rate) { - value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; - if (txData.tx.usdPrice) { - value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); - // Price of eth on transaction exceute - $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); + if (txData.tx.success) { + // Custom price value + if(txData.tx.value && Ethplorer.ethPrice.rate) { + value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; + if (txData.tx.usdPrice) { + value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); + // Price of eth on transaction exceute + $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); + } } + $('#transfer-operation-value').html(value); + } else { + // if no history show with using fillValues + operationFields.push('operation.valueEth'); } - $('#transfer-operation-value').html(value); + + Ethplorer.fillValues('transfer', txData, operationFields); + Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); if(oTx.blockNumber && !txData.pending){ $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); @@ -1839,7 +1845,7 @@ Ethplorer = { var cls = change > 0 ? 'diff-up' : 'diff-down'; var diff = ""; // var diff = change ? (' (' + Ethplorer.Utils.round(change, 2) + '%)') : ''; - res = res + '
    $ ' + price + diff + ''; + res = res + '
    $ ' + price + diff + ''; } } value = res; From fd0f24932aacf064268de77ee863d893841276ef Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 28 Jun 2018 21:30:21 +0700 Subject: [PATCH 358/658] cutZeroes fix for formatNum and e- situation --- js/ethplorer.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index efb590c8..f9657c09 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2070,15 +2070,11 @@ Ethplorer = { return num.toString(); } if((num.toString().indexOf("e-") > 0) && withDecimals){ - return Ethplorer.Utils.toBig(num).toFixed(decimals); - /* - var parts = num.toString().split("e-"); - var res = parts[0].replace('.', ''); - for(var i=1; i Date: Fri, 29 Jun 2018 14:22:05 +0700 Subject: [PATCH 359/658] Csv downloading fixed. --- js/ethplorer.js | 4 ++++ service/csv.php | 2 ++ 2 files changed, 6 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index 24f077c7..02504e20 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1892,7 +1892,11 @@ Ethplorer = { console.log('Download data for ' + address); address = address.replace(/^\s+/, '').replace(/\s+$/, ''); if(address.length && Ethplorer.Utils.isAddress(address)){ + var showTx = Ethplorer.Storage.get('showTx', null); var data = {data: address, csv: true}; + if(showTx){ + data['showTx'] = showTx; + } $.get(Ethplorer.service, data, function(data, textStatus, jqXHR){ //console.log(data); Ethplorer.saveData(data, 'ethplorer.csv', 'text/csv'); diff --git a/service/csv.php b/service/csv.php index 0f00c15c..e2da3350 100644 --- a/service/csv.php +++ b/service/csv.php @@ -21,6 +21,8 @@ $data = isset($_GET["data"]) ? $_GET["data"] : false; $hash = isset($_GET["hash"]) ? $_GET["hash"] : false; +$showTx = isset($_GET["showTx"]) ? $_GET["showTx"] : false; +if($showTx) $es->setShowTx($showTx); // Allow cross-domain ajax requests // header('Access-Control-Allow-Origin: *'); From 161c0629c0ece475b469cea100f8d9063b2660ab Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:26:08 +0700 Subject: [PATCH 360/658] Csv downloading fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 67ee9e70..bbd5ab55 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1562,7 +1562,7 @@ public function getAddressOperations($address, $limit = 10, $offset = FALSE, arr public function getAddressOperationsCSV($address, $type = 'transfer'){ $limit = 1000; - $cache = 'address_operations_csv-' . $address . '-' . $limit; + $cache = 'address_operations_csv-' . $address . '-' . $limit . '-' . $this->showTx; $result = $this->oCache->get($cache, false, true, 600); if(FALSE === $result){ $cr = "\r\n"; From c4e591006b31744a76e3a18ddb87f6092b4d8955 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:32:06 +0700 Subject: [PATCH 361/658] Csv downloading fixed. --- js/ethplorer.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 01dda0ef..ca4a3f96 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -94,6 +94,11 @@ Ethplorer = { if(href.indexOf('&hash') == -1){ href += '&hash=' + md5($(this).attr("href") + hashDate); } + var showTx = Ethplorer.Storage.get('showTx', null); + if(showTx){ + href += '&showTx=' + showTx; + } + $(this).attr("href", href); /*$('.export-csv').hide(); $('.export-csv-spinner').show(); @@ -1898,11 +1903,7 @@ Ethplorer = { console.log('Download data for ' + address); address = address.replace(/^\s+/, '').replace(/\s+$/, ''); if(address.length && Ethplorer.Utils.isAddress(address)){ - var showTx = Ethplorer.Storage.get('showTx', null); var data = {data: address, csv: true}; - if(showTx){ - data['showTx'] = showTx; - } $.get(Ethplorer.service, data, function(data, textStatus, jqXHR){ //console.log(data); Ethplorer.saveData(data, 'ethplorer.csv', 'text/csv'); From f5b4a6b6cffe1cfe574f925125699064af845317 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:43:56 +0700 Subject: [PATCH 362/658] Csv downloading with eth transfers. --- service/lib/ethplorer.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index bbd5ab55..db98cdff 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1604,7 +1604,15 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $tokenName = ''; $tokenSymbol = ''; $contract = $record['contract']; - $token = isset($aTokenInfo[$contract]) ? $aTokenInfo[$contract] : $this->getToken($contract, TRUE); + if(isset($aTokenInfo[$contract])){ + $token = $aTokenInfo[$contract]; + }else{ + if($contract == self::ADDRESS_ETH){ + $token = $this->getEthToken(); + }else{ + $token = $this->getToken($contract, TRUE); + } + } if($token){ $tokenName = isset($token['name']) ? $token['name'] : ''; $tokenSymbol = isset($token['symbol']) ? $token['symbol'] : ''; From ff8a31c3f33fe8b1426aa68bae0d04dda5488417 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:48:12 +0700 Subject: [PATCH 363/658] Csv downloading with eth transfers. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index db98cdff..87f2f728 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1607,7 +1607,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ if(isset($aTokenInfo[$contract])){ $token = $aTokenInfo[$contract]; }else{ - if($contract == self::ADDRESS_ETH){ + if($contract == 'ETH'){ $token = $this->getEthToken(); }else{ $token = $this->getToken($contract, TRUE); From 4270d094990e978c78ce85c56ad32d707baa2636 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:50:20 +0700 Subject: [PATCH 364/658] Csv downloading with eth transfers. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 87f2f728..b1fc2788 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1607,7 +1607,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ if(isset($aTokenInfo[$contract])){ $token = $aTokenInfo[$contract]; }else{ - if($contract == 'ETH'){ + if($contract == 'ETH' || $contract = self::ADDRESS_ETH){ $token = $this->getEthToken(); }else{ $token = $this->getToken($contract, TRUE); From e957c6139c1437365251812849b00b15fb8081f6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 14:56:03 +0700 Subject: [PATCH 365/658] Csv downloading with eth transfers. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index b1fc2788..9ccfff26 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1600,7 +1600,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $from = isset($record['from']) ? $record['from'] : ''; $to = isset($record['to']) ? $record['to'] : ''; $tokenAddress = ''; - if($addTokenInfo && isset($record['contract'])){ + if(isset($record['contract'])){ $tokenName = ''; $tokenSymbol = ''; $contract = $record['contract']; From e1ad46c85882e5d22ce47a252f133774b65fdb62 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 15:02:30 +0700 Subject: [PATCH 366/658] Csv downloading with eth transfers. --- service/lib/ethplorer.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 9ccfff26..27d2e68e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1599,6 +1599,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $hash = $record['transactionHash']; $from = isset($record['from']) ? $record['from'] : ''; $to = isset($record['to']) ? $record['to'] : ''; + $dec = false; $tokenAddress = ''; if(isset($record['contract'])){ $tokenName = ''; @@ -1607,7 +1608,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ if(isset($aTokenInfo[$contract])){ $token = $aTokenInfo[$contract]; }else{ - if($contract == 'ETH' || $contract = self::ADDRESS_ETH){ + if($contract == 'ETH'){ $token = $this->getEthToken(); }else{ $token = $this->getToken($contract, TRUE); @@ -1617,7 +1618,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $tokenName = isset($token['name']) ? $token['name'] : ''; $tokenSymbol = isset($token['symbol']) ? $token['symbol'] : ''; $tokenAddress = isset($token['address']) ? $token['address'] : ''; - if(isset($token['decimals'])) $dec = Decimal::create($token['decimals']); + if(isset($token['decimals']) && ($contract != 'ETH')) $dec = Decimal::create($token['decimals']); if(!isset($aTokenInfo[$contract])) $aTokenInfo[$contract] = $token; } } From b97e53e44054e7e691acd1c9f07288dd423f00d3 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 15:31:17 +0700 Subject: [PATCH 367/658] Show eth transfers. --- js/ethplorer.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index ca4a3f96..2e738ea4 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -59,6 +59,14 @@ Ethplorer = { } } Ethplorer.showTx = Ethplorer.Storage.get('showTx', null); + var showTxHash = window.location.hash.substr(1); + if(showTxHash){ + aShowTxHash = showTxHash.split('='); + if(aShowTxHash.length > 1 && (aShowTxHash[0] == 'showTx') && (['all', 'eth', 'tokens'].indexOf(aShowTxHash[1]) >= 0)){ + Ethplorer.showTx = aShowTxHash[1]; + Ethplorer.Storage.set('showTx', aShowTxHash[1]); + } + } Ethplorer.route(); $('#network').text(Ethplorer.Config.testnet ? 'Test' : 'Modern'); $('.navbar-nav li[data-page]').click(function(){ From 8dce7a345b37994f122be6038a443315121e0030 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 15:32:13 +0700 Subject: [PATCH 368/658] Ver. increased. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index ec10ee16..98aa28d0 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "214"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "215"; $error = TRUE; $header = ""; From a3aa3f1249cb4a99fe8ebadc1d1439375432ceee Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 15:57:13 +0700 Subject: [PATCH 369/658] Csv downloading with usd prices. --- service/lib/ethplorer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 27d2e68e..d9af7331 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1599,6 +1599,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $hash = $record['transactionHash']; $from = isset($record['from']) ? $record['from'] : ''; $to = isset($record['to']) ? $record['to'] : ''; + $usdPrice = isset($record['usdPrice']) ? $record['usdPrice'] : ''; $dec = false; $tokenAddress = ''; if(isset($record['contract'])){ @@ -1627,7 +1628,8 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $value = Decimal::create($record['value']); $value = $value->div($ten->pow($dec), 4); } - $result .= $date . $spl . $hash . $spl . $from . $spl . $to . $spl . $tokenName . $spl . $tokenAddress . $spl . $value . $spl . $tokenSymbol . $cr; + $value = str_replace(".", ",", $value); + $result .= $date . $spl . $hash . $spl . $from . $spl . $to . $spl . $tokenName . $spl . $tokenAddress . $spl . $value . $spl . $usdPrice . $spl . $tokenSymbol . $cr; } $this->oCache->save($cache, $result); } From 6ecddb3157b1dd1b7da8f2ff5c3200a51269264b Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 16:00:11 +0700 Subject: [PATCH 370/658] Csv downloading with usd prices. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index d9af7331..b0581853 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1567,7 +1567,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ if(FALSE === $result){ $cr = "\r\n"; $spl = ";"; - $result = 'date;txhash;from;to;token-name;token-address;value;symbol' . $cr; + $result = 'date;txhash;from;to;token-name;token-address;value;usdPrice;symbol' . $cr; $options = array( 'address' => $address, From 5d77ee26fa56402ed75eeca40b63cf06f1517975 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 29 Jun 2018 16:01:36 +0700 Subject: [PATCH 371/658] Csv downloading with usd prices. --- service/lib/ethplorer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index b0581853..44caa284 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1629,6 +1629,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $value = $value->div($ten->pow($dec), 4); } $value = str_replace(".", ",", $value); + $usdPrice = str_replace(".", ",", $usdPrice); $result .= $date . $spl . $hash . $spl . $from . $spl . $to . $spl . $tokenName . $spl . $tokenAddress . $spl . $value . $spl . $usdPrice . $spl . $tokenSymbol . $cr; } $this->oCache->save($cache, $result); From 8545c124323d8fa6caf360a54fd195767b092c0f Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 29 Jun 2018 18:44:17 +0700 Subject: [PATCH 372/658] dot fix --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 2e738ea4..c91756d3 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2085,7 +2085,7 @@ Ethplorer = { if((num.toString().indexOf("e-") > 0) && withDecimals){ var res = Ethplorer.Utils.toBig(num).toFixed(decimals); if(cutZeroes){ - res = res.replace(/0*$/, ''); + res = res.replace(/0*$/, '').replace(/\.$/, ''); } return res; } From 70c60fb76c178e99af3e8338d1b771dea452857c Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 29 Jun 2018 18:46:29 +0700 Subject: [PATCH 373/658] another dot fix --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index c91756d3..9fff8cb5 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2085,7 +2085,7 @@ Ethplorer = { if((num.toString().indexOf("e-") > 0) && withDecimals){ var res = Ethplorer.Utils.toBig(num).toFixed(decimals); if(cutZeroes){ - res = res.replace(/0*$/, '').replace(/\.$/, ''); + res = res.replace(/0*$/, '').replace(/\.$/, '.00'); } return res; } From 677c37075e2708cddc6d6a527f1fe6fb5b8af04e Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 3 Jul 2018 23:18:40 +0700 Subject: [PATCH 374/658] fix refresh page when request fail --- js/ethplorer.js | 59 +++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 9fff8cb5..71cf8be2 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -322,36 +322,43 @@ Ethplorer = { } var stopCheckingPendingAt = Date.now() + 1800000; // after 30 minutes function loadTxDetails(showResult = true) { - $.getJSON(Ethplorer.service, requestData, function(_txHash){ - return function(data){ - if(data.debug){ - Ethplorer.requestDebug = data.debug; + $.getJSON(Ethplorer.service, requestData) + .done(function(_txHash){ + return function(data){ + if(data.debug){ + Ethplorer.requestDebug = data.debug; + } + if(data.ethPrice){ + Ethplorer.ethPrice = data.ethPrice; + } + if(showResult) { + // if transaction is pending need send ga event + if (data.pending) { + Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-pending'); + } + Ethplorer.showTxDetails(_txHash, data); + } else if (!data.pending) { + // Transaction not pending anymore. Reloading the view. + location.reload(); + } + // is transaction is pending + if(data.pending && stopCheckingPendingAt > Date.now()){ + setTimeout(function() { + loadTxDetails(false); + }, 30000); // every 30 seconds + } } if(data.ethPrice){ Ethplorer.ethPrice = data.ethPrice; } - if(showResult) { - // if transaction is pending need send ga event - if (data.pending) { - Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-pending'); - } - Ethplorer.showTxDetails(_txHash, data); - } else if (!data.pending) { - // Transaction not pending anymore. Reloading the view. - location.reload(); - } - // is transaction is pending - if(data.pending && stopCheckingPendingAt > Date.now()){ - setTimeout(function() { - loadTxDetails(false); - }, 30000); // every 30 seconds - } - } - if(data.ethPrice){ - Ethplorer.ethPrice = data.ethPrice; - } - Ethplorer.showTxDetails(_txHash, data); - }(txHash)); + Ethplorer.showTxDetails(_txHash, data); + }(txHash)) + .fail(function() { + // Try send request again after 30 seconds + setTimeout(function() { + loadTxDetails(false); + }, 30000); + }); } loadTxDetails(); }, From 32ead9e49710af25d3eb030121468ffa797b9666 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 4 Jul 2018 14:25:41 +0700 Subject: [PATCH 375/658] fix value for panding transactions --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 44caa284..42c9458a 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -795,7 +795,7 @@ private function getTokenOperationData($input, $decimals = 18) { $ten = Decimal::create(10); $dec = Decimal::create($decimals); $value = Decimal::create(hexdec($operation['value'])); - $operation['value'] = '' . $value->div($ten->pow($dec), 4); + $operation['value'] = (string)$value; return $operation; } From 2cebdb6fb158c578b168e2ecf8bad03eaad40880 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 4 Jul 2018 14:50:26 +0700 Subject: [PATCH 376/658] small fix + hide operation block for failed eth transations --- js/ethplorer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 71cf8be2..5952afcc 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -476,7 +476,7 @@ Ethplorer = { var titleAdd = ''; $('#tx-parsed').hide(); - if(oTx.input.length){ + if(oTx.input && oTx.input.length){ oTx.input = oTx.input.toUpperCase().replace(/^0x/i, ''); Ethplorer.dataFields['transaction-tx-input'] = { hex: oTx.input, @@ -727,7 +727,8 @@ Ethplorer = { if ( (Ethplorer.Storage.get('showTx') === 'all' || Ethplorer.Storage.get('showTx') === 'eth') && (!txData.tx.operations || !txData.tx.operations.length) && - txData.tx.value > 0 + txData.tx.value > 0 && + txData.tx.success !== false ) { $('#token-operation-block').show(); $('#token-operation-block .token-name:eq(0)').html('ETH'); From f70b9d2fbfd589ed896a8221d7300d5a8cceb355 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 17:40:57 +0700 Subject: [PATCH 377/658] Show eth transfers. --- js/ethplorer.js | 4 ++-- service/lib/ethplorer.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 5952afcc..0b567e4e 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -58,7 +58,7 @@ Ethplorer = { } } } - Ethplorer.showTx = Ethplorer.Storage.get('showTx', null); + Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); var showTxHash = window.location.hash.substr(1); if(showTxHash){ aShowTxHash = showTxHash.split('='); @@ -102,7 +102,7 @@ Ethplorer = { if(href.indexOf('&hash') == -1){ href += '&hash=' + md5($(this).attr("href") + hashDate); } - var showTx = Ethplorer.Storage.get('showTx', null); + var showTx = Ethplorer.Storage.get('showTx', 'all'); if(showTx){ href += '&showTx=' + showTx; } diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 42c9458a..66bea872 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -110,7 +110,7 @@ class Ethplorer { * * @var string */ - protected $showTx = self::SHOW_TX_TOKENS; + protected $showTx = self::SHOW_TX_ALL; /** * Cache for getTokens @@ -1249,7 +1249,7 @@ public function getContract($address, $calculateTransactions = TRUE){ * @param string $address Contract address * @return int */ - public function countOperations($address, $useFilter = TRUE, $showTx = self::SHOW_TX_TOKENS){ + public function countOperations($address, $useFilter = TRUE, $showTx = self::SHOW_TX_ALL){ evxProfiler::checkpoint('countOperations', 'START', 'address=' . $address . ', useFilter = ' . ($useFilter ? 'ON' : 'OFF')); $cache = 'countOperations-' . $address . '-' . $showTx; $result = $this->oCache->get($cache, false, true, 30); @@ -1492,7 +1492,7 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ * @param int $limit Maximum number of records * @return array */ - public function getAddressOperations($address, $limit = 10, $offset = FALSE, array $aTypes = NULL, $showTx = self::SHOW_TX_TOKENS){ + public function getAddressOperations($address, $limit = 10, $offset = FALSE, array $aTypes = NULL, $showTx = self::SHOW_TX_ALL){ evxProfiler::checkpoint('getAddressOperations', 'START', 'address=' . $address . ', limit=' . $limit . ', offset=' . (is_array($offset) ? print_r($offset, TRUE) : (int)$offset)); $result = array(); From a486fe30b95cb356e6435ffa7bb03f72c2068e72 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 17:47:31 +0700 Subject: [PATCH 378/658] Code version increased. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 98aa28d0..ee62a18c 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "215"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "216"; $error = TRUE; $header = ""; From dcc8c18b202a7364313d1719f6ef16884ba356cb Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 17:55:37 +0700 Subject: [PATCH 379/658] Hide incorrect balance out --- js/ethplorer.js | 4 +++- service/lib/ethplorer.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 0b567e4e..c57ade90 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -863,7 +863,9 @@ Ethplorer = { var aValues = ['address', 'balance']; if(data.balanceIn){ aValues.push('balanceIn'); - aValues.push('balanceOut'); + if('undefined' === typeof(data.hideBalanceOut)){ + aValues.push('balanceOut'); + } } Ethplorer.fillValues('address', data, aValues); $('#address-token-balances, #address-token-details').hide(); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 66bea872..1f251571 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -475,6 +475,7 @@ public function getAddressDetails($address, $limit = 50){ if($out < 0){ $in = $result['balance']; $out = 0; + $result['hideBalanceOut'] = true; } $result['balanceOut'] = $out; $result['balanceIn'] = $in; From 01bb09c224bef14bf9959357c094f2d5ecdc4f4c Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 19:45:25 +0700 Subject: [PATCH 380/658] Require path changed --- tests/serviceTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/serviceTest.php b/tests/serviceTest.php index aff63232..13717ca0 100644 --- a/tests/serviceTest.php +++ b/tests/serviceTest.php @@ -1,6 +1,6 @@ config = include('../service/config.php'); + $this->config = include(__DIR__ . '/../service/config.php'); $this->ethplorer = Ethplorer::db($this->config); } From c11310680030e28991ee1c9c099bf5daea73e3b2 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 20:26:20 +0700 Subject: [PATCH 381/658] Test commit --- tests/apiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index e232c84b..d67525a9 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -771,4 +771,4 @@ protected function getCommandLineParameter($param, $default){ } return $default; } -} \ No newline at end of file +} From bf320e42e6582debcbde238a3c96dda4674e2e76 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 20:42:19 +0700 Subject: [PATCH 382/658] Hide filter for big lists. --- js/ethplorer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 0b567e4e..82cf6779 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -58,6 +58,7 @@ Ethplorer = { } } } + Ethplorer.maxListSize = 0; Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); var showTxHash = window.location.hash.substr(1); if(showTxHash){ @@ -956,6 +957,7 @@ Ethplorer = { if(data.pager && data.pager.transfers){ data.token.transfersCount = data.pager.transfers.total; + if(data.token.transfersCount > Ethplorer.maxListSize) Ethplorer.maxListSize = data.token.transfersCount; } if(data.pager && data.pager.issuances){ data.token.issuancesCount = ''; @@ -969,6 +971,7 @@ Ethplorer = { if(data.contract && data.contract.txsCount && (data.contract.txsCount > data.token.txsCount)){ data.token.txsCount = data.contract.txsCount; + if(data.token.txsCount > Ethplorer.maxListSize) Ethplorer.maxListSize = data.token.txsCount; } var fields = [ @@ -1147,7 +1150,7 @@ Ethplorer = { showFilter: function(data){ var activeTab = Ethplorer.getActiveTab(); if(activeTab && data.pager && data.pager[activeTab]){ - if(data.pager[activeTab].records > 100000 || ((activeTab == 'transfers') && (data.token && data.token.txsCount && data.token.txsCount > 100000))){ + if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ $('#filter_list').hide(); }else{ if(Ethplorer.showTx && data.token){ @@ -1340,6 +1343,7 @@ Ethplorer = { if(data.pager && data.pager.transfers){ var pagination = $(''); Ethplorer.drawPager(pagination.find('td'), data.pager.transfers); + if(data.pager.transfers.total && (data.pager.transfers.total > Ethplorer.maxListSize)) Ethplorer.maxListSize = data.pager.transfers.total; $('#' + tableId + ' .table').append(pagination); } } From 7c0f5994def203f4be813010ac7151880a125c39 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 20:58:46 +0700 Subject: [PATCH 383/658] Don't show total supply usd amounts over 1e+12 --- js/ethplorer.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index c57ade90..4d1f760d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -380,7 +380,12 @@ Ethplorer = { var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + if(pf < 1e+12){ + pf = Ethplorer.Utils.formatNum(pf, true, 2, true); + }else{ + pf = "--"; + } + totalSupply = totalSupply + '
    $ ' + pf + ''; $('#transaction-token-totalSupply').html(totalSupply); } } @@ -575,7 +580,12 @@ Ethplorer = { var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + if(pf < 1e+12){ + pf = Ethplorer.Utils.formatNum(pf, true, 2, true); + }else{ + pf = "--"; + } + totalSupply = totalSupply + '
    $ ' + pf + ''; $('#transaction-token-totalSupply').html(totalSupply); } } From c45ad4c82aea101398a802f78bd72ef01b665160 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:10:51 +0700 Subject: [PATCH 384/658] Hide filter for big lists. --- js/ethplorer.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index 62928ad8..d0427c13 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -973,6 +973,8 @@ Ethplorer = { if(data.contract && data.contract.txsCount && (data.contract.txsCount > data.token.txsCount)){ data.token.txsCount = data.contract.txsCount; + } + if(data.token && data.token.txsCount){ if(data.token.txsCount > Ethplorer.maxListSize) Ethplorer.maxListSize = data.token.txsCount; } From a0b7c5f3a1233b393009845aa24fbbc7a4e63d48 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:28:18 +0700 Subject: [PATCH 385/658] Show eth transfers. --- index.php | 2 +- js/ethplorer.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index ee62a18c..5dda1873 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "216"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "217"; $error = TRUE; $header = ""; diff --git a/js/ethplorer.js b/js/ethplorer.js index b3a3e792..f9ce5193 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1163,6 +1163,11 @@ Ethplorer = { }, showFilter: function(data){ var activeTab = Ethplorer.getActiveTab(); + if(activeTab != 'transfers'){ + Ethplorer.showTx = false; + }else{ + Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); + } if(activeTab && data.pager && data.pager[activeTab]){ if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ $('#filter_list').hide(); From 748574e9b8cf1fb50140ae53dcdadeadb48881ee Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:31:32 +0700 Subject: [PATCH 386/658] Show eth transfers. --- js/ethplorer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index f9ce5193..15357bd2 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1163,12 +1163,12 @@ Ethplorer = { }, showFilter: function(data){ var activeTab = Ethplorer.getActiveTab(); - if(activeTab != 'transfers'){ - Ethplorer.showTx = false; - }else{ - Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); - } if(activeTab && data.pager && data.pager[activeTab]){ + if(activeTab != 'transfers'){ + Ethplorer.showTx = false; + }else{ + Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); + } if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ $('#filter_list').hide(); }else{ From aa6cfff9274fe042c28a1c767623d8ab063a4a31 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:35:40 +0700 Subject: [PATCH 387/658] Show eth transfers. --- js/ethplorer.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 15357bd2..cd5ea4ab 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -94,6 +94,14 @@ Ethplorer = { }); $(document).on('click', '[data-toggle="tab"]', function(){ Ethplorer.Nav.set('tab', $(this).parent().attr('id')); + var activeTab = Ethplorer.getActiveTab(); + if(activeTab){ + if(activeTab != 'transfers'){ + Ethplorer.showTx = false; + }else{ + Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); + } + } if(Ethplorer.data) Ethplorer.showFilter(Ethplorer.data); }); $('.download').click(function(){ @@ -1164,11 +1172,6 @@ Ethplorer = { showFilter: function(data){ var activeTab = Ethplorer.getActiveTab(); if(activeTab && data.pager && data.pager[activeTab]){ - if(activeTab != 'transfers'){ - Ethplorer.showTx = false; - }else{ - Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); - } if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ $('#filter_list').hide(); }else{ From 08e9823d937522fdffe77d587ace67e7f1b812d3 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:47:13 +0700 Subject: [PATCH 388/658] Show eth transfers. --- js/ethplorer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index cd5ea4ab..baafca14 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -97,9 +97,9 @@ Ethplorer = { var activeTab = Ethplorer.getActiveTab(); if(activeTab){ if(activeTab != 'transfers'){ - Ethplorer.showTx = false; + $('#showTxChecks').hide(); }else{ - Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); + $('#showTxChecks').show(); } } if(Ethplorer.data) Ethplorer.showFilter(Ethplorer.data); @@ -1262,7 +1262,7 @@ Ethplorer = { var tableId = data.token ? 'address-token-transfers' : 'address-transfers'; $('#' + tableId).find('.table').empty(); if(Ethplorer.showTx && !$('#showTxEth').length){ - var showTxChecks = ' ' + ' '; + var showTxChecks = ' ' + ' '; if(!data.token){ $('.filter-form').prepend('' + showTxChecks); From 4d94676b13c2772a1e05df4e31d0d960c63632b5 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 21:52:10 +0700 Subject: [PATCH 389/658] Show eth transfers. --- js/ethplorer.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index baafca14..8b76ac7b 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1172,6 +1172,11 @@ Ethplorer = { showFilter: function(data){ var activeTab = Ethplorer.getActiveTab(); if(activeTab && data.pager && data.pager[activeTab]){ + if(activeTab != 'transfers'){ + $('#showTxChecks').hide(); + }else{ + $('#showTxChecks').show(); + } if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ $('#filter_list').hide(); }else{ From f48ea78aed6b4705dad9ede6975dd1c3a1539aaf Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 9 Jul 2018 22:38:22 +0700 Subject: [PATCH 390/658] Widgets customizations. --- api/widget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/widget.js b/api/widget.js index 5258f238..1dcd9ca0 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1406,7 +1406,7 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat title: 'Token operations', format: '#,### K', viewWindow: { - max: 1000 + max: 1250 }, }, 1: { @@ -1714,7 +1714,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te rangeStart = new Date(strFirstDate); var date = stDate.getDate(); fnDate.setDate(date - this.options.period + 1); - rangeStart.setDate(date - (this.options.period > 60 ? 60 : this.options.period) + 1); + rangeStart.setDate(date - (this.options.period > 90 ? 90 : this.options.period) + 1); // prepare data var aCountData = {}; @@ -1750,7 +1750,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te if(!priceNotFound){ noPrice = false; aData.push(['Day', 'Low', 'Open', 'Close', 'High', {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Token operations', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Volume', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - if(this.options.period > 60){ + if(this.options.period > 90){ fnDate = startPriceDate; } } From b519081f303bcd6225da7f5a1d4dcc4a0c869455 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 23:01:47 +0700 Subject: [PATCH 391/658] Cut zero bug fixed --- js/ethplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index b3813d35..28c0aa51 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2108,7 +2108,7 @@ Ethplorer = { } if((num.toString().indexOf("e-") > 0) && withDecimals){ var res = Ethplorer.Utils.toBig(num).toFixed(decimals); - if(cutZeroes){ + if(cutZeroes && (res.indexOf(".") > 0)){ res = res.replace(/0*$/, '').replace(/\.$/, '.00'); } return res; From 1b0b37d0157f81355d1c902608542f1936a56207 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 9 Jul 2018 23:13:06 +0700 Subject: [PATCH 392/658] Gwei output fixed --- js/ethplorer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 6ad6ef40..edb43c3d 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1882,7 +1882,11 @@ Ethplorer = { value = "N/A"; }else{ var gwei = Ethplorer.Utils.toBig(value).mul(Math.pow(10, 9)).toString(); - value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + Ethplorer.Utils.formatNum(gwei, true, 3, true).toString().replace(/[0.]*$/, '', 'g') + ' Gwei)'; + gwei = Ethplorer.Utils.formatNum(gwei, true, 3, true).toString(); + if(gwei.toString().indexOf(".") > 0){ + gwei = gwei.replace(/0*$/, '', 'g').replace(/\.$/, '', 'g'); + } + value = Ethplorer.Utils.formatNum(value, true, 18, true) + '  ETH (' + gwei + ' Gwei)'; } break; case 'ether-full': From ebef9222606781104dcce8ae357446d11c07c36b Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 10 Jul 2018 17:36:42 +0700 Subject: [PATCH 393/658] Default period for pool txs/ops decreased. --- api/controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/controller.php b/api/controller.php index fee7a8fc..86fb6848 100644 --- a/api/controller.php +++ b/api/controller.php @@ -597,7 +597,7 @@ public function getPoolAddresses(){ public function getPoolLastTransactions(){ $result = array(); $poolId = $this->getRequest('poolId', FALSE); - $period = max(min(abs((int)$this->getRequest('period', 86400)), 864000), 1); + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); if($poolId){ $result = $this->db->getPoolLastTransactions($poolId, $period); } @@ -613,7 +613,7 @@ public function getPoolLastTransactions(){ public function getPoolLastOperations(){ $result = array(); $poolId = $this->getRequest('poolId', FALSE); - $period = max(min(abs((int)$this->getRequest('period', 86400)), 864000), 1); + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); if($poolId){ $result = $this->db->getPoolLastOperations($poolId, $period); } From 34333947532b2bbf15cffef73947a02ff0f39784 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 11 Jul 2018 16:22:03 +0700 Subject: [PATCH 394/658] Memory limit increased. --- bin/cache_top.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/cache_top.php b/bin/cache_top.php index 5aa65b50..d5f65a85 100644 --- a/bin/cache_top.php +++ b/bin/cache_top.php @@ -15,6 +15,8 @@ * limitations under the License. */ +ini_set('memory_limit', '512M'); + require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; From c15d4dc7c1ac35718328334cffdd978831c3712f Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 11 Jul 2018 22:26:20 +0700 Subject: [PATCH 395/658] parseInt -> parseFloat --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index edb43c3d..5df7c9e1 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1747,9 +1747,9 @@ Ethplorer = { oToken[property] = Ethplorer.Config.tokens[oToken.address][property]; } } + oToken.decimals = parseFloat(Ethplorer.Utils.toBig(oToken.decimals).toString()); oToken.totalSupply = Ethplorer.Utils.toBig(oToken.totalSupply); if(oToken.decimals){ - oToken.decimals = parseInt(Ethplorer.Utils.toBig(oToken.decimals).toString()); // To handle ether-like tokens with 18 decimals if(oToken.decimals > 20){ // Too many decimals, must be invalid value, use 0 instead oToken.decimals = 0; @@ -1763,7 +1763,7 @@ Ethplorer = { oToken.totalIn = oToken.totalIn / k; oToken.totalOut = oToken.totalOut / k; } - if(parseInt(oToken.totalSupply.toString()) >= 1e+18){ + if(parseFloat(oToken.totalSupply.toString()) >= 1e+18){ if(!oToken.decimals){ oToken.estimatedDecimals = true; oToken.decimals = 18; From 32019687c190e1ce233b4c00cb44e347103837de Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Jul 2018 17:30:22 +0700 Subject: [PATCH 396/658] Use round only if realy needed --- js/ethplorer.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 5df7c9e1..a6142565 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2132,11 +2132,14 @@ Ethplorer = { } return res; } - + var parts = num.toString().split('.'); if(withDecimals){ - num = math('round', num, decimals); + if(parts.length > 1){ + if(parts[1].length > decimals){ + num = math('round', num, decimals); + } + } } - var parts = num.toString().split('.'); var res = parts[0].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); var zeroCount = cutZeroes ? 2 : decimals; if(withDecimals && decimals){ From 87df5c304e7e2f85e4da27d27a18c39ec0363c51 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Jul 2018 17:45:45 +0700 Subject: [PATCH 397/658] round improved --- js/ethplorer.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index a6142565..d5f6a94c 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2095,10 +2095,6 @@ Ethplorer = { if(!num){ num = 0; } - function math(command, val, decimals){ - var k = Math.pow(10, decimals ? parseInt(decimals) : 0); - return Math[command](val * k) / k; - } function padZero(s, len){ while(s.length < len) s += '0'; return s; @@ -2132,13 +2128,8 @@ Ethplorer = { } return res; } - var parts = num.toString().split('.'); if(withDecimals){ - if(parts.length > 1){ - if(parts[1].length > decimals){ - num = math('round', num, decimals); - } - } + num = Ethplorer.Utils.round(num, decimals); } var res = parts[0].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); var zeroCount = cutZeroes ? 2 : decimals; @@ -2181,10 +2172,6 @@ Ethplorer = { postfix = ' M'; } } - function math(command, val, decimals){ - var k = Math.pow(10, decimals ? parseInt(decimals) : 0); - return Math[command](val * k) / k; - } function padZero(s, len){ while(s.length < len) s += '0'; return s; @@ -2210,7 +2197,7 @@ Ethplorer = { } if(withDecimals){ - num = math('round', num, decimals); + num = Ethplorer.Utils.round(num, decimals); } var parts = num.toString().split('.'); var res = parts[0].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); @@ -2391,9 +2378,14 @@ Ethplorer = { }, round: function(val, decimals){ decimals = decimals ? parseInt(decimals) : 0; - var k = decimals ? Math.pow(10, decimals) : 1; - - return Math.round(val * k) / k; + var parts = val.toString().split('.'); + if(parts.length > 1){ + if(parts[1].length > decimals){ + var k = decimals ? Math.pow(10, decimals) : 1; + return Math.round(val * k) / k; + } + } + return val; }, floor: function(val, decimals){ decimals = decimals ? parseInt(decimals) : 0; From 2dc195f06385c92b9cca86b68062a2f70b162b0b Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Jul 2018 17:47:23 +0700 Subject: [PATCH 398/658] fix --- js/ethplorer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index d5f6a94c..29703893 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -2131,6 +2131,7 @@ Ethplorer = { if(withDecimals){ num = Ethplorer.Utils.round(num, decimals); } + var parts = num.toString().split('.'); var res = parts[0].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); var zeroCount = cutZeroes ? 2 : decimals; if(withDecimals && decimals){ From d3788d8cfd4e5119e7bfdcbcac6f1965d6577619 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 12 Jul 2018 18:24:11 +0700 Subject: [PATCH 399/658] Fixed transfer values --- js/ethplorer.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 29703893..e324cf07 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -618,7 +618,7 @@ Ethplorer = { op.index = idx; var opToken = Ethplorer.prepareToken(op.token); var valFloat = 0; - if('undefined' !== typeof(op.value)){ + if('undefined' !== typeof(op.value)){ valFloat = parseFloat(Ethplorer.Utils.toBig(op.value).toString()); valFloat = valFloat / Math.pow(10, opToken.decimals) if(Ethplorer.Utils.isSafari()){ @@ -1288,7 +1288,14 @@ Ethplorer = { }else{ var txToken = Ethplorer.prepareToken(data.token ? data.token : data.tokens[tx.contract]); } - if(!tx.isEth) qty = qty / Math.pow(10, txToken.decimals); + if(!tx.isEth){ + var k = Math.pow(10, txToken.decimals); + if(Ethplorer.Utils.isSafari()){ + qty = qty / Math.pow(10, k); + }else{ + qty = parseFloat(Ethplorer.Utils.toBig(tx.value).div(k).toString()); + } + } var row = $(''); var tdDate = $('').addClass('hide-small'); var tdData = $(''); From 9dd5506381f813df999fee535dc39f5153502dca Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 17 Jul 2018 18:03:40 +0700 Subject: [PATCH 400/658] safari bug fixed --- js/ethplorer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index e324cf07..8a9e69cd 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -619,8 +619,8 @@ Ethplorer = { var opToken = Ethplorer.prepareToken(op.token); var valFloat = 0; if('undefined' !== typeof(op.value)){ - valFloat = parseFloat(Ethplorer.Utils.toBig(op.value).toString()); - valFloat = valFloat / Math.pow(10, opToken.decimals) + valFloat = parseFloat(Ethplorer.Utils.toBig(op.value).toString()); + valFloat = valFloat / Math.pow(10, opToken.decimals); if(Ethplorer.Utils.isSafari()){ op.value = valFloat; }else{ @@ -1291,7 +1291,7 @@ Ethplorer = { if(!tx.isEth){ var k = Math.pow(10, txToken.decimals); if(Ethplorer.Utils.isSafari()){ - qty = qty / Math.pow(10, k); + qty = qty / k; }else{ qty = parseFloat(Ethplorer.Utils.toBig(tx.value).div(k).toString()); } From 8e27b8038b5615eeb503e9d458afc6f56cece47f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 19 Jul 2018 20:52:24 +0700 Subject: [PATCH 401/658] Style for self tx added. --- css/ethplorer.css | 5 +++++ index.php | 2 +- js/ethplorer.js | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index b57d8faf..427c6ccf 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -613,6 +613,11 @@ a.dashed { color: #ae2525 !important; } +.self { + font-size: 16px; + color: #fff !important; +} + .diff-up { color: #1e8c1e !important; } diff --git a/index.php b/index.php index 5dda1873..bf6ea6e3 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "217"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "218"; $error = TRUE; $header = ""; diff --git a/js/ethplorer.js b/js/ethplorer.js index 8a9e69cd..3fe976ff 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1309,7 +1309,9 @@ Ethplorer = { var to = tx.to ? ((tx.to !== address) ? Ethplorer.Utils.getEthplorerLink(tx.to) : ('' + address + '')) : false; var _address = (tx.address && (tx.address === address )) ? ('' + address + '') : tx.address; var rowClass = ''; - if(from && (tx.from === address)){ + if(from && to && (tx.from === address) && (tx.to === address)){ + rowClass = 'self'; + }else if(from && (tx.from === address)){ value = '-' + value; rowClass = 'outgoing'; }else if(to && (tx.to === address)){ From d83e97d755b4a846f49759fb246d7dec261f373a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 19 Jul 2018 20:56:03 +0700 Subject: [PATCH 402/658] Revert commit. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index bf6ea6e3..5dda1873 100644 --- a/index.php +++ b/index.php @@ -18,7 +18,7 @@ require dirname(__FILE__) . '/service/lib/ethplorer.php'; $es = Ethplorer::db(array()); -$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "218"; +$codeVersion = isset($aConfig['codeVersion']) ? $aConfig['codeVersion'] : "217"; $error = TRUE; $header = ""; From d5341bbbe505095f45995b88d3855257c72cf47b Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 23 Jul 2018 19:26:02 +0700 Subject: [PATCH 403/658] Error case added to jsonrpc call --- service/lib/ethplorer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1f251571..230e0cd6 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3200,6 +3200,9 @@ protected function _jsonrpcall($service, $method, $params = array()){ if(isset($json["result"])){ $result = $json["result"]; } + if(isset($json["error"])){ + $result = ["error" => $json["error"]]; + } } return $result; } From 5a5aab6a4d80fa1c4c2395d66ac2a1d865219f59 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 24 Jul 2018 14:10:25 +0700 Subject: [PATCH 404/658] monitor id to uid --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1f251571..d50fc2f6 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3007,7 +3007,7 @@ public function getPoolAddresses($poolId, $updateCache = FALSE){ $cache = 'pool_addresses-' . $poolId; $aAddresses = $this->oCache->get($cache, false, true, 600); if($updateCache || (false === $aAddresses)){ - $cursor = $this->oMongoPools->find('pools', array('id' => $poolId)); + $cursor = $this->oMongoPools->find('pools', array('uid' => $poolId)); $result = array(); foreach($cursor as $result) break; if($result){ From c780c43c4c43bbbabb346fd884125a907f933f8c Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 24 Jul 2018 19:12:36 +0700 Subject: [PATCH 405/658] delete method for cache --- service/lib/cache.php | 23 +++++++++++++++++++++++ service/lib/ethplorer.php | 5 ++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index b212daff..4da13149 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -144,6 +144,29 @@ public function clearLocalCache(){ $this->aData = array(); } + /** + * Clean cache by key + * @param String $entryName + */ + public function delete($entryName) { + switch ($this->driver) { + case 'redis': + $this->oDriver->del($entryName); + break; + + case 'memcached': + $this->oDriver->delete($entryName); + break; + + case 'file': + @unlink($this->path . '/' . $entryName . '.tmp'); + break; + + default: + throw \Exception('The method for delete of cache driver not implemented'); + } + } + /** * Saves data to file. * diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 801772c8..24d73f43 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2993,7 +2993,10 @@ public function deletePool($poolId = NULL){ } public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ - return $this->_jsonrpcall($this->aSettings['pools'], 'updatePool', array($method, $poolId, $addresses)); + $response = $this->_jsonrpcall($this->aSettings['pools'], 'updatePool', array($method, $poolId, $addresses)); + // clean cache + $this->oCache->delete('pool_addresses-' . $poolId, false); + return $response; } /** From 86915aee45beddbb83dfac1ee90fbf05f96b0b59 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 24 Jul 2018 20:37:02 +0700 Subject: [PATCH 406/658] fixes --- api/controller.php | 8 ++++---- service/lib/ethplorer.php | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/controller.php b/api/controller.php index 86fb6848..34675842 100644 --- a/api/controller.php +++ b/api/controller.php @@ -530,13 +530,13 @@ public function getLastBlock(){ } public function createPool(){ + $apiKey = $this->getPostRequest('apiKey'); $addresses = $this->getPostRequest('addresses'); - $poolId = $this->db->createPool($addresses); - if(!$poolId){ + $pool = $this->db->createPool($apiKey, $addresses); + if(!$pool){ $this->sendError(105, 'Error creating pool'); } - $result = array('poolId' => $poolId); - $this->sendResult($result); + $this->sendResult($pool); } public function deletePool(){ diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 24d73f43..5be7b173 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2984,8 +2984,14 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w return $result; } - public function createPool($addresses = NULL){ - return $this->_jsonrpcall($this->aSettings['pools'], 'createPool', array($addresses)); + /** + * Create pool + * @param String $apiKey + * @param String $addresses + * @return Array + */ + public function createPool($apiKey, $addresses = NULL){ + return $this->_jsonrpcall($this->aSettings['pools'], 'createPool', array($apiKey, $addresses)); } public function deletePool($poolId = NULL){ From a16cbbded10cfa463a4bfd2f34bee14fd2a99364 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 24 Jul 2018 21:29:26 +0700 Subject: [PATCH 407/658] Temoprary fix --- service/lib/ethplorer.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 801772c8..fcc9bfef 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2796,8 +2796,15 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w $result = false; $updateCache = false; } - + if(FALSE === $result || $updateCache){ + + $opCount = $this->countOperations($address, FALSE); + if($opCount >= 10000){ + evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'FINISH', 'Address has >10000 operations, skip'); + return FALSE; + } + $aSearch = array('from', 'to', 'address'); $aTypes = array('transfer', 'issuance', 'burn', 'mint'); $aResult = array(); From 6952af391f31435013ab0647b14c3699655fd3cb Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 15:33:07 +0700 Subject: [PATCH 408/658] add $statusCode to sendResult refactoring logic pools api --- api/controller.php | 61 ++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/api/controller.php b/api/controller.php index 34675842..c344e9a6 100644 --- a/api/controller.php +++ b/api/controller.php @@ -84,22 +84,23 @@ public function getPostRequest($name, $default = NULL){ return (FALSE !== $result) && (!is_null($result)) ? $result : $default; } - public function sendResult(array $result){ + public function sendResult(array $result, $statusCode = 200){ if($this->getRequest('debugId')){ $result['debug'] = $this->db->getDebugData(); } + http_response_code($statusCode); echo json_encode($result, JSON_UNESCAPED_SLASHES); die(); } - public function sendError($code, $message){ + public function sendError($code, $message, $statusCode = 200){ $result = array( 'error' => array( 'code' => $code, 'message' => $message ) ); - $this->sendResult($result); + $this->sendResult($result, $statusCode); } /** @@ -532,19 +533,22 @@ public function getLastBlock(){ public function createPool(){ $apiKey = $this->getPostRequest('apiKey'); $addresses = $this->getPostRequest('addresses'); - $pool = $this->db->createPool($apiKey, $addresses); - if(!$pool){ - $this->sendError(105, 'Error creating pool'); + $response = $this->db->createPool($apiKey, $addresses); + if (isset($response['error'])) { + $this->sendError(105, 'Error creating pool', 400); } - $this->sendResult($pool); + $this->sendResult($response); } public function deletePool(){ $poolId = $this->getPostRequest('poolId'); - if(!$poolId){ - $this->sendError(106, 'Missing pool ID'); + if (!$poolId) { + $this->sendError(106, 'Missing pool ID', 400); + } + $response = $this->db->deletePool($poolId); + if (isset($response['error'])) { + $this->sendError(110, 'Error deleting pool', 400); } - $result = $this->db->deletePool($poolId); $this->sendResult($result); } @@ -562,15 +566,18 @@ public function clearPoolAddresses(){ public function updatePool($method = FALSE){ if(!$method){ - $this->sendError(107, 'Missing method name'); + $this->sendError(107, 'Missing method name', 400); } $poolId = $this->getPostRequest('poolId'); if(!$poolId){ - $this->sendError(106, 'Missing pool ID'); + $this->sendError(106, 'Missing pool ID', 400); } $addresses = $this->getPostRequest('addresses'); - $result = $this->db->updatePool($method, $poolId, $addresses); - $this->sendResult($result); + $response = $this->db->updatePool($method, $poolId, $addresses); + if (isset($response['error'])) { + $this->sendError(109, 'Fail update the pool', 400); + } + $this->sendResult($response); } /** @@ -580,11 +587,11 @@ public function updatePool($method = FALSE){ * @return array */ public function getPoolAddresses(){ - $result = array('addresses' => array()); $poolId = $this->getRequest('poolId', FALSE); - if($poolId){ - $result = array('addresses' => $this->db->getPoolAddresses($poolId)); + if (!$poolId) { + $this->sendError(106, 'Missing pool ID', 400); } + $result = array('addresses' => $this->db->getPoolAddresses($poolId)); $this->sendResult($result); } @@ -594,13 +601,13 @@ public function getPoolAddresses(){ * @undocumented * @return array */ - public function getPoolLastTransactions(){ - $result = array(); + public function getPoolLastTransactions() { $poolId = $this->getRequest('poolId', FALSE); - $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); - if($poolId){ - $result = $this->db->getPoolLastTransactions($poolId, $period); + if (!$poolId) { + $this->sendError(106, 'Missing pool ID', 400); } + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); + $result = $this->db->getPoolLastTransactions($poolId, $period); $this->sendResult($result); } @@ -610,13 +617,13 @@ public function getPoolLastTransactions(){ * @undocumented * @return array */ - public function getPoolLastOperations(){ - $result = array(); + public function getPoolLastOperations() { $poolId = $this->getRequest('poolId', FALSE); - $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); - if($poolId){ - $result = $this->db->getPoolLastOperations($poolId, $period); + if (!$poolId) { + $this->sendError(106, 'Missing pool ID', 400); } + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); + $result = $this->db->getPoolLastOperations($poolId, $period); $this->sendResult($result); } From f2cfca938e8d5a3f7f6d398a7460cad287de6ea3 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 25 Jul 2018 16:16:09 +0700 Subject: [PATCH 409/658] Some fixes --- service/lib/ethplorer.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index e5e1645d..2cb12058 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -136,6 +136,8 @@ class Ethplorer { protected $useOperations2 = FALSE; + protected $getTokensCacheCreation = FALSE; + /** * Constructor. * @@ -977,7 +979,10 @@ public function getTokens($updateCache = false){ return $this->aTokens; } $aResult = $this->oCache->get('tokens', false, true); - if($updateCache || (false === $aResult)){ + if(!$this->getTokensCacheCreation && ($updateCache || (false === $aResult))){ + // Recursion protection + $this->getTokensCacheCreation = true; + evxProfiler::checkpoint('getTokens', 'START'); $aPrevTokens = array(); if($updateCache){ @@ -2081,7 +2086,7 @@ protected function _sortByTxCount($a, $b){ public function getTokenHistoryGrouped($period = 30, $address = FALSE, $type = 'daily', $cacheLifetime = 1800, $showEth = FALSE, $updateCache = FALSE){ $cache = 'token_history_grouped-' . ($address ? ($address . '-') : '') . $period . (($type == 'hourly') ? '-hourly' : '') . ($showEth ? '-eth' : ''); $result = $address ? $this->oCache->get($cache, false, true, $cacheLifetime) : $this->oCache->get($cache, false, true); - if(FALSE === $result || $updateCache){ + if(($address && FALSE === $result) || $updateCache){ // Chainy if($address && ($address == self::ADDRESS_CHAINY)){ return $this->getChainyTokenHistoryGrouped($period); @@ -2805,7 +2810,7 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w return FALSE; } - $aSearch = array('from', 'to', 'address'); + $aSearch = array('from', 'to', 'address'); // @todo: research "addresses" $aTypes = array('transfer', 'issuance', 'burn', 'mint'); $aResult = array(); $aContracts = array(); From 53563239b3754a8d3f5cbcb180e7001a9c04342d Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 25 Jul 2018 16:30:14 +0700 Subject: [PATCH 410/658] cacheTokens update --- bin/cache_tokens.php | 2 ++ service/lib/ethplorer.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 663d7314..05ca58ba 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -17,6 +17,8 @@ ini_set('memory_limit', '512M'); +// define('ETHPLORER_SHOW_OUTPUT', 1); + require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2cb12058..fe51097e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -979,7 +979,7 @@ public function getTokens($updateCache = false){ return $this->aTokens; } $aResult = $this->oCache->get('tokens', false, true); - if(!$this->getTokensCacheCreation && ($updateCache || (false === $aResult))){ + if(!$this->getTokensCacheCreation && ($updateCache/* || (false === $aResult)*/)){ // Recursion protection $this->getTokensCacheCreation = true; From 7d4da6c987c68ca55baf14bc3eaff3066d1ae65c Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 25 Jul 2018 16:55:38 +0700 Subject: [PATCH 411/658] cache_tokens updated (debug and memory limit) --- bin/cache_tokens.php | 2 +- service/lib/ethplorer.php | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 05ca58ba..26626aa2 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -15,7 +15,7 @@ * limitations under the License. */ -ini_set('memory_limit', '512M'); +ini_set('memory_limit', '1G'); // define('ETHPLORER_SHOW_OUTPUT', 1); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index fe51097e..f35054fd 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1000,9 +1000,7 @@ public function getTokens($updateCache = false){ unset($aToken["_id"]); $aResult[$address] = $aToken; if(!isset($aPrevTokens[$address]) || ($aPrevTokens[$address]['transfersCount'] < $aToken['transfersCount'])){ - if(defined('ETHPLORER_SHOW_OUTPUT')){ - echo $address . " was recently updated (transfers count = " . $aToken['transfersCount'] . ")\n"; - } + $this->_cliDebug($address . " was recently updated (transfers count = " . $aToken['transfersCount'] . ")"); $aResult[$address]['issuancesCount'] = $this->getContractOperationCount(array('$in' => array('issuance', 'burn', 'mint')), $address, FALSE); $hc = $this->getTokenHoldersCount($address);; if(FALSE !== $hc){ @@ -3325,7 +3323,8 @@ protected function getEthToken(){ } protected function _cliDebug($message){ - if(isset($this->aSettings['cliDebug']) && $this->aSettings['cliDebug'] && (php_sapi_name() === 'cli')){ + $showDebug = ((isset($this->aSettings['cliDebug']) && $this->aSettings['cliDebug']) || defined('ETHPLORER_SHOW_OUTPUT')) && (php_sapi_name() === 'cli'); + if($showDebug){ echo '[' . date("Y-m-d H:i:s") . '] ' . $message . "\n"; } } From 3a1eb6c9351bd053afd5c9412925cbb5dac5d284 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 19:33:33 +0700 Subject: [PATCH 412/658] rename error messages --- api/controller.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/controller.php b/api/controller.php index c344e9a6..eabd179f 100644 --- a/api/controller.php +++ b/api/controller.php @@ -543,7 +543,7 @@ public function createPool(){ public function deletePool(){ $poolId = $this->getPostRequest('poolId'); if (!$poolId) { - $this->sendError(106, 'Missing pool ID', 400); + $this->sendError(106, 'Invalid pool id', 400); } $response = $this->db->deletePool($poolId); if (isset($response['error'])) { @@ -566,16 +566,16 @@ public function clearPoolAddresses(){ public function updatePool($method = FALSE){ if(!$method){ - $this->sendError(107, 'Missing method name', 400); + $this->sendError(107, 'Invalid method name', 400); } $poolId = $this->getPostRequest('poolId'); if(!$poolId){ - $this->sendError(106, 'Missing pool ID', 400); + $this->sendError(106, 'Invalid pool id', 400); } $addresses = $this->getPostRequest('addresses'); $response = $this->db->updatePool($method, $poolId, $addresses); if (isset($response['error'])) { - $this->sendError(109, 'Fail update the pool', 400); + $this->sendError(109, 'Error update the pool', 400); } $this->sendResult($response); } @@ -589,7 +589,7 @@ public function updatePool($method = FALSE){ public function getPoolAddresses(){ $poolId = $this->getRequest('poolId', FALSE); if (!$poolId) { - $this->sendError(106, 'Missing pool ID', 400); + $this->sendError(106, 'Invalid pool id', 400); } $result = array('addresses' => $this->db->getPoolAddresses($poolId)); $this->sendResult($result); @@ -604,7 +604,7 @@ public function getPoolAddresses(){ public function getPoolLastTransactions() { $poolId = $this->getRequest('poolId', FALSE); if (!$poolId) { - $this->sendError(106, 'Missing pool ID', 400); + $this->sendError(106, 'Invalid pool id', 400); } $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastTransactions($poolId, $period); @@ -620,7 +620,7 @@ public function getPoolLastTransactions() { public function getPoolLastOperations() { $poolId = $this->getRequest('poolId', FALSE); if (!$poolId) { - $this->sendError(106, 'Missing pool ID', 400); + $this->sendError(106, 'Invalid pool id', 400); } $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastOperations($poolId, $period); From 0f8bd7869c7646c2651afdfb0daf86bde04c393a Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 20:35:20 +0700 Subject: [PATCH 413/658] fix --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index eabd179f..c0de4ebd 100644 --- a/api/controller.php +++ b/api/controller.php @@ -549,7 +549,7 @@ public function deletePool(){ if (isset($response['error'])) { $this->sendError(110, 'Error deleting pool', 400); } - $this->sendResult($result); + $this->sendResult($response); } public function addPoolAddresses(){ From 1e0862f76c19fcb60ea6507778ed1e3f5d8be01e Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 21:11:26 +0700 Subject: [PATCH 414/658] fix /getPoolAddresses --- api/controller.php | 2 +- service/lib/ethplorer.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/controller.php b/api/controller.php index c0de4ebd..7da079e3 100644 --- a/api/controller.php +++ b/api/controller.php @@ -587,7 +587,7 @@ public function updatePool($method = FALSE){ * @return array */ public function getPoolAddresses(){ - $poolId = $this->getRequest('poolId', FALSE); + $poolId = $this->getParam(1, FALSE); if (!$poolId) { $this->sendError(106, 'Invalid pool id', 400); } diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index f35054fd..751a1c55 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3029,8 +3029,8 @@ public function getPoolAddresses($poolId, $updateCache = FALSE){ $cursor = $this->oMongoPools->find('pools', array('uid' => $poolId)); $result = array(); foreach($cursor as $result) break; - if($result){ - $aAddresses = explode(",", $result['addresses']); + if(isset($result['addresses'])){ + $aAddresses = $result['addresses']; $this->oCache->save($cache, $aAddresses); } } From 6218c567eaedf766a7173f4d66f5675efbd32d23 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 21:14:12 +0700 Subject: [PATCH 415/658] Monitor API get methods fixes --- api/controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/controller.php b/api/controller.php index 7da079e3..ce83a658 100644 --- a/api/controller.php +++ b/api/controller.php @@ -602,7 +602,7 @@ public function getPoolAddresses(){ * @return array */ public function getPoolLastTransactions() { - $poolId = $this->getRequest('poolId', FALSE); + $poolId = $this->getParam(1, FALSE); if (!$poolId) { $this->sendError(106, 'Invalid pool id', 400); } @@ -618,7 +618,7 @@ public function getPoolLastTransactions() { * @return array */ public function getPoolLastOperations() { - $poolId = $this->getRequest('poolId', FALSE); + $poolId = $this->getParam(1, FALSE); if (!$poolId) { $this->sendError(106, 'Invalid pool id', 400); } From 22d44f2d7cbe1636a74371a93b2b3c899aad69d4 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 25 Jul 2018 21:36:57 +0700 Subject: [PATCH 416/658] fix params for bulk api --- api/controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/controller.php b/api/controller.php index ce83a658..01bcc36f 100644 --- a/api/controller.php +++ b/api/controller.php @@ -587,7 +587,7 @@ public function updatePool($method = FALSE){ * @return array */ public function getPoolAddresses(){ - $poolId = $this->getParam(1, FALSE); + $poolId = $this->getParam(0, FALSE); if (!$poolId) { $this->sendError(106, 'Invalid pool id', 400); } @@ -618,7 +618,7 @@ public function getPoolLastTransactions() { * @return array */ public function getPoolLastOperations() { - $poolId = $this->getParam(1, FALSE); + $poolId = $this->getParam(0, FALSE); if (!$poolId) { $this->sendError(106, 'Invalid pool id', 400); } From d23bc08b739274bc76439b911fb92e10f347b5cf Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 26 Jul 2018 14:13:07 +0700 Subject: [PATCH 417/658] 403 when no api key --- api/controller.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/api/controller.php b/api/controller.php index 01bcc36f..45a39161 100644 --- a/api/controller.php +++ b/api/controller.php @@ -114,21 +114,18 @@ public function run(){ if($command && (in_array($command, $this->apiCommands) || in_array($command, $this->apiPostCommands)) && method_exists($this, $command)){ $key = in_array($command, $this->apiCommands) ? $this->getRequest('apiKey', FALSE) : $this->getPostRequest('apiKey', FALSE); if(!$key || !$this->db->checkAPIkey($key)){ - header('HTTP/1.1 403 Forbidden'); - $this->sendError(1, 'Invalid API key'); + $this->sendError(1, 'Invalid API key', 403); } $this->defaults = $this->db->getAPIKeyDefaults($key, $command); if($this->db->isSuspendedAPIKey($key)){ - header('HTTP/1.1 403 Forbidden'); - $this->sendError(133, 'API key temporary suspended. Contact support.'); + $this->sendError(133, 'API key temporary suspended. Contact support.', 403); } if(in_array($command, $this->apiPostCommands)){ // @todo: Temporary solution, special key property will be used later if($key == "freekey"){ - header('HTTP/1.1 403 Forbidden'); - $this->sendError(1, 'Invalid API key'); + $this->sendError(1, 'Invalid API key', 403); } $result = call_user_func(array($this, $command)); return $result; From 2034e870976d9526fbb6d4900ec0fd7fa664b8b4 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 26 Jul 2018 14:48:46 +0700 Subject: [PATCH 418/658] predis and sentry added --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 536bc79a..4a177368 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,8 @@ { "require": { - "litipk/php-bignumbers": "0.7.3" + "litipk/php-bignumbers": "0.7.3", + "predis/predis": "1.1.1", + "sentry/sentry": "^1.10@dev" }, "minimum-stability": "dev", "prefer-stable" : false From 46a396aca33a754376f43993492ffa6645dc02c4 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 14:50:53 +0700 Subject: [PATCH 419/658] TTL for locks changed. --- bin/cache_last_block.php | 2 +- bin/cache_price_history.php | 2 +- bin/cache_prices.php | 2 +- bin/cache_tokens.php | 2 +- bin/cache_tokens_full_history.php | 2 +- bin/cache_tokens_history.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/cache_last_block.php b/bin/cache_last_block.php index 659f4e8d..d245e40c 100644 --- a/bin/cache_last_block.php +++ b/bin/cache_last_block.php @@ -22,7 +22,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('lastBlock.lock'); +$es->createProcessLock('lastBlock.lock', 5); $es->getLastBlock(true); $ms = round(microtime(TRUE) - $startTime, 4); diff --git a/bin/cache_price_history.php b/bin/cache_price_history.php index b76237b1..12ff730b 100644 --- a/bin/cache_price_history.php +++ b/bin/cache_price_history.php @@ -22,7 +22,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('priceHistory.lock'); +$es->createProcessLock('priceHistory.lock', 1800); foreach($aConfig['updateRates'] as $address){ $es->getCache()->clearLocalCache(); $es->getTokenPriceHistory($address, 0, 'hourly', TRUE); diff --git a/bin/cache_prices.php b/bin/cache_prices.php index 2fe07e6f..2675a09f 100644 --- a/bin/cache_prices.php +++ b/bin/cache_prices.php @@ -25,7 +25,7 @@ $maxTimeGetPrice = 0; $es = Ethplorer::db($aConfig); -$lock = $es->createProcessLock('prices.lock', 1200); +$lock = $es->createProcessLock('prices.lock', 600); foreach($aConfig['updateRates'] as $address){ $startGetPrice = microtime(TRUE); $es->getCache()->clearLocalCache(); diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php index 26626aa2..f800d313 100644 --- a/bin/cache_tokens.php +++ b/bin/cache_tokens.php @@ -26,7 +26,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('tokens.lock'); +$es->createProcessLock('tokens.lock', 600); $es->getTokens(true); $es->getTopTokens(10, 90); diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index 21f97763..3c0b8ae4 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -22,7 +22,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('tokens.full.history.lock'); +$es->createProcessLock('tokens.full.history.lock', 1800); $es->getTokenFullHistoryGrouped(); $es->getTokenCapHistory(0, TRUE); diff --git a/bin/cache_tokens_history.php b/bin/cache_tokens_history.php index 43500b1b..71e58f2b 100644 --- a/bin/cache_tokens_history.php +++ b/bin/cache_tokens_history.php @@ -22,7 +22,7 @@ echo "\n[".date("Y-m-d H:i")."], Started."; $es = Ethplorer::db($aConfig); -$es->createProcessLock('tokens.history.lock'); +$es->createProcessLock('tokens.history.lock', 600); $es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); From 381c0a3e2a54eedb338f41a6c1fc7020664b8223 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 26 Jul 2018 15:53:14 +0700 Subject: [PATCH 420/658] Notice fixed --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 751a1c55..369c0f98 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -530,7 +530,7 @@ public function getEtherTotalIn($address, $updateCache = FALSE, $parityOnly = FA $cursor = $this->oMongo->find('ethBalances', array('address' => $address)); foreach($cursor as $balance) break; } - if($balance && isset($balance['balance'])){ + if($balance && isset($balance['balance']) && isset($balance['totalIn'])){ $result = $balance['totalIn']; }else{ // Get from parity From 72d5328706a6f0ae5ba3285bbbf661c812b29004 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 15:57:59 +0700 Subject: [PATCH 421/658] Allow generating cache only from cron jobs --- bin/cache_tokens_full_history.php | 2 +- service/lib/ethplorer.php | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php index 3c0b8ae4..ef1fd5c6 100644 --- a/bin/cache_tokens_full_history.php +++ b/bin/cache_tokens_full_history.php @@ -24,7 +24,7 @@ $es = Ethplorer::db($aConfig); $es->createProcessLock('tokens.full.history.lock', 1800); -$es->getTokenFullHistoryGrouped(); +$es->getTokenFullHistoryGrouped(TRUE); $es->getTokenCapHistory(0, TRUE); $ms = round(microtime(TRUE) - $startTime, 4); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 751a1c55..c08bf499 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2137,7 +2137,7 @@ public function getTokenHistoryGrouped($period = 30, $address = FALSE, $type = ' * * @return array */ - public function getTokenFullHistoryGrouped($showEth = FALSE){ + public function getTokenFullHistoryGrouped($updateCache = FALSE){ $tsNow = time(); $tsStart = 1451606400; // 01.01.2016 $tsEnd = 1459468800; @@ -2152,17 +2152,11 @@ public function getTokenFullHistoryGrouped($showEth = FALSE){ $cacheLifetime = 24 * 60 * 60; } $result = $this->oCache->get($cache, FALSE, TRUE, $cacheLifetime); - if(FALSE === $result){ + if(FALSE === $result && $updateCache){ $result = array(); $aMatch = array("timestamp" => array('$gte' => $tsStart + 1, '$lte' => $tsEnd)); - if(!$showEth){ - if($this->useOperations2){ - $aMatch['isEth'] = false; - }else{ - $aMatch["contract"] = array('$ne' => 'ETH'); - } - } + $aMatch['isEth'] = false; $_id = array( "year" => array('$year' => array('$add' => array($this->oMongo->toDate(0), array('$multiply' => array('$timestamp', 1000))))), "month" => array('$month' => array('$add' => array($this->oMongo->toDate(0), array('$multiply' => array('$timestamp', 1000))))), From f7567df3f7c09171832e894da05f36364a050251 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 26 Jul 2018 16:07:33 +0700 Subject: [PATCH 422/658] remove unused parameter --- service/lib/ethplorer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 751a1c55..12009e3a 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3011,7 +3011,7 @@ public function deletePool($poolId = NULL){ public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ $response = $this->_jsonrpcall($this->aSettings['pools'], 'updatePool', array($method, $poolId, $addresses)); // clean cache - $this->oCache->delete('pool_addresses-' . $poolId, false); + $this->oCache->delete('pool_addresses-' . $poolId); return $response; } @@ -3223,6 +3223,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ $result = ["error" => $json["error"]]; } } + return $result; } From 4c8e8efe8a519870cf8fe3f1c0ba92f1338ffc18 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 16:10:20 +0700 Subject: [PATCH 423/658] Allow generating cache only from cron jobs. --- service/lib/ethplorer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 093ff826..b3249cbf 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -979,6 +979,7 @@ public function getTokens($updateCache = false){ return $this->aTokens; } $aResult = $this->oCache->get('tokens', false, true); + // Allow generating cache only from cron jobs if(!$this->getTokensCacheCreation && ($updateCache/* || (false === $aResult)*/)){ // Recursion protection $this->getTokensCacheCreation = true; @@ -2152,6 +2153,7 @@ public function getTokenFullHistoryGrouped($updateCache = FALSE){ $cacheLifetime = 24 * 60 * 60; } $result = $this->oCache->get($cache, FALSE, TRUE, $cacheLifetime); + // Allow generating cache only from cron jobs if(FALSE === $result && $updateCache){ $result = array(); From 21702a07d0db461e8e7cdcf0a604835613f51efa Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 26 Jul 2018 19:13:54 +0700 Subject: [PATCH 424/658] getEtherTotalIn fix bug with absent cache of HL addresses --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 369c0f98..7db975b5 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -532,7 +532,7 @@ public function getEtherTotalIn($address, $updateCache = FALSE, $parityOnly = FA } if($balance && isset($balance['balance']) && isset($balance['totalIn'])){ $result = $balance['totalIn']; - }else{ + }elseif(!$parityOnly){ // Get from parity $aResult = $this->oMongo->aggregate('operations2', array( array('$match' => array("to" => $address, "isEth" => true)), From 1bb5b59d3b2ed94f9ed404037a480570ddc0ed93 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 26 Jul 2018 19:17:00 +0700 Subject: [PATCH 425/658] Invalid condition fixed --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 689ea21a..31a64802 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -532,7 +532,7 @@ public function getEtherTotalIn($address, $updateCache = FALSE, $parityOnly = FA } if($balance && isset($balance['balance']) && isset($balance['totalIn'])){ $result = $balance['totalIn']; - }elseif(!$parityOnly){ + }elseif($parityOnly){ // Get from parity $aResult = $this->oMongo->aggregate('operations2', array( array('$match' => array("to" => $address, "isEth" => true)), From 004910f7e6be1a34abc6ea6c4b617e4dfd479ce4 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 19:49:35 +0700 Subject: [PATCH 426/658] Added ability add non expiration data into cache. --- service/lib/cache.php | 19 +++++++++++++++---- service/lib/ethplorer.php | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 4da13149..e23e49d0 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -51,6 +51,11 @@ class evxCache { */ const LOCK_WAITING_REPEATS = 20; + /** + * Lifetime key value for keys without associated expire time + */ + const NON_EXPIRATION_LIFETIME = -1; + /** * Cache storage. * @@ -173,7 +178,7 @@ public function delete($entryName) { * @param string $entryName Cache entry name * @param mixed $data Data to store */ - public function save($entryName, $data){ + public function save($entryName, $data, $nonExpiration = FALSE){ $saveRes = false; $this->store($entryName, $data); switch($this->driver){ @@ -184,7 +189,9 @@ public function save($entryName, $data){ $lifetime = time() + $cacheLifetime; }*/ $ttl = evxCache::DAY; - if(!$lifetime){ + if($nonExpiration){ + $lifetime = evxCache::NON_EXPIRATION_LIFETIME; + }else if(!$lifetime){ // 1 day if cache lifetime is not set $lifetime = time() + evxCache::DAY; }else{ @@ -193,7 +200,11 @@ public function save($entryName, $data){ } $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ - $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); + if($nonExpiration){ + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData)); + }else{ + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); + } $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); @@ -292,7 +303,7 @@ public function loadCachedData($entryName, $default = NULL, $cacheLifetime = FAL $memcachedData = ('redis' == $this->driver) ? json_decode($this->oDriver->get($entryName), TRUE) : $this->oDriver->get($entryName); if($memcachedData && isset($memcachedData['lifetime']) && isset($memcachedData['data'])){ $result['data'] = $memcachedData['data']; - if($memcachedData['lifetime'] < time()){ + if($memcachedData['lifetime'] > 0 && $memcachedData['lifetime'] < time()){ $result['expired'] = TRUE; } } diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 1ee9486c..21f0825b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2180,7 +2180,7 @@ public function getTokenFullHistoryGrouped($updateCache = FALSE){ ); if(is_array($dbData) && !empty($dbData['result'])){ $result = $dbData['result']; - $this->oCache->save($cache, $result); + $this->oCache->save($cache, $result, $cacheLifetime ? FALSE : TRUE); } } if(is_array($result) && sizeof($result)){ From b7a6a6a04e6e759c715c8d0d87a3f9b8dd72a906 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 20:20:18 +0700 Subject: [PATCH 427/658] Change cache ttl for full tokens history. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index bbf71b99..c42b7047 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2150,7 +2150,7 @@ public function getTokenFullHistoryGrouped($updateCache = FALSE){ $cache = 'token_full_history_grouped-' . $tsEnd; $cacheLifetime = FALSE; if($tsEnd > $tsNow){ - $cacheLifetime = 24 * 60 * 60; + $cacheLifetime = 1 * 60 * 60; } $result = $this->oCache->get($cache, FALSE, TRUE, $cacheLifetime); // Allow generating cache only from cron jobs From b8b981313b43bb02b589b36758c65c336b642744 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 26 Jul 2018 21:00:48 +0700 Subject: [PATCH 428/658] rpc custom message --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 45a39161..60910481 100644 --- a/api/controller.php +++ b/api/controller.php @@ -572,7 +572,7 @@ public function updatePool($method = FALSE){ $addresses = $this->getPostRequest('addresses'); $response = $this->db->updatePool($method, $poolId, $addresses); if (isset($response['error'])) { - $this->sendError(109, 'Error update the pool', 400); + $this->sendError(109, $response['error']['message'] ?? 'Error update the pool', 400); } $this->sendResult($response); } From 9862f0ee3092eb59ab412a81a42ff8dddf3d42fd Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 26 Jul 2018 21:47:28 +0700 Subject: [PATCH 429/658] Change cache ttl for full tokens history. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c42b7047..bbf71b99 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2150,7 +2150,7 @@ public function getTokenFullHistoryGrouped($updateCache = FALSE){ $cache = 'token_full_history_grouped-' . $tsEnd; $cacheLifetime = FALSE; if($tsEnd > $tsNow){ - $cacheLifetime = 1 * 60 * 60; + $cacheLifetime = 24 * 60 * 60; } $result = $this->oCache->get($cache, FALSE, TRUE, $cacheLifetime); // Allow generating cache only from cron jobs From 3520c76bceb1d6a711f0954c0ee842375e9941f1 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Thu, 26 Jul 2018 21:51:45 +0700 Subject: [PATCH 430/658] getPoolAddresses fixes --- service/lib/ethplorer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c42b7047..9e4f5846 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3020,10 +3020,10 @@ public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ public function getPoolAddresses($poolId, $updateCache = FALSE){ evxProfiler::checkpoint('getPoolAddresses', 'START'); $cache = 'pool_addresses-' . $poolId; - $aAddresses = $this->oCache->get($cache, false, true, 600); + $aAddresses = $this->oCache->get($cache, false, true, 600) ?: ''; if($updateCache || (false === $aAddresses)){ - $cursor = $this->oMongoPools->find('pools', array('uid' => $poolId)); - $result = array(); + $cursor = $this->oMongoPools->find('pools', ['uid' => $poolId]); + $result = ""; foreach($cursor as $result) break; if(isset($result['addresses'])){ $aAddresses = $result['addresses']; From 5175cbbb3274319b33b53086ef79b2e339e01486 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 27 Jul 2018 16:14:52 +0700 Subject: [PATCH 431/658] Memory limit increased. --- bin/cache_price_history.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/cache_price_history.php b/bin/cache_price_history.php index 12ff730b..700d2c0c 100644 --- a/bin/cache_price_history.php +++ b/bin/cache_price_history.php @@ -15,6 +15,8 @@ * limitations under the License. */ +ini_set('memory_limit', '1G'); + require dirname(__FILE__) . '/../service/lib/ethplorer.php'; $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; From 24f4b13af8e6b8528487b23a218fc5493ab13aa6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 27 Jul 2018 16:23:40 +0700 Subject: [PATCH 432/658] Remove eos from eth tokens. --- service/lib/ethplorer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ed5c6099..50354f68 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1715,6 +1715,7 @@ public function getTopTokens($limit = 10, $period = 30, $updateCache = FALSE, $s * @return array */ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = false){ + $aSkippedTokens = array('0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0'); $topLimit = 100; if($criteria != 'count'){ $topLimit++; @@ -1762,6 +1763,7 @@ public function getTokensTop($limit = 50, $criteria = 'trade', $updateCache = fa foreach($aTokens as $aToken){ $address = $aToken['address']; + if(in_array($address, $aSkippedTokens)) continue; $curHour = (int)date('H'); $isEth = false; From 54fc4c05acf22b0e15b05e167887647030af9399 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 17:40:25 +0700 Subject: [PATCH 433/658] ga pageView -> ethpPageView --- js/ethplorer.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index 3fe976ff..da0e77ab 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -321,7 +321,7 @@ Ethplorer = { // Check TX hash format first txHash = txHash.toLowerCase(); if(!/^0x[0-9a-f]{64}$/i.test(txHash)){ - Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-invalid-hash'); + Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-invalid-hash'); Ethplorer.error('Invalid transaction hash'); return; } @@ -343,7 +343,7 @@ Ethplorer = { if(showResult) { // if transaction is pending need send ga event if (data.pending) { - Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-pending'); + Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-pending'); } Ethplorer.showTxDetails(_txHash, data); } else if (!data.pending) { @@ -464,10 +464,10 @@ Ethplorer = { var oTx = txData.tx; if(false === oTx){ - Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-not-found'); + Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-not-found'); Ethplorer.error( 'Transaction not found', - 'If transaction was created recently, it may not have reached mempool yet.
    Wait a minute and try to refresh the page.' + 'If transaction was created recently, it may not have reached mempool yet.
    Wait a minute and try to refresh the page.' ); return; } @@ -829,7 +829,7 @@ Ethplorer = { $("table").find("tr:visible:even").addClass("even"); $("table").find("tr:visible:last").addClass("last"); - Ethplorer.gaSendEvent('pageView', 'viewTx', 'tx-ok'); + Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-ok'); }, getAddressDetails: function(address){ // Check Address format first @@ -1020,7 +1020,7 @@ Ethplorer = { $('#address-token-decimals').append(' (estimated)'); } - Ethplorer.gaSendEvent('pageView', 'viewToken', oToken.name ? oToken.name : 'N/A'); + Ethplorer.gaSendEvent('ethpPageView', 'viewToken', oToken.name ? oToken.name : 'N/A'); }else if(data.balances && data.balances.length){ // Fill prices @@ -1119,7 +1119,7 @@ Ethplorer = { }else{ $('#address-balances-total').html(' '); } - Ethplorer.gaSendEvent('pageView', 'viewAddress'); + Ethplorer.gaSendEvent('ethpPageView', 'viewAddress'); } if(!data.isContract || !data.token){ From f072d20181d5216e70bef925f5ffd658979bfdc7 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Fri, 27 Jul 2018 18:36:33 +0700 Subject: [PATCH 434/658] new errors for bulk api --- api/controller.php | 95 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/api/controller.php b/api/controller.php index 60910481..6245413c 100644 --- a/api/controller.php +++ b/api/controller.php @@ -25,6 +25,49 @@ class ethplorerController { protected $startTime; protected $cacheState = ''; + protected $APIErrors = [ + 'API_KEY_NOT_FOUND' => [ + 'code' => 105, + 'message' => 'Field apiKey is required' + ], + 'INTERNAL_ERROR' => [ + 'code' => 106, + 'message' => 'Internal error' + ], + 'NO_POOL_ID' => [ + 'code' => 107, + 'message' => 'Field poolId is required' + ], + 'NO_ACTION_NAME' => [ + 'code' => 109, + 'message' => 'Bad request' + ], + 'INVALID_ACTION_NAME' => [ + 'code' => 110, + 'message' => 'Invalid action' + ], + 'ADDRESS_REQUIRED' => [ + 'code' => 111, + 'message' => 'Field addresses is required' + ], + 'INVALID_ADDRESS' => [ + 'code' => 112, + 'message' => 'One or more addresses is not invalid' + ], + 'NOT_IMPLEMENTED' => [ + 'code' => 113, + 'message' => 'Not implemented' + ], + 'POOL_NOT_FOUND' => [ + 'code' => 114, + 'message' => 'Pool not found' + ], + 'ADDRESS_IS_CONTRACT' => [ + 'code' => 115, + 'message' => 'You can not use contract addresses' + ] + ]; + public function __construct($es){ if(!($es instanceof Ethplorer)){ $this->sendError(3, 'Database connection failed'); @@ -531,21 +574,30 @@ public function createPool(){ $apiKey = $this->getPostRequest('apiKey'); $addresses = $this->getPostRequest('addresses'); $response = $this->db->createPool($apiKey, $addresses); - if (isset($response['error'])) { - $this->sendError(105, 'Error creating pool', 400); + + $error = $response['error']['message'] ?? null; + if ($error) { + $rpcError = $this->APIErrors[$error]; + $this->sendError($rpcError['code'], $rpcError['message'], 400); } + $this->sendResult($response); } public function deletePool(){ $poolId = $this->getPostRequest('poolId'); if (!$poolId) { - $this->sendError(106, 'Invalid pool id', 400); + $apiError = $this->APIErrors['NO_POOL_ID']; + $this->sendError($apiError['code'], $apiError['message'], 400); } $response = $this->db->deletePool($poolId); - if (isset($response['error'])) { - $this->sendError(110, 'Error deleting pool', 400); + + $error = $response['error']['message'] ?? null; + if ($error) { + $apiError = $this->APIErrors[$error]; + $this->sendError($apiError['code'], $apiError['message'], 400); } + $this->sendResult($response); } @@ -561,19 +613,25 @@ public function clearPoolAddresses(){ $this->updatePool('clearPoolAddresses'); } - public function updatePool($method = FALSE){ - if(!$method){ - $this->sendError(107, 'Invalid method name', 400); - } + public function updatePool($method) { $poolId = $this->getPostRequest('poolId'); - if(!$poolId){ - $this->sendError(106, 'Invalid pool id', 400); + if (!$poolId) { + $apiError = $this->APIErrors['NO_POOL_ID']; + $this->sendError($apiError['code'], $apiError['message'], 400); } $addresses = $this->getPostRequest('addresses'); + if ($method !== 'clearPoolAddresses' && empty($addresses)) { + $apiError = $this->APIErrors['ADDRESS_REQUIRED']; + $this->sendError($apiError['code'], $apiError['message'], 400); + } $response = $this->db->updatePool($method, $poolId, $addresses); - if (isset($response['error'])) { - $this->sendError(109, $response['error']['message'] ?? 'Error update the pool', 400); + $error = $response['error']['message'] ?? null; + + if ($error) { + $apiError = $this->APIErrors[$error]; + $this->sendError($apiError['code'], $apiError['message'], 400); } + $this->sendResult($response); } @@ -586,7 +644,8 @@ public function updatePool($method = FALSE){ public function getPoolAddresses(){ $poolId = $this->getParam(0, FALSE); if (!$poolId) { - $this->sendError(106, 'Invalid pool id', 400); + $apiError = $this->APIErrors['NO_POOL_ID']; + $this->sendError($apiError['code'], $apiError['message'], 400); } $result = array('addresses' => $this->db->getPoolAddresses($poolId)); $this->sendResult($result); @@ -599,9 +658,10 @@ public function getPoolAddresses(){ * @return array */ public function getPoolLastTransactions() { - $poolId = $this->getParam(1, FALSE); + $poolId = $this->getParam(0, FALSE); if (!$poolId) { - $this->sendError(106, 'Invalid pool id', 400); + $apiError = $this->APIErrors['NO_POOL_ID']; + $this->sendError($apiError['code'], $apiError['message'], 400); } $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastTransactions($poolId, $period); @@ -617,7 +677,8 @@ public function getPoolLastTransactions() { public function getPoolLastOperations() { $poolId = $this->getParam(0, FALSE); if (!$poolId) { - $this->sendError(106, 'Invalid pool id', 400); + $apiError = $this->APIErrors['NO_POOL_ID']; + $this->sendError($apiError['code'], $apiError['message'], 400); } $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastOperations($poolId, $period); From aab6c3b5d4e1641166257b6574bb4d08fece59c9 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 19:19:01 +0700 Subject: [PATCH 435/658] Widgets to api2 --- api/widget.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/widget.js b/api/widget.js index 1dcd9ca0..2cf8cda2 100644 --- a/api/widget.js +++ b/api/widget.js @@ -28,6 +28,9 @@ ethplorerWidget = { if(widgetOptions.onLoad) delete widgetOptions.onLoad; options.widgetOptions = widgetOptions; options.widgetType = type; + if(document.location.href.indexOf("//ethplorer.io") > 0){ + ethplorerWidget.api = ethplorerWidget.api.replace('api', 'api2'); + } if('undefined' === typeof(jQuery)){ console.error('Cannot initialize Ethplorer widget: jQuery not found.'); console.log('Add next string in the section of the page:'); From 50e07d6a430125687a7ffe8c8e5efe390b5d3e86 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 19:21:02 +0700 Subject: [PATCH 436/658] bug fixed --- api/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 2cf8cda2..74085e83 100644 --- a/api/widget.js +++ b/api/widget.js @@ -29,7 +29,7 @@ ethplorerWidget = { options.widgetOptions = widgetOptions; options.widgetType = type; if(document.location.href.indexOf("//ethplorer.io") > 0){ - ethplorerWidget.api = ethplorerWidget.api.replace('api', 'api2'); + ethplorerWidget.api = ethplorerWidget.api.replace('api.', 'api2.'); } if('undefined' === typeof(jQuery)){ console.error('Cannot initialize Ethplorer widget: jQuery not found.'); From 4990adb740cb5b556d1bac1eeb14a9b38a92989e Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 19:27:26 +0700 Subject: [PATCH 437/658] domain reporting updated --- api/widget.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 74085e83..da18b1a9 100644 --- a/api/widget.js +++ b/api/widget.js @@ -493,12 +493,15 @@ ethplorerWidget.Type['tokenHistory'] = function(element, options, templates){ var requestOptions = ['limit', 'address', 'ts', 'showEth']; var params = { apiKey: 'ethplorer.widget', - type: 'transfer' + type: 'transfer', + domain: document.location.href, }; + /* if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; } + */ for(var key in this.options){ if(requestOptions.indexOf(key) >= 0){ params[key] = this.options[key]; From 6bce50992b845dbf1cdc58dc609528e4a8b1a433 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 19:51:31 +0700 Subject: [PATCH 438/658] api version fix updated --- api/widget.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/api/widget.js b/api/widget.js index da18b1a9..dbcfe89a 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1,6 +1,6 @@ ethplorerWidget = { // Ethplorer API URL - api: 'https://api.ethplorer.io', + api: 'https://api' + ((document.location.href.indexOf("//ethplorer.io") > 0) ? '2' : '') + '.ethplorer.io', // Ethplorer URL url: 'https://ethplorer.io', @@ -28,9 +28,6 @@ ethplorerWidget = { if(widgetOptions.onLoad) delete widgetOptions.onLoad; options.widgetOptions = widgetOptions; options.widgetType = type; - if(document.location.href.indexOf("//ethplorer.io") > 0){ - ethplorerWidget.api = ethplorerWidget.api.replace('api.', 'api2.'); - } if('undefined' === typeof(jQuery)){ console.error('Cannot initialize Ethplorer widget: jQuery not found.'); console.log('Add next string in the section of the page:'); From 5ed17f18079457887aee498ac96a349d61338c0c Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 27 Jul 2018 20:18:34 +0700 Subject: [PATCH 439/658] Remove eos from eth tokens. --- service/lib/ethplorer.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 50354f68..1e4001dc 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2541,6 +2541,10 @@ public function getTokenPrice30d($address){ public function getTokenPrice($address, $updateCache = FALSE){ // evxProfiler::checkpoint('getTokenPrice', 'START', 'address=' . $address . ', updateCache=' . ($updateCache ? 'TRUE' : 'FALSE')); $result = FALSE; + // exclude eos + if($address == '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0'){ + return $result; + } if(!$updateCache && isset($this->aPrices[$address])){ return $this->aPrices[$address]; } From 08f697b94bffc7228623a41f464d154f26b2f4c1 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 20:27:50 +0700 Subject: [PATCH 440/658] topTokens widget domain reporting fix --- api/widget.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index dbcfe89a..3c7ce518 100644 --- a/api/widget.js +++ b/api/widget.js @@ -724,12 +724,15 @@ ethplorerWidget.Type['topTokens'] = function(element, options, templates){ this.getRequestParams = function(additionalParams){ var requestOptions = ['limit', 'period', 'criteria']; var params = { - apiKey: 'ethplorer.widget' + apiKey: 'ethplorer.widget', + domain: document.location.href }; + /* if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; } + */ for(var key in this.options){ if(requestOptions.indexOf(key) >= 0){ params[key] = this.options[key]; From 14f89034ac214fdcf399d595ba7de3491ef15a33 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 27 Jul 2018 20:34:01 +0700 Subject: [PATCH 441/658] tokensTop fix --- api/widget.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 3c7ce518..ef7eac99 100644 --- a/api/widget.js +++ b/api/widget.js @@ -976,12 +976,15 @@ ethplorerWidget.Type['top'] = function(element, options, templates){ this.getRequestParams = function(additionalParams){ var requestOptions = ['limit', 'period', 'criteria']; var params = { - apiKey: 'ethplorer.widget' + apiKey: 'ethplorer.widget', + domain: document.location.href }; + /* if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; } + */ for(var key in this.options){ if(requestOptions.indexOf(key) >= 0){ params[key] = this.options[key]; From 38a7cae9631e7efab3f2c49c884a1b9453e9754c Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 30 Jul 2018 14:31:16 +0700 Subject: [PATCH 442/658] added OVER_LIMIT error for monitor api fix for method getPoolAddresses --- api/controller.php | 6 +++++- service/lib/ethplorer.php | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/api/controller.php b/api/controller.php index 6245413c..954e3c3a 100644 --- a/api/controller.php +++ b/api/controller.php @@ -65,6 +65,10 @@ class ethplorerController { 'ADDRESS_IS_CONTRACT' => [ 'code' => 115, 'message' => 'You can not use contract addresses' + ], + 'OVER_LIMIT' => [ + 'code' => 116, + 'message' => 'Poll is full' ] ]; @@ -574,7 +578,7 @@ public function createPool(){ $apiKey = $this->getPostRequest('apiKey'); $addresses = $this->getPostRequest('addresses'); $response = $this->db->createPool($apiKey, $addresses); - + $error = $response['error']['message'] ?? null; if ($error) { $rpcError = $this->APIErrors[$error]; diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 50354f68..67467a33 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3019,12 +3019,12 @@ public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ * @param int $poolId Pool id * @return array */ - public function getPoolAddresses($poolId, $updateCache = FALSE){ + public function getPoolAddresses($poolId, $updateCache = FALSE) { evxProfiler::checkpoint('getPoolAddresses', 'START'); $cache = 'pool_addresses-' . $poolId; - $aAddresses = $this->oCache->get($cache, false, true, 600) ?: ''; - if($updateCache || (false === $aAddresses)){ - $cursor = $this->oMongoPools->find('pools', ['uid' => $poolId]); + $aAddresses = $this->oCache->get($cache, false, true, 600); + if ($updateCache || (false === $aAddresses)) { + $cursor = $this->oMongoPools->find('pools', ['uid' => $poolId], false, 1); $result = ""; foreach($cursor as $result) break; if(isset($result['addresses'])){ From ad2b9ba5278d3e183075bbfe1ba95fbf39643a92 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 30 Jul 2018 14:38:29 +0700 Subject: [PATCH 443/658] error message fix --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 954e3c3a..f20516ff 100644 --- a/api/controller.php +++ b/api/controller.php @@ -68,7 +68,7 @@ class ethplorerController { ], 'OVER_LIMIT' => [ 'code' => 116, - 'message' => 'Poll is full' + 'message' => 'Pool capacity limit reached' ] ]; From 690029b23db3f3e4edffcfa306d891b63669e79c Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 30 Jul 2018 18:19:48 +0700 Subject: [PATCH 444/658] Log redis errors. --- service/lib/cache.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service/lib/cache.php b/service/lib/cache.php index e23e49d0..387fe9d7 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -205,6 +205,9 @@ public function save($entryName, $data, $nonExpiration = FALSE){ }else{ $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); } + if('OK' !== $saveRes){ + error_log("Write data to redis failed: " . $saveRes . " Data: " . json_encode($aCachedData) . " TTL: " . $ttl); + } $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); From 5a6f093499cb627e644007a7365641e270cef58c Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 30 Jul 2018 18:28:53 +0700 Subject: [PATCH 445/658] Log redis errors. --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index 387fe9d7..e6bd074f 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -205,7 +205,7 @@ public function save($entryName, $data, $nonExpiration = FALSE){ }else{ $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); } - if('OK' !== $saveRes){ + if('OK' !== (string)$saveRes){ error_log("Write data to redis failed: " . $saveRes . " Data: " . json_encode($aCachedData) . " TTL: " . $ttl); } $this->oDriver->getConnection()->switchToSlave(); From 74bb4bb317ee7c226dc045cfb3f2c40dbbeabaa8 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 31 Jul 2018 16:35:39 +0700 Subject: [PATCH 446/658] added pool exist checking method --- api/controller.php | 20 ++++++++++++++++++++ service/lib/ethplorer.php | 24 +++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index f20516ff..da8319f2 100644 --- a/api/controller.php +++ b/api/controller.php @@ -651,6 +651,13 @@ public function getPoolAddresses(){ $apiError = $this->APIErrors['NO_POOL_ID']; $this->sendError($apiError['code'], $apiError['message'], 400); } + + $addresses = $this->db->getPoolAddresses($poolId); + if ($addresses === false) { + $apiError = $this->APIErrors['POOL_NOT_FOUND']; + $this->sendError($apiError['code'], $apiError['message'], 400); + } + $result = array('addresses' => $this->db->getPoolAddresses($poolId)); $this->sendResult($result); } @@ -667,8 +674,15 @@ public function getPoolLastTransactions() { $apiError = $this->APIErrors['NO_POOL_ID']; $this->sendError($apiError['code'], $apiError['message'], 400); } + + if (!$this->db->isPoolExist($poolId)) { + $apiError = $this->APIErrors['POOL_NOT_FOUND']; + $this->sendError($apiError['code'], $apiError['message'], 400); + } + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastTransactions($poolId, $period); + $this->sendResult($result); } @@ -684,6 +698,12 @@ public function getPoolLastOperations() { $apiError = $this->APIErrors['NO_POOL_ID']; $this->sendError($apiError['code'], $apiError['message'], 400); } + + if (!$this->db->isPoolExist($poolId)) { + $apiError = $this->APIErrors['POOL_NOT_FOUND']; + $this->sendError($apiError['code'], $apiError['message'], 400); + } + $period = max(min(abs((int)$this->getRequest('period', 600)), 864000), 1); $result = $this->db->getPoolLastOperations($poolId, $period); $this->sendResult($result); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 00992ff4..c2a63b2c 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2996,6 +2996,24 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w return $result; } + /** + * Return true if pool exist + * @param String poolId + * @return Array + */ + public function isPoolExist($poolId) { + evxProfiler::checkpoint('isPoolExist', 'START'); + $cache = "pool-exist-{$poolId}"; + $pool = $this->oCache->get($cache, null, true, 600); + if ($pool === null) { + $cursor = $this->oMongoPools->find('pools', [ 'uid' => $poolId ], false, 1, false, [ 'uid' => 1 ]); + foreach($cursor as $result) break; + $this->oCache->save($cache, !empty($result)); + } + evxProfiler::checkpoint('isPoolExist', 'FINISH'); + return $pool; + } + /** * Create pool * @param String $apiKey @@ -3008,6 +3026,10 @@ public function createPool($apiKey, $addresses = NULL){ public function deletePool($poolId = NULL){ return $this->_jsonrpcall($this->aSettings['pools'], 'deletePool', array($poolId)); + // remove from cache + $this->oCache->delete("pool_addresses-{$poolId}"); + $this->oCache->delete("pool-exist-{$poolId}"); + } public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ @@ -3026,7 +3048,7 @@ public function updatePool($method = NULL, $poolId = NULL, $addresses = NULL){ public function getPoolAddresses($poolId, $updateCache = FALSE) { evxProfiler::checkpoint('getPoolAddresses', 'START'); $cache = 'pool_addresses-' . $poolId; - $aAddresses = $this->oCache->get($cache, false, true, 600); + $aAddresses = $this->oCache->get($cache, "", true, 600); if ($updateCache || (false === $aAddresses)) { $cursor = $this->oMongoPools->find('pools', ['uid' => $poolId], false, 1); $result = ""; From 2443fe6874cb7c1ba911d4d49f877a8842f656ce Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 31 Jul 2018 16:50:38 +0700 Subject: [PATCH 447/658] debugRPC param added --- service/lib/ethplorer.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 00992ff4..c5a146ba 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3205,6 +3205,9 @@ protected function _jsonrpcall($service, $method, $params = array()){ ); $result = false; $json = json_encode($data); + if(filter_input(INPUT_REQUEST, "debugRPC")){ + echo "Request: " . var_export($json, true) . "\n"; + } $ch = curl_init($service); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( @@ -3216,6 +3219,10 @@ protected function _jsonrpcall($service, $method, $params = array()){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $rjson = curl_exec($ch); + if(filter_input(INPUT_REQUEST, "debugRPC")){ + echo "Response: " . var_export($rjson, true) . "\n"; + die; + } if($rjson && (is_string($rjson)) && ('{' === $rjson[0])){ $json = json_decode($rjson, JSON_OBJECT_AS_ARRAY); if(isset($json["result"])){ From 59437f7279f6a7cfc7ffff377e2b364f80535a47 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 31 Jul 2018 17:03:16 +0700 Subject: [PATCH 448/658] debugRPC update --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 3191f17a..675201bd 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3227,7 +3227,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ ); $result = false; $json = json_encode($data); - if(filter_input(INPUT_REQUEST, "debugRPC")){ + if(filter_input(INPUT_GET, "debugRPC")){ echo "Request: " . var_export($json, true) . "\n"; } $ch = curl_init($service); @@ -3241,7 +3241,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $rjson = curl_exec($ch); - if(filter_input(INPUT_REQUEST, "debugRPC")){ + if(filter_input(INPUT_GET, "debugRPC")){ echo "Response: " . var_export($rjson, true) . "\n"; die; } From 6070038f73cfddd053b9c4bf66e3c31eac155505 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 31 Jul 2018 19:45:14 +0700 Subject: [PATCH 449/658] resolve conflicts --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index e6bd074f..cc096e8c 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -208,7 +208,7 @@ public function save($entryName, $data, $nonExpiration = FALSE){ if('OK' !== (string)$saveRes){ error_log("Write data to redis failed: " . $saveRes . " Data: " . json_encode($aCachedData) . " TTL: " . $ttl); } - $this->oDriver->getConnection()->switchToSlave(); + // $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } From 589273961e92ad60b7524aee93464f370277455b Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 31 Jul 2018 19:45:56 +0700 Subject: [PATCH 450/658] added method isPoolExist --- service/lib/ethplorer.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c2a63b2c..eefcc483 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3004,14 +3004,15 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w public function isPoolExist($poolId) { evxProfiler::checkpoint('isPoolExist', 'START'); $cache = "pool-exist-{$poolId}"; - $pool = $this->oCache->get($cache, null, true, 600); - if ($pool === null) { + $result = $this->oCache->get($cache, false, true, 600); + if ($result === false) { $cursor = $this->oMongoPools->find('pools', [ 'uid' => $poolId ], false, 1, false, [ 'uid' => 1 ]); - foreach($cursor as $result) break; - $this->oCache->save($cache, !empty($result)); + foreach($cursor as $pool) break; + $result = !empty($pool); + $this->oCache->save($cache, $result); } evxProfiler::checkpoint('isPoolExist', 'FINISH'); - return $pool; + return $result; } /** From b5cc0c543271ed9ebf6abd71e1c4be8197eb6c70 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Tue, 31 Jul 2018 20:17:12 +0700 Subject: [PATCH 451/658] return redis slave --- service/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index cc096e8c..e6bd074f 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -208,7 +208,7 @@ public function save($entryName, $data, $nonExpiration = FALSE){ if('OK' !== (string)$saveRes){ error_log("Write data to redis failed: " . $saveRes . " Data: " . json_encode($aCachedData) . " TTL: " . $ttl); } - // $this->oDriver->getConnection()->switchToSlave(); + $this->oDriver->getConnection()->switchToSlave(); }else{ $saveRes = $this->oDriver->set($entryName, $aCachedData); } From 3e70d9f7f411109cbbaf75c09cb93ed3310d94ec Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 1 Aug 2018 17:04:55 +0700 Subject: [PATCH 452/658] fix for getPoolLastTransactions and getPoolLastOperations methods --- service/lib/ethplorer.php | 6 +++--- service/lib/mongo_pools.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index a9bdac62..6f4b44bd 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3075,9 +3075,9 @@ public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ $cache = 'pool_transactions-' . $poolId. '-' . $period; $aTxs = $this->oCache->get($cache, false, true, 300); if($updateCache || (false === $aTxs)){ - $cursor = $this->oMongoPools->find('transactions', array('pool' => $poolId, 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); + $cursor = $this->oMongoPools->find('transactions', ['pools' => $poolId, 'timestamp' => ['$gte' => time() - $period] ], ['timestamp' => -1]); $aTxs = array(); - foreach($cursor as $tx){ + foreach($cursor as $tx) { $aAddresses = [$tx["from"]]; if($tx["from"] != $tx["to"]){ $aAddresses[] = $tx["to"]; @@ -3123,7 +3123,7 @@ public function getPoolLastOperations($poolId, $period, $updateCache = FALSE){ $cache = 'pool_operations-' . $poolId. '-' . $period; $aOps = $this->oCache->get($cache, false, true, 300); if($updateCache || (false === $aOps)){ - $cursor = $this->oMongoPools->find('operations', array('pool' => $poolId, 'contract' => array('$ne' => 'ETH'), 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); + $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'contract' => array('$ne' => 'ETH'), 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); $aOps = array(); foreach($cursor as $op){ $aAddresses = [$op["from"]]; diff --git a/service/lib/mongo_pools.php b/service/lib/mongo_pools.php index 4634e837..9f2ac5a9 100644 --- a/service/lib/mongo_pools.php +++ b/service/lib/mongo_pools.php @@ -46,8 +46,8 @@ protected function connectDb(){ $oDB = $this->oMongo->{$this->dbName}; $this->aDBs = array( 'pools' => $oDB->pools, - 'transactions' => $oDB->transactions, - 'operations' => $oDB->operations + 'transactions' => $oDB->monitor_transactions, + 'operations' => $oDB->monitor_operations ); break; // php version 5.6, 7.x use mongodb extension @@ -55,8 +55,8 @@ protected function connectDb(){ $this->oMongo = new MongoDB\Driver\Manager($aSettings['server']); $this->aDBs = array( 'pools' => "pools", - 'transactions' => "transactions", - 'operations' => "operations" + 'transactions' => "monitor_transactions", + 'operations' => "monitor_operations" ); break; default: From fe842de3c00af32c834b99b2ddc7951f5c9a0a33 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 1 Aug 2018 17:06:50 +0700 Subject: [PATCH 453/658] filterCommands added --- api/controller.php | 11 +++++------ service/lib/ethplorer.php | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/api/controller.php b/api/controller.php index da8319f2..bca447e0 100644 --- a/api/controller.php +++ b/api/controller.php @@ -103,9 +103,6 @@ public function __destruct(){ $ms = round(microtime(TRUE) - $this->startTime, 4); $date = date("Y-m-d H:i"); $key = $this->getRequest('apiKey', "-"); - if($key && ('freekey' !== $key)){ - file_put_contents($cacheDir . '/apiKey-' . md5($key) . '.tmp', $date); - } $source = $this->getRequest('domain', FALSE); if($source){ file_put_contents($logsDir . '/widget-request.log', "[$date] Widget: {$this->command}, source: {$source}\n", FILE_APPEND); @@ -158,8 +155,10 @@ public function sendError($code, $message, $statusCode = 200){ public function run(){ $result = FALSE; $command = $this->getCommand(); - if($command && (in_array($command, $this->apiCommands) || in_array($command, $this->apiPostCommands)) && method_exists($this, $command)){ - $key = in_array($command, $this->apiCommands) ? $this->getRequest('apiKey', FALSE) : $this->getPostRequest('apiKey', FALSE); + $isMethodGET = in_array($command, $this->db->getAllowedAPICommands($this->apiCommands)); + $isMethodPOST = in_array($command, $this->db->getAllowedAPICommands($this->apiPostCommands)); + if($command && ($isMethodGET || $isMethodPOST) && method_exists($this, $command)){ + $key = $isMethodGET ? $this->getRequest('apiKey', FALSE) : $this->getPostRequest('apiKey', FALSE); if(!$key || !$this->db->checkAPIkey($key)){ $this->sendError(1, 'Invalid API key', 403); } @@ -169,7 +168,7 @@ public function run(){ $this->sendError(133, 'API key temporary suspended. Contact support.', 403); } - if(in_array($command, $this->apiPostCommands)){ + if($isMethodPOST){ // @todo: Temporary solution, special key property will be used later if($key == "freekey"){ $this->sendError(1, 'Invalid API key', 403); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 675201bd..dc9dc551 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2237,6 +2237,20 @@ public function getTokensCountForLastDay($limit = 30, $showEth = FALSE){ return $result; } + public function getAllowedAPICommands(array $commands){ + $result = array(); + if(!empty($this->aSettings['allowedMethods'])){ + foreach($this->aSettings['allowedMethods'] as $command){ + if(in_array($command, $commands)){ + $result[] = $command; + } + } + }else{ + $result = $commands; + } + return $result; + } + public function checkAPIKey($key){ return isset($this->aSettings['apiKeys']) && isset($this->aSettings['apiKeys'][$key]); } From 3f157283e9b1d7ca11f74b2101adc5ed680af895 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 1 Aug 2018 17:08:21 +0700 Subject: [PATCH 454/658] realtime counts disabled in getTokenInfo --- api/controller.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/controller.php b/api/controller.php index bca447e0..a7ce163f 100644 --- a/api/controller.php +++ b/api/controller.php @@ -216,12 +216,14 @@ public function getTokenInfo(){ // unset($result['transfersCount']); // @todo: check what's wrong with cache + /* $result['countOps'] = $this->db->countOperations($address); $result['transfersCount'] = (int)$result['countOps']; if(isset($result['issuancesCount']) && $result['issuancesCount']){ $result['transfersCount'] = $result['transfersCount'] - (int)$result['issuancesCount']; } $result['holdersCount'] = $this->db->getTokenHoldersCount($address); + */ }else{ $this->sendError(150, 'Address is not a token contract'); } From e8cf724c118144c1573c61a200e95e4c6a54912e Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 1 Aug 2018 17:09:50 +0700 Subject: [PATCH 455/658] countOps reverted --- api/controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index a7ce163f..1535fccc 100644 --- a/api/controller.php +++ b/api/controller.php @@ -213,7 +213,8 @@ public function getTokenInfo(){ if($result && is_array($result)){ unset($result['checked']); unset($result['txsCount']); - // unset($result['transfersCount']); + + $result['countOps'] = isset($result['transfersCount']) ? $result['transfersCount'] : 0; // @todo: check what's wrong with cache /* From b4afa36845ee79aca9166ed0fb9c9b5b4235b451 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 1 Aug 2018 17:14:09 +0700 Subject: [PATCH 456/658] store apiKey in class --- api/controller.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/controller.php b/api/controller.php index 1535fccc..d4d78096 100644 --- a/api/controller.php +++ b/api/controller.php @@ -16,6 +16,7 @@ */ class ethplorerController { + protected $apiKey; protected $db; protected $command; protected $params = array(); @@ -180,6 +181,7 @@ public function run(){ $timestamp = $this->getRequest('ts', FALSE); $needCache = (FALSE !== $timestamp) || ($command === 'getAddressHistory'); + $this->apiKey = $key; if($needCache){ $cacheId = 'API-' . $command . '-' . md5($_SERVER["REQUEST_URI"]); $oCache = $this->db->getCache(); From e3b609e754224814bd203be3751d69222cc5f55f Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 1 Aug 2018 18:07:14 +0700 Subject: [PATCH 457/658] getPoolLastOperations and getPoolLastTransactions output fix --- service/lib/ethplorer.php | 87 ++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 6f4b44bd..2df522bc 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3076,31 +3076,37 @@ public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ $aTxs = $this->oCache->get($cache, false, true, 300); if($updateCache || (false === $aTxs)){ $cursor = $this->oMongoPools->find('transactions', ['pools' => $poolId, 'timestamp' => ['$gte' => time() - $period] ], ['timestamp' => -1]); - $aTxs = array(); + $aTxs = []; + $poolAddresses = $this->getPoolAddresses($poolId); foreach($cursor as $tx) { - $aAddresses = [$tx["from"]]; - if($tx["from"] != $tx["to"]){ - $aAddresses[] = $tx["to"]; + $gasLimit = $tx['gas']; + $gasUsed = isset($tx['gasUsed']) ? $tx['gasUsed'] : 0; + $success = ((21000 == $gasUsed) || ($gasUsed < $gasLimit)); + $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; + $transaction = [ + 'timestamp' => $tx["timestamp"], + 'blockNumber' => $tx["blockNumber"], + 'from' => $tx["from"], + 'to' => $tx["to"], + 'hash' => $tx["hash"], + 'value' => $tx["value"], + 'input' => $tx["input"], + 'balances' => $tx["balances"], + 'success' => $success + ]; + + if (stripos($poolAddresses, $tx["from"]) !== false) { + if (!is_array($aTxs[$tx["from"]])) { + $aTxs[$tx["from"]] = []; + } + $aTxs[$tx["from"]][] = $transaction; } - for($i = 0; $i < sizeof($aAddresses); $i++){ - if(!isset($aTxs[$aAddresses[$i]])){ - $aTxs[$aAddresses[$i]] = array(); + + if (stripos($poolAddresses, $tx["to"]) !== false) { + if (!is_array($aTxs[$tx["to"]])) { + $aTxs[$tx["to"]] = []; } - $gasLimit = $tx['gas']; - $gasUsed = isset($tx['gasUsed']) ? $tx['gasUsed'] : 0; - $success = ((21000 == $gasUsed) || ($gasUsed < $gasLimit)); - $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; - $aTxs[$aAddresses[$i]][] = array( - 'timestamp' => $tx["timestamp"], - 'blockNumber' => $tx["blockNumber"], - 'from' => $tx["from"], - 'to' => $tx["to"], - 'hash' => $tx["hash"], - 'value' => $tx["value"], - 'input' => $tx["input"], - 'balances' => $tx["balances"], - 'success' => $success, - ); + $aTxs[$tx["to"]][] = $transaction; } } if($aTxs){ @@ -3123,23 +3129,30 @@ public function getPoolLastOperations($poolId, $period, $updateCache = FALSE){ $cache = 'pool_operations-' . $poolId. '-' . $period; $aOps = $this->oCache->get($cache, false, true, 300); if($updateCache || (false === $aOps)){ - $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'contract' => array('$ne' => 'ETH'), 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); + $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); $aOps = array(); - foreach($cursor as $op){ - $aAddresses = [$op["from"]]; - if($op["from"] != $op["to"]){ - $aAddresses[] = $op["to"]; - } - foreach($op['addresses'] as $addr){ - if(!in_array($addr, $aAddresses)) $aAddresses[] = $addr; - } - for($i = 0; $i < sizeof($aAddresses); $i++){ - if(!isset($aOps[$aAddresses[$i]])){ - $aOps[$aAddresses[$i]] = array(); + $poolAddresses = $this->getPoolAddresses($poolId); + foreach($cursor as $op) { + $operation = [ + 'timestamp' => $op["timestamp"], + 'blockNumber' => $op["blockNumber"], + 'contract' => $op["contract"], + 'value' => $op["value"], + 'type' => $op["type"], + 'priority' => $op["priority"], + 'from' => $op["from"], + 'to' => $op["to"], + 'addresses' => $op["addresses"], + 'hash' => $op["hash"], + 'balances' => $op["balances"] + ]; + + if (stripos($poolAddresses, $op["from"]) !== false) { + $aOps[$op["from"]] = $operation; } - unset($op['_id']); - unset($op['pool']); - $aOps[$aAddresses[$i]][] = $op; + + if (stripos($poolAddresses, $op["to"]) !== false) { + $aOps[$op["to"]] = $operation; } } if($aOps){ From 09d569f14ddf09b1e805863b7bd36dbee30ff7d5 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 1 Aug 2018 18:13:25 +0700 Subject: [PATCH 458/658] create array if no records in getPoolLastOperations --- service/lib/ethplorer.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 226ce04c..49c9954e 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3162,10 +3162,16 @@ public function getPoolLastOperations($poolId, $period, $updateCache = FALSE){ ]; if (stripos($poolAddresses, $op["from"]) !== false) { - $aOps[$op["from"]] = $operation; + if (!is_array($aOps[$op["from"]])) { + $aOps[$op["from"]] = []; } + $aOps[$op["from"]] = $operation; + } if (stripos($poolAddresses, $op["to"]) !== false) { + if (!is_array($aOps[$op["to"]])) { + $aOps[$op["to"]] = []; + } $aOps[$op["to"]] = $operation; } } From 456141983bbd03795a35827ea330d6dff7c813a4 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 1 Aug 2018 18:56:52 +0700 Subject: [PATCH 459/658] no cache for getPoolLastOperations and getPoolLastTransactions --- service/lib/ethplorer.php | 136 +++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 75 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 49c9954e..abff0646 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3084,47 +3084,40 @@ public function getPoolAddresses($poolId, $updateCache = FALSE) { * @param int $period Period * @return array */ - public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ + public function getPoolLastTransactions($poolId, $period) { evxProfiler::checkpoint('getPoolLastTransactions', 'START'); - $cache = 'pool_transactions-' . $poolId. '-' . $period; - $aTxs = $this->oCache->get($cache, false, true, 300); - if($updateCache || (false === $aTxs)){ - $cursor = $this->oMongoPools->find('transactions', ['pools' => $poolId, 'timestamp' => ['$gte' => time() - $period] ], ['timestamp' => -1]); - $aTxs = []; - $poolAddresses = $this->getPoolAddresses($poolId); - foreach($cursor as $tx) { - $gasLimit = $tx['gas']; - $gasUsed = isset($tx['gasUsed']) ? $tx['gasUsed'] : 0; - $success = ((21000 == $gasUsed) || ($gasUsed < $gasLimit)); - $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; - $transaction = [ - 'timestamp' => $tx["timestamp"], - 'blockNumber' => $tx["blockNumber"], - 'from' => $tx["from"], - 'to' => $tx["to"], - 'hash' => $tx["hash"], - 'value' => $tx["value"], - 'input' => $tx["input"], - 'balances' => $tx["balances"], - 'success' => $success - ]; - - if (stripos($poolAddresses, $tx["from"]) !== false) { - if (!is_array($aTxs[$tx["from"]])) { - $aTxs[$tx["from"]] = []; - } - $aTxs[$tx["from"]][] = $transaction; - } - - if (stripos($poolAddresses, $tx["to"]) !== false) { - if (!is_array($aTxs[$tx["to"]])) { - $aTxs[$tx["to"]] = []; - } - $aTxs[$tx["to"]][] = $transaction; - } - } - if($aTxs){ - $this->oCache->save($cache, $aTxs); + $cursor = $this->oMongoPools->find('transactions', ['pools' => $poolId, 'timestamp' => ['$gte' => time() - $period] ], ['timestamp' => -1]); + $aTxs = []; + $poolAddresses = $this->getPoolAddresses($poolId); + foreach($cursor as $tx) { + $gasLimit = $tx['gas']; + $gasUsed = isset($tx['gasUsed']) ? $tx['gasUsed'] : 0; + $success = ((21000 == $gasUsed) || ($gasUsed < $gasLimit)); + $success = isset($tx['status']) ? $this->txSuccessStatus($tx) : $success; + $transaction = [ + 'timestamp' => $tx["timestamp"], + 'blockNumber' => $tx["blockNumber"], + 'from' => $tx["from"], + 'to' => $tx["to"], + 'hash' => $tx["hash"], + 'value' => $tx["value"], + 'input' => $tx["input"], + 'balances' => $tx["balances"], + 'success' => $success + ]; + + if (stripos($poolAddresses, $tx["from"]) !== false) { + if (!is_array($aTxs[$tx["from"]])) { + $aTxs[$tx["from"]] = []; + } + $aTxs[$tx["from"]][] = $transaction; + } + + if (stripos($poolAddresses, $tx["to"]) !== false) { + if (!is_array($aTxs[$tx["to"]])) { + $aTxs[$tx["to"]] = []; + } + $aTxs[$tx["to"]][] = $transaction; } } evxProfiler::checkpoint('getPoolLastTransactions', 'FINISH'); @@ -3138,45 +3131,38 @@ public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ * @param int $period Period * @return array */ - public function getPoolLastOperations($poolId, $period, $updateCache = FALSE){ + public function getPoolLastOperations($poolId, $period) { evxProfiler::checkpoint('getPoolLastOperations', 'START'); - $cache = 'pool_operations-' . $poolId. '-' . $period; - $aOps = $this->oCache->get($cache, false, true, 300); - if($updateCache || (false === $aOps)){ - $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); - $aOps = array(); - $poolAddresses = $this->getPoolAddresses($poolId); - foreach($cursor as $op) { - $operation = [ - 'timestamp' => $op["timestamp"], - 'blockNumber' => $op["blockNumber"], - 'contract' => $op["contract"], - 'value' => $op["value"], - 'type' => $op["type"], - 'priority' => $op["priority"], - 'from' => $op["from"], - 'to' => $op["to"], - 'addresses' => $op["addresses"], - 'hash' => $op["hash"], - 'balances' => $op["balances"] - ]; - - if (stripos($poolAddresses, $op["from"]) !== false) { - if (!is_array($aOps[$op["from"]])) { - $aOps[$op["from"]] = []; - } - $aOps[$op["from"]] = $operation; + $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); + $aOps = array(); + $poolAddresses = $this->getPoolAddresses($poolId); + foreach($cursor as $op) { + $operation = [ + 'timestamp' => $op["timestamp"], + 'blockNumber' => $op["blockNumber"], + 'contract' => $op["contract"], + 'value' => $op["value"], + 'type' => $op["type"], + 'priority' => $op["priority"], + 'from' => $op["from"], + 'to' => $op["to"], + 'addresses' => $op["addresses"], + 'hash' => $op["hash"], + 'balances' => $op["balances"] + ]; + + if (stripos($poolAddresses, $op["from"]) !== false) { + if (!is_array($aOps[$op["from"]])) { + $aOps[$op["from"]] = []; } + $aOps[$op["from"]] = $operation; + } - if (stripos($poolAddresses, $op["to"]) !== false) { - if (!is_array($aOps[$op["to"]])) { - $aOps[$op["to"]] = []; - } - $aOps[$op["to"]] = $operation; + if (stripos($poolAddresses, $op["to"]) !== false) { + if (!is_array($aOps[$op["to"]])) { + $aOps[$op["to"]] = []; } - } - if($aOps){ - $this->oCache->save($cache, $aOps); + $aOps[$op["to"]] = $operation; } } evxProfiler::checkpoint('getPoolLastOperations', 'FINISH'); From a53629be06e579730a3cb5d566ec5fd1cceecf56 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Wed, 1 Aug 2018 18:59:58 +0700 Subject: [PATCH 460/658] 30 seconds cache for getPoolLastOperations and getPoolLastTransactions --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 49c9954e..f3687169 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3087,7 +3087,7 @@ public function getPoolAddresses($poolId, $updateCache = FALSE) { public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ evxProfiler::checkpoint('getPoolLastTransactions', 'START'); $cache = 'pool_transactions-' . $poolId. '-' . $period; - $aTxs = $this->oCache->get($cache, false, true, 300); + $aTxs = $this->oCache->get($cache, false, true, 30); if($updateCache || (false === $aTxs)){ $cursor = $this->oMongoPools->find('transactions', ['pools' => $poolId, 'timestamp' => ['$gte' => time() - $period] ], ['timestamp' => -1]); $aTxs = []; @@ -3141,7 +3141,7 @@ public function getPoolLastTransactions($poolId, $period, $updateCache = FALSE){ public function getPoolLastOperations($poolId, $period, $updateCache = FALSE){ evxProfiler::checkpoint('getPoolLastOperations', 'START'); $cache = 'pool_operations-' . $poolId. '-' . $period; - $aOps = $this->oCache->get($cache, false, true, 300); + $aOps = $this->oCache->get($cache, false, true, 30); if($updateCache || (false === $aOps)){ $cursor = $this->oMongoPools->find('operations', array('pools' => $poolId, 'timestamp' => array('$gte' => time() - $period)), array("timestamp" => -1)); $aOps = array(); From 48c31cf447a2aab3b3df435db9f978cb20fbff23 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 6 Aug 2018 17:18:51 +0700 Subject: [PATCH 461/658] getPoolLastOperations contract case added --- service/lib/ethplorer.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index bcae26e8..45c4c7d3 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3160,6 +3160,13 @@ public function getPoolLastOperations($poolId, $period, $updateCache = false) { 'hash' => $op["hash"], 'balances' => $op["balances"] ]; + + if (stripos($poolAddresses, $op["contract"]) !== false) { + if (!is_array($aOps[$op["contract"]])) { + $aOps[$op["contract"]] = []; + } + $aOps[$op["contract"]] = $operation; + } if (stripos($poolAddresses, $op["from"]) !== false) { if (!is_array($aOps[$op["from"]])) { From 7dc5202e2a5f841375d1b206cee6d2fb9b0bf299 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 6 Aug 2018 17:21:29 +0700 Subject: [PATCH 462/658] Array bug fix --- service/lib/ethplorer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 45c4c7d3..c6167ab4 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3165,21 +3165,21 @@ public function getPoolLastOperations($poolId, $period, $updateCache = false) { if (!is_array($aOps[$op["contract"]])) { $aOps[$op["contract"]] = []; } - $aOps[$op["contract"]] = $operation; + $aOps[$op["contract"]][] = $operation; } if (stripos($poolAddresses, $op["from"]) !== false) { if (!is_array($aOps[$op["from"]])) { $aOps[$op["from"]] = []; } - $aOps[$op["from"]] = $operation; + $aOps[$op["from"]][] = $operation; } if (stripos($poolAddresses, $op["to"]) !== false) { if (!is_array($aOps[$op["to"]])) { $aOps[$op["to"]] = []; } - $aOps[$op["to"]] = $operation; + $aOps[$op["to"]][] = $operation; } } if($aOps){ From 30ecea71b3872cedd169de33f9195e1d5d49089a Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Mon, 6 Aug 2018 17:24:37 +0700 Subject: [PATCH 463/658] hide addresses field in pool operations --- service/lib/ethplorer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index c6167ab4..a287af08 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3156,7 +3156,6 @@ public function getPoolLastOperations($poolId, $period, $updateCache = false) { 'priority' => $op["priority"], 'from' => $op["from"], 'to' => $op["to"], - 'addresses' => $op["addresses"], 'hash' => $op["hash"], 'balances' => $op["balances"] ]; From 3ceb3cca0aa1fb9eb3c1e759f635ab3115b417f5 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 6 Aug 2018 18:36:07 +0700 Subject: [PATCH 464/658] getMongo added --- service/lib/ethplorer.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index a287af08..52f14b14 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -217,6 +217,15 @@ public function getCache(){ return $this->oCache; } + /** + * Returns mongo object + * + * @return evxMongo + */ + public function getMongo(){ + return $this->oMongo; + } + /** * Returns some debug data * From 382591c3634465a3b9937c044b23f77bc5a86009 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 8 Aug 2018 14:27:51 +0700 Subject: [PATCH 465/658] Chainy bug fixed. --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index d4d78096..5f90e71f 100644 --- a/api/controller.php +++ b/api/controller.php @@ -518,7 +518,7 @@ public function getPriceHistoryGrouped(){ $this->sendResult($result); return; } - if($token = $this->db->getToken($address) || $address == $this->db->ADDRESS_CHAINY){ + if($token = $this->db->getToken($address) || $address == $this->db::ADDRESS_CHAINY){ $this->getTokenPriceHistoryGrouped(); }else{ $this->getAddressPriceHistoryGrouped(); From 7f401e2da343cf4f7a0bba80c45bbba8474ddf31 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 8 Aug 2018 14:29:54 +0700 Subject: [PATCH 466/658] Chainy bug fixed. --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 5f90e71f..65f447fc 100644 --- a/api/controller.php +++ b/api/controller.php @@ -518,7 +518,7 @@ public function getPriceHistoryGrouped(){ $this->sendResult($result); return; } - if($token = $this->db->getToken($address) || $address == $this->db::ADDRESS_CHAINY){ + if($token = $this->db->getToken($address) || $this->db->isChainyAddress($address)){ $this->getTokenPriceHistoryGrouped(); }else{ $this->getAddressPriceHistoryGrouped(); From 9e6add50343207a8457e72e8c0e014beed67b562 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 8 Aug 2018 15:14:23 +0700 Subject: [PATCH 467/658] Chainy bug fixed. --- service/lib/ethplorer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 52f14b14..9d11cb99 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2421,7 +2421,7 @@ public function getAllHolders(){ */ protected function getChainyTransactions($limit = 10, $offset = FALSE){ $result = array(); - $search = array('to' => self::ADDRESS_CHAINY); + $search = array('to' => self::ADDRESS_CHAINY, 'status' => array('$ne' => '0x0')); if($this->filter){ $search = array( '$and' => array( @@ -2491,7 +2491,7 @@ protected function getChainyTokenHistoryGrouped($period = 30){ * @return int */ public function countChainy($useFilter = TRUE){ - $search = array('to' => self::ADDRESS_CHAINY); + $search = array('to' => self::ADDRESS_CHAINY, 'status' => array('$ne' => '0x0')); if($useFilter && $this->filter){ $search = array( '$and' => array( From 048f2bea70f371a8b80fb2fea3ce8e300ba0df37 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 8 Aug 2018 15:41:58 +0700 Subject: [PATCH 468/658] Chainy bug fixed. --- service/lib/ethplorer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 9d11cb99..b293a94d 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2459,7 +2459,8 @@ protected function getChainyTokenHistoryGrouped($period = 30){ $result = array(); $aMatch = array( "timestamp" => array('$gt' => time() - $period * 24 * 3600), - "to" => self::ADDRESS_CHAINY + "to" => self::ADDRESS_CHAINY, + 'status' => array('$ne' => '0x0') ); $dbData = $this->oMongo->aggregate( 'transactions', From 6a5ffc79701e1cef49853924fd57cb95bc7b55cd Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 5 Sep 2018 21:08:53 +0700 Subject: [PATCH 469/658] Short cache for getLastTransfers added --- service/lib/ethplorer.php | 65 +++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index b293a94d..6fc6b1d3 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1461,40 +1461,45 @@ public function getAddressBalances($address, $withZero = TRUE, $withEth = FALSE) * @return array */ public function getLastTransfers(array $options = array(), $showEth = FALSE){ - $search = array(); - if(isset($options['address']) && !isset($options['history'])){ - $search['contract'] = $options['address']; - } - if(isset($options['address']) && isset($options['history'])){ - $search['addresses'] = $options['address']; - } - if(isset($options['token']) && isset($options['history'])){ - $search['contract'] = $options['token']; - } - if(!$showEth){ - $search['isEth'] = false; - } - if(!isset($options['type'])){ - $search['type'] = 'transfer'; - }else{ - if(FALSE !== $options['type']){ - $search['type'] = $options['type']; + $cache = 'get-last-transfers-' . md5(json_encode($options)) . '-' . ($showEth ? 'eth' : 'no-eth'); + $result = $this->oCache->get($cache, false, true, 10); + if(FALSE === $result){ + $search = array(); + if(isset($options['address']) && !isset($options['history'])){ + $search['contract'] = $options['address']; } - } - $sort = array("timestamp" => -1); + if(isset($options['address']) && isset($options['history'])){ + $search['addresses'] = $options['address']; + } + if(isset($options['token']) && isset($options['history'])){ + $search['contract'] = $options['token']; + } + if(!$showEth){ + $search['isEth'] = false; + } + if(!isset($options['type'])){ + $search['type'] = 'transfer'; + }else{ + if(FALSE !== $options['type']){ + $search['type'] = $options['type']; + } + } + $sort = array("timestamp" => -1); - if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ - $search['timestamp'] = array('$lte' => $options['timestamp']); - } + if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ + $search['timestamp'] = array('$lte' => $options['timestamp']); + } - $limit = isset($options['limit']) ? (int)$options['limit'] : false; - $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); + $limit = isset($options['limit']) ? (int)$options['limit'] : false; + $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); - $result = array(); - foreach($cursor as $transfer){ - $transfer['token'] = $this->getToken($transfer['contract'], true); - unset($transfer["_id"]); - $result[] = $transfer; + $result = array(); + foreach($cursor as $transfer){ + $transfer['token'] = $this->getToken($transfer['contract'], true); + unset($transfer["_id"]); + $result[] = $transfer; + } + $this->oCache->save($cache, $result); } return $result; } From 3148d91a68611cae8f2c7faf8ee1761b82af0d1f Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 5 Sep 2018 21:14:58 +0700 Subject: [PATCH 470/658] Caching updated --- service/lib/ethplorer.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 6fc6b1d3..288c2084 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1462,10 +1462,11 @@ public function getAddressBalances($address, $withZero = TRUE, $withEth = FALSE) */ public function getLastTransfers(array $options = array(), $showEth = FALSE){ $cache = 'get-last-transfers-' . md5(json_encode($options)) . '-' . ($showEth ? 'eth' : 'no-eth'); - $result = $this->oCache->get($cache, false, true, 10); + $searchToken = (isset($options['address']) && !isset($options['history'])); + $result = $this->oCache->get($cache, false, true, (($searchToken && !$showEth) ? 60 : 10)); if(FALSE === $result){ $search = array(); - if(isset($options['address']) && !isset($options['history'])){ + if($searchToken){ $search['contract'] = $options['address']; } if(isset($options['address']) && isset($options['history'])){ From 8686efb1a974978c529efd59a906e71b895c4183 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 5 Sep 2018 21:20:38 +0700 Subject: [PATCH 471/658] Reverted and optimized --- service/lib/ethplorer.php | 66 ++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 288c2084..2c08d627 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1461,46 +1461,40 @@ public function getAddressBalances($address, $withZero = TRUE, $withEth = FALSE) * @return array */ public function getLastTransfers(array $options = array(), $showEth = FALSE){ - $cache = 'get-last-transfers-' . md5(json_encode($options)) . '-' . ($showEth ? 'eth' : 'no-eth'); - $searchToken = (isset($options['address']) && !isset($options['history'])); - $result = $this->oCache->get($cache, false, true, (($searchToken && !$showEth) ? 60 : 10)); - if(FALSE === $result){ - $search = array(); - if($searchToken){ - $search['contract'] = $options['address']; - } - if(isset($options['address']) && isset($options['history'])){ - $search['addresses'] = $options['address']; - } - if(isset($options['token']) && isset($options['history'])){ - $search['contract'] = $options['token']; - } - if(!$showEth){ - $search['isEth'] = false; - } - if(!isset($options['type'])){ - $search['type'] = 'transfer'; - }else{ - if(FALSE !== $options['type']){ - $search['type'] = $options['type']; - } + $search = array(); + if(isset($options['address']) && !isset($options['history'])){ + $search['contract'] = $options['address']; + } + if(isset($options['address']) && isset($options['history'])){ + $search['addresses'] = $options['address']; + } + if(isset($options['token']) && isset($options['history'])){ + $search['contract'] = $options['token']; + } + if(!$showEth && !isset($search['contract'])){ + $search['isEth'] = false; + } + if(!isset($options['type'])){ + $search['type'] = 'transfer'; + }else{ + if(FALSE !== $options['type']){ + $search['type'] = $options['type']; } - $sort = array("timestamp" => -1); + } + $sort = array("timestamp" => -1); - if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ - $search['timestamp'] = array('$lte' => $options['timestamp']); - } + if(isset($options['timestamp']) && ($options['timestamp'] > 0)){ + $search['timestamp'] = array('$lte' => $options['timestamp']); + } - $limit = isset($options['limit']) ? (int)$options['limit'] : false; - $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); + $limit = isset($options['limit']) ? (int)$options['limit'] : false; + $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); - $result = array(); - foreach($cursor as $transfer){ - $transfer['token'] = $this->getToken($transfer['contract'], true); - unset($transfer["_id"]); - $result[] = $transfer; - } - $this->oCache->save($cache, $result); + $result = array(); + foreach($cursor as $transfer){ + $transfer['token'] = $this->getToken($transfer['contract'], true); + unset($transfer["_id"]); + $result[] = $transfer; } return $result; } From 00c38025476abad6cb9fedd8d29f2f10b7fd045c Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 5 Sep 2018 21:48:23 +0700 Subject: [PATCH 472/658] getToken caching --- service/lib/ethplorer.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2c08d627..ffee9fff 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1491,8 +1491,14 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ $cursor = $this->oMongo->find('operations2', $search, $sort, $limit); $result = array(); + $aTokens = array(); foreach($cursor as $transfer){ - $transfer['token'] = $this->getToken($transfer['contract'], true); + if(!$transfer['isEth']){ + if(!isset($aTokens[$transfer['contract']])){ + $aTokens[$transfer['contract']] = $this->getToken($transfer['contract'], true); + } + $transfer['token'] = $aTokens[$transfer['contract']]; + } unset($transfer["_id"]); $result[] = $transfer; } From 36610668db5dda2bd0f2565c596165d1eed6fca0 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 7 Sep 2018 14:37:09 +0700 Subject: [PATCH 473/658] Cursor timeout added --- service/lib/ethplorer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ffee9fff..2a50e67b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1003,6 +1003,7 @@ public function getTokens($updateCache = false){ } $this->_cliDebug("prevTokens count = " . count($aPrevTokens)); $cursor = $this->oMongo->find('tokens', array(), array("transfersCount" => -1)); + $cursor->timeout(-1); $aResult = array(); foreach($cursor as $index => $aToken){ $address = $aToken["address"]; From 02bdce280db934539ed19e82a188878362c730dd Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 7 Sep 2018 14:46:11 +0700 Subject: [PATCH 474/658] Revert wrong code --- service/lib/ethplorer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2a50e67b..ffee9fff 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1003,7 +1003,6 @@ public function getTokens($updateCache = false){ } $this->_cliDebug("prevTokens count = " . count($aPrevTokens)); $cursor = $this->oMongo->find('tokens', array(), array("transfersCount" => -1)); - $cursor->timeout(-1); $aResult = array(); foreach($cursor as $index => $aToken){ $address = $aToken["address"]; From 616c0e80f20419f9351bf3c24ea5d187920071b3 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 7 Sep 2018 14:51:59 +0700 Subject: [PATCH 475/658] Notes updated --- css/ethplorer.css | 4 ++++ js/ethplorer-note.js | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/css/ethplorer.css b/css/ethplorer.css index 427c6ccf..2e78f616 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -53,6 +53,10 @@ tr.paginationFooter td ul.pagination { font-weight: 300; } +#ethplorer-note.warning { + background-color: rgba(255,0,0,1); +} + #ethplorer-note .ethplorer-note img { height: 35px; margin-top: -10px; diff --git a/js/ethplorer-note.js b/js/ethplorer-note.js index 0da2c4ee..5eaf441a 100644 --- a/js/ethplorer-note.js +++ b/js/ethplorer-note.js @@ -48,6 +48,11 @@ EthplorerNote = { EthplorerNote.container.show(); var note = EthplorerNote.notes[EthplorerNote.next]; + if(note.warning){ + EthplorerNote.container.addClass('warning'); + }else{ + EthplorerNote.container.removeClass('warning'); + } EthplorerNote.inner.fadeOut(500, function(_data){ return function(){ var link = "/go.php?link=" + _data.link; From 141d189d501368a0c23c6bf7c2a42f6765449bf8 Mon Sep 17 00:00:00 2001 From: Nikolay Evseev Date: Fri, 7 Sep 2018 17:08:03 +0700 Subject: [PATCH 476/658] rename rpc error code ADDRESS_IS_CONTRACT to ADDRESS_IS_TOKEN --- api/controller.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/controller.php b/api/controller.php index 65f447fc..4166c9e9 100644 --- a/api/controller.php +++ b/api/controller.php @@ -63,9 +63,9 @@ class ethplorerController { 'code' => 114, 'message' => 'Pool not found' ], - 'ADDRESS_IS_CONTRACT' => [ + 'ADDRESS_IS_TOKEN' => [ 'code' => 115, - 'message' => 'You can not use contract addresses' + 'message' => 'You can not use token addresses' ], 'OVER_LIMIT' => [ 'code' => 116, @@ -168,7 +168,7 @@ public function run(){ if($this->db->isSuspendedAPIKey($key)){ $this->sendError(133, 'API key temporary suspended. Contact support.', 403); } - + if($isMethodPOST){ // @todo: Temporary solution, special key property will be used later if($key == "freekey"){ From dd4fb9a8bd4a9d0ff096d42064ff1c5a89794ff9 Mon Sep 17 00:00:00 2001 From: Artem Date: Fri, 7 Sep 2018 19:49:37 +0700 Subject: [PATCH 477/658] getTokens - save cache even on exception --- service/lib/ethplorer.php | 79 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ffee9fff..05041c8b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1003,45 +1003,52 @@ public function getTokens($updateCache = false){ } $this->_cliDebug("prevTokens count = " . count($aPrevTokens)); $cursor = $this->oMongo->find('tokens', array(), array("transfersCount" => -1)); - $aResult = array(); - foreach($cursor as $index => $aToken){ - $address = $aToken["address"]; - $this->_cliDebug("Token #" . $index . " / " . $address); - unset($aToken["_id"]); - $aResult[$address] = $aToken; - if(!isset($aPrevTokens[$address]) || ($aPrevTokens[$address]['transfersCount'] < $aToken['transfersCount'])){ - $this->_cliDebug($address . " was recently updated (transfers count = " . $aToken['transfersCount'] . ")"); - $aResult[$address]['issuancesCount'] = $this->getContractOperationCount(array('$in' => array('issuance', 'burn', 'mint')), $address, FALSE); - $hc = $this->getTokenHoldersCount($address);; - if(FALSE !== $hc){ - $aResult[$address]['holdersCount'] = $hc; - } - }else if(!isset($aPrevTokens[$address]) || !isset($aPrevTokens[$address]['issuancesCount'])){ - $aResult[$address]['issuancesCount'] = $this->getContractOperationCount(array('$in' => array('issuance', 'burn', 'mint')), $address, FALSE); - }else{ - $aResult[$address]['issuancesCount'] = isset($aPrevTokens[$address]['issuancesCount']) ? $aPrevTokens[$address]['issuancesCount'] : 0; - $aResult[$address]['holdersCount'] = isset($aPrevTokens[$address]['holdersCount']) ? $aPrevTokens[$address]['holdersCount'] : 0; - } - if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens'])){ - $aClientTokens = $this->aSettings['client']['tokens']; - if(isset($aClientTokens[$address])){ - $aResult[$address] = array_merge($aResult[$address], $aClientTokens[$address]); + // Do not clear old data, just update records + if(!is_array($aResult)){ + $aResult = array(); + } + try { + foreach($cursor as $index => $aToken){ + $address = $aToken["address"]; + $this->_cliDebug("Token #" . $index . " / " . $address); + unset($aToken["_id"]); + $aResult[$address] = $aToken; + if(!isset($aPrevTokens[$address]) || ($aPrevTokens[$address]['transfersCount'] < $aToken['transfersCount'])){ + $this->_cliDebug($address . " was recently updated (transfers count = " . $aToken['transfersCount'] . ")"); + $aResult[$address]['issuancesCount'] = $this->getContractOperationCount(array('$in' => array('issuance', 'burn', 'mint')), $address, FALSE); + $hc = $this->getTokenHoldersCount($address);; + if(FALSE !== $hc){ + $aResult[$address]['holdersCount'] = $hc; + } + }else if(!isset($aPrevTokens[$address]) || !isset($aPrevTokens[$address]['issuancesCount'])){ + $aResult[$address]['issuancesCount'] = $this->getContractOperationCount(array('$in' => array('issuance', 'burn', 'mint')), $address, FALSE); + }else{ + $aResult[$address]['issuancesCount'] = isset($aPrevTokens[$address]['issuancesCount']) ? $aPrevTokens[$address]['issuancesCount'] : 0; + $aResult[$address]['holdersCount'] = isset($aPrevTokens[$address]['holdersCount']) ? $aPrevTokens[$address]['holdersCount'] : 0; + } + if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens'])){ + $aClientTokens = $this->aSettings['client']['tokens']; + if(isset($aClientTokens[$address])){ + $aResult[$address] = array_merge($aResult[$address], $aClientTokens[$address]); + } + } + if(isset($aResult[$address]['name'])){ + $aResult[$address]['name'] = htmlspecialchars($aResult[$address]['name']); + } + if(isset($aResult[$address]['symbol'])){ + $aResult[$address]['symbol'] = htmlspecialchars($aResult[$address]['symbol']); } - } - if(isset($aResult[$address]['name'])){ - $aResult[$address]['name'] = htmlspecialchars($aResult[$address]['name']); - } - if(isset($aResult[$address]['symbol'])){ - $aResult[$address]['symbol'] = htmlspecialchars($aResult[$address]['symbol']); - } - $cursor2 = $this->oMongo->find('addressCache', array("address" => $address)); - $aCachedData = false; - foreach($cursor2 as $aCachedData) break; - if(false !== $aCachedData){ - $aResult[$address]['txsCount'] = $aCachedData['txsCount']; - if(isset($aCachedData['ethTransfersCount'])) $aResult[$address]['ethTransfersCount'] = $aCachedData['ethTransfersCount']; + $cursor2 = $this->oMongo->find('addressCache', array("address" => $address)); + $aCachedData = false; + foreach($cursor2 as $aCachedData) break; + if(false !== $aCachedData){ + $aResult[$address]['txsCount'] = $aCachedData['txsCount']; + if(isset($aCachedData['ethTransfersCount'])) $aResult[$address]['ethTransfersCount'] = $aCachedData['ethTransfersCount']; + } } + }catch(\Exception $e){ + $this->_cliDebug("Exception: " . $e->getMessage()); } if(isset($aResult[self::ADDRESS_ETH])){ unset($aResult[self::ADDRESS_ETH]); From f3f068e8b6d10f43a6239d0f8eb1061d54ae91ba Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 7 Sep 2018 20:40:18 +0700 Subject: [PATCH 478/658] Testing historic data fixed. --- tests/ratesTest.php | 49 ++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/tests/ratesTest.php b/tests/ratesTest.php index dea79002..17961bd3 100644 --- a/tests/ratesTest.php +++ b/tests/ratesTest.php @@ -25,38 +25,22 @@ public function ratesProvider() [[ 'type' => 'compare', 'method' => 'getCurrencyHistory', - 'description' => '= Comparing historical currencies with USD =', + 'description' => '= Comparing historical currencies (THB, MMK, EUR, CNY, GBP, JPY, RUB, BTC) with USD =', 'compareFrom' => 'USD', - 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB'], + 'compareTo' => ['THB', 'MMK', 'EUR', 'CNY', 'GBP', 'JPY', 'RUB', 'BTC'], 'compareType' => 'normal', - 'compareSourceParam' => 'CURRFX', 'compareTime' => 'historic', - 'callback' => function($database, $dataset){ - $apiKey = 'SS1Kj9CAzyj9bGssEQz9'; - $url = 'https://www.quandl.com/api/v1/datasets/'.$database. - '/'.$dataset.'.json?auth_token='.$apiKey.'&trim_start=2015-04-01'; - $json = file_get_contents($url); - $result = json_decode($json, TRUE); - return $result['data']; - } - ]], - [[ - 'type' => 'compare', - 'method' => 'getCurrencyHistory', - 'description' => '= Comparing historical BTC to USD =', - 'compareFrom' => 'USD', - 'compareTo' => ['BTC'], - 'compareReplace' => 'MKPRU', - 'compareType' => 'reverse', - 'compareSourceParam' => 'BCHAIN', - 'compareTime' => 'historic', - 'callback' => function($database, $dataset){ - $apiKey = 'SS1Kj9CAzyj9bGssEQz9'; - $url = 'https://www.quandl.com/api/v1/datasets/'.$database. - '/'.$dataset.'.json?auth_token='.$apiKey.'&trim_start=2015-04-01'; + 'callback' => function($currency){ + $apiKey = $this->getOxrApiKey(); + $randomDate = date("Y-m-d", mt_rand(1427846400, time() - (24 * 60 * 60))); + $url = 'https://openexchangerates.org/api/historical/' . $randomDate . '.json?app_id=' . $apiKey; $json = file_get_contents($url); $result = json_decode($json, TRUE); - return $result['data']; + $rate = 0; + if(isset($result['rates']) && isset($result['rates'][$currency])){ + $rate = $result['rates'][$currency]; + } + return array('currency' => $currency, 'date' => $randomDate, 'rate' => $rate); } ]], [[ @@ -202,7 +186,7 @@ public function ratesProvider() 'compareType' => 'key', 'compareTime' => 'current', 'callback' => function(){ - $apiKey = '56373b75d3204d008efa8b62e0589743'; + $apiKey = $this->getOxrApiKey(); $url = 'https://openexchangerates.org/api/latest.json?app_id='.$apiKey; $json = file_get_contents($url); $result = json_decode($json, TRUE); @@ -234,7 +218,7 @@ public function ratesProvider() 'compareType' => 'key-reverse', 'compareTime' => 'current', 'callback' => function(){ - $apiKey = '56373b75d3204d008efa8b62e0589743'; + $apiKey = $this->getOxrApiKey(); $url = 'https://openexchangerates.org/api/latest.json?app_id='.$apiKey; $json = file_get_contents($url); $result = json_decode($json, TRUE); @@ -244,6 +228,11 @@ public function ratesProvider() ]; } + protected function getOxrApiKey(){ + global $argv; + return $argv[2]; + } + private function getDataFromHtml($html) { $DOM = new DOMDocument; @@ -269,7 +258,7 @@ private function getHtmlData($currency) $array_elem = array(); foreach ($values as $innerkey => $val) { - if ($innerkey == 1){ + if ($innerkey == 0){ $val = date('Y-m-d', strtotime($val)); } else { $val = str_replace( ',', '', $val ); From 2d4f0d6f74354acde62b1d02f6e3e8279a86a4f1 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 11 Sep 2018 17:38:52 +0700 Subject: [PATCH 479/658] Getting daily price history changed. --- service/lib/ethplorer.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 05041c8b..d29ab9a8 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2744,10 +2744,9 @@ public function getTokenPriceHistory($address, $period = 0, $type = 'hourly', $u if(!$curDate || ($curDate != $aPriceHistory[$i]['date'])){ $aDailyRecord = $aPriceHistory[$i]; $firstRecord = true; - }else{ - if(($i == (count($aPriceHistory) - 1)) || ($aPriceHistory[$i]['date'] != $aPriceHistory[$i + 1]['date'])){ - $lastRecord = true; - } + } + if(($i == (count($aPriceHistory) - 1)) || ($aPriceHistory[$i]['date'] != $aPriceHistory[$i + 1]['date'])){ + $lastRecord = true; if($lastRecord){ $aDailyRecord['close'] = $aPriceHistory[$i]['close']; } From d8875ef7d58ebf1a425b01a6253f32597a292872 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 11 Sep 2018 17:46:54 +0700 Subject: [PATCH 480/658] Getting daily price history fixed. --- service/lib/ethplorer.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index d29ab9a8..f634873c 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2770,7 +2770,10 @@ public function getTokenPriceHistory($address, $period = 0, $type = 'hourly', $u if($prevVolC && (($aDailyRecord['volumeConverted'] / $prevVolC) > 1000000)){ $aDailyRecord['volumeConverted'] = $prevVolC; } - $aDailyRecord['average'] = $aDailyRecord['volume'] ? ($aDailyRecord['volumeConverted'] / $aDailyRecord['volume']) : 0; + if($aDailyRecord['volume'] && $aDailyRecord['volumeConverted']){ + $aDailyRecord['average'] = $aDailyRecord['volumeConverted'] / $aDailyRecord['volume']; + } + if(!isset($aDailyRecord['average'])) $aDailyRecord['average'] = 0; $aPriceHistoryDaily[] = $aDailyRecord; $prevVol = $aDailyRecord['volume']; $prevVolC = $aDailyRecord['volumeConverted']; From 7bb7cd9b8ac5834168c88482ba0efa9454dff0b7 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 12 Sep 2018 17:08:21 +0700 Subject: [PATCH 481/658] Widget token price history updated. --- api/widget.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/api/widget.js b/api/widget.js index ef7eac99..3c547dbb 100644 --- a/api/widget.js +++ b/api/widget.js @@ -253,7 +253,7 @@ ethplorerWidget = { // Use local path for develop instances fixPath: function(){ if((document.location.host !== 'ethplorer.io') && (document.location.host.indexOf('ethplorer') >= 0)){ - ethplorerWidget.api = '//' + document.location.host + '/api'; + //ethplorerWidget.api = '//' + document.location.host + '/api'; ethplorerWidget.url = '//' + document.location.host; } }, @@ -1615,7 +1615,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te } }; - this.getTooltip = function(noPrice, date, low, open, close, high, operations, volume, convertedVolume, rate, diff){ + this.getTooltip = function(noPrice, date, low, open, close, high, operations, volume, convertedVolume, rate, diff, onlyPrice){ var tooltipDateFormatter = new google.visualization.DateFormat({ pattern: "MMM dd, yyyy '+UTC'" }); @@ -1635,10 +1635,20 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te }else{ if(volume > 0) var avg = convertedVolume / volume; else var avg = (open + close) / 2; + + if(onlyPrice && !diff){ + diff = ethplorerWidget.Utils.pdiff(close, open, true); + if('x' === diff){ + diff = 0; + }else{ + var numDec = Math.abs(diff) > 99 ? 0 : 2; + var diff = ethplorerWidget.Utils.formatNum(diff, true, numDec, false, true); + } + } var diffHtml = ' (' + diff + '%)'; if(rate && rate > 0){ - tooltip += 'Price: ' + avgFormatter.formatValue(rate) + ' USD' + diffHtml + '
    '; + tooltip += 'Price: ' + (onlyPrice ? currencyFormatter.formatValue(rate) : avgFormatter.formatValue(rate)) + ' USD' + diffHtml + '
    '; }else{ diffHtml = ''; var diff = ethplorerWidget.Utils.pdiff(close, open, true); @@ -1653,16 +1663,17 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te 'Open: ' + currencyFormatter.formatValue(open) + ' Close: ' + currencyFormatter.formatValue(close) + diffHtml +'
    ' + 'High: ' + currencyFormatter.formatValue(high) + ' Low: ' + currencyFormatter.formatValue(low) + '
    '; } - tooltip += 'Token operations: ' + numFormatter.formatValue(operations) + '
    ' + - 'Volume: ' + numFormatter.formatValue(volume.toFixed(0)) + ' (' + numFormatter.formatValue(convertedVolume.toFixed(2)) + ' USD)'; + tooltip += 'Token operations: ' + numFormatter.formatValue(operations) + '' + + (onlyPrice ? '' : ('
    Volume: ' + numFormatter.formatValue(volume.toFixed(0)) + ' (' + numFormatter.formatValue(convertedVolume.toFixed(2)) + ' USD)')); } tooltip += '
    '; return tooltip; } this.drawChart = function(aTxData, widgetPriceData, currentPrice){ + onlyPrice = false; + if('undefined' !== typeof(currentPrice) && 'undefined' !== typeof(currentPrice.onlyPrice)) onlyPrice = currentPrice.onlyPrice; var aData = []; - if(aTxData.length){ if(widgetPriceData && widgetPriceData.length){ if(currentPrice){ @@ -1674,7 +1685,8 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te var prevDatePriceKey = prevDate.getFullYear() + '-' + (prevDate.getMonth() < 9 ? '0' : '') + (prevDate.getMonth() + 1) + '-' + (prevDate.getDate() < 10 ? '0' : '') + prevDate.getDate(); if(widgetPriceData[widgetPriceData.length - 1].date != currentDatePriceKey && widgetPriceData[widgetPriceData.length - 1].date == prevDatePriceKey){ - if(currentPrice.rate && (currentPrice.rate > 0) && currentPrice.volume24h && currentPrice.ts){ + if(!currentPrice.volume24h) currentPrice.volume24h = 0; + if(currentPrice.rate && (currentPrice.rate > 0) && (currentPrice.volume24h || onlyPrice) && currentPrice.ts){ var diff = ethplorerWidget.Utils.pdiff(currentPrice.rate, widgetPriceData[widgetPriceData.length - 1].close, true); if('x' === diff){ var diff = 0; @@ -1808,7 +1820,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te if(chartDay < 10) chartDay = '0' + chartDay; var strChartDate = d.getFullYear() + '-' + chartMonth + '-' + chartDay + 'T00:00:00Z'; - var tooltip = this.getTooltip(noPrice, new Date(strChartDate), low, open, close, high, cnt, volume, volumeConverted, rate, diff); + var tooltip = this.getTooltip(noPrice, new Date(strChartDate), low, open, close, high, cnt, volume, volumeConverted, rate, diff, onlyPrice); if(noPrice){ aData.push([new Date(strChartDate), cnt, 'opacity: 0.5', tooltip]); }else{ From 9722ea2b24349eab6853fb19795d25cdce5ea370 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 12 Sep 2018 17:08:48 +0700 Subject: [PATCH 482/658] Mistype fixed. --- api/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 3c547dbb..6500da70 100644 --- a/api/widget.js +++ b/api/widget.js @@ -253,7 +253,7 @@ ethplorerWidget = { // Use local path for develop instances fixPath: function(){ if((document.location.host !== 'ethplorer.io') && (document.location.host.indexOf('ethplorer') >= 0)){ - //ethplorerWidget.api = '//' + document.location.host + '/api'; + ethplorerWidget.api = '//' + document.location.host + '/api'; ethplorerWidget.url = '//' + document.location.host; } }, From 25aaa06dc6f9c1c913b8b7f5119753703a925c73 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 12 Sep 2018 17:20:36 +0700 Subject: [PATCH 483/658] Price history widget customizations. --- api/widget.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/widget.js b/api/widget.js index 6500da70..3e494128 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1671,8 +1671,10 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te } this.drawChart = function(aTxData, widgetPriceData, currentPrice){ - onlyPrice = false; + var onlyPrice = false, + defaultPriceFormat = '$ #,##0.00##'; if('undefined' !== typeof(currentPrice) && 'undefined' !== typeof(currentPrice.onlyPrice)) onlyPrice = currentPrice.onlyPrice; + var aData = []; if(aTxData.length){ if(widgetPriceData && widgetPriceData.length){ @@ -1708,6 +1710,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te volume: currentPrice.volume24h / currentPrice.rate, diff: pdiff }); + if(currentPrice.rate < 0.1) defaultPriceFormat = '$ #,##0.0000'; } } } @@ -1882,7 +1885,7 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te var vAxes = { 1: { title: 'Price', - format: '$ #,##0.00##' + format: defaultPriceFormat //format: 'currency' }, 0: { From dfc657e498e06df7e8ab59b89790dd45ffbda572 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 12 Sep 2018 17:30:01 +0700 Subject: [PATCH 484/658] Token price customizations. --- js/ethplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index da0e77ab..b5db5f80 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1010,8 +1010,8 @@ Ethplorer = { if(oToken.price && oToken.price.rate){ var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; + pf = Ethplorer.Utils.round(pf * oToken.price.rate, oToken.price.rate < 0.1 ? 4 : 2); + totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, oToken.price.rate < 0.1 ? 4 : 2, true) + ''; $('#address-token-totalSupply').html(totalSupply); } } From c5df295be7e4cfda4e36bd270fc1560cb8b98d89 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Wed, 12 Sep 2018 17:38:53 +0700 Subject: [PATCH 485/658] Token price customizations. --- js/ethplorer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/ethplorer.js b/js/ethplorer.js index b5db5f80..1a04b0fe 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1010,8 +1010,8 @@ Ethplorer = { if(oToken.price && oToken.price.rate){ var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, oToken.price.rate < 0.1 ? 4 : 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, oToken.price.rate < 0.1 ? 4 : 2, true) + ''; + pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); + totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; $('#address-token-totalSupply').html(totalSupply); } } @@ -1865,7 +1865,7 @@ Ethplorer = { if(value && value.rate){ var rate = value; var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); - var price = rate.rate < 0.01 ? rate.rate : Ethplorer.Utils.formatNum(rate.rate, true, 2, true); + var price = rate.rate < 0.01 ? rate.rate : Ethplorer.Utils.formatNum(rate.rate, true, rate.rate < 0.1 ? 4 : 2, true); value = '$ ' + price + '
    '; From ca6c217bff17f11fd58ce63ec9030cbb2feb1db8 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 15:58:26 +0700 Subject: [PATCH 486/658] Memusage added to logs output --- api/controller.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 4166c9e9..ef77b032 100644 --- a/api/controller.php +++ b/api/controller.php @@ -108,7 +108,9 @@ public function __destruct(){ if($source){ file_put_contents($logsDir . '/widget-request.log', "[$date] Widget: {$this->command}, source: {$source}\n", FILE_APPEND); } - file_put_contents($logsDir . '/api-request.log', "[$date] Call: {$this->command}, Key: {$key} URI: {$_SERVER["REQUEST_URI"]}, IP: {$_SERVER['REMOTE_ADDR']}, {$ms} s." . $this->cacheState . "\n", FILE_APPEND); + $memUsage = round(memory_get_usage(TRUE) / (1024 * 1024), 2); + $logStr = "[$date] Call: {$this->command}, Key: {$key} URI: {$_SERVER["REQUEST_URI"]}, IP: {$_SERVER['REMOTE_ADDR']}, {$ms} s. Mem: {$memUsage} MB. {$this->cacheState}\n"; + file_put_contents($logsDir . '/api-request.log', $logStr, FILE_APPEND); } public function getCommand(){ From 15141af6f511688318617b895bf939c79150a92b Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 16:25:45 +0700 Subject: [PATCH 487/658] storeMemoryUsage debug function --- service/lib/ethplorer.php | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index f634873c..f257eb86 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -137,6 +137,10 @@ class Ethplorer { protected $useOperations2 = FALSE; protected $getTokensCacheCreation = FALSE; + + protected $debug = false; + + protected $memUsage = []; /** * Constructor. @@ -183,14 +187,18 @@ protected function __construct(array $aConfig){ evxMongoPools::init($this->aSettings['bundles']); $this->oMongoPools = evxMongoPools::getInstance(); } + + if(isset($this->aSettings['debugId']) && $this->aSettings['debugId']){ + $this->debug = $this->aSettings['debugId']; + } } public function __destruct(){ // Todo: profiler config evxProfiler::checkpoint('Ethplorer', 'FINISH'); $total = evxProfiler::getTotalTime(); - if(isset($this->aSettings['debugId']) && $this->aSettings['debugId']){ - evxProfiler::log($this->aSettings['logsDir'] . 'profiler-' . /* time() . '-' . */ md5($this->aSettings['debugId']) . '.log'); + if($this->debug){ + evxProfiler::log($this->aSettings['logsDir'] . 'profiler-' . /* time() . '-' . */ md5($this->debug) . '.log'); } $slowQueryTime = isset($this->aSettings['slowQueryTime']) ? (int)$this->aSettings['slowQueryTime'] : 10; if(($total > $slowQueryTime) && (php_sapi_name() !== 'cli')){ @@ -226,6 +234,16 @@ public function getMongo(){ return $this->oMongo; } + public function storeMemoryUsage($label = false){ + if(!$label){ + $label = microtime(); + } + $this->memUsage[$label] = [ + 'php' => memory_get_usage(), + 'real' => memory_get_usage(TRUE) + ]; + } + /** * Returns some debug data * @@ -235,7 +253,8 @@ public function getDebugData(){ return array( 'totalTime' => evxProfiler::getTotalTime(), 'dbConnected' => $this->oMongo->dbConnected(), - 'queries' => $this->oMongo->getQueryProfileData() + 'queries' => $this->oMongo->getQueryProfileData(), + 'memUsage' => $this->memUsage ); } From c4008f91ce7900c746140e7289554516a53f9037 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 16:29:34 +0700 Subject: [PATCH 488/658] bytes to megabytes in debug output --- service/lib/ethplorer.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index f257eb86..fceee8fc 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -235,13 +235,16 @@ public function getMongo(){ } public function storeMemoryUsage($label = false){ - if(!$label){ - $label = microtime(); + if($this->debug){ + if(!$label){ + $label = microtime(); + } + $mb = 1024 * 1024; + $this->memUsage[$label] = [ + 'php' => round(memory_get_usage() / $mb, 2), + 'real' => round(memory_get_usage(TRUE) / $mb, 2) + ]; } - $this->memUsage[$label] = [ - 'php' => memory_get_usage(), - 'real' => memory_get_usage(TRUE) - ]; } /** From b629ce1f3f1e7d7e709d91f57b6c0dc07db8d975 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 16:37:51 +0700 Subject: [PATCH 489/658] Debug updates --- api/index.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/index.php b/api/index.php index 96918e6c..c0b0ae6a 100644 --- a/api/index.php +++ b/api/index.php @@ -23,6 +23,10 @@ require dirname(__FILE__) . '/controller.php'; try { + $aConfig = require_once dirname(__FILE__) . '/../service/config.php'; + if($debugId = filter_input(INPUT_GET, 'debugId')){ + $aConfig['debugId'] = $debugId; + } $es = Ethplorer::db(require_once dirname(__FILE__) . '/../service/config.php'); }catch(Exception $e){ // MongoDB connection error From 079be6c35050f1a882e80c495d5e0674d2a45bab Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 16:40:04 +0700 Subject: [PATCH 490/658] Bug fixed --- api/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/index.php b/api/index.php index c0b0ae6a..5ee65a1f 100644 --- a/api/index.php +++ b/api/index.php @@ -27,7 +27,7 @@ if($debugId = filter_input(INPUT_GET, 'debugId')){ $aConfig['debugId'] = $debugId; } - $es = Ethplorer::db(require_once dirname(__FILE__) . '/../service/config.php'); + $es = Ethplorer::db($aConfig); }catch(Exception $e){ // MongoDB connection error $es = FALSE; From 5239a6bc0d1b5ba31008c1f487305542d02c96bc Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 19:09:07 +0700 Subject: [PATCH 491/658] getToken optimization --- service/lib/ethplorer.php | 99 ++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index fceee8fc..75a5d8af 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1178,65 +1178,70 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ public function getToken($address, $fast = FALSE){ // evxProfiler::checkpoint('getToken', 'START', 'address=' . $address); $cache = 'token-' . $address; + $tokenDetailsCache = 'tokend-' . $address; if($fast){ - $aTokens = $this->getTokens(); - $result = isset($aTokens[$address]) ? $aTokens[$address] : false; - if($result && is_array($result)){ + $result = $this->oCache->get($tokenDetailsCache, false, true, 600); + if(false === $result){ + $aTokens = $this->getTokens(); + $result = isset($aTokens[$address]) ? $aTokens[$address] : []; unset($result["_id"]); - $price = $this->getTokenPrice($address); - if(is_array($price)){ - $price['currency'] = 'USD'; - } - $result['price'] = $price ? $price : false; + $this->oCache->save($tokenDetailsCache, $result); } - return $result; - } - $result = $this->oCache->get($cache, false, true, 30); - if(FALSE === $result){ - $aTokens = $this->getTokens(); - $result = isset($aTokens[$address]) ? $aTokens[$address] : false; - if($result){ - unset($result["_id"]); - $result += array('txsCount' => 0, 'transfersCount' => 0, 'ethTransfersCount' => 0, 'issuancesCount' => 0, 'holdersCount' => 0, "symbol" => ""); - if(!isset($result['decimals']) || !intval($result['decimals'])){ - $result['decimals'] = 0; - if(isset($result['totalSupply']) && ((float)$result['totalSupply'] > 1e+18)){ - $result['decimals'] = 18; - $result['estimatedDecimals'] = true; + }else{ + $result = $this->oCache->get($cache, false, true, 30); + if(false === $result){ + $result = $this->oCache->get($tokenDetailsCache, false, true, 600); + if(false === $result){ + $aTokens = $this->getTokens(); + $result = isset($aTokens[$address]) ? $aTokens[$address] : []; + unset($result["_id"]); + $this->oCache->save($tokenDetailsCache, $result); + } + if(empty($result)) $result = false; + if(is_array($result)){ + $result += array('txsCount' => 0, 'transfersCount' => 0, 'ethTransfersCount' => 0, 'issuancesCount' => 0, 'holdersCount' => 0, "symbol" => ""); + if(!isset($result['decimals']) || !intval($result['decimals'])){ + $result['decimals'] = 0; + if(isset($result['totalSupply']) && ((float)$result['totalSupply'] > 1e+18)){ + $result['decimals'] = 18; + $result['estimatedDecimals'] = true; + } } - } - // Ask DB for fresh counts - $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); - $token = false; - if($cursor){ - foreach($cursor as $token){ - break; - } - } - if($token){ - $result['txsCount'] = $token['txsCount']; - $result['transfersCount'] = $token['transfersCount']; - } - - $result['txsCount'] = (int)$result['txsCount'] + 1; // Contract creation tx - - if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens'])){ - $aClientTokens = $this->aSettings['client']['tokens']; - if(isset($aClientTokens[$address])){ - $aClientToken = $aClientTokens[$address]; - if(isset($aClientToken['name'])){ - $result['name'] = $aClientToken['name']; + // Ask DB for fresh counts + $cursor = $this->oMongo->find('tokens', array('address' => $address), array(), false, false, array('txsCount', 'transfersCount')); + $token = false; + if($cursor){ + foreach($cursor as $token){ + break; } - if(isset($aClientToken['symbol'])){ - $result['symbol'] = $aClientToken['symbol']; + } + if($token){ + $result['txsCount'] = $token['txsCount']; + $result['transfersCount'] = $token['transfersCount']; + } + + $result['txsCount'] = (int)$result['txsCount'] + 1; // Contract creation tx + + if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens'])){ + $aClientTokens = $this->aSettings['client']['tokens']; + if(isset($aClientTokens[$address])){ + $aClientToken = $aClientTokens[$address]; + if(isset($aClientToken['name'])){ + $result['name'] = $aClientToken['name']; + } + if(isset($aClientToken['symbol'])){ + $result['symbol'] = $aClientToken['symbol']; + } } } + $this->oCache->save($cache, $result); } - $this->oCache->save($cache, $result); } } + if(empty($result)) $result = false; if(is_array($result)){ + unset($result["_id"]); $price = $this->getTokenPrice($address); if(is_array($price)){ $price['currency'] = 'USD'; From c85b7ea9d2af3aa36c898ffebee7bb7408fde5c1 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 19:38:21 +0700 Subject: [PATCH 492/658] getToken optimization --- service/lib/ethplorer.php | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 75a5d8af..2314f1f0 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1169,6 +1169,29 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ return $result; } + /** + * Get data from token cache and sores it as a single record + * + * @param string $address + * @return array + */ + protected function getTokenByAddress($address){ + $result = false; + if($address){ + $cache = 'tokend-' . $address; + $result = $this->oCache->get($cache, false, true, 600); + if(false === $result){ + $aTokens = $this->getTokens(); + $result = isset($aTokens[$address]) ? $aTokens[$address] : "notfound"; + if(is_array($result) && isset($result["_id"])){ + unset($result["_id"]); + } + $this->oCache->save($cache, $result); + } + } + return is_array($result) && !empty($result) ? $result : false; + } + /** * Returns token data by contract address. * @@ -1178,26 +1201,12 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ public function getToken($address, $fast = FALSE){ // evxProfiler::checkpoint('getToken', 'START', 'address=' . $address); $cache = 'token-' . $address; - $tokenDetailsCache = 'tokend-' . $address; if($fast){ - $result = $this->oCache->get($tokenDetailsCache, false, true, 600); - if(false === $result){ - $aTokens = $this->getTokens(); - $result = isset($aTokens[$address]) ? $aTokens[$address] : []; - unset($result["_id"]); - $this->oCache->save($tokenDetailsCache, $result); - } + $result = $this->getTokenByAddress($address); }else{ $result = $this->oCache->get($cache, false, true, 30); if(false === $result){ - $result = $this->oCache->get($tokenDetailsCache, false, true, 600); - if(false === $result){ - $aTokens = $this->getTokens(); - $result = isset($aTokens[$address]) ? $aTokens[$address] : []; - unset($result["_id"]); - $this->oCache->save($tokenDetailsCache, $result); - } - if(empty($result)) $result = false; + $result = $this->getTokenByAddress($address); if(is_array($result)){ $result += array('txsCount' => 0, 'transfersCount' => 0, 'ethTransfersCount' => 0, 'issuancesCount' => 0, 'holdersCount' => 0, "symbol" => ""); if(!isset($result['decimals']) || !intval($result['decimals'])){ @@ -1239,7 +1248,6 @@ public function getToken($address, $fast = FALSE){ } } } - if(empty($result)) $result = false; if(is_array($result)){ unset($result["_id"]); $price = $this->getTokenPrice($address); From 639aa71ede339da97728b51b2358ef46a10a602d Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 19:57:13 +0700 Subject: [PATCH 493/658] do not cache fast getToken --- service/lib/ethplorer.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 2314f1f0..4b37cf61 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1175,18 +1175,23 @@ public function getTokenHolders($address, $limit = FALSE, $offset = FALSE){ * @param string $address * @return array */ - protected function getTokenByAddress($address){ + protected function getTokenByAddress($address, $noCache = false){ $result = false; if($address){ - $cache = 'tokend-' . $address; - $result = $this->oCache->get($cache, false, true, 600); - if(false === $result){ + if($noCache){ $aTokens = $this->getTokens(); - $result = isset($aTokens[$address]) ? $aTokens[$address] : "notfound"; - if(is_array($result) && isset($result["_id"])){ - unset($result["_id"]); + $result = isset($aTokens[$address]) ? $aTokens[$address] : false; + }else{ + $cache = 'tokend-' . $address; + $result = $this->oCache->get($cache, false, true, 600); + if(false === $result){ + $aTokens = $this->getTokens(); + $result = isset($aTokens[$address]) ? $aTokens[$address] : "notfound"; + if(is_array($result) && isset($result["_id"])){ + unset($result["_id"]); + } + $this->oCache->save($cache, $result); } - $this->oCache->save($cache, $result); } } return is_array($result) && !empty($result) ? $result : false; @@ -1202,7 +1207,7 @@ public function getToken($address, $fast = FALSE){ // evxProfiler::checkpoint('getToken', 'START', 'address=' . $address); $cache = 'token-' . $address; if($fast){ - $result = $this->getTokenByAddress($address); + $result = $this->getTokenByAddress($address, true); }else{ $result = $this->oCache->get($cache, false, true, 30); if(false === $result){ From 3f18eeb5cdb2083a08c16ca34dbe88d1d09ff1ed Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 17 Sep 2018 20:44:17 +0700 Subject: [PATCH 494/658] gc_collect_cycles added --- api/controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/api/controller.php b/api/controller.php index ef77b032..adb417b0 100644 --- a/api/controller.php +++ b/api/controller.php @@ -137,6 +137,7 @@ public function sendResult(array $result, $statusCode = 200){ } http_response_code($statusCode); echo json_encode($result, JSON_UNESCAPED_SLASHES); + gc_collect_cycles(); die(); } From 69ac827d403d08d340606d5c9fd5dd50cb4eeb3b Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Sep 2018 20:10:42 +0700 Subject: [PATCH 495/658] Peak memory usage logging --- api/controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index adb417b0..cd530156 100644 --- a/api/controller.php +++ b/api/controller.php @@ -109,7 +109,8 @@ public function __destruct(){ file_put_contents($logsDir . '/widget-request.log', "[$date] Widget: {$this->command}, source: {$source}\n", FILE_APPEND); } $memUsage = round(memory_get_usage(TRUE) / (1024 * 1024), 2); - $logStr = "[$date] Call: {$this->command}, Key: {$key} URI: {$_SERVER["REQUEST_URI"]}, IP: {$_SERVER['REMOTE_ADDR']}, {$ms} s. Mem: {$memUsage} MB. {$this->cacheState}\n"; + $peakMemUsage = round(memory_get_peak_usage(TRUE) / (1024 * 1024), 2); + $logStr = "[$date] Call: {$this->command}, Key: {$key} URI: {$_SERVER["REQUEST_URI"]}, IP: {$_SERVER['REMOTE_ADDR']}, {$ms} s. Mem: {$memUsage} MB. Peak: {$peakMemUsage} MB. {$this->cacheState}\n"; file_put_contents($logsDir . '/api-request.log', $logStr, FILE_APPEND); } From be1950f6f2699d628bbcd54502a47cce002c2f3f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 1 Oct 2018 21:16:15 +0700 Subject: [PATCH 496/658] Rename csv.php to exportcsv.php --- index.php | 2 +- service/exportcsv.php | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 service/exportcsv.php diff --git a/index.php b/index.php index 5dda1873..bdbc4fbf 100644 --- a/index.php +++ b/index.php @@ -88,7 +88,7 @@ $csvExport = ''; if(is_array($rParts) && isset($rParts[2])){ - $csvExport = ' Export...Export as CSV'; + $csvExport = ' Export...Export as CSV'; } ?> diff --git a/service/exportcsv.php b/service/exportcsv.php new file mode 100644 index 00000000..e2da3350 --- /dev/null +++ b/service/exportcsv.php @@ -0,0 +1,50 @@ +setShowTx($showTx); + +// Allow cross-domain ajax requests +// header('Access-Control-Allow-Origin: *'); + +if($hash){ + if((false !== $data) && $es->isValidAddress($data)){ + $md5 = md5('/service/csv.php?data=' . $data . date("Y-n-j")); + if($md5 == $hash){ + $result = $es->getAddressOperationsCSV($data); + header('Content-Description: File Transfer'); + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=ethplorer.csv'); + header('Content-Length: ' . strlen($result)); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Expires: 0'); + header('Pragma: public'); + echo $result; + die; + } + } +} + +header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); +header("Status: 404 Not Found"); +die; From d8b0784bcf88f1045d5d6f00886470955d92fafc Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 1 Oct 2018 21:23:40 +0700 Subject: [PATCH 497/658] Rename csv.php to exportcsv.php --- service/exportcsv.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/exportcsv.php b/service/exportcsv.php index e2da3350..ec63ff6a 100644 --- a/service/exportcsv.php +++ b/service/exportcsv.php @@ -29,7 +29,7 @@ if($hash){ if((false !== $data) && $es->isValidAddress($data)){ - $md5 = md5('/service/csv.php?data=' . $data . date("Y-n-j")); + $md5 = md5('/service/exportcsv.php?data=' . $data . date("Y-n-j")); if($md5 == $hash){ $result = $es->getAddressOperationsCSV($data); header('Content-Description: File Transfer'); From 3d99948cec12f53b1b633cbb7bece4856027a255 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Tue, 2 Oct 2018 21:12:11 +0700 Subject: [PATCH 498/658] Example widgets changed. --- widgets.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widgets.php b/widgets.php index 287ae1e2..f48006f1 100644 --- a/widgets.php +++ b/widgets.php @@ -393,13 +393,13 @@ function getWidgetCode(ta) { '#token-history-grouped-2', // Placeholder element 'tokenHistoryGrouped', // Widget type { - 'period': 10, + 'period': 90, 'type': 'column', // supported types: area, column, line options: { 'title': 'Ethereum Tokens Pulse', 'pointSize': 2, 'hAxis': { - 'title': '10 days token operations chart', + 'title': '90 days token operations chart', 'titleTextStyle': { 'color': '#3366CC', 'italic': true @@ -444,6 +444,7 @@ function getWidgetCode(ta) { '#token-history-grouped-3', // Placeholder element 'tokenHistoryGrouped', // Widget type { + 'period': 90, 'theme': 'dark', options: { From 63c1f1d0006a969b43f913b77603f9cbac77ac98 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 12 Oct 2018 18:25:19 +0700 Subject: [PATCH 499/658] Widget charts customizations. --- api/widget.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/api/widget.js b/api/widget.js index 3e494128..741ec6ce 100644 --- a/api/widget.js +++ b/api/widget.js @@ -1363,6 +1363,9 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat gridlines: { count: ethplorerWidget.getGoogleChartAxisCount(aData.length), color: "none" + }, + minorGridlines: { + count: 0 } }, vAxis: { @@ -1377,6 +1380,9 @@ ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templat gridlines: { color: "none" }, + minorGridlines: { + count: 0 + }, maxValue: 3, format: '#,###', }, @@ -1939,6 +1945,9 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te count: ethplorerWidget.getGoogleChartAxisCount(aData.length), color: "none" }, + minorGridlines: { + count: 0 + } }, vAxis: { viewWindowMode: 'maximized', @@ -1949,6 +1958,9 @@ ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, te gridlines: { color: "none" }, + minorGridlines: { + count: 0 + }, //format: '#,###', /*minValue: 0, maxValue: 3, @@ -2407,6 +2419,9 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, count: ethplorerWidget.getGoogleChartAxisCount(aData.length), color: "none" }, + minorGridlines: { + count: 0 + } }, vAxis: { viewWindowMode: 'maximized', @@ -2421,6 +2436,9 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, gridlines: { color: "none" }, + minorGridlines: { + count: 0 + } }, vAxes: vAxes, pointSize: 3, From 492c0e2b6d885a300f4466f980e931f6b5342380 Mon Sep 17 00:00:00 2001 From: Dennis Webb Date: Mon, 22 Oct 2018 22:18:46 -0500 Subject: [PATCH 500/658] Updates php-bignumbers to 0.8.6 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 536bc79a..b19407b6 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "require": { - "litipk/php-bignumbers": "0.7.3" + "litipk/php-bignumbers": "0.8.6" }, "minimum-stability": "dev", "prefer-stable" : false -} \ No newline at end of file +} From 43134d2a85d03460c8a32749cb1088e318d24848 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 24 Oct 2018 20:00:31 +0700 Subject: [PATCH 501/658] getAPIKey added for test and ability to use env variable as api key --- tests/apiTest.php | 105 ++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index d67525a9..7c673277 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -8,7 +8,7 @@ class apiTest extends TestCase { protected $url = 'https://api.ethplorer.io/'; const APIKey = 'freekey'; - + /** * @dataProvider provider */ @@ -28,7 +28,7 @@ public function provider() 'method' => 'getTokenInfo', 'description' => '= Success =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B280', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ // Must be converted to ->assertTrue(isset($result[field])) ['type' => 'isset', 'fields' => ['address', 'totalSupply', 'holdersCount']], @@ -42,7 +42,7 @@ public function provider() 'method' => 'getTokenInfo', 'description' => '= Error: invalid address format =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B28', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => 'error:code', 'equals' => 104], @@ -53,7 +53,7 @@ public function provider() 'method' => 'getTokenInfo', 'description' => '= Error: address is not a token =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B281', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => 'error:code', 'equals' => 150], @@ -79,7 +79,7 @@ public function provider() 'method' => 'getAddressInfo', 'description' => '= Success =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['address', 'ETH', 'countTxs']], ['type' => '!isset', 'fields' => ['error']], @@ -93,7 +93,7 @@ public function provider() 'method' => 'getAddressInfo', 'description' => '= Success with token parameter =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'token' => '0x49aec0752e68d0282db544c677f6ba407ba17ed7'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'token' => '0x49aec0752e68d0282db544c677f6ba407ba17ed7'], 'asserts' => [ ['type' => 'isset', 'fields' => ['address', 'ETH', 'countTxs']], ['fields' => 'address', 'equals' => strtolower('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07')], @@ -109,7 +109,7 @@ public function provider() 'method' => 'getAddressInfo', 'description' => '= Error: invalid address format =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B28', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => 'error:code', 'equals' => 104], @@ -121,7 +121,7 @@ public function provider() 'description' => '= wrong token type =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B28', 'GET_params' => [ - 'apiKey' => apiTest::APIKey, + 'apiKey' => $this->getAPIKey(), 'token' => 'ec0752e68d0282db544c677f6ba407ba17ed7' ], 'asserts' => [ @@ -149,7 +149,7 @@ public function provider() 'method' => 'getTokenHistory', 'description' => '= Check limit =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 5], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 5], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -167,7 +167,7 @@ public function provider() 'method' => 'getTokenHistory', 'description' => 'Check with incorrect limit value', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 'incorrect'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 'incorrect'], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -180,7 +180,7 @@ public function provider() 'method' => 'getTokenHistory', 'description' => 'Check with limit = 0', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 0], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 0], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -193,7 +193,7 @@ public function provider() 'method' => 'getTokenHistory', 'description' => 'Check with limit = 51', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 51], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 51], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -207,7 +207,7 @@ public function provider() [[ 'method' => 'getTxInfo', 'URL_params' => '0x0bd079304c36ff6741382125e1ba4bd02cdd29dd30f7a08b8ccd9e801cbc2be3', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['hash', 'timestamp', 'blockNumber', 'from', 'value', 'gasLimit', 'gasUsed']], ['fields' => 'hash', 'equals' => '0x0bd079304c36ff6741382125e1ba4bd02cdd29dd30f7a08b8ccd9e801cbc2be3'], @@ -218,7 +218,7 @@ public function provider() [[ 'method' => 'getTxInfo', 'URL_params' => '0x0bd079304c36ff6741382125e1ba4bd02cdd29dd30f7a08b8ccd9e801cbc2be2', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => 'error'], ['fields' => 'error:code', 'equals' => 404], @@ -229,7 +229,7 @@ public function provider() 'method' => 'getTxInfo', 'description' => 'Checks tx format', 'URL_params' => 'xx0bd079304c36ff6741382125e1ba4bd02cdd29dd30f7a08b8ccd9e801cbc2be2', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => 'error'], ['fields' => 'error:code', 'equals' => 102], @@ -255,7 +255,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => '= Check limit =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 5, ], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 5, ], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -270,7 +270,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => '= Check limit with token parameter =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 5, 'token'=>'0xb9b4cfe4194d7e8511aa9b9f1260bc7b9634249e'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 5, 'token'=>'0xb9b4cfe4194d7e8511aa9b9f1260bc7b9634249e'], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -285,7 +285,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => 'Check with incorrect limit value', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 'incorrect'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 'incorrect'], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -298,7 +298,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => 'Check with limit = 0', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 0], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 0], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -311,7 +311,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => 'Check with limit = 51', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 51], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 51], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -324,7 +324,7 @@ public function provider() 'method' => 'getAddressHistory', 'description' => '= Error: invalid address format =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C0', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => 'error:code', 'equals' => 104], @@ -349,7 +349,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= check request without parameters =', 'URL_params' => '0xb297cacf0f91c86dd9d2fb47c6d12783121ab780', - 'GET_params' => ['apiKey' => apiTest::APIKey, ], + 'GET_params' => ['apiKey' => $this->getAPIKey(), ], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['timestamp', 'from', 'to', 'hash', 'value', 'input', 'success']], ['type' => '!isset', 'fields' => ['error']], @@ -360,7 +360,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= check request with "limit" parameter =', 'URL_params' => '0xb297cacf0f91c86dd9d2fb47c6d12783121ab780', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit'=>'5'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'5'], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['timestamp', 'from', 'to', 'hash', 'value', 'input', 'success']], ['type' => '!isset', 'fields' => ['error']], @@ -372,7 +372,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= check request with "showZeroValues" parameter =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'showZeroValues'=>'true'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'showZeroValues'=>'true'], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['timestamp', 'from', 'to', 'hash', 'value', 'input', 'success']], ['type' => '!isset', 'fields' => ['error']], @@ -384,7 +384,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= check if limit=0 return correct amount of objects =', 'URL_params' => '0xb297cacf0f91c86dd9d2fb47c6d12783121ab780', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'showZeroValues'=>'true'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'showZeroValues'=>'true'], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['timestamp', 'from', 'to', 'hash', 'value', 'input', 'success']], ['type' => '!isset', 'fields' => ['error']], @@ -396,7 +396,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= Error: invalid address format =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C0', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => 'error:code', 'equals' => 104], @@ -407,7 +407,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= Error: empty result =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B281', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'empty', 'fields' => [' ']], ] @@ -417,7 +417,7 @@ public function provider() 'method' => 'getAddressTransactions', 'description' => '= request with wrong "limit" parameter contains only 1 object =', 'URL_params' => '0xb297cacf0f91c86dd9d2fb47c6d12783121ab780', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit' => 'asd'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 'asd'], 'asserts' => [ ['fields' => [''], 'array' => 'true', 'type' => 'count', 'range' => [1,1]], ] @@ -441,7 +441,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request without parameters =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -454,7 +454,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with "period" parameter =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'period'=>'5'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'5'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -467,7 +467,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with "limit" parameter =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit'=>'5'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'5'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -481,7 +481,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with "limit" parameter equals 0 =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit'=>'5'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'5'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -494,7 +494,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with "limit" parameter equals 51 =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit'=>'51'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'51'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -508,7 +508,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= Error: period equals 0 =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'period'=>'0'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'0'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -520,7 +520,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with wrong "limit" parameter =', 'URL_params' => '', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'limit'=>'asd'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'asd'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -547,7 +547,7 @@ public function provider() 'method' => 'getTokenHistoryGrouped', 'description' => '= request without parameters =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['countTxs']], ['type' => '!empty', 'fields' => ['countTxs']], @@ -557,7 +557,7 @@ public function provider() //check timestamp with last block and last token history [[ 'method' => 'getTokenHistory', - 'GET_params' => ['apiKey' => apiTest::APIKey,], + 'GET_params' => ['apiKey' => $this->getAPIKey(),], 'asserts' => [ ['type' => 'checkLastBlock', 'fields' => ['operations'], 'time' => 90], ] @@ -567,7 +567,7 @@ public function provider() 'method' => 'getTokenHistoryGrouped', 'description' => '= request with "period" field =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'period'=>'1'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'1'], 'asserts' => [ ['type' => 'isset', 'fields' => ['countTxs']], ['type' => '!isset', 'fields' => ['error']], @@ -579,7 +579,7 @@ public function provider() 'method' => 'getTokenHistoryGrouped', 'description' => '= Error: invalid address format =', 'URL_params' => 'xxd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => ['error:code'], 'equals' => 104], @@ -590,7 +590,7 @@ public function provider() 'method' => 'getTokenHistoryGrouped', 'description' => '= Error: empty result =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B281', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['countTxs']], ['type' => 'empty', 'fields' => ['countTxs']], @@ -616,7 +616,7 @@ public function provider() 'method' => 'getTokenPriceHistoryGrouped', 'description' => '= request without parameters =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['history', 'history:countTxs', 'history:prices']], ['type' => '!empty', 'fields' => ['history']], @@ -628,7 +628,7 @@ public function provider() 'method' => 'getTokenPriceHistoryGrouped', 'description' => '= request with "period" field =', 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'period'=>'1'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'1'], 'asserts' => [ ['type' => 'isset', 'fields' => ['history', 'history:countTxs', 'history:prices']], ['type' => '!empty', 'fields' => ['history']], @@ -641,7 +641,7 @@ public function provider() 'method' => 'getTokenPriceHistoryGrouped', 'description' => '= Error: invalid address format =', 'URL_params' => 'xxd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'isset', 'fields' => ['error']], ['fields' => ['error:code'], 'equals' => 104], @@ -652,7 +652,7 @@ public function provider() 'method' => 'getTokenPriceHistoryGrouped', 'description' => '= Error: empty result =', 'URL_params' => '0xB97048628DB6B661D4C2aA833e95Dbe1A905B281', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'empty', 'fields' => ['history:countTxs']], ['type' => '!isset', 'fields' => ['error']], @@ -675,7 +675,7 @@ public function provider() // Success [[ 'method' => 'getLastBlock', - 'GET_params' => ['apiKey' => apiTest::APIKey], + 'GET_params' => ['apiKey' => $this->getAPIKey()], 'asserts' => [ ['type' => 'timeCheck', 'fields' => ['time' => 90]] ] @@ -697,7 +697,7 @@ public function provider() // Success [[ 'method' => 'getBlockTransactions', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'block' => 4895558], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'block' => 4895558], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'count' => 5, 'fields' => ['from', 'to', 'value', 'timestamp']], ['type' => '!contain', 'array' => 'true', 'fields' => ['value'], 'equals' => 0], @@ -707,7 +707,7 @@ public function provider() // with showZeroValues = 1 [[ 'method' => 'getBlockTransactions', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'block' => 4895558, 'showZeroValues' => 1], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'block' => 4895558, 'showZeroValues' => 1], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['from', 'to', 'value', 'timestamp']], ['type' => 'contain', 'array' => 'true', 'fields' => ['value'], 'equals' => 0], @@ -716,7 +716,7 @@ public function provider() // check last block [[ 'method' => 'getBlockTransactions', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'block' => 'last'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'block' => 'last'], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'count' => 5, 'fields' => ['from', 'to', 'value', 'timestamp']], ['type' => '!contain', 'array' => 'true', 'fields' => ['value'], 'equals' => 0], @@ -726,7 +726,7 @@ public function provider() // check last block with showZeroValues = 1 [[ 'method' => 'getBlockTransactions', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'block' => 'last', 'showZeroValues' => 1], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'block' => 'last', 'showZeroValues' => 1], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['from', 'to', 'value', 'timestamp']], ['type' => 'contain', 'array' => 'true', 'fields' => ['value'], 'equals' => 0], @@ -735,7 +735,7 @@ public function provider() //check block transaction with etherscan.io [[ 'method' => 'getBlockTransactions', - 'GET_params' => ['apiKey' => apiTest::APIKey, 'block' => 'last'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'block' => 'last'], 'asserts' => [ ['type' => 'compareArrays', 'count' => 5, 'callback' => function($hash){ $url = "https://api.etherscan.io/api?module=proxy&action=eth_getTransactionByHash&txhash=%s&apikey=YourApiKeyToken"; @@ -771,4 +771,9 @@ protected function getCommandLineParameter($param, $default){ } return $default; } + + protected function getAPIKey() + { + return !empty($_ENV['APIKEY']) ? $_ENV['APIKEY'] : apiTest::APIKey; + } } From b02b8a3928c734078f6bf23c35565adaf3079883 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 24 Oct 2018 21:01:05 +0700 Subject: [PATCH 502/658] ENV to argv changed --- tests/apiTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index 7c673277..3c5faa57 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -774,6 +774,7 @@ protected function getCommandLineParameter($param, $default){ protected function getAPIKey() { - return !empty($_ENV['APIKEY']) ? $_ENV['APIKEY'] : apiTest::APIKey; + global $argv; + return !empty($argv[2]) ? $argv[2] : apiTest::APIKey; } } From 6a1087cbe4e8958b202ed55adfbb356c1a63d4a5 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 24 Oct 2018 21:26:41 +0700 Subject: [PATCH 503/658] APIKEY=... arg param support added --- tests/apiTest.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index 3c5faa57..0d3a7ac5 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -774,7 +774,16 @@ protected function getCommandLineParameter($param, $default){ protected function getAPIKey() { - global $argv; - return !empty($argv[2]) ? $argv[2] : apiTest::APIKey; + global $argc, $argv; + $apiKey = apiTest::APIKey; + if($argc){ + foreach($argv as $i => $arg){ + if(0 === strpos($arg, 'APIKEY=')){ + $apiKey = str_replace('APIKEY=', '', $arg); + break; + } + } + } + return $apiKey; } } From 142a3a61be50a0cda49651a53162cc8a47eb54c8 Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 25 Oct 2018 15:27:13 +0700 Subject: [PATCH 504/658] API tests updated (freekey where it needed) --- tests/apiTest.php | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index 0d3a7ac5..de32c37a 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -7,7 +7,7 @@ class apiTest extends TestCase { protected $url = 'https://api.ethplorer.io/'; - const APIKey = 'freekey'; + const FreeKey = 'freekey'; /** * @dataProvider provider @@ -166,8 +166,9 @@ public function provider() [[ 'method' => 'getTokenHistory', 'description' => 'Check with incorrect limit value', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 'incorrect'], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 'incorrect'], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -179,8 +180,9 @@ public function provider() [[ 'method' => 'getTokenHistory', 'description' => 'Check with limit = 0', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 0], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 0], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -192,8 +194,9 @@ public function provider() [[ 'method' => 'getTokenHistory', 'description' => 'Check with limit = 51', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 51], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 51], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -284,8 +287,9 @@ public function provider() [[ 'method' => 'getAddressHistory', 'description' => 'Check with incorrect limit value', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 'incorrect'], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 'incorrect'], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -297,8 +301,9 @@ public function provider() [[ 'method' => 'getAddressHistory', 'description' => 'Check with limit = 0', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 0], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 0], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -310,8 +315,9 @@ public function provider() [[ 'method' => 'getAddressHistory', 'description' => 'Check with limit = 51', + 'sleep' => 5, 'URL_params' => '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit' => 51], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit' => 51], 'asserts' => [ ['type' => 'isset', 'fields' => ['operations']], ['type' => '!empty', 'fields' => ['operations']], @@ -383,8 +389,9 @@ public function provider() [[ 'method' => 'getAddressTransactions', 'description' => '= check if limit=0 return correct amount of objects =', + 'sleep' => 5, 'URL_params' => '0xb297cacf0f91c86dd9d2fb47c6d12783121ab780', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'showZeroValues'=>'true'], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'showZeroValues'=>'true'], 'asserts' => [ ['type' => 'isset', 'array' => 'true', 'fields' => ['timestamp', 'from', 'to', 'hash', 'value', 'input', 'success']], ['type' => '!isset', 'fields' => ['error']], @@ -480,8 +487,9 @@ public function provider() [[ 'method' => 'getTopTokens', 'description' => '= request with "limit" parameter equals 0 =', + 'sleep' => 5, 'URL_params' => '', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'5'], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit'=>'0'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -493,8 +501,9 @@ public function provider() [[ 'method' => 'getTopTokens', 'description' => '= request with "limit" parameter equals 51 =', + 'sleep' => 5, 'URL_params' => '', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'limit'=>'51'], + 'GET_params' => ['apiKey' => $this->getFreeKey(), 'limit'=>'51'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], @@ -772,10 +781,14 @@ protected function getCommandLineParameter($param, $default){ return $default; } + protected function getFreeKey(){ + return apiTest::FreeKey; + } + protected function getAPIKey() { global $argc, $argv; - $apiKey = apiTest::APIKey; + $apiKey = $this->getFreeKey(); if($argc){ foreach($argv as $i => $arg){ if(0 === strpos($arg, 'APIKEY=')){ From b93fd564414b95d3261fd95885d1b6d842c206fd Mon Sep 17 00:00:00 2001 From: Artem Date: Thu, 25 Oct 2018 15:42:23 +0700 Subject: [PATCH 505/658] Use period=10 instead of 5 --- tests/apiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/apiTest.php b/tests/apiTest.php index de32c37a..0adce1fd 100644 --- a/tests/apiTest.php +++ b/tests/apiTest.php @@ -461,7 +461,7 @@ public function provider() 'method' => 'getTopTokens', 'description' => '= request with "period" parameter =', 'URL_params' => '', - 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'5'], + 'GET_params' => ['apiKey' => $this->getAPIKey(), 'period'=>'10'], 'asserts' => [ ['type' => 'isset', 'fields' => ['tokens']], ['type' => '!empty', 'fields' => ['tokens']], From 36bf0ec3357b17da14b9ca92cdb835f61a12ad8f Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 29 Oct 2018 16:17:20 +0700 Subject: [PATCH 506/658] CSV export fixed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 4b37cf61..d4e97a43 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1653,7 +1653,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $tokenSymbol = ''; $isToken = $this->getToken($address); if($isToken){ - $operations = $this->getLastTransfers($options); + $operations = $this->getLastTransfers($options, $this->showTx ? TRUE : FALSE); $dec = Decimal::create($isToken['decimals']); $tokenName = isset($isToken['name']) ? $isToken['name'] : ''; $tokenSymbol = isset($isToken['symbol']) ? $isToken['symbol'] : ''; From 96ab2b75b554dc075b82a76b855e17ef932ffd9c Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 29 Oct 2018 16:29:41 +0700 Subject: [PATCH 507/658] additional logging for jsonrpc calls --- service/lib/ethplorer.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 4b37cf61..5472af5d 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3334,7 +3334,9 @@ protected function _jsonrpcall($service, $method, $params = array()){ $json = json_encode($data); if(filter_input(INPUT_GET, "debugRPC")){ echo "Request: " . var_export($json, true) . "\n"; - } + } + $id = uniqid(); + @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Request {$id}: " . var_export($json, true) . "\n", FILE_APPEND); $ch = curl_init($service); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( @@ -3350,6 +3352,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ echo "Response: " . var_export($rjson, true) . "\n"; die; } + @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Response {$id}: " . var_export($rjson, true) . "\n", FILE_APPEND); if($rjson && (is_string($rjson)) && ('{' === $rjson[0])){ $json = json_decode($rjson, JSON_OBJECT_AS_ARRAY); if(isset($json["result"])){ @@ -3359,7 +3362,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ $result = ["error" => $json["error"]]; } } - + @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Result {$id}: " . var_export($result, true) . "\n", FILE_APPEND); return $result; } From 16babcd9028e88ef75ca3ddd03b26159ff4c9777 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 29 Oct 2018 16:48:52 +0700 Subject: [PATCH 508/658] More logging --- service/lib/ethplorer.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index da09ef1e..e3d6fad7 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3322,7 +3322,7 @@ protected function _callRPC($method, $params = array()){ } return $this->_jsonrpcall($this->aSettings['ethereum'], $method, $params); } - + protected function _jsonrpcall($service, $method, $params = array()){ $data = array( 'jsonrpc' => "2.0", @@ -3330,13 +3330,12 @@ protected function _jsonrpcall($service, $method, $params = array()){ 'method' => $method, 'params' => $params ); + $logFile = 'jsonrpc-request'; + $log = ($method !== 'eth_getBalance') && true; + $id = uniqid(); $result = false; $json = json_encode($data); - if(filter_input(INPUT_GET, "debugRPC")){ - echo "Request: " . var_export($json, true) . "\n"; - } - $id = uniqid(); - @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Request {$id}: " . var_export($json, true) . "\n", FILE_APPEND); + $this->log($logFile, "Request {$id}: " . var_export($json, true), $log); $ch = curl_init($service); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( @@ -3348,11 +3347,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $rjson = curl_exec($ch); - if(filter_input(INPUT_GET, "debugRPC")){ - echo "Response: " . var_export($rjson, true) . "\n"; - die; - } - @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Response {$id}: " . var_export($rjson, true) . "\n", FILE_APPEND); + $this->log($logFile, "Response {$id}: " . var_export($rjson, true), $log); if($rjson && (is_string($rjson)) && ('{' === $rjson[0])){ $json = json_decode($rjson, JSON_OBJECT_AS_ARRAY); if(isset($json["result"])){ @@ -3362,7 +3357,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ $result = ["error" => $json["error"]]; } } - @file_put_contents(__DIR__ . '/../log/jsonrpc-request.log', '[' . date('Y-m-d H:i:s') . "] Result {$id}: " . var_export($result, true) . "\n", FILE_APPEND); + $this->log($logFile, "Result {$id}: " . var_export($result, true), $log); return $result; } @@ -3462,6 +3457,12 @@ protected function getEthToken(){ ); } + protected function log($file, $message, $log = true){ + if($log){ + @file_put_contents(__DIR__ . '/../log/' . $file . '.log', '[' . date('Y-m-d H:i:s') . "] " . $message . "\n", FILE_APPEND); + } + } + protected function _cliDebug($message){ $showDebug = ((isset($this->aSettings['cliDebug']) && $this->aSettings['cliDebug']) || defined('ETHPLORER_SHOW_OUTPUT')) && (php_sapi_name() === 'cli'); if($showDebug){ From f0c25b2b980b07a55f54ad328463752dec0494d0 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 29 Oct 2018 17:02:53 +0700 Subject: [PATCH 509/658] CSV export fixed. --- service/lib/ethplorer.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index d4e97a43..bc39071b 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1507,7 +1507,7 @@ public function getAddressBalances($address, $withZero = TRUE, $withEth = FALSE) * @param int $limit Maximum number of records * @return array */ - public function getLastTransfers(array $options = array(), $showEth = FALSE){ + public function getLastTransfers(array $options = array(), $showTx = FALSE){ $search = array(); if(isset($options['address']) && !isset($options['history'])){ $search['contract'] = $options['address']; @@ -1518,9 +1518,16 @@ public function getLastTransfers(array $options = array(), $showEth = FALSE){ if(isset($options['token']) && isset($options['history'])){ $search['contract'] = $options['token']; } - if(!$showEth && !isset($search['contract'])){ + if(!$showTx && !isset($search['contract'])){ $search['isEth'] = false; } + if($showTx == self::SHOW_TX_ETH){ + $search['isEth'] = true; + }else if($showTx == self::SHOW_TX_TOKENS){ + $search['isEth'] = false; + }else if($showTx && isset($search['isEth'])){ + unset($search['isEth']); + } if(!isset($options['type'])){ $search['type'] = 'transfer'; }else{ @@ -1653,7 +1660,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $tokenSymbol = ''; $isToken = $this->getToken($address); if($isToken){ - $operations = $this->getLastTransfers($options, $this->showTx ? TRUE : FALSE); + $operations = $this->getLastTransfers($options); $dec = Decimal::create($isToken['decimals']); $tokenName = isset($isToken['name']) ? $isToken['name'] : ''; $tokenSymbol = isset($isToken['symbol']) ? $isToken['symbol'] : ''; From 008a20a69b8b5cabfdd3f568a780cf9496da2826 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 29 Oct 2018 17:13:20 +0700 Subject: [PATCH 510/658] logging fix --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 5fac1277..10151c81 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3338,7 +3338,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ 'params' => $params ); $logFile = 'jsonrpc-request'; - $log = ($method !== 'eth_getBalance') && true; + $log = ($method !== 'eth_getBalance') && ($method !== 'getCurencyCurrent') && true; $id = uniqid(); $result = false; $json = json_encode($data); From ce7705c0df74ae96f2c5f058f9abc78b48718a4e Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 29 Oct 2018 17:14:21 +0700 Subject: [PATCH 511/658] Typo fixed --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 10151c81..9903cf54 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -3338,7 +3338,7 @@ protected function _jsonrpcall($service, $method, $params = array()){ 'params' => $params ); $logFile = 'jsonrpc-request'; - $log = ($method !== 'eth_getBalance') && ($method !== 'getCurencyCurrent') && true; + $log = ($method !== 'eth_getBalance') && ($method !== 'getCurrencyCurrent') && true; $id = uniqid(); $result = false; $json = json_encode($data); From 148703c22be6a519e3053549443542c37ccf3743 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 29 Oct 2018 19:42:20 +0700 Subject: [PATCH 512/658] CSV export fixed. --- service/lib/ethplorer.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 9903cf54..8a335ab5 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1646,7 +1646,8 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $options = array( 'address' => $address, 'type' => $type, - 'limit' => $limit + 'limit' => $limit, + 'history' => true ); $aTokens = array(); $addTokenInfo = true; From 16698056676abe67c12b019540ef9ba46eea13cc Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 29 Oct 2018 20:07:54 +0700 Subject: [PATCH 513/658] Revert "CSV export fixed." This reverts commit 148703c22be6a519e3053549443542c37ccf3743. --- service/lib/ethplorer.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 8a335ab5..9903cf54 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1646,8 +1646,7 @@ public function getAddressOperationsCSV($address, $type = 'transfer'){ $options = array( 'address' => $address, 'type' => $type, - 'limit' => $limit, - 'history' => true + 'limit' => $limit ); $aTokens = array(); $addTokenInfo = true; From 195be403034277a9b25a9ae6cef72b567be72aff Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 28 Nov 2018 14:11:04 +0700 Subject: [PATCH 514/658] Last block cache updated --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 9903cf54..55e060d2 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1451,7 +1451,7 @@ public function getContractIssuances($address, $limit = 10, $offset = FALSE){ */ public function getLastBlock($updateCache = FALSE){ evxProfiler::checkpoint('getLastBlock', 'START'); - $lastblock = $this->oCache->get('lastBlock', false, true, 300); + $lastblock = $this->oCache->get('lastBlock', false, true, 5); if($updateCache || (false === $lastblock)){ $cursor = $this->oMongo->find('blocks', array(), array('number' => -1), 1, false, array('number')); $block = false; From 508c9a97893336b9f0003eb2b067571eaaaee9c7 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 28 Nov 2018 14:56:08 +0700 Subject: [PATCH 515/658] Cron script updated to cache last block more frequentely --- bin/cache_last_block.php | 6 +++++- service/lib/ethplorer.php | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/cache_last_block.php b/bin/cache_last_block.php index d245e40c..84d9cae0 100644 --- a/bin/cache_last_block.php +++ b/bin/cache_last_block.php @@ -23,7 +23,11 @@ $es = Ethplorer::db($aConfig); $es->createProcessLock('lastBlock.lock', 5); -$es->getLastBlock(true); + +for($i=0; $i<9; $i++){ + $es->getLastBlock(true); + sleep(5); +} $ms = round(microtime(TRUE) - $startTime, 4); echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 55e060d2..135e4601 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -1451,11 +1451,11 @@ public function getContractIssuances($address, $limit = 10, $offset = FALSE){ */ public function getLastBlock($updateCache = FALSE){ evxProfiler::checkpoint('getLastBlock', 'START'); - $lastblock = $this->oCache->get('lastBlock', false, true, 5); + $lastblock = $this->oCache->get('lastBlock', false, true, 300); if($updateCache || (false === $lastblock)){ $cursor = $this->oMongo->find('blocks', array(), array('number' => -1), 1, false, array('number')); $block = false; - foreach($cursor as $block) break; + foreach($cursor as $block) break; $lastblock = $block && isset($block['number']) ? $block['number'] : false; $this->oCache->save('lastBlock', $lastblock); } From 840ba6a4c2e1bdad73386e8674627c23b67782e5 Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 3 Dec 2018 20:30:37 +0700 Subject: [PATCH 516/658] Switch the incomplete test off --- tests/serviceTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/serviceTest.php b/tests/serviceTest.php index 13717ca0..c9a1d308 100644 --- a/tests/serviceTest.php +++ b/tests/serviceTest.php @@ -1,4 +1,9 @@ assertArrayHasKey('pending', $txDetails); $this->assertTrue($txDetails['pending']); } -} \ No newline at end of file +} From e4c32a488d4eb1a47927aec3d62587ca5a8dec9e Mon Sep 17 00:00:00 2001 From: Artem Date: Mon, 3 Dec 2018 20:36:04 +0700 Subject: [PATCH 517/658] PHPUnit error fix --- tests/serviceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/serviceTest.php b/tests/serviceTest.php index c9a1d308..c91ffc84 100644 --- a/tests/serviceTest.php +++ b/tests/serviceTest.php @@ -9,7 +9,7 @@ class serviceTest {} use EverexIO\PHPUnitIterator\TestCase; -class serviceTest extends TestCase +class serviceTestOld extends TestCase { private $ethplorer; private $config; From 7df8c3408f4483a8d30975007ffa9bdca2f953ae Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 11 Dec 2018 14:56:53 +0700 Subject: [PATCH 518/658] APIKey work refactoring, command filtering at APIKey level added --- api/controller.php | 5 +++++ service/lib/ethplorer.php | 42 +++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/api/controller.php b/api/controller.php index cd530156..fec29019 100644 --- a/api/controller.php +++ b/api/controller.php @@ -173,6 +173,11 @@ public function run(){ $this->sendError(133, 'API key temporary suspended. Contact support.', 403); } + $apiKeyAllowedCommands = $this->db->getAPIKeyAllowedCommands($key); + if(!empty($apiKeyAllowedCommands) && (!in_array($command, $apiKeyAllowedCommands))){ + $this->sendError(135, 'Route ' + $command + 'disabled for this API key', 403); + } + if($isMethodPOST){ // @todo: Temporary solution, special key property will be used later if($key == "freekey"){ diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 135e4601..ada63513 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2320,32 +2320,40 @@ public function getAllowedAPICommands(array $commands){ return $result; } + public function getAPIKeySettings($key){ + return isset($this->aSettings['apiKeys']) && isset($this->aSettings['apiKeys'][$key]) ? $this->aSettings['apiKeys'][$key] : false; + } + public function checkAPIKey($key){ - return isset($this->aSettings['apiKeys']) && isset($this->aSettings['apiKeys'][$key]); + return is_array($this->getAPIKeySettings($key)); } public function isSuspendedAPIKey($key){ - return (isset($this->aSettings['apiKeys'][$key]['suspended']) && $this->aSettings['apiKeys'][$key]['suspended']); + $keyData = $this->getAPIKeySettings($key); + return ($keyData && isset($keyData['suspended']) && !!$keyData['suspended']); + } + + public function getAPIKeyAllowedCommands($key){ + $keyData = $this->getAPIKeySettings($key); + return ($keyData && isset($keyData['allowedCommands']) && is_array($keyData['allowedCommands'])) ? $keyData['allowedCommands'] : []; } public function getAPIKeyDefaults($key, $option = FALSE){ $res = FALSE; if($this->checkAPIKey($key)){ - if(is_array($this->aSettings['apiKeys'][$key])){ - if(FALSE === $option){ - $res = $this->aSettings['apiKeys'][$key]; - }else{ - if(isset($this->aSettings['apiKeys'][$key][$option])){ - $res = $this->aSettings['apiKeys'][$key][$option]; - } - - if($key != 'freekey' && isset($this->aSettings['personalLimits'])){ - foreach($this->aSettings['personalLimits'] as $cmd => $aLimits){ - if($cmd == $option){ - foreach($aLimits as $opt => $limit){ - if(!isset($res[$opt]) || ($res[$opt] < $limit)){ - $res[$opt] = $limit; - } + $keyData = $this->getAPIKeySettings($key); + if(FALSE === $option){ + $res = $keyData; + }else{ + if(isset($keyData[$option])){ + $res = $$keyData[$option]; + } + if($key != 'freekey' && isset($this->aSettings['personalLimits'])){ + foreach($this->aSettings['personalLimits'] as $cmd => $aLimits){ + if($cmd == $option){ + foreach($aLimits as $opt => $limit){ + if(!isset($res[$opt]) || ($res[$opt] < $limit)){ + $res[$opt] = $limit; } } } From 2cc18e72fd8f364bfef794274c43b061a35fa7d2 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 11 Dec 2018 15:31:11 +0700 Subject: [PATCH 519/658] Invalid string concatination fixed --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index fec29019..33dbf51a 100644 --- a/api/controller.php +++ b/api/controller.php @@ -175,7 +175,7 @@ public function run(){ $apiKeyAllowedCommands = $this->db->getAPIKeyAllowedCommands($key); if(!empty($apiKeyAllowedCommands) && (!in_array($command, $apiKeyAllowedCommands))){ - $this->sendError(135, 'Route ' + $command + 'disabled for this API key', 403); + $this->sendError(135, 'Route ' . $command . 'disabled for this API key', 403); } if($isMethodPOST){ From 863da9ca8c82e31173a6252338fc2b68edfd4ddb Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 11 Dec 2018 15:32:01 +0700 Subject: [PATCH 520/658] Space added --- api/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controller.php b/api/controller.php index 33dbf51a..80b32cb9 100644 --- a/api/controller.php +++ b/api/controller.php @@ -175,7 +175,7 @@ public function run(){ $apiKeyAllowedCommands = $this->db->getAPIKeyAllowedCommands($key); if(!empty($apiKeyAllowedCommands) && (!in_array($command, $apiKeyAllowedCommands))){ - $this->sendError(135, 'Route ' . $command . 'disabled for this API key', 403); + $this->sendError(135, 'Route ' . $command . ' disabled for this API key', 403); } if($isMethodPOST){ From 9be303ade31831b713f9e2e9d42ee03d453e8628 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 13 Dec 2018 20:54:47 +0700 Subject: [PATCH 521/658] Address price history with showTx param. --- api/controller.php | 5 +++-- service/lib/ethplorer.php | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/api/controller.php b/api/controller.php index 80b32cb9..bf357579 100644 --- a/api/controller.php +++ b/api/controller.php @@ -568,8 +568,9 @@ public function getAddressPriceHistoryGrouped(){ $this->sendError(104, 'Invalid address format'); } } - $withEth = (isset($_GET["withEth"]) && (bool)$_GET["withEth"]) ? TRUE : FALSE; - $result = array('history' => $this->db->getAddressPriceHistoryGrouped($address, FALSE, $withEth)); + $showTx = isset($_GET["showTx"]) ? $_GET["showTx"] : 'tokens'; + if($showTx) $this->db->setShowTx($showTx); + $result = array('history' => $this->db->getAddressPriceHistoryGrouped($address, FALSE)); if(isset($result['history']['cache'])) $this->cacheState = $result['history']['cache']; else $this->cacheState = ''; $this->sendResult($result); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index ada63513..968eada2 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2882,10 +2882,10 @@ public function getTokenPriceHistoryGrouped($address, $period = 365, $type = 'da return $aResult; } - public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $withEth = FALSE){ - evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'START', 'address=' . $address . ', withEth=' . ($withEth ? 'TRUE' : 'FALSE')); + public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE){ + evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'START', 'address=' . $address . ', showTx=' . $this->showTx); - $cache = 'address_operations_history-' . $address . ($withEth ? '-eth' : ''); + $cache = 'address_operations_history-' . $address . '-' . $this->showTx; $result = $this->oCache->get($cache, false, true); $updateCache = false; if($result && isset($result['timestamp'])){ @@ -2895,7 +2895,10 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w $result = false; $updateCache = false; } - + $withEth = FALSE; + if($this->showTx == self::SHOW_TX_ALL || $this->showTx == self::SHOW_TX_ETH){ + $withEth = TRUE; + } if(FALSE === $result || $updateCache){ $opCount = $this->countOperations($address, FALSE); @@ -2920,12 +2923,10 @@ public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE, $w foreach($aSearch as $cond){ $search = array($cond => $address); - if(!$withEth){ - if($this->useOperations2){ - $search['isEth'] = false; - }else{ - $search['contract'] = array('$ne' => 'ETH'); - } + if($this->showTx == self::SHOW_TX_ETH){ + $search['isEth'] = true; + }else if($this->showTx == self::SHOW_TX_TOKENS){ + $search['isEth'] = false; } if($updateCache){ $search = array('$and' => array($search, array('timestamp' => array('$gt' => $result['timestamp'])))); From 027ab6245a4b919ed355e5b9798163ad778243f2 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 13 Dec 2018 21:10:27 +0700 Subject: [PATCH 522/658] Address price history widget with showTx param. --- api/widget.js | 4 ++-- js/ethplorer.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/api/widget.js b/api/widget.js index 741ec6ce..5909beee 100644 --- a/api/widget.js +++ b/api/widget.js @@ -161,7 +161,7 @@ ethplorerWidget = { apiKey: 'ethplorer.widget', domain: document.location.href, period: 730, - withEth: preloadMethod.options.withEth ? preloadMethod.options.withEth : '', + showTx: preloadMethod.options.showTx ? preloadMethod.options.showTx : '', }; $.getJSON(api, params, function(_address){ @@ -2489,7 +2489,7 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, }; this.getRequestParams = function(additionalParams){ - var requestOptions = ['period', 'address', 'withEth', 'type', 'theme']; + var requestOptions = ['period', 'address', 'showTx', 'type', 'theme']; var params = { apiKey: 'ethplorer.widget' }; diff --git a/js/ethplorer.js b/js/ethplorer.js index 1a04b0fe..3c1a9d88 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1239,8 +1239,9 @@ Ethplorer = { getCode: true, address: address, period: 730, + showTx: Ethplorer.showTx }; - if(Ethplorer.Storage.get('withEth', false)) opt['withEth'] = true; + //if(Ethplorer.Storage.get('withEth', false)) opt['withEth'] = true; ethplorerWidget.init( '#token-price-history-grouped-widget', 'addressPriceHistoryGrouped', From b3c5b19e215225a0e630b9d53ef35255aa902434 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 13 Dec 2018 21:51:04 +0700 Subject: [PATCH 523/658] Address price history widget with showTx param. --- api/widget.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/widget.js b/api/widget.js index 5909beee..6db9ff7d 100644 --- a/api/widget.js +++ b/api/widget.js @@ -157,11 +157,17 @@ ethplorerWidget = { address = preloadMethod.options.address.toString().toLowerCase(); api += ('/' + address); } + var showTx = 'all'; + try{ + if(localStorage && (null !== localStorage.getItem('showTx'))){ + showTx = localStorage.getItem('showTx'); + } + }catch(e){} var params = { apiKey: 'ethplorer.widget', domain: document.location.href, period: 730, - showTx: preloadMethod.options.showTx ? preloadMethod.options.showTx : '', + showTx: showTx, }; $.getJSON(api, params, function(_address){ From a386827484d6fd6697ea4d644c59ee92940badf6 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Thu, 13 Dec 2018 21:57:42 +0700 Subject: [PATCH 524/658] Cache keys changed. --- service/lib/ethplorer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 968eada2..03a8580a 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -2885,7 +2885,7 @@ public function getTokenPriceHistoryGrouped($address, $period = 365, $type = 'da public function getAddressPriceHistoryGrouped($address, $updateCache = FALSE){ evxProfiler::checkpoint('getAddressPriceHistoryGrouped', 'START', 'address=' . $address . ', showTx=' . $this->showTx); - $cache = 'address_operations_history-' . $address . '-' . $this->showTx; + $cache = 'address_operations_history-' . $address . '-showTx-' . $this->showTx; $result = $this->oCache->get($cache, false, true); $updateCache = false; if($result && isset($result['timestamp'])){ From 5ac6ace6e7f30a684ee0bc110b6e4adbfb9cbfab Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 14:06:45 +0700 Subject: [PATCH 525/658] Reloading address price history widget. --- api/widget.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/api/widget.js b/api/widget.js index 6db9ff7d..206d7d78 100644 --- a/api/widget.js +++ b/api/widget.js @@ -87,10 +87,10 @@ ethplorerWidget = { google.load('visualization', '1', {'packages': ['controls'], 'language': 'en', callback : ethplorerWidget.drawGoogleControlCharts}); } }, - drawGoogleControlCharts: function(){ + drawGoogleControlCharts: function(reloadData){ if(ethplorerWidget.chartControlWidgets && ethplorerWidget.chartControlWidgets.length) for(var i=0; iLoading...
    ', }; - this.load = function(){ + this.load = function(reloadData){ var address; if(options && options.address){ address = options.address.toString().toLowerCase(); } - if(address && ethplorerWidget.preloadPriceHistory && ethplorerWidget.preloadPriceHistory[address]){ + if(reloadData){ + this.reloadData = true; + } + if(!this.reloadData && address && ethplorerWidget.preloadPriceHistory && ethplorerWidget.preloadPriceHistory[address]){ //console.log(ethplorerWidget.preloadPriceHistory[address]); this.refreshWidget(ethplorerWidget.preloadPriceHistory[address]); }else{ + if(this.reloadData){ + this.el.empty(); + this.el.html(this.templates.loader); + this.reloadData = false; + } $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); } }; From da514dfcb633a593fbf43cf5f4abd09e88418e08 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 14:13:08 +0700 Subject: [PATCH 526/658] Reloading address price history widget. --- js/ethplorer.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/ethplorer.js b/js/ethplorer.js index 3c1a9d88..86958547 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1397,6 +1397,7 @@ Ethplorer = { $('#' + tableId).show(); }, showTransfers: function(switcher, type){ + var data = Ethplorer.data; Ethplorer.Nav.del('transfers'); if(switcher.checked){ type = 'all'; @@ -1413,6 +1414,9 @@ Ethplorer = { Ethplorer.gaSendEvent('userAction', 'listShowTx', type); Ethplorer.Storage.set('showTx', type); Ethplorer.Nav.set('showTx', type); + if(!data.token && ethplorerWidget && ethplorerWidget.drawGoogleControlCharts){ + ethplorerWidget.drawGoogleControlCharts(true); + } //if(type != 'all') Ethplorer.Nav.set('showTx', type); //else Ethplorer.Nav.del('showTx'); var tab = Ethplorer.getActiveTab(); From 7d354b9fa57a3af9da4ec334973165c20e04ceca Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 14:54:16 +0700 Subject: [PATCH 527/658] Reloading address price history widget. --- api/widget.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/widget.js b/api/widget.js index 206d7d78..e79d55c2 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2182,6 +2182,11 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, this.refreshWidget(ethplorerWidget.preloadPriceHistory[address]); }else{ if(this.reloadData){ + try{ + if(localStorage && (null !== localStorage.getItem('showTx'))){ + this.options['showTx'] = localStorage.getItem('showTx'); + } + }catch(e){} this.el.empty(); this.el.html(this.templates.loader); this.reloadData = false; From 9a15a72aaf745db572e8a81d75a1eac6f0ee6ca3 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 15:25:05 +0700 Subject: [PATCH 528/658] Reloading address price history widget. --- api/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/widget.js b/api/widget.js index e79d55c2..391cbc5e 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2513,10 +2513,10 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, var params = { apiKey: 'ethplorer.widget' }; - if('undefined' === typeof(this.pathReported)){ + //if('undefined' === typeof(this.pathReported)){ params['domain'] = document.location.href; this.pathReported = true; - } + //} for(var key in this.options){ if(requestOptions.indexOf(key) >= 0){ params[key] = this.options[key]; From c9a9677449cce479039695670b7f4f0726ff4cd1 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 15:38:24 +0700 Subject: [PATCH 529/658] Reloading address price history widget. --- api/widget.js | 14 ++++++-------- js/ethplorer.js | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/api/widget.js b/api/widget.js index 391cbc5e..4c771c35 100644 --- a/api/widget.js +++ b/api/widget.js @@ -87,10 +87,10 @@ ethplorerWidget = { google.load('visualization', '1', {'packages': ['controls'], 'language': 'en', callback : ethplorerWidget.drawGoogleControlCharts}); } }, - drawGoogleControlCharts: function(reloadData){ + drawGoogleControlCharts: function(reloadData, opt){ if(ethplorerWidget.chartControlWidgets && ethplorerWidget.chartControlWidgets.length) for(var i=0; iLoading...
    ', }; - this.load = function(reloadData){ + this.load = function(reloadData, opt){ var address; if(options && options.address){ address = options.address.toString().toLowerCase(); @@ -2182,11 +2182,9 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, this.refreshWidget(ethplorerWidget.preloadPriceHistory[address]); }else{ if(this.reloadData){ - try{ - if(localStorage && (null !== localStorage.getItem('showTx'))){ - this.options['showTx'] = localStorage.getItem('showTx'); - } - }catch(e){} + if(opt && opt.showTx){ + this.options['showTx'] = opt.showTx; + } this.el.empty(); this.el.html(this.templates.loader); this.reloadData = false; diff --git a/js/ethplorer.js b/js/ethplorer.js index 86958547..f477be4a 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1415,7 +1415,7 @@ Ethplorer = { Ethplorer.Storage.set('showTx', type); Ethplorer.Nav.set('showTx', type); if(!data.token && ethplorerWidget && ethplorerWidget.drawGoogleControlCharts){ - ethplorerWidget.drawGoogleControlCharts(true); + ethplorerWidget.drawGoogleControlCharts(true, {showTx: type}); } //if(type != 'all') Ethplorer.Nav.set('showTx', type); //else Ethplorer.Nav.del('showTx'); From 90bd612343f34b5d187730bdf6b9f0c4efb549f9 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 17:00:29 +0700 Subject: [PATCH 530/658] Reloading address price history widget. --- api/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/widget.js b/api/widget.js index 4c771c35..c05cb893 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2185,8 +2185,8 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, if(opt && opt.showTx){ this.options['showTx'] = opt.showTx; } - this.el.empty(); - this.el.html(this.templates.loader); + //this.el.empty(); + //this.el.html(this.templates.loader); this.reloadData = false; } $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); From 09f9a2665f040aa5a5cc1662ccdc5347401046de Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 17:05:50 +0700 Subject: [PATCH 531/658] Reloading address price history widget. --- api/widget.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/widget.js b/api/widget.js index c05cb893..ef3c826e 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2187,7 +2187,7 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, } //this.el.empty(); //this.el.html(this.templates.loader); - this.reloadData = false; + //this.reloadData = false; } $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); } @@ -2537,7 +2537,7 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, obj.widgetData = data.history; obj.el.find('.txs-loading').remove(); obj.drawChart(data.history); - ethplorerWidget.appendEthplorerLink(obj); + if(!obj.reloadData) ethplorerWidget.appendEthplorerLink(obj); if('function' === typeof(obj.options.onLoad)){ obj.options.onLoad(); } @@ -2548,6 +2548,7 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, $('.txs-loading').css('min-height', '1px'); $('.txs-loading').css('padding-top', '10px'); } + obj.reloadData = false; }; }(this); From c1eb2eb8482f8fd6e880a6c72b8fb2039588d88e Mon Sep 17 00:00:00 2001 From: Lexa M Date: Fri, 14 Dec 2018 17:30:51 +0700 Subject: [PATCH 532/658] Reloading address price history widget. --- api/widget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/api/widget.js b/api/widget.js index ef3c826e..a41e0162 100644 --- a/api/widget.js +++ b/api/widget.js @@ -2541,6 +2541,7 @@ ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, if('function' === typeof(obj.options.onLoad)){ obj.options.onLoad(); } + if(obj.reloadData) obj.el.fadeOut(250, () => {obj.el.fadeIn(150);}); setTimeout(ethplorerWidget.fixTilda, 300); }else{ obj.el.find('.txs-loading').text('No data for chart'); From 2baa47a1aeb0bf9128d3ad1120b1b37e54fae262 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 17 Dec 2018 19:23:33 +0700 Subject: [PATCH 533/658] Address balance customization. --- css/ethplorer.css | 6 +++--- index.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 2e78f616..99440de0 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -409,7 +409,7 @@ td.list-field { text-overflow: ellipsis; } -.token-related .blue td { +.address-balance, .token-related .blue td { font-size: 20px; white-space: normal; } @@ -1184,7 +1184,7 @@ li.ui-menu-item.have-more { } @media screen and (max-width: 699px) { - .token-related .blue td { + .address-balance, .token-related .blue td { font-size: 18px; } @@ -1235,7 +1235,7 @@ li.ui-menu-item.have-more { #address-issuances tr td:last-child { min-width: 140px; } - .token-related .blue td { + .address-balance, .token-related .blue td { font-size: 16px; } #address-token-transfers td { diff --git a/index.php b/index.php index bdbc4fbf..e9608d2d 100644 --- a/index.php +++ b/index.php @@ -524,7 +524,7 @@ Create Tx - + Balance From 1ad5f02a9fab84d1c66c6350cc1a0689597d0335 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 17 Dec 2018 20:03:49 +0700 Subject: [PATCH 534/658] Address eth and token balances. --- index.php | 2 +- js/ethplorer.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index e9608d2d..ab933e91 100644 --- a/index.php +++ b/index.php @@ -550,7 +550,7 @@
    -

    Token Balances +

    Balances (ETH+Tokens)

    diff --git a/js/ethplorer.js b/js/ethplorer.js index f477be4a..e75d61da 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1026,6 +1026,13 @@ Ethplorer = { // Fill prices var totalPrice = 0; var lastTotalPrice = 0; + if(Ethplorer.ethPrice && Ethplorer.ethPrice.rate && data.balance){ + totalPrice = Ethplorer.ethPrice.rate * data.balance; + if(Ethplorer.ethPrice.diff){ + var lastEthRate = Ethplorer.ethPrice.diff > -100 ? (Ethplorer.ethPrice.rate / (1 + Ethplorer.ethPrice.diff / 100)) : 0; + lastTotalPrice += lastEthRate * data.balance; + } + } for(var k=0; k Date: Mon, 17 Dec 2018 20:15:32 +0700 Subject: [PATCH 535/658] Address eth and token balances. --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index ab933e91..8da18c9f 100644 --- a/index.php +++ b/index.php @@ -550,7 +550,7 @@
    -

    Balances (ETH+Tokens) +

    Balances (ETH+Tokens)

    From c7355d5ba9ffa5eb57ddd8b83d5222d3c03f815a Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 17 Dec 2018 20:27:18 +0700 Subject: [PATCH 536/658] Address balance customization. --- css/ethplorer.css | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/css/ethplorer.css b/css/ethplorer.css index 99440de0..c8c0a4f6 100644 --- a/css/ethplorer.css +++ b/css/ethplorer.css @@ -1604,4 +1604,16 @@ a.token-update { padding-bottom: 7px; display: inline-block; margin-right: 10px; -} \ No newline at end of file +} + +@media screen and (min-width: 992px) and (max-width: 1199px) { + #address-full-balance { + display: none; + } +} + +@media screen and (max-width: 499px) { + #address-full-balance { + display: none; + } +} From d931d23d260cd4018a6bd9b3cfa622ae0be34d98 Mon Sep 17 00:00:00 2001 From: Lexa M Date: Mon, 17 Dec 2018 20:37:27 +0700 Subject: [PATCH 537/658] Address balance customization. --- index.php | 2 +- js/ethplorer.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index 8da18c9f..9baf0e6b 100644 --- a/index.php +++ b/index.php @@ -524,7 +524,7 @@ Create Tx - + Balance diff --git a/js/ethplorer.js b/js/ethplorer.js index e75d61da..efbd500a 100644 --- a/js/ethplorer.js +++ b/js/ethplorer.js @@ -1113,6 +1113,9 @@ Ethplorer = { row.find('td:eq(1)').addClass('text-right'); $('#address-token-balances table').append(row); } + $('#addr-balance').addClass('blue'); + $('#addr-balance').addClass('even'); + $('#addr-balance').addClass('address-balance'); if(totalPrice){ var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); if(totalDiff){ From 9978e1cf52c25145dfabbb8385a2b39899263bd1 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Dec 2018 18:04:39 +0700 Subject: [PATCH 538/658] Search memory issues fixed --- service/lib/cache.php | 5 ++- service/lib/ethplorer.php | 80 +++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/service/lib/cache.php b/service/lib/cache.php index e6bd074f..8b0aad1d 100644 --- a/service/lib/cache.php +++ b/service/lib/cache.php @@ -200,10 +200,11 @@ public function save($entryName, $data, $nonExpiration = FALSE){ } $aCachedData = array('lifetime' => $lifetime, 'data' => $data, 'lock' => true); if('redis' == $this->driver){ + $saveOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR; if($nonExpiration){ - $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData)); + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData, $saveOptions)); }else{ - $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData), 'ex', $ttl); + $saveRes = $this->oDriver->set($entryName, json_encode($aCachedData, $saveOptions), 'ex', $ttl); } if('OK' !== (string)$saveRes){ error_log("Write data to redis failed: " . $saveRes . " Data: " . json_encode($aCachedData) . " TTL: " . $ttl); diff --git a/service/lib/ethplorer.php b/service/lib/ethplorer.php index 03a8580a..ddbb1956 100644 --- a/service/lib/ethplorer.php +++ b/service/lib/ethplorer.php @@ -998,7 +998,7 @@ public function getTransfers($tx){ public function getIssuances($tx){ return $this->getOperations($tx, array('$in' => array('issuance', 'burn', 'mint'))); } - + /** * Returns list of known tokens. * @@ -3377,46 +3377,60 @@ protected function _jsonrpcall($service, $method, $params = array()){ return $result; } - public function searchToken($token){ - $result = array('results' => array(), 'total' => 0); - $found = array(); - $aTokens = $this->getTokens(); - $aTokens['0xf3763c30dd6986b53402d41a8552b8f7f6a6089b'] = array( - 'name' => 'Chainy', - 'symbol' => false, - 'txsCount' => 99999 - ); - if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens'])){ - $aClientTokens = $this->aSettings['client']['tokens']; - foreach($aClientTokens as $address => $aClientToken){ - if(isset($aTokens[$address])){ - if(isset($aClientToken['name'])){ - $aTokens[$address]['name'] = $aClientToken['name']; + protected function getTokensForSearch(){ + $aResult = $this->oCache->get('tokens-simple', false, true, 3600); + if(false === $aResult){ + $aResult = []; + $this->getTokens(); + $this->aTokens['0xf3763c30dd6986b53402d41a8552b8f7f6a6089b'] = array( + 'name' => 'Chainy', + 'symbol' => false, + 'txsCount' => 99999 + ); + foreach($this->aTokens as $address => $aToken){ + $name = substr($aToken['name'], 0, 32); + if($name && ($name[0] === "\t")) continue; + $aSearchToken = [ + 'address' => $address, + 'name' => trim($name), + 'symbol' => trim($aToken['symbol']), + 'txsCount' => $aToken['txsCount'] + ]; + if(isset($this->aSettings['client']) && isset($this->aSettings['client']['tokens']) && isset($this->aSettings['client']['tokens'][$address])){ + $aClientToken = $this->aSettings['client']['tokens'][$address]; + if(!empty($aClientToken['name'])){ + $aSearchToken['name'] = $aClientToken['name']; } - if(isset($aClientToken['symbol'])){ - $aTokens[$address]['symbol'] = $aClientToken['symbol']; + if(!empty($aClientToken['symbol'])){ + $aSearchToken['symbol'] = $aClientToken['symbol']; } } + $aResult[] = $aSearchToken; } - } - foreach($aTokens as $address => $aToken){ - $search = strtolower($token); - if((strpos($address, $search) !== FALSE) || (!empty($aToken['name']) && (strpos(strtolower($aToken['name']), $search) !== FALSE)) || (!empty($aToken['symbol']) && (strpos(strtolower($aToken['symbol']), $search) !== FALSE))){ - $aToken['address'] = $address; - $found[] = $aToken; + uasort($aResult, array($this, 'sortTokensByTxsCount')); + foreach($aResult as $i => $aToken){ + unset($aResult[$i]['txsCount']); } + $this->oCache->save('tokens-simple', $aResult); } - uasort($found, array($this, 'sortTokensByTxsCount')); - $i = 0; - foreach($found as $aToken){ - if($i < 6){ - $aToken += array('name' => '', 'symbol' => ''); - $result['results'][] = array($aToken['name'], $aToken['symbol'], $aToken['address']); + return $aResult; + } + + public function searchToken($token, $maxResults = 5){ + $result = array('results' => array(), 'search' => $token, 'total' => 0); + $found = array(); + $aTokens = $this->getTokensForSearch(); + $count = 0; + $search = strtolower($token); + foreach($aTokens as $aToken){ + if((FALSE !== strpos($aToken['address'], $search)) || (FALSE !== strpos(strtolower($aToken['name']), $search)) || (FALSE !== strpos(strtolower($aToken['symbol']), $search))){ + $count++; + $result['total'] = $count; + if($count <= $maxResults){ + $result['results'][] = [$aToken['name'], $aToken['symbol'], $aToken['address']]; + } } - $i++; } - $result['total'] = $i; - $result['search'] = $token; return $result; } From 18845ea3418858d610d8d36f5e3dd1a9717997e7 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Dec 2018 18:35:28 +0700 Subject: [PATCH 539/658] includeLocal added --- index.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.php b/index.php index 9baf0e6b..e0b068b2 100644 --- a/index.php +++ b/index.php @@ -86,6 +86,10 @@ } } +function includeLocal($name){ + if(file_exists(__DIR__ . '/index.' . $name . '.local.php')) requre_once(__DIR__ . '/index.' . $name . '.local.php'); +} + $csvExport = ''; if(is_array($rParts) && isset($rParts[2])){ $csvExport = ' Export...Export as CSV'; @@ -165,6 +169,7 @@ +
    @@ -196,12 +201,7 @@
    - - - - +

    ERROR

    From bcada8a9cc6c5ab583cbdace1785670597189a82 Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Dec 2018 18:36:57 +0700 Subject: [PATCH 540/658] Typo fixed --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index e0b068b2..cc07e0f6 100644 --- a/index.php +++ b/index.php @@ -87,7 +87,7 @@ } function includeLocal($name){ - if(file_exists(__DIR__ . '/index.' . $name . '.local.php')) requre_once(__DIR__ . '/index.' . $name . '.local.php'); + if(file_exists(__DIR__ . '/index.' . $name . '.local.php')) require_once(__DIR__ . '/index.' . $name . '.local.php'); } $csvExport = ''; From 657b725e580cb05785ea5765a0d839071802d3cf Mon Sep 17 00:00:00 2001 From: Artem Date: Tue, 18 Dec 2018 18:55:41 +0700 Subject: [PATCH 541/658] Local file for bottom added --- index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/index.php b/index.php index cc07e0f6..98bf5a0c 100644 --- a/index.php +++ b/index.php @@ -715,6 +715,7 @@ function includeLocal($name){
    +
    '); - return; - } - if(type == 'tokenHistoryGrouped'){ - if(options && options.full) ethplorerWidget.addGoogleAPI = true; - else ethplorerWidget.addGoogleLoader = true; - } - if(type == 'tokenPriceHistoryGrouped' || type == 'addressPriceHistoryGrouped'){ - ethplorerWidget.addGoogleAPI = true; - } - var el = $(selector); - if(!el.length){ - console.error('Cannot initialize Ethplorer widget: element ' + selector + ' not found.'); - return; - } - if('undefined' === ethplorerWidget.eventsAdded){ - $(window).resize(ethplorerWidget.fixTilda); - ethplorerWidget.eventsAdded = true; - } - if('undefined' !== typeof(ethplorerWidget.Type[type])){ - return new ethplorerWidget.Type[type](el, options, templates); - }else{ - console.error('Cannot initialize Ethplorer widget: invalid widget type "' + type + '".'); - } - }, - loadScript: function(url, callback){ - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = url; - script.onreadystatechange = callback; - script.onload = callback; - head.appendChild(script); - }, - addStyles: function(){ - ethplorerWidget.fixPath(); - var linkElem = document.createElement('link'); - linkElem.setAttribute("rel", 'stylesheet'); - linkElem.setAttribute("type", 'text/css'); - linkElem.setAttribute("href", ethplorerWidget.api + '/widget.css?v=' + ethplorerWidget.cssVersion); - document.getElementsByTagName("head")[0].appendChild(linkElem); - }, - loadGoogleCharts: function(){ - if(('undefined' !== typeof(google)) && google && google.charts){ - google.charts.load('current', {packages: ['corechart']}); - - if(ethplorerWidget.chartWidgets && ethplorerWidget.chartWidgets.length) - for(var i=0; i 365) ? 'yyyy' : ((size > 90) ? "MMM ''yy" : "MMM d"), - format: (options.full || size > 90) ? "MMM ''yy" : "MMM d", - gridlines: { - color: (options.full || (size > 90)) ? '#999999' : "none", - count: (options.full || size > 90) ? 6 : 6 - }, - }, - series: series - } - } - } - }; - if(options['theme'] == 'dark'){ - controlOptions.options.ui.chartOptions.colors = ['#DEDEDE']; - controlOptions.options.ui.chartOptions.backgroundColor = {fill: 'transparent'}; - controlOptions.options.ui.chartOptions.hAxis.textStyle = {color: '#DEDEDE'}; - controlOptions.options.ui.chartOptions.hAxis.titleTextStyle.color = '#DEDEDE'; - controlOptions.options.ui.chartOptions.hAxis.baselineColor = '#DEDEDE'; - } - return controlOptions; - }, - getGoogleChartAxisFormat: function(size){ - if(size > 90) return "MMM ''yy"; - else return "MMM d"; - }, - getGoogleChartAxisCount: function(size){ - if(size > 90) return 10; - else return 7; - }, - preloadData: function(methods){ - for(var i=0; i'; - if((document.location.host !== host) && (document.location.host.indexOf("amilabs.cc") < 0)){ - if(!document.getElementById('ethpLink')){ - if(!link) link = 'Ethplorer.io'; - obj.el.append(divLink + link + '
    '); - } - }else if('undefined' !== typeof(obj.options.getCode) && obj.options.getCode){ - var divLink = '
    '; - var popupId = obj.el.attr('id') + '-code'; - obj.el.append(divLink + 'Get widget code
    '); - obj.el.find('.widget-code-link').data("widget", obj); - $("body").append('
    '); - $("#" + popupId).dialog({ - 'autoOpen': false, - 'resizable': false, - 'width': $(window).width() / 2, - 'height': 'auto', - 'open': function(){ - $(this).parents(".ui-dialog:first").find(".ui-dialog-content").click(function(){ - ethplorerWidget.Utils.selectText(popupId); - }); - } - }).css("font-size", "12px"); - } - }, - getWidgetCode: function(obj){ - var widget = $(obj).data().widget, - cr = "\n", - id = widget.el.attr('id'), - popupId = id + '-code', - widgetOptions = $.extend(true, {}, widget.options.widgetOptions || {}); - - if('undefined' !== typeof(widgetOptions.getCode)) delete widgetOptions.getCode; - - var widgetCode = '1. Add jQuery in the HEAD section of your page (if not present):' + cr; - widgetCode += '' + cr + cr; - widgetCode += '2. Put code displayed below somewhere in BODY section.' + cr + cr; - widgetCode += '
    ' + cr; - widgetCode += ''; - - if('undefined' !== typeof(widget.type) && (widget.type === 'tokenPriceHistoryGrouped' || widget.type === 'addressPriceHistoryGrouped')){ - widgetCode = '

    Coming soon!Follow Ethplorer\'s twitter to know first.
    '; - $("#" + popupId).html(widgetCode); - }else{ - $("#" + popupId).text(widgetCode); - var popupContent = $("#" + popupId).html(); - $("#" + popupId).html(popupContent.replace(/(\n)/gm, "
    ")); - } - - $("#" + popupId).dialog('open'); - }, - parseTemplate: function(template, data){ - var res = template; - for(var key in data){ - var reg = new RegExp('%' + key + '%', 'g') - res = res.replace(reg, data[key]); - } - return res; - }, - // Tilda css hack - fixTilda: function(){ - var height = parseInt($('.t-cover__wrapper').height()); - $('.t-cover, .t-cover__carrier, .t-cover__wrapper, .t-cover__filter').height(height + 'px'); - }, - // Use local path for develop instances - fixPath: function(){ - if((document.location.host !== 'ethplorer.io') && (document.location.host.indexOf('ethplorer') >= 0)){ - ethplorerWidget.api = '//' + document.location.host + '/api'; - ethplorerWidget.url = '//' + document.location.host; - } - }, - Utils: { - link: function(data, text, title, hash, addClass){ - title = title || text; - if(data === '0x0000000000000000000000000000000000000000'){ - return '' + text + ''; - } - hash = hash || false; - if((false !== hash) && hash){ - hash = '#' + hash; - }else{ - hash = ''; - } - var linkType = (data && (42 === data.toString().length)) ? 'address' : 'tx'; - if(!addClass){ - addClass = ""; - } - var target = ''; - if((document.location.host !== 'ethplorer.io') && (document.location.host.indexOf('ethplorer.io') < 0)){ - target = ' target="_blank"'; - } - return '' + text + ''; - }, - - // Timestamp to local date - ts2date: function(ts, withTime, withGMT){ - withGMT = 'undefined' !== typeof(withGMT) ? withGMT : true; - ts *= 1000; - function padZero(s){ - return (s < 10) ? '0' + s : s.toString(); - } - var res = ''; - var dt = new Date(ts); - res += (dt.getFullYear() + '-' + padZero((dt.getMonth() + 1)) + '-' + padZero(dt.getDate())); - if(withTime){ - res += ' '; - res += ethplorerWidget.Utils.ts2time(ts, withGMT); - } - return res; - }, - //Timestamp to local time - ts2time: function(ts, withGMT){ - withGMT = 'undefined' !== typeof(withGMT) ? withGMT : true; - ts *= 1000; - function padZero(s){ - return (s < 10) ? '0' + s : s.toString(); - } - var res = ''; - var dt = new Date(ts); - res += (padZero(dt.getHours()) + ':' + padZero(dt.getMinutes()) + ':' + padZero(dt.getSeconds())); - if(withGMT){ - res += (' (' + Ethplorer.Utils.getTZOffset() + ')'); - } - return res; - }, - // Return local offset - getTZOffset: function(){ - var offset = -Math.round(new Date().getTimezoneOffset() / 60); - return 'GMT' + (offset > 0 ? '+' : '-') + offset; - }, - /** - * Number formatter (separates thousands with comma, adds zeroes to decimal part). - * - * @param {int} num - * @param {bool} withDecimals - * @param {int} decimals - * @param {bool} cutZeroes - * @returns {string} - */ - formatNum: function(num, withDecimals /* = false */, decimals /* = 2 */, cutZeroes /* = false */, withPostfix /* = false */, numLimitPostfix /* = 999999 */){ - var postfix = ''; - if(withPostfix){ - if(!numLimitPostfix) numLimitPostfix = 999999; - if(num > 999 && num <= numLimitPostfix){ - num = num / 1000; - postfix = ' K'; - }else if(num > numLimitPostfix){ - num = num / 1000000; - postfix = ' M'; - } - } - function math(command, val, decimals){ - var k = Math.pow(10, decimals ? parseInt(decimals) : 0); - return Math[command](val * k) / k; - } - function padZero(s, len){ - while(s.length < len) s += '0'; - return s; - } - if(('object' === typeof(num)) && ('undefined' !== typeof(num.c))){ - num = parseFloat(Ethplorer.Utils.toBig(num).toString()); - } - cutZeroes = !!cutZeroes; - withDecimals = !!withDecimals; -// decimals = decimals || (cutZeroes ? 0 : 2); - - if((num.toString().indexOf("e+") > 0)){ - return num.toString(); - } - - if((num.toString().indexOf("e-") > 0) && withDecimals){ - var parts = num.toString().split("e-"); - var res = parts[0].replace('.', ''); - for(var i=1; i 1){ - res += '.'; - var tail = parts[1].substring(0, decimals); - if(tail.length < zeroCount){ - tail = padZero(tail, zeroCount); - } - res += tail; - }else{ - res += padZero('.', parseInt(zeroCount) + 1); - } - } - res = res.replace(/\.$/, ''); - return res + postfix; - }, - selectText: function(containerid){ - if(document.selection){ - var range = document.body.createTextRange(); - range.moveToElementText(document.getElementById(containerid)); - range.select(); - }else if(window.getSelection){ - var range = document.createRange(); - range.selectNode(document.getElementById(containerid)); - window.getSelection().addRange(range); - } - }, - pdiff: function(a, b, x){ - var res = 100; - if(x && !b){ - return (a > 0) ? 'x' : 0; - } - if(a !== b){ - if(a && b){ - res = (a / b) * 100 - 100; - }else{ - res *= ((a - b) < 0) ? -1 : 1; - } - }else{ - res = 0; - } - if(x && (Math.abs(res) > 10000) && (b < 10)){ - res = 'x'; - } - return res; - } - } -}; - -/** - * Last Token transactions Widget. - * - * @param {type} element - * @param {type} options - * @param {type} templates - * @returns {undefined} - */ -ethplorerWidget.Type['tokenHistory'] = function(element, options, templates){ - this.el = element; - this.options = options; - this.api = ethplorerWidget.api + '/getTokenHistory'; - if(options && options.address){ - this.api += ('/' + options.address.toString().toLowerCase()); - } - this.ts = false; - this.interval = false; - - this.templates = { - header: '
    Recent token transactions
    ', - loader: '
    Loading...
    ', - debug: '
    ', - // Big table row - bigScreenTable: '' + - '%time%' + - 'from %from%to%to%' + - '%amount%' + - '%token%' + - '', - // Small table row - smallScreenTable: '' + - '%time%' + - 'from %from%' + - '' + - ' ' + - 'to%to%' + - '' + - '%amount% %token%' + - '' - }; - - // Override default templates with custom - if('object' === typeof(templates)){ - for(var key in templates){ - this.templates[key] = templates[key]; - } - } - - this.refresh = function(obj){ - return function(){ - $.getJSON(obj.api, obj.getRequestParams(obj.ts ? {ts: obj.ts} : false), obj.refreshWidget); - } - }(this); - - this.load = function(){ - this.el.html(this.templates.header + this.templates.loader); - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-tokenHistory'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.interval = setInterval(this.refresh, 15000); - this.load(); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['limit', 'address', 'ts', 'showEth']; - var params = { - apiKey: 'ethplorer.widget', - type: 'transfer', - domain: document.location.href, - }; - /* - if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - } - */ - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.setPlayPause = function(obj){ - return function(){ - if(obj.interval){ - clearInterval(obj.interval); - obj.interval = false; - obj.el.find('.txs-stop').html('►'); - obj.el.find('.txs-stop').attr('title', 'Start refresh'); - obj.el.find('.txs-stop').css('color', '#00ff00'); - }else{ - obj.interval = setInterval(obj.refresh, 15000); - obj.el.find('.txs-stop').html('❚❚'); - obj.el.find('.txs-stop').attr('title', 'Pause refresh'); - obj.el.find('.txs-stop').css('color', 'yellow'); - }; - }; - }(this); - - this.refreshWidget = function(obj){ - return function(data){ - if(!obj.ts){ - return obj.cbFirstLoad(data); - } - return obj.cbRefresh(data); - }; - }(this); - - this.cbFirstLoad = function(data){ - if(data && !data.error && data.operations && data.operations.length){ - this.el.find('.txs-loading').remove(); - if(this.ts === data.operations[0].timestamp){ - // Skip redraw if nothing changed - return; - } - this.ts = data.operations[0].timestamp; - var txTable = ''; - var txSmall = '
    '; - for(var i=0; i=0; i--){ - var rowData = this.prepareData(data.operations[i]); - var bigRows = $(ethplorerWidget.parseTemplate(this.templates.bigScreenTable, rowData)); - var smallRows = $(ethplorerWidget.parseTemplate(this.templates.smallScreenTable, rowData)); - bigRows.addClass('hidden'); - smallRows.addClass('hidden'); - txTable.prepend(bigRows); - txSmall.prepend(smallRows); - setTimeout( - function(el){ - return function(){ - el.find('.hidden').removeClass('hidden'); - } - }(this.el), - 200 - ); - - var limit = this.options.limit ? this.options.limit : 10; - var rowsToKill = limit * bigRows.length; - if(rowsToKill){ - txTable.find('tr').each(function(i){ - if(i >= rowsToKill){ - $(this).remove(); - } - }); - } - var rowsToKill = limit * smallRows.length; - if(rowsToKill){ - txSmall.find('tr').each(function(i){ - if(i >= rowsToKill){ - $(this).remove(); - } - }); - } - } - } - }; - - this.prepareData = function(tr){ - if(!tr.tokenInfo){ - tr.tokenInfo = {symbol: "", decimals: 0}; - } - if(!tr.tokenInfo.symbol && tr.tokenInfo.name){ - tr.tokenInfo.symbol = tr.tokenInfo.name; - } - var k = Math.pow(10, tr.tokenInfo.decimals); - if(tr.isEth){ - k = 1; - tr.tokenInfo = {symbol: "ETH", decimals: 18, address: '0x0000000000000000000000000000000000000000'}; - } - var amount = ethplorerWidget.Utils.formatNum(tr.value / k, true, parseInt(tr.tokenInfo.decimals), true); - - var hash = tr.priority ? tr.priority : false; - - return { - date: ethplorerWidget.Utils.link(tr.transactionHash, ethplorerWidget.Utils.ts2date(tr.timestamp, false, false), tr.transactionHash, hash), - time: ethplorerWidget.Utils.link(tr.transactionHash, ethplorerWidget.Utils.ts2time(tr.timestamp, false), tr.transactionHash, hash), - datetime: ethplorerWidget.Utils.link(tr.transactionHash, ethplorerWidget.Utils.ts2date(tr.timestamp, true, false), tr.transactionHash, hash), - from: ethplorerWidget.Utils.link(tr.from, tr.from), - to: ethplorerWidget.Utils.link(tr.to, tr.to), - amount: ethplorerWidget.Utils.link(tr.tokenInfo.address, amount, amount + ' ' + tr.tokenInfo.symbol), - token: ethplorerWidget.Utils.link(tr.tokenInfo.address, tr.tokenInfo.symbol, tr.tokenInfo.symbol + ' ' + tr.tokenInfo.address) - }; - }; - - this.init(); -} - -/** - * Top Tokens list Widget. - * - * @param {type} element - * @param {type} options - * @param {type} templates - * @returns {undefined} - */ -ethplorerWidget.Type['topTokens'] = function(element, options, templates){ - this.el = element; - - this.options = { - limit: 10, - period: 30 - }; - - if(options){ - for(var key in options){ - this.options[key] = options[key]; - } - } - - var row = '' + - ''; - - var criteria = options.criteria ? options.criteria : false; - - this.api = ethplorerWidget.api + '/getTopTokens'; - - this.templates = { - header: '
    Top %limit% tokens for %period% days
    ', - loader: '
    Loading...
    ', - }; - - switch(criteria){ - case 'byPrice': - row += ''; - row = row +''; - break; - case 'byCurrentVolume': - this.templates.header = '
    Top %limit% tokens
    '; - case 'byPeriodVolume': - row += ''; - row += ''; - break; - default: - row += ''; - row = row + '' + ''; - } - - this.templates.row = row; - - // Override default templates with custom - if('object' === typeof(templates)){ - for(var key in templates){ - this.templates[key] = templates[key]; - } - } - - this.load = function(){ - this.el.html(ethplorerWidget.parseTemplate(this.templates.header, this.options) + this.templates.loader); - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-topTokens'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.load(); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['limit', 'period', 'criteria']; - var params = { - apiKey: 'ethplorer.widget', - domain: document.location.href - }; - /* - if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - } - */ - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.refreshWidget = function(obj){ - return function(data){ - if(data && !data.error && data.tokens && data.tokens.length){ - obj.el.find('.txs-loading').remove(); - var txTable = '
    %position%%name%%price%%name_symbol%%volume%%name%%opCount%
    '; - for(var i=0; iTokens Cap: $ %cap% B%capTrend% for %tokens% Tokens. Trade Vol (24h): $ %volume24h%%volumeTrend%' : ''), - header: '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    by Capitalization
    ' + - '
    ' + - '
    ' + - '
    by Trade Volume
    ' + - '
    ' + - '
    ' + - '
    by Operations
    ' + - '
    ' + - '
    ' + - '
    ' + - '' + - '
    ' + - '
    ' + - '
    ', - loader: '
    Loading...
    ', - criteria: { - cap: { - rowHeader: '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - row: '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - rowMobile: '' + - '' + - '' + - '' + - '' + - '' - }, - trade: { - rowHeader: '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - row: '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - rowMobile: '' + - '' + - '' + - '' + - '' + - '' - }, - count: { - rowHeader: '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - row: '' + - '' + - '' + - '' + - '' + - '' + - '' + - '', - rowMobile: '' + - '' + - '' + - '' + - '' - }, - } - }; - - // Override default templates with custom - if('object' === typeof(templates)){ - for(var key in templates){ - this.templates[key] = templates[key]; - } - } - - this.load = function(hash){ - if('undefined' !== typeof(this.templates.criteria[this.options.criteria])){ - var criteriaTpl = this.templates.criteria[this.options.criteria]; - if(criteriaTpl.header){ - this.templates.header = criteriaTpl.header; - } - if(criteriaTpl.row){ - this.templates.row = criteriaTpl.row; - } - if(criteriaTpl.rowMobile){ - this.templates.rowMobile = criteriaTpl.rowMobile; - } - if(criteriaTpl.rowHeader){ - this.templates.rowHeader = criteriaTpl.rowHeader; - } - } - if('undefined' === typeof(this.cache[this.options.criteria])){ - this.el.html(ethplorerWidget.parseTemplate(this.templates.header, this.options) + this.templates.loader); - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - }else{ - this.el.html(ethplorerWidget.parseTemplate(this.templates.header, this.options)); - this.refreshWidget(this.cache[this.options.criteria]); - } - if(hash){ - window.location.hash = this.options.criteria; - } - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-topTokens'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.load(); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['limit', 'period', 'criteria']; - var params = { - apiKey: 'ethplorer.widget', - domain: document.location.href - }; - /* - if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - } - */ - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.refreshWidget = function(obj){ - return function(data){ - ethplorerWidget.appendEthplorerLink(obj, 'source: Ethplorer.io', 'text-align:right;font-size:11px;padding-bottom:4px;padding-right:5px;margin-top:-10px;'); - if(data && !data.error && data.tokens && data.tokens.length){ - if('undefined' === typeof(obj.cache[obj.options.criteria])){ - obj.cache[obj.options.criteria] = data; - } - var totalsHtml = ''; - if(data.totals){ - var cap = data.totals.cap ? (ethplorerWidget.Utils.formatNum(data.totals.cap / 1000000000, true, 1, true)) : '?'; - var volume24h = data.totals.volume24h ? (ethplorerWidget.Utils.formatNum(data.totals.volume24h, true, 0, true, true, 99999999)) : '?'; - - var ivdiff = ethplorerWidget.Utils.pdiff(data.totals.cap, data.totals.capPrevious, true); - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - if('x' === ivdiff){ - var capTrend = ''; - }else{ - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var capTrend = ' (' + vdiff + ' %' + ')'; - } - - var ivdiff = ethplorerWidget.Utils.pdiff(data.totals.volume24h, data.totals.volumePrevious, true); - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - if('x' === ivdiff){ - var volumeTrend = ''; - }else{ - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var volumeTrend = ' (' + vdiff + ' %' + ')'; - } - - totalsHtml = ethplorerWidget.parseTemplate(obj.templates.total, {cap: cap, capTrend: capTrend, tokens: data.totals.tokensWithPrice, volume24h: volume24h, volumeTrend: volumeTrend}); - } - obj.el.find('.txs-loading, .txs').remove(); - if(totalsHtml && obj.options.totalPlace != 'down') obj.el.append(totalsHtml); - var txTable = '
    #TokenCapPrice24h7d30d
    %position%%name_symbol%%cap%%price%%trend_1d%%trend_7d%%trend_30d%
    %position%%name_symbol%
    Cap:%cap%
    Price:%price%
    24h:%trend_1d%
    7d:%trend_7d%
    30d:%trend_30d%
    #TokenPriceVolume (24h)24h7d30d
    %position%%name_symbol%%price%%volume%%trend_1d%%trend_7d%%trend_30d%
    %position%%name_symbol%
    Price:%price%
    Volume (24h):%volume%
    24h:%trend_1d%
    7d:%trend_7d%
    30d:%trend_30d%
    #TokenOperations (24h)24h7d30d
    %position%%name_symbol%%txsCount%%trend_1d%%trend_7d%%trend_30d%
    %position%%name_symbol%
    Operations (24h):%txsCount%
    24h:%trend_1d%
    7d:%trend_7d%
    30d:%trend_30d%
    '; - var txMobileTable = '
    '; - txTable += obj.templates.rowHeader; - for(var i=0; i 99 ? 0 : 1; - if('x' === ivdiff){ - var trend_30d = '--'; - }else{ - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var trend_30d = '' + vdiff + ' %' + ''; - } - - if(criteria == 'cap' && data.price && ('undefined' !== typeof(data.price.diff7d))){ - ivdiff = data.price.diff7d; - }else{ - var ivdiff = ethplorerWidget.Utils.pdiff(data7dCurrent, data7dPrevious, true); - } - if('x' === ivdiff){ - var trend_7d = (trend_30d != '--') ? '0 %' : '--'; - }else{ - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var trend_7d = '' + vdiff + ' %' + ''; - } - - if(criteria == 'cap' && data.price && ('undefined' !== typeof(data.price.diff))){ - var ivdiff = data.price.diff; - }else{ - var ivdiff = ethplorerWidget.Utils.pdiff(data1dCurrent, data1dPrevious, true); - } - if('x' === ivdiff){ - var trend_1d = (trend_7d != '--') ? '0 %' : '--'; - }else{ - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var trend_1d = '' + vdiff + ' %' + ''; - } - - return { - address: ethplorerWidget.Utils.link(data.address, data.address, data.address), - name: ethplorerWidget.Utils.link(data.address, name, name, false, data.name ? "" : "tx-unknown"), - name_symbol: ethplorerWidget.Utils.link(data.address, name + (symbol ? ' (' + symbol + ')' : ''), name + (symbol ? ' (' + symbol + ')' : ''), false, data.name ? "" : "tx-unknown"), - txsCount: data.txsCount24, - price_full: (data.price && data.price.rate) ? data.price.rate : '$ 0.00', - price: (data.price && data.price.rate) ? ((data.price.rate < 0.005 ? '>' : '') + '$ ' + ethplorerWidget.Utils.formatNum(data.price.rate, true, 2, false)) : '$ 0.00', - volume: data.volume ? ('$ ' + ethplorerWidget.Utils.formatNum(data.volume, true, data.volume >= 1000 ? 0 : 2, true, true, 99999999)) : '', - cap: data.cap ? ('$ ' + ethplorerWidget.Utils.formatNum(data.cap, true, data.cap >= 1000 ? 0 : 2, true, true, 99999999)) : '', - trend_1d: trend_1d, - trend_7d: trend_7d, - trend_30d: trend_30d - }; - }; - - this.init(); -} - -/** - * Token history grouped Widget. - * - * @param {type} element - * @param {type} options - * @param {type} templates - * @returns {undefined} - */ -ethplorerWidget.Type['tokenHistoryGrouped'] = function(element, options, templates){ - this.el = element; - this.widgetData = null; - this.resizeTimer = null; - this.cachedWidth = $(window).width(); - - this.options = { - period: 30, - type: 'area', - theme: 'light', - options: {} - }; - - if(options){ - for(var key in options){ - this.options[key] = options[key]; - } - } - - this.api = ethplorerWidget.api + '/getTokenHistoryGrouped'; - if(options && options.address){ - this.api += ('/' + options.address.toString().toLowerCase()); - } - - this.templates = { - loader: '
    Loading...
    ', - }; - - this.load = function(){ - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - }; - - this.getTooltip = function(date, cnt, cap){ - var tooltipDateFormatter = new google.visualization.DateFormat({ - pattern: "MMM dd, yyyy '+UTC'" - }); - var numFormatter = new google.visualization.NumberFormat({ - pattern: "#,### K" - }); - var currencyFormatter = new google.visualization.NumberFormat({ - //pattern: '$ #,### B' - pattern: '$ #,##0.0 B' - }); - var tooltip = '
    '; - tooltip += '' + tooltipDateFormatter.formatValue(date) + '
    ' + - 'Token operations: ' + ((cnt < 1) ? '<1 K' : numFormatter.formatValue(cnt)) + '
    ' + - 'Tokens Cap: ' + ((cap < 0.1) ? '<0.1 B' : currencyFormatter.formatValue(cap)) + '' + - '
    '; - return tooltip; - } - - this.drawChart = function(aTxData, aCap, aTotals){ - - var totalsHtml = ''; - if(this.options.total && aTotals && aTotals.cap){ - var cap = aTotals.cap ? (ethplorerWidget.Utils.formatNum(aTotals.cap / 1000000000, true, 1, true)) : '?'; - var volume24h = aTotals.volume24h ? (ethplorerWidget.Utils.formatNum(aTotals.volume24h, true, 0, true, true, 99999999)) : '?'; - var ivdiff = ethplorerWidget.Utils.pdiff(aTotals.cap, aTotals.capPrevious, true); - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - if('x' === ivdiff){ - var capTrend = ''; - }else{ - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var capTrend = ' (' + vdiff + ' %' + ')'; - } - var ivdiff = ethplorerWidget.Utils.pdiff(aTotals.volume24h, aTotals.volumePrevious, true); - var numDec = Math.abs(ivdiff) > 99 ? 0 : 1; - if('x' === ivdiff){ - var volumeTrend = ''; - }else{ - var vdiff = ethplorerWidget.Utils.formatNum(ivdiff, true, numDec, false, true); - var volumeTrend = ' (' + vdiff + ' %' + ')'; - } - var tpl = '
    Tokens Cap: $ %cap% B%capTrend% for %tokens% Tokens. Trade Vol (24h): $ %volume24h%%volumeTrend%
    '; - totalsHtml = ethplorerWidget.parseTemplate(tpl, {cap: cap, capTrend: capTrend, tokens: aTotals.tokensWithPrice, volume24h: volume24h, volumeTrend: volumeTrend}); - if(this.options.full) this.el.append(totalsHtml); - } - - var aData = []; - if(this.options.cap && aCap){ - aData.push(['Day', 'Token operations', {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Tokens Cap', {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - }else{ - aData.push(['Day', 'Token operations']); - } - - var stDate = new Date(), - fnDate = new Date(); - var date = stDate.getDate(); - stDate.setDate(date - 1); - fnDate.setDate(date - this.options.period - 1); - var dteRangeStart = fnDate, - dteRangeEnd = new Date(); - dteRangeEnd.setDate(stDate.getDate()); - - var aCountData = {}; - var minTs = 0, - minYear, - minMonth, - minDate; - for(var i = 0; i < aTxData.length; i++){ - var aDayData = aTxData[i]; - aCountData[aDayData._id.year + '-' + aDayData._id.month + '-' + aDayData._id.day] = aDayData.cnt; - if((minTs == 0) || (minTs > aDayData.ts)){ - minTs = aDayData.ts; - minYear = aDayData._id.year; - minMonth = aDayData._id.month; - if(aDayData._id.month < 10) minMonth = '0' + minMonth; - minDate = aDayData._id.day; - if(aDayData._id.day < 10) minDate = '0' + minDate; - } - } - if(this.options.full) fnDate = new Date(minYear + '-' + minMonth + '-' + minDate + 'T00:00:00Z'); - - var curDate = true, - firstDate = true; - while(stDate > fnDate){ - var skipDate = false; - var key = stDate.getFullYear() + '-' + (stDate.getMonth() + 1) + '-' + stDate.getDate(); - var cnt = ('undefined' !== typeof(aCountData[key])) ? aCountData[key] : 0; - if(this.options.cap && aCap) cnt = Math.round(cnt / 1000); - if(curDate && cnt == 0){ - curDate = false; - continue; - } - if(this.options.cap && aCap){ - var capKeyMonth = stDate.getMonth() + 1; - if(capKeyMonth < 10) capKeyMonth = '0' + capKeyMonth; - var capKeyDay = stDate.getDate(); - if(capKeyDay < 10) capKeyDay = '0' + capKeyDay; - var capKey = stDate.getFullYear() + '-' + capKeyMonth + '-' + capKeyDay; - var cap = ('undefined' !== typeof(aCap[capKey])) ? aCap[capKey] : 0; - if(cap <= 1000000000 && firstDate) skipDate = true; - if(aTotals && aTotals.cap && firstDate){ - var capdiff = ethplorerWidget.Utils.pdiff(cap, aTotals.cap); - if(Math.abs(capdiff) >= 30) skipDate = true; - } - //cap = Math.round(cap / 1000000000); - cap = parseFloat(ethplorerWidget.Utils.formatNum(cap / 1000000000, true, 1, true)); - var tooltip = this.getTooltip(new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt, cap); - if(!skipDate) aData.push([new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt, tooltip, cap, tooltip]); - }else{ - aData.push([new Date(stDate.getFullYear(), stDate.getMonth(), stDate.getDate()), cnt]); - } - firstDate = false; - var newDate = stDate.setDate(stDate.getDate() - 1); - dteRangeStart = new Date(newDate); - stDate = new Date(newDate); - } - if(this.options.period > 90 || this.options.full){ - dteRangeStart = new Date(); - dteRangeStart.setDate(date - 90); - } - - var data = google.visualization.arrayToDataTable(aData); - var tooltipFormatter = new google.visualization.DateFormat({ - pattern: "MMM dd, yyyy '+UTC'" - }); - tooltipFormatter.format(data, 0); - - var defOptions = { - title: '', - legend: { position: 'none' }, - tooltip: { - format: 'MMM d', - isHtml: (this.options.cap && aCap) ? true : false - }, - hAxis : { - title: '', - titleTextStyle: { - italic: false - }, - textPosition: 'out', - slantedText: false, - maxAlternation: 1, - maxTextLines: 1, - format: ethplorerWidget.getGoogleChartAxisFormat(aData.length), - gridlines: { - count: ethplorerWidget.getGoogleChartAxisCount(aData.length), - color: "none" - }, - minorGridlines: { - count: 0 - } - }, - vAxis: { - title: '', - titleTextStyle: { - italic: false - }, - minValue: 0, - viewWindow: { - min: 0 - }, - gridlines: { - color: "none" - }, - minorGridlines: { - count: 0 - }, - maxValue: 3, - format: '#,###', - }, - pointSize: 5, - }; - if(this.options['theme'] == 'dark'){ - defOptions.colors = this.options.cap ? ['#B5A81B', '#47C2FF'] : ['#47C2FF', '#FCEC0F']; - defOptions.titleTextStyle = {color: '#DEDEDE'}; - defOptions.backgroundColor = {fill: 'transparent'}; - - defOptions.hAxis.textStyle = {color: '#DEDEDE'}; - defOptions.hAxis.titleTextStyle.color = '#DEDEDE'; - defOptions.hAxis.baselineColor = '#DEDEDE'; - - defOptions.vAxis.textStyle = {color: '#DEDEDE'}; - defOptions.vAxis.titleTextStyle.color = '#DEDEDE'; - defOptions.vAxis.baselineColor = 'none'; - } - - if(this.options.cap && aCap){ - var series = { - 0: { - type: 'steppedArea', - targetAxisIndex: 0, - lineWidth: 1, - //areaOpacity: 0 - }, - 1: { - type: 'line', - targetAxisIndex: 1, - lineWidth: 3 - } - }; - var vAxes = { - 0: { - title: 'Token operations', - format: '#,### K', - viewWindow: { - max: 1250 - }, - }, - 1: { - title: 'Tokens Cap', - format: '$ #,### B' - } - }; - defOptions.series = series; - defOptions.vAxes = vAxes; - } - - if(this.options.full){ - this.el.append($('
    ', {id: 'chart'})); - this.el.append($('
    ', {id: 'control'})); - $('#control').attr('style', 'height: 50px;'); - - var dashboard = new google.visualization.Dashboard(this.el); - var controlSeries = { - 0: { - type: 'area', - lineWidth: 0 - }, - 1: { - targetAxisIndex: 1, - type: 'area', - lineWidth: 1 - } - }; - - var defControlOptions = ethplorerWidget.getGoogleControlOptions(dteRangeStart, dteRangeEnd, this.options, controlSeries, aData.length); - var controlOptions = $.extend(true, defControlOptions, this.options['controlOptions']); - var control = new google.visualization.ControlWrapper(controlOptions); - - var def = { - chartType: 'ComboChart', - containerId: 'chart', - options: defOptions - }; - - def.options = $.extend(true, def.options, this.options['options']); - var chart = new google.visualization.ChartWrapper(def); - dashboard.bind(control, chart); - dashboard.draw(data); - }else{ - var options = $.extend(true, defOptions, this.options['options']); - - if(this.options['type'] == 'area') var chart = new google.visualization.AreaChart(this.el[0]); - else if(this.options['type'] == 'line') var chart = new google.visualization.LineChart(this.el[0]); - else var chart = new google.visualization.ColumnChart(this.el[0]); - - chart.draw(data, options); - - if(this.options.total && aTotals && aTotals.cap) this.el.prepend(totalsHtml); - } - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-tokenHistoryGrouped'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.el.html(this.templates.loader); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['period', 'address', 'type', 'theme', 'cap', 'full']; - var params = { - apiKey: 'ethplorer.widget' - }; - if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - } - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.showWidget = function(obj, data){ - obj.el.find('.txs-loading').remove(); - obj.drawChart(data.countTxs, data.cap, data.totals); - ethplorerWidget.appendEthplorerLink(obj); - if('function' === typeof(obj.options.onLoad)){ - obj.options.onLoad(); - } - setTimeout(ethplorerWidget.fixTilda, 300); - } - - this.refreshWidget = function(obj){ - return function(data){ - if(data && !data.error && data.countTxs){ - obj.widgetData = data.countTxs; - obj.widgetDataCap = data.cap; - obj.widgetDataTotals = data.totals; - if(obj.options.full){ - obj.showWidget(obj, data); - }else{ - google.charts.setOnLoadCallback( - function(){ - obj.showWidget(obj, data); - } - ); - } - }else{ - obj.el.find('.txs-loading').remove(); - } - }; - }(this); - - $(window).resize(this, function(){ - var newWidth = $(window).width(); - var obj = arguments[0].data; - if(newWidth !== obj.cachedWidth){ - obj.cachedWidth = newWidth; - }else{ - return; - } - if(obj.resizeTimer) clearTimeout(obj.resizeTimer); - obj.resizeTimer = setTimeout(function(){ - if(obj.widgetData){ - obj.el.empty(); - obj.drawChart(obj.widgetData, obj.widgetDataCap, obj.widgetDataTotals); - ethplorerWidget.appendEthplorerLink(obj); - } - }, 500); - }); - - this.init(); - - if(this.options.full) ethplorerWidget.chartControlWidgets.push(this); - else ethplorerWidget.chartWidgets.push(this); -}; - -/** - * Token history with prices grouped Widget. - * - * @param {type} element - * @param {type} options - * @param {type} templates - * @returns {undefined} - */ -ethplorerWidget.Type['tokenPriceHistoryGrouped'] = function(element, options, templates){ - this.type = 'tokenPriceHistoryGrouped'; - this.el = element; - this.widgetData = null; - this.widgetPriceData = null; - this.resizeTimer = null; - this.cachedWidth = $(window).width(); - - this.options = { - period: 365, - type: 'area', - theme: 'light', - options: {}, - controlOptions: {} - }; - - if(options){ - for(var key in options){ - this.options[key] = options[key]; - } - } - if(this.options.period <= 0){ - this.options.period = 365; - }else if(this.options.period < 7){ - this.options.period = 7; - } - - this.api = ethplorerWidget.api + '/getTokenPriceHistoryGrouped'; - if(options && options.address){ - this.api += ('/' + options.address.toString().toLowerCase()); - } - - this.templates = { - loader: '
    Loading...
    ', - }; - - this.load = function(){ - var address; - if(options && options.address){ - address = options.address.toString().toLowerCase(); - } - if(address && ethplorerWidget.preloadPriceHistory && ethplorerWidget.preloadPriceHistory[address]){ - //console.log(ethplorerWidget.preloadPriceHistory[address]); - this.refreshWidget(ethplorerWidget.preloadPriceHistory[address]); - }else{ - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - } - }; - - this.getTooltip = function(noPrice, date, low, open, close, high, operations, volume, convertedVolume, rate, diff, onlyPrice, avg, curDate){ - var tooltipDateFormatter = new google.visualization.DateFormat({ - pattern: "MMM dd, yyyy '+UTC'" - }); - var numFormatter = new google.visualization.NumberFormat({ - pattern: "#,###" - }); - var currencyFormatter = new google.visualization.NumberFormat({ - pattern: '#,##0.00###' - }); - var avgFormatter = new google.visualization.NumberFormat({ - pattern: '#,##0.00' - }); - var tooltip = '
    '; - tooltip += tooltipDateFormatter.formatValue(date) + '
    '; - if(noPrice){ - tooltip += 'Token operations: ' + operations + '
    '; - }else{ - if(!avg){ - if(volume > 0) avg = convertedVolume / volume; - else avg = (open + close) / 2; - } - - if(onlyPrice && !diff){ - diff = ethplorerWidget.Utils.pdiff(close, open, true); - if('x' === diff){ - diff = 0; - }else{ - var numDec = Math.abs(diff) > 99 ? 0 : 2; - var diff = ethplorerWidget.Utils.formatNum(diff, true, numDec, false, true); - } - } - var diffHtml = ' (' + diff + '%)'; - - if(rate && rate > 0){ - tooltip += 'Price: ' + (onlyPrice ? currencyFormatter.formatValue(rate) : avgFormatter.formatValue(rate)) + ' USD' + diffHtml + '
    '; - }else{ - diffHtml = ''; - var diff = ethplorerWidget.Utils.pdiff(close, open, true); - if('x' === diff){ - var pdiff = 0; - }else{ - var numDec = Math.abs(diff) > 99 ? 0 : 2; - var pdiff = ethplorerWidget.Utils.formatNum(diff, true, numDec, false, true); - } - var diffHtml = ' (' + pdiff + '%)'; - tooltip += 'Average: ' + avgFormatter.formatValue(avg) + ' USD' + - (curDate ? '' : ('
    Open: ' + currencyFormatter.formatValue(open) + ' Close: ' + currencyFormatter.formatValue(close) + diffHtml)) - +'
    ' + - 'High: ' + currencyFormatter.formatValue(high) + ' Low: ' + currencyFormatter.formatValue(low) + '
    '; - } - tooltip += 'Token operations: ' + numFormatter.formatValue(operations) + '' + - (onlyPrice ? '' : ('
    Volume: ' + numFormatter.formatValue(volume.toFixed(0)) + ' (' + numFormatter.formatValue(convertedVolume.toFixed(2)) + ' USD)')); - } - tooltip += '
    '; - return tooltip; - } - - this.drawChart = function(aTxData, widgetPriceData, currentPrice){ - var onlyPrice = false, - defaultPriceFormat = '$ #,##0.00##'; - if('undefined' !== typeof(currentPrice) && 'undefined' !== typeof(currentPrice.onlyPrice)) onlyPrice = currentPrice.onlyPrice; - - var aData = []; - if(aTxData.length){ - if(widgetPriceData && widgetPriceData.length){ - if(currentPrice){ - var currentDate = new Date(); - var currentDatePriceKey = currentDate.getFullYear() + '-' + (currentDate.getMonth() < 9 ? '0' : '') + (currentDate.getMonth() + 1) + '-' + (currentDate.getDate() < 10 ? '0' : '') + currentDate.getDate(); - - var prevDate = new Date(); - prevDate.setDate(currentDate.getDate() - 1); - var prevDatePriceKey = prevDate.getFullYear() + '-' + (prevDate.getMonth() < 9 ? '0' : '') + (prevDate.getMonth() + 1) + '-' + (prevDate.getDate() < 10 ? '0' : '') + prevDate.getDate(); - - if(widgetPriceData[widgetPriceData.length - 1].date != currentDatePriceKey && widgetPriceData[widgetPriceData.length - 1].date == prevDatePriceKey){ - if(!currentPrice.volume24h) currentPrice.volume24h = 0; - if(currentPrice.rate && (currentPrice.rate > 0) && (currentPrice.volume24h || onlyPrice) && currentPrice.ts){ - var diff = ethplorerWidget.Utils.pdiff(currentPrice.rate, widgetPriceData[widgetPriceData.length - 1].close, true); - if('x' === diff){ - var diff = 0; - }else{ - var numDec = Math.abs(diff) > 99 ? 0 : 2; - var pdiff = ethplorerWidget.Utils.formatNum(diff, true, numDec, false, true); - } - widgetPriceData.push({ - ts: currentPrice.ts, - date: currentDatePriceKey, - hour: 0, - open: widgetPriceData[widgetPriceData.length - 1].close, - close: parseFloat(currentPrice.rate), - high: 0, - low: 0, - average: 0, - rate: currentPrice.rate, - volumeConverted: parseFloat(currentPrice.volume24h), - volume: currentPrice.volume24h / currentPrice.rate, - diff: pdiff - }); - if(currentPrice.rate < 0.1) defaultPriceFormat = '$ #,##0.0000'; - } - } - } - - var strLastPriceDate = widgetPriceData[widgetPriceData.length - 1].date + 'T00:00:00Z'; - var strFirstDate = strLastPriceDate; - }else{ - var currentDate = new Date(); - var currentDateKey = currentDate.getFullYear() + '-' + (currentDate.getMonth() < 9 ? '0' : '') + (currentDate.getMonth() + 1) + '-' + (currentDate.getDate() < 10 ? '0' : '') + currentDate.getDate(); - var strFirstDate = currentDateKey + 'T00:00:00Z'; - } - - /*if(widgetPriceData && widgetPriceData.length){ - var strLastPriceDate = widgetPriceData[widgetPriceData.length - 1].date + 'T00:00:00Z'; - }*/ - if(strLastPriceDate && (new Date(strLastPriceDate) > new Date(strFirstDate))){ - strFirstDate = strLastPriceDate; - } - }else{ - return; - } - - var stDate = new Date(strFirstDate); - fnDate = new Date(strFirstDate), - rangeStart = new Date(strFirstDate); - var date = stDate.getDate(); - fnDate.setDate(date - this.options.period + 1); - rangeStart.setDate(date - (this.options.period > 90 ? 90 : this.options.period) + 1); - - // prepare data - var aCountData = {}; - var aPriceData = {}; - for(var i = 0; i < aTxData.length; i++){ - var aDayData = aTxData[i]; - aCountData[aDayData._id.year + '-' + aDayData._id.month + '-' + aDayData._id.day] = aDayData.cnt; - } - var noPrice = true, - startPriceDate = new Date(), - priceNotFound = true; - if(widgetPriceData && widgetPriceData.length){ - for(var i = 0; i < widgetPriceData.length; i++){ - var aDayPriceData = widgetPriceData[i], - numZeroes = 0; - if(aDayPriceData.low == 0) numZeroes++; - if(aDayPriceData.open == 0) numZeroes++; - if(aDayPriceData.close == 0) numZeroes++; - if(aDayPriceData.high == 0) numZeroes++; - - if((numZeroes >= 3) && priceNotFound){ - continue; - }else{ - aPriceData[aDayPriceData.date] = aDayPriceData; - if(priceNotFound){ - var strPriceDate = aDayPriceData.date.substring(0, 4) + '-' + aDayPriceData.date.substring(5, 7) + '-' + aDayPriceData.date.substring(8) + 'T00:00:00Z'; - startPriceDate = new Date(strPriceDate); - } - priceNotFound = false; - } - } - - if(!priceNotFound){ - noPrice = false; - aData.push(['Day', 'Low', 'Open', 'Close', 'High', {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Token operations', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Volume', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - if(this.options.period > 90){ - fnDate = startPriceDate; - } - } - } - if(noPrice){ - var strMonth = aTxData[aTxData.length - 1]._id.month < 10 ? ('0' + aTxData[aTxData.length - 1]._id.month) : aTxData[aTxData.length - 1]._id.month, - strDay = aTxData[aTxData.length - 1]._id.day < 10 ? ('0' + aTxData[aTxData.length - 1]._id.day) : aTxData[aTxData.length - 1]._id.day; - var strDate = aTxData[aTxData.length - 1]._id.year + '-' + strMonth + '-' + strDay + 'T00:00:00Z'; - fnDate = new Date(strDate); - aData.push(['Day', 'Token operations', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - } - //console.log(aCountData); - //console.log(aPriceData); - - var timeDiff = Math.abs(new Date(strFirstDate).getTime() - fnDate.getTime()); - var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1; - if(diffDays < 7) fnDate.setDate(fnDate.getDate() - (7 - diffDays)); - - var curDate = true; - for(var d = new Date(strFirstDate); d >= fnDate; d.setDate(d.getDate() - 1)){ - // get tx count - var key = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate(); - var cnt = ('undefined' !== typeof(aCountData[key])) ? aCountData[key] : 0; - - // get price data - var keyPrice = d.getFullYear() + '-' + (d.getMonth() < 9 ? '0' : '') + (d.getMonth() + 1) + '-' + (d.getDate() < 10 ? '0' : '') + d.getDate(); - //console.log(keyPrice); - - // 'Low', 'Open', 'Close', 'High' - var low = 0, open = 0, high = 0, close = 0, volume = 0, volumeConverted = 0, rate = 0, diff = 0, avg = 0; - if('undefined' !== typeof(aPriceData[keyPrice])){ - low = aPriceData[keyPrice]['low']; - open = aPriceData[keyPrice]['open']; - close = aPriceData[keyPrice]['close']; - high = aPriceData[keyPrice]['high']; - volume = ('undefined' !== typeof(aPriceData[keyPrice]['volume'])) ? aPriceData[keyPrice]['volume'] : 0; - volumeConverted = ('undefined' !== typeof(aPriceData[keyPrice]['volumeConverted'])) ? aPriceData[keyPrice]['volumeConverted'] : 0; - rate = ('undefined' !== typeof(aPriceData[keyPrice]['rate'])) ? aPriceData[keyPrice]['rate'] : 0; - diff = ('undefined' !== typeof(aPriceData[keyPrice]['diff'])) ? aPriceData[keyPrice]['diff'] : 0; - avg = ('undefined' !== typeof(aPriceData[keyPrice]['average'])) ? aPriceData[keyPrice]['average'] : 0; - } - - var chartMonth = d.getMonth() + 1; - if(chartMonth < 10) chartMonth = '0' + chartMonth; - var chartDay = d.getDate(); - if(chartDay < 10) chartDay = '0' + chartDay; - var strChartDate = d.getFullYear() + '-' + chartMonth + '-' + chartDay + 'T00:00:00Z'; - - var tooltip = this.getTooltip(noPrice, new Date(strChartDate), low, open, close, high, cnt, volume, volumeConverted, rate, diff, onlyPrice, avg, curDate); - if(noPrice){ - aData.push([new Date(strChartDate), cnt, 'opacity: 0.5', tooltip]); - }else{ - aData.push([new Date(strChartDate), low, open, close, high, tooltip, cnt, 'opacity: 0.5', tooltip, volume, this.options['theme'] == 'dark' ? 'opacity: 0.15' : 'opacity: 0.5', tooltip]); - } - curDate = false; - } - //console.log(aData); - var data = google.visualization.arrayToDataTable(aData); - - // create div's - this.el.append($('
    ', {id: 'chart'})); - this.el.append($('
    ', {id: 'control'})); - $('#control').attr('style', 'height: 50px;'); - if(this.options.period < 2){ - $('#control').hide(); - } - - // create dashboard and control wrapper - var dashboard = new google.visualization.Dashboard(this.el); - var controlSeries = { - 0: { - type: 'area', - lineWidth: 0 - }, - 1: { - targetAxisIndex: 1, - type: 'area', - lineWidth: 1 - } - }; - if(noPrice){ - controlSeries = { - 0: { - type: 'area', - targetAxisIndex: 0, - lineWidth: 1 - } - }; - } - var defControlOptions = ethplorerWidget.getGoogleControlOptions(rangeStart, new Date(strFirstDate), this.options, controlSeries, aData.length); - var controlOptions = $.extend(true, defControlOptions, this.options['controlOptions']); - var control = new google.visualization.ControlWrapper(controlOptions); - - // create combo chart - var series = { - 0: { - type: 'candlesticks', - targetAxisIndex: 1 - }, - 1: { - type: 'line', - targetAxisIndex: 0 - }, - 2: { - type: 'bars', - targetAxisIndex: 2, - }, - }; - var vAxes = { - 1: { - title: 'Price', - format: defaultPriceFormat - //format: 'currency' - }, - 0: { - title: 'Token operations', - format: 'decimal', - }, - 2: { - textStyle: { - color: 'none' - } - } - }; - if(noPrice){ - series = { - 0: { - type: noPrice ? 'area' : 'line', - targetAxisIndex: 0 - }, - }; - vAxes = { - 0: { - title: 'Token operations', - format: 'decimal', - } - }; - } - var def = { - chartType: 'ComboChart', - containerId: 'chart', - options: { - //theme: 'maximized', - title: '', - legend: { position: 'none' }, - tooltip: { - //format: 'MMM d', - isHtml: true - }, - colors: ['#65A5DF', 'black'], - series: series, - hAxis : { - title: '', - titleTextStyle: { - italic: false - }, - textPosition: 'out', - slantedText: false, - maxAlternation: 1, - maxTextLines: 1, - format: ethplorerWidget.getGoogleChartAxisFormat(aData.length), - gridlines: { - count: ethplorerWidget.getGoogleChartAxisCount(aData.length), - color: "none" - }, - minorGridlines: { - count: 0 - } - }, - vAxis: { - viewWindowMode: 'maximized', - title: '', - titleTextStyle: { - italic: false - }, - gridlines: { - color: "none" - }, - minorGridlines: { - count: 0 - }, - //format: '#,###', - /*minValue: 0, - maxValue: 3, - viewWindow: { - min: 0 - },*/ - }, - vAxes: vAxes, - pointSize: noPrice ? 2 : 0, - lineWidth: 1, - bar: { groupWidth: '70%' }, - candlestick: { - fallingColor: { - // red - strokeWidth: 1, - fill: '#951717', - stroke: '#8b0000' - }, - risingColor: { - // green - strokeWidth: 1, - fill: '#177217', - stroke: '#006400' - } - } - } - }; - var color = '#989795' - if(this.options['theme'] == 'dark'){ - def.options.colors = noPrice ? ['#FCEC0F']: [color, '#FCEC0F', '#DEDEDE']; - def.options.titleTextStyle = {color: '#DEDEDE'}; - def.options.backgroundColor = {fill: 'transparent'}; - - def.options.hAxis.textStyle = {color: '#DEDEDE'}; - def.options.hAxis.titleTextStyle.color = '#DEDEDE'; - def.options.hAxis.baselineColor = '#DEDEDE'; - - def.options.vAxis.textStyle = {color: '#DEDEDE'}; - def.options.vAxis.titleTextStyle.color = '#DEDEDE'; - def.options.vAxis.baselineColor = 'none'; - } - def.options = $.extend(true, def.options, this.options['options']); - var chart = new google.visualization.ChartWrapper(def); - - if(!noPrice){ - var $chartEl = $("#chart") - $("#chart").bind("DOMNodeInserted",function(){ - // console.log('DOMNodeInserted') - $chartEl.find('[width="2"][fill="' + color + '"]') - .each(function (index, item) { - var sibling = $(item).siblings()[0]; - if (sibling) { - var width = $(sibling).attr('width'); - var w = width > 27 ? 2 : (width > 2 ? 1 : + width / 2); - var x = +$(sibling).attr('x') + (width - w) / 2; - $(item) - .attr('width', w) - .attr('x', x) - } - }) - }); - google.visualization.events.addListener(chart, 'ready', function(){ - // console.log('ready') - $chartEl.find('[width="2"][fill="'+color+'"]').each(function (index, item) { - var sibling = $(item).siblings()[0]; - if (sibling) { - var width = $(sibling).attr('width'); - var w = width > 27 ? 2 : (width > 2 ? 1 : + width / 2); - var x = +$(sibling).attr('x') + (width - w) / 2; - $(item) - .attr('width', w) - .attr('x', x) - } - }) - }); - } - // draw chart - dashboard.bind(control, chart); - dashboard.draw(data); - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-tokenHistoryGrouped'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.el.html(this.templates.loader); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['period', 'address', 'type', 'theme']; - var params = { - apiKey: 'ethplorer.widget' - }; - if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - } - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.refreshWidget = function(obj){ - return function(data){ - if(data && !data.error && data.history){ - //console.log(data); - obj.widgetData = data.history.countTxs; - obj.widgetPriceData = data.history.prices; - obj.el.find('.txs-loading').remove(); - if(!obj.widgetData.length){ - obj.el.hide(); - }else{ - obj.drawChart(data.history.countTxs, data.history.prices, data.history.current); - ethplorerWidget.appendEthplorerLink(obj); - if('function' === typeof(obj.options.onLoad)){ - obj.options.onLoad(); - } - } - setTimeout(ethplorerWidget.fixTilda, 300); - }else{ - obj.el.find('.txs-loading').remove(); - } - }; - }(this); - - $(window).resize(this, function(){ - var newWidth = $(window).width(); - var obj = arguments[0].data; - if(newWidth !== obj.cachedWidth){ - obj.cachedWidth = newWidth; - }else{ - return; - } - if(obj.resizeTimer) clearTimeout(obj.resizeTimer); - obj.resizeTimer = setTimeout(function(){ - if(obj.widgetData){ - obj.el.empty(); - obj.drawChart(obj.widgetData, obj.widgetPriceData); - ethplorerWidget.appendEthplorerLink(obj); - } - }, 500); - }); - - this.init(); - ethplorerWidget.chartControlWidgets.push(this); -}; - -/** - * Address history with prices grouped Widget. - * - * @param {type} element - * @param {type} options - * @param {type} templates - * @returns {undefined} - */ -ethplorerWidget.Type['addressPriceHistoryGrouped'] = function(element, options, templates){ - this.type = 'addressPriceHistoryGrouped'; - this.el = element; - this.widgetData = null; - this.widgetPriceData = null; - this.resizeTimer = null; - this.cachedWidth = $(window).width(); - this.reloadData = false; - this.addEthplorerLink = false; - - this.options = { - period: 365, - type: 'area', - theme: 'light', - options: {}, - controlOptions: {} - }; - - if(options){ - for(var key in options){ - this.options[key] = options[key]; - } - } - if(this.options.period <= 0){ - this.options.period = 365; - }else if(this.options.period < 7){ - this.options.period = 7; - } - - this.api = ethplorerWidget.api + '/getAddressPriceHistoryGrouped'; - if(options && options.address){ - this.api += ('/' + options.address.toString().toLowerCase()); - } - - this.templates = { - loader: '
    Loading...
    ', - }; - - this.load = function(reloadData, opt){ - var address; - if(options && options.address){ - address = options.address.toString().toLowerCase(); - } - if(reloadData){ - this.reloadData = true; - } - if(!this.reloadData && address && ethplorerWidget.preloadPriceHistory && ethplorerWidget.preloadPriceHistory[address]){ - //console.log(ethplorerWidget.preloadPriceHistory[address]); - this.refreshWidget(ethplorerWidget.preloadPriceHistory[address]); - }else{ - if(this.reloadData){ - if(opt && opt.showTx){ - this.options['showTx'] = opt.showTx; - } - //this.el.empty(); - //this.el.html(this.templates.loader); - //this.reloadData = false; - } - $.getJSON(this.api, this.getRequestParams(), this.refreshWidget); - } - }; - - this.getTooltip = function(noPrice, date, balance, volume, txs, dteUpdated){ - var tooltipDateFormatter = new google.visualization.DateFormat({ - pattern: "MMM dd, yyyy '+UTC'" - }); - var numFormatter = new google.visualization.NumberFormat({ - pattern: "#,###" - }); - var currencyFormatter = new google.visualization.NumberFormat({ - pattern: '#,##0' - }); - var tooltip = '
    '; - tooltip += '' + tooltipDateFormatter.formatValue(date) + '
    ' + - (noPrice ? '' : 'Volume: ' + currencyFormatter.formatValue(volume) + ' USD
    ') + - (noPrice ? '' : 'Balance: ' + currencyFormatter.formatValue(balance) + ' USD
    ') + - 'Transfers: ' + numFormatter.formatValue(txs) + '' + - (dteUpdated ? ('
    Updated: ' + dteUpdated + '') : '') + - '
    '; - return tooltip; - } - - this.drawChart = function(widgetData){ - var aData = []; - - if('undefined' === typeof(widgetData['volume']) && 'undefined' === typeof(widgetData['txs'])){ - return; - /*var firstMonth = aTxData[0]._id.month, - firstDay = aTxData[0]._id.day; - if(firstMonth < 10) firstMonth = '0' + firstMonth; - if(firstDay < 10) firstDay = '0' + firstDay; - var strFirstDate = aTxData[0]._id.year + '-' + firstMonth + '-' + firstDay + 'T00:00:00Z';*/ - } - if('undefined' === typeof(widgetData['volume'])) widgetData['volume'] = []; - if('undefined' === typeof(widgetData['balances'])) widgetData['balances'] = []; - if('undefined' === typeof(widgetData['txs'])) widgetData['txs'] = []; - - var noPrice = true; - - // prepare prices - var lastAverage = 0; - var aPrices = {}; - if('undefined' !== typeof(widgetData['prices'])){ - for(var token in widgetData['prices']){ - aPrices[token] = {}; - if(widgetData['prices'][token].length > 0) noPrice = false; - for(var i = widgetData['prices'][token].length - 1; i >= 0; i--){ - var priceData = widgetData['prices'][token][i]; - if(priceData['average'] > 0) lastAverage = priceData['average']; - else if(priceData['rate'] > 0) lastAverage = priceData['rate']; - aPrices[token][priceData['date']] = lastAverage; - } - } - } - console.log('noPrice ' + noPrice); - - if(noPrice){ - aData.push(['Day', 'Transfers', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - }else{ - aData.push(['Day', 'Balance', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Transfers', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}, 'Volume', {role: 'style'}, {type: 'string', role: 'tooltip', 'p': {'html': true}}]); - } - - if('undefined' === typeof(widgetData['firstDate'])){ - for(var t in widgetData['txs']){ - widgetData['firstDate'] = t; - break; - } - } - - var rangeStart = null, - rangeEnd, - curDate = new Date(), - fnMonth = curDate.getUTCMonth() + 1, - fnDay = curDate.getUTCDate(), - fnDate = new Date(curDate.getUTCFullYear() + '-' + (fnMonth < 10 ? '0' + fnMonth : fnMonth) + '-' + (fnDay < 10 ? '0' + fnDay : fnDay) + 'T00:00:00Z'), - aBalances = {}, - strFirstDate = widgetData['firstDate'] + 'T00:00:00Z', - dteUpdated; - - for(var d = new Date(strFirstDate); d <= fnDate; d.setDate(d.getDate() + 1)){ - var month = 1 + d.getMonth(), - day = d.getDate(), - volumeDate = d.getFullYear() + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day), - strVolumeDate = volumeDate + 'T00:00:00Z'; - - // get volumes - var volume = 0; - if(!noPrice && 'undefined' !== typeof(widgetData['volume'][volumeDate])){ - for(var token in widgetData['volume'][volumeDate]){ - if('undefined' === typeof(widgetData['tokenPrices'][token])){ - continue; - } - if(d.getTime() == fnDate.getTime() && ('undefined' !== typeof(widgetData['tokenPrices'][token]['rate']))){ - aPrices[token][volumeDate] = widgetData['tokenPrices'][token]['rate']; - } - if('undefined' !== typeof(aPrices[token]) && 'undefined' !== typeof(aPrices[token][volumeDate])){ - volume += parseFloat(widgetData['volume'][volumeDate][token]) * parseFloat(aPrices[token][volumeDate]); - } - } - - if(!rangeStart && volume != 0){ - rangeStart = strVolumeDate; - } - } - - // get balances - var balance = 0; - if(!noPrice){ - if('undefined' !== typeof(widgetData['balances'][volumeDate])){ - for(var token in widgetData['balances'][volumeDate]){ - aBalances[token] = parseFloat(widgetData['balances'][volumeDate][token]); - } - } - for(var token in aBalances){ - if(d.getTime() == fnDate.getTime() && ('undefined' !== typeof(widgetData['tokenPrices'][token]) && 'undefined' !== typeof(widgetData['tokenPrices'][token]['rate']))){ - aPrices[token][volumeDate] = widgetData['tokenPrices'][token]['rate']; - } - if('undefined' !== typeof(aPrices[token]) && 'undefined' !== typeof(aPrices[token][volumeDate])){ - balance += parseFloat(aBalances[token]) * parseFloat(aPrices[token][volumeDate]); - } - } - } - - // get transfers - var transfers = 0; - if('undefined' !== typeof(widgetData['txs'][volumeDate])){ - transfers = widgetData['txs'][volumeDate]; - } - - if(d.getTime() == fnDate.getTime() && ('undefined' !== typeof(widgetData['updated']))){ - dteUpdated = widgetData['updated']; - } - - rangeEnd = strVolumeDate; - var tooltip = this.getTooltip(noPrice, new Date(strVolumeDate), balance, volume, transfers, dteUpdated); - if(noPrice){ - aData.push([new Date(strVolumeDate), transfers, 'opacity: 0.5', tooltip]); - }else{ - aData.push([new Date(strVolumeDate), balance, 'opacity: 0.5', tooltip, transfers, 'opacity: 0.5', tooltip, volume, this.options['theme'] == 'dark' ? 'opacity: 0.15' : 'opacity: 0.5', tooltip]); - } - } - - var dteRangeStart = new Date(rangeStart), - dteRangeEnd = new Date(rangeEnd); - - var timeDiff = Math.abs(dteRangeEnd.getTime() - dteRangeStart.getTime()); - var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1; - if(diffDays < 7) dteRangeStart.setDate(dteRangeStart.getDate() - (7 - diffDays)); - else if(diffDays > 90) dteRangeStart.setDate(dteRangeStart.getDate() + (diffDays - 90)); - - //console.log(dteRangeStart); - //console.log(dteRangeEnd); - //console.log(aData); - var data = google.visualization.arrayToDataTable(aData); - - // create div's - this.el.append($('
    ', {id: 'chart'})); - this.el.append($('
    ', {id: 'control'})); - $('#control').attr('style', 'height: 50px;'); - if(this.options.period < 2){ - $('#control').hide(); - } - - // create dashboard and control wrapper - var dashboard = new google.visualization.Dashboard(this.el); - var controlSeries = { - 0: { - targetAxisIndex: 0, - type: 'area', - lineWidth: 1 - } - }; - var defControlOptions = ethplorerWidget.getGoogleControlOptions(dteRangeStart, dteRangeEnd, this.options, controlSeries, aData.length); - var controlOptions = $.extend(true, defControlOptions, this.options['controlOptions']); - var control = new google.visualization.ControlWrapper(controlOptions); - - // create combo chart - var series = { - 0: { - type: 'area', - targetAxisIndex: 0 - }, - 1: { - type: 'line', - targetAxisIndex: 2 - }, - 2: { - type: 'bars', - targetAxisIndex: 1, - }, - }; - var vAxes = { - 0: { - title: 'Price', - format: '$ #,##0' - }, - 1: { - title: 'Volume', - format: 'decimal', - }, - 2: { - textStyle: { - color: 'none' - } - } - }; - if(noPrice){ - series = { - 0: { - type: 'line', - targetAxisIndex: 0 - }, - }; - vAxes = { - 0: { - title: 'Transfers', - format: "#,###", - } - }; - } - var def = { - chartType: 'ComboChart', - containerId: 'chart', - options: { - //theme: 'maximized', - title: '', - legend: { position: 'none' }, - tooltip: { - //format: 'MMM d', - isHtml: true - }, - colors: ['#65A5DF', 'black'], - series: series, - hAxis : { - title: '', - titleTextStyle: { - italic: false - }, - textPosition: 'out', - slantedText: false, - maxAlternation: 1, - maxTextLines: 1, - format: ethplorerWidget.getGoogleChartAxisFormat(aData.length), - gridlines: { - count: ethplorerWidget.getGoogleChartAxisCount(aData.length), - color: "none" - }, - minorGridlines: { - count: 0 - } - }, - vAxis: { - viewWindowMode: 'maximized', - minValue: 0, - viewWindow: { - min: 0 - }, - title: '', - titleTextStyle: { - italic: false - }, - gridlines: { - color: "none" - }, - minorGridlines: { - count: 0 - } - }, - vAxes: vAxes, - pointSize: 3, - lineWidth: 1, - bar: { groupWidth: '70%' }, - candlestick: { - fallingColor: { - // red - strokeWidth: 1, - fill: '#951717', - stroke: '#8b0000' - }, - risingColor: { - // green - strokeWidth: 1, - fill: '#177217', - stroke: '#006400' - } - } - } - }; - if(this.options['theme'] == 'dark'){ - def.options.colors = noPrice ? ['#FCEC0F']: ['#47C2FF', '#FCEC0F', '#DEDEDE']; - def.options.titleTextStyle = {color: '#DEDEDE'}; - def.options.backgroundColor = {fill: 'transparent'}; - - def.options.hAxis.textStyle = {color: '#DEDEDE'}; - def.options.hAxis.titleTextStyle.color = '#DEDEDE'; - def.options.hAxis.baselineColor = '#DEDEDE'; - - def.options.vAxis.textStyle = {color: '#DEDEDE'}; - def.options.vAxis.titleTextStyle.color = '#DEDEDE'; - def.options.vAxis.baselineColor = 'none'; - } - def.options = $.extend(true, def.options, this.options['options']); - var chart = new google.visualization.ChartWrapper(def); - - // draw chart - dashboard.bind(control, chart); - dashboard.draw(data); - }; - - this.init = function(){ - this.el.addClass('ethplorer-widget'); - this.el.addClass('widget-tokenHistoryGrouped'); - this.el.addClass('theme-' + (this.options.theme ? this.options.theme : 'ethplorer')); - this.el.html(this.templates.loader); - }; - - this.getRequestParams = function(additionalParams){ - var requestOptions = ['period', 'address', 'showTx', 'type', 'theme']; - var params = { - apiKey: 'ethplorer.widget' - }; - //if('undefined' === typeof(this.pathReported)){ - params['domain'] = document.location.href; - this.pathReported = true; - //} - for(var key in this.options){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = this.options[key]; - } - } - if('object' === typeof(additionalParams)){ - for(var key in additionalParams){ - if(requestOptions.indexOf(key) >= 0){ - params[key] = additionalParams[key]; - } - } - } - return params; - }; - - this.refreshWidget = function(obj){ - return function(data){ - if(data && !data.error && data.history && !(('undefined' === typeof(data.history['volume']) && 'undefined' === typeof(data.history['txs'])))){ - //console.log(data); - obj.widgetData = data.history; - obj.el.find('.txs-loading').remove(); - obj.drawChart(data.history); - if(!obj.reloadData || obj.addEthplorerLink){ - ethplorerWidget.appendEthplorerLink(obj); - obj.addEthplorerLink = false; - } - if('function' === typeof(obj.options.onLoad)){ - obj.options.onLoad(); - } - if(obj.reloadData) obj.el.fadeOut(250, () => {obj.el.fadeIn(150);}); - setTimeout(ethplorerWidget.fixTilda, 300); - }else{ - if(obj.reloadData){ - obj.widgetData = null; - obj.el.html('
    '); - }else{ - obj.el.html(obj.templates.loader); - } - obj.el.find('.txs-loading').text('No data for chart'); - if(!obj.reloadData){ - $('.ethplorer-widget').css('min-height', '1px'); - $('.txs-loading').css('min-height', '1px'); - $('.txs-loading').css('padding-top', '10px'); - }else{ - obj.addEthplorerLink = true; - $('.ethplorer-widget').css('height', '300px'); - $('.txs-loading').css('height', '300px'); - $('.txs-loading').css('padding-top', '80px'); - } - } - obj.reloadData = false; - }; - }(this); - - $(window).resize(this, function(){ - var newWidth = $(window).width(); - var obj = arguments[0].data; - if(newWidth !== obj.cachedWidth){ - obj.cachedWidth = newWidth; - }else{ - return; - } - if(obj.resizeTimer) clearTimeout(obj.resizeTimer); - obj.resizeTimer = setTimeout(function(){ - if(obj.widgetData){ - obj.el.empty(); - obj.drawChart(obj.widgetData); - ethplorerWidget.appendEthplorerLink(obj); - } - }, 500); - }); - - this.init(); - ethplorerWidget.chartControlWidgets.push(this); -}; - -if('undefined' !== typeof(ethplorerWidgetPreload)){ - ethplorerWidget.preloadData(ethplorerWidgetPreload); -} - -/** - * Document on ready widgets initialization. - * Initializes all widgets added using eWgs array. - */ -(function(){ - function ethpWiInit(){ - var eWgs = window.eWgs || []; - if(eWgs && eWgs.length) - for(var i=0; iDt~nOWK4^|8cOIBa)sq@zgx*o1BvOYbZS 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 0, - '< 0.1s' => 0, - '< 1s' => 0, - '< 5s' => 0, - '< 10s' => 0, - '> 10s' => 0, - 'slow_queries' => array() - ); - } - $time = (float)$parts[10]; - - if($time > 1000) continue; - - $aDates[$date]['total_requests']++; - if($time < 0.1){ - $aDates[$date]['< 0.1s']++; - }else if($time < 1){ - $aDates[$date]['< 1s']++; - }else{ - if($time < 5){ - $aDates[$date]['< 5s']++; - }else if($time < 10){ - $aDates[$date]['< 10s']++; - }else{ - $aDates[$date]['> 10s']++; - } - $request = explode('?', $parts[7]); - $request = $request[0]; - if(FALSE === strpos($request, 'widget')){ - if(!isset($aDates[$date]['slow_queries'][$request])){ - $aDates[$date]['slow_queries'][$request] = array('num' => 0, 'average_time' => 0); - }; - $aDates[$date]['slow_queries'][$request]['num']++; - $aDates[$date]['slow_queries'][$request]['average_time'] = ($aDates[$date]['slow_queries'][$request]['average_time'] + $time) / ($aDates[$date]['slow_queries'][$request]['num'] > 1 ? 2 : 1); - } - } -} -fclose($f); - -var_export($aDates); diff --git a/bin/cache_all_prices.php b/bin/cache_all_prices.php deleted file mode 100644 index e811ead4..00000000 --- a/bin/cache_all_prices.php +++ /dev/null @@ -1,33 +0,0 @@ -createProcessLock('all.prices.lock', 180); -$es->getCache()->clearLocalCache(); -$result = $es->getAllTokenPrice(); -// get THBEX price -$es->getTokenPrice('0xff71cb760666ab06aa73f34995b42dd4b85ea07b', TRUE); -unset($lock); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i:s")."], Finished, {$ms} s. Total prices: " . (is_array($result) ? sizeof($result) : 0); diff --git a/bin/cache_eth_out.php b/bin/cache_eth_out.php deleted file mode 100644 index 9fb7905c..00000000 --- a/bin/cache_eth_out.php +++ /dev/null @@ -1,30 +0,0 @@ -createProcessLock('ethOut.lock'); -$aHolders = $es->getAllHolders(); -var_dump(count($aHolders)); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_last_block.php b/bin/cache_last_block.php deleted file mode 100644 index 84d9cae0..00000000 --- a/bin/cache_last_block.php +++ /dev/null @@ -1,33 +0,0 @@ -createProcessLock('lastBlock.lock', 5); - -for($i=0; $i<9; $i++){ - $es->getLastBlock(true); - sleep(5); -} - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_price_history.php b/bin/cache_price_history.php deleted file mode 100644 index fc488734..00000000 --- a/bin/cache_price_history.php +++ /dev/null @@ -1,34 +0,0 @@ -createProcessLock('priceHistory.lock', 7200); -foreach($aConfig['updateRates'] as $address){ - $es->getCache()->clearLocalCache(); - $es->getTokenPriceHistory($address, 0, 'hourly', TRUE); -} - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_prices.php b/bin/cache_prices.php deleted file mode 100644 index 37961ed7..00000000 --- a/bin/cache_prices.php +++ /dev/null @@ -1,44 +0,0 @@ -createProcessLock('prices.lock', 600); -foreach($aConfig['updateRates'] as $address){ - $startGetPrice = microtime(TRUE); - $es->getCache()->clearLocalCache(); - $es->getTokenPrice($address, TRUE); - $timeGetPrice = round(microtime(TRUE) - $startGetPrice, 4); - echo "\n[".date("Y-m-d H:i:s")."], Get price for address: " . $address . " Time : " . $timeGetPrice; - - $numPrices++; - if($timeGetPrice > $maxTimeGetPrice) $maxTimeGetPrice = $timeGetPrice; -} -unset($lock); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i:s")."], Finished, {$ms} s. Total prices: " . $numPrices . " Max. time : " . $maxTimeGetPrice; diff --git a/bin/cache_tokens.php b/bin/cache_tokens.php deleted file mode 100644 index f800d313..00000000 --- a/bin/cache_tokens.php +++ /dev/null @@ -1,36 +0,0 @@ -createProcessLock('tokens.lock', 600); - -$es->getTokens(true); -$es->getTopTokens(10, 90); -$es->getTopTokens(50, 90); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_full_history.php b/bin/cache_tokens_full_history.php deleted file mode 100644 index 9b173386..00000000 --- a/bin/cache_tokens_full_history.php +++ /dev/null @@ -1,31 +0,0 @@ -createProcessLock('tokens.full.history.lock', 7200); - -$es->getTokenFullHistoryGrouped(TRUE); -$es->getTokenCapHistory(0, TRUE); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_history.php b/bin/cache_tokens_history.php deleted file mode 100644 index 71e58f2b..00000000 --- a/bin/cache_tokens_history.php +++ /dev/null @@ -1,30 +0,0 @@ -createProcessLock('tokens.history.lock', 600); - -$es->getTokenHistoryGrouped(90, FALSE, 'daily', 1800, FALSE, TRUE); - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_tokens_with_prices.php b/bin/cache_tokens_with_prices.php deleted file mode 100644 index 01cd4cdd..00000000 --- a/bin/cache_tokens_with_prices.php +++ /dev/null @@ -1,68 +0,0 @@ - '2.0', - 'method' => 'getTokensWithPrices', - 'params' => array(), - 'id' => mt_rand() -)); - -$context = stream_context_create(array( - 'http' => array( - 'method' => 'POST', - 'header' => 'Content-Type: application/json\r\n', - 'content' => $jsonRequest - ) -)); -$jsonResponse = file_get_contents($aConfig['currency'], false, $context); - -if($jsonResponse){ - try{ - $response = json_decode($jsonResponse, true); - if($response && !isset($response['error']) && isset($response['result']) && (sizeof($response['result']) > MIN_TOKENS_NUM)){ - $confPrices = ' MIN_TOKENS_NUM){ - $file = dirname(__FILE__) . '/../service/config.prices.php'; - file_put_contents($file . '.tmp', $confPrices); - rename($file . '.tmp', $file); - } - } - }catch(\Exception $e){ - // - var_dump($e); - } -} - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/bin/cache_top.php b/bin/cache_top.php deleted file mode 100644 index 64981cff..00000000 --- a/bin/cache_top.php +++ /dev/null @@ -1,53 +0,0 @@ -createProcessLock('topTokens.lock', 1800); -$aCriteries = array('cap', 'trade', 'count'); -$aTotals = null; -foreach($aCriteries as $criteria){ - $res = $es->getTokensTop(100, $criteria, TRUE); - if(!$aTotals && isset($res['totals'])){ - $aTotals = $res['totals']; - } -} - -// save cap history into file -if($aTotals){ - $aTotals['date'] = gmdate("Y-m-d H:i", time()); - - $data = array(); - $historyFile = dirname(__FILE__) . '/cap_history.json'; - if(file_exists($historyFile)){ - $history = @file_get_contents($historyFile); - $data = json_decode($history, TRUE); - } - $data[] = $aTotals; - $json = json_encode($data, JSON_PRETTY_PRINT); - @file_put_contents($historyFile, $json); -} - -$ms = round(microtime(TRUE) - $startTime, 4); -echo "\n[".date("Y-m-d H:i")."], Finished, {$ms} s."; diff --git a/composer.json b/composer.json deleted file mode 100644 index 89b2c318..00000000 --- a/composer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "require": { - "litipk/php-bignumbers": "0.8.6", - "predis/predis": "1.1.1", - "sentry/sentry": "^1.10@dev", - "domnikl/statsd": "~2.0" - }, - "minimum-stability": "dev", - "prefer-stable" : false -} diff --git a/config.php b/config.php deleted file mode 100644 index b4b2e1fb..00000000 --- a/config.php +++ /dev/null @@ -1,15 +0,0 @@ -.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/css/cookie-notify.css b/css/cookie-notify.css deleted file mode 100644 index d8fce801..00000000 --- a/css/cookie-notify.css +++ /dev/null @@ -1,123 +0,0 @@ -#cookie-notification { - font-family: 'Open Sans', sans-serif; - font-size: 13px; - position: fixed; - z-index: 1000; - width: 100%; - bottom: 0; - padding: 10px 0; - background: #eaeaea; -} - -#cookie-notification span span { - white-space: nowrap; -} - -#cookie-notification span:first-child { - padding-bottom: 7px; - display: inline-block; - margin-right: 10px; -} - -@media (min-width: 992px) { - #cookie-notification .cn-container { - width: 970px; - } -} - -@media (min-width: 768px) { - #cookie-notification .cn-container { - width: 750px; - } -} - -@media (min-width: 992px) { - #cookie-notification .cn-container { - width: 970px; - } -} - -@media (min-width: 1200px) { - #cookie-notification .cn-container { - width: 1170px; - } -} - -#cookie-notification .cn-container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -#cookie-notification .text-center { - text-align: center; -} - -#cookie-notification .cn-btn-group-lg > .cn-btn, #cookie-notification .cn-btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} - -#cookie-notification .cn-btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} - -#cookie-notification .cn-btn-primary:hover { - color: #fff; - background-color: #2c679b; - border-color: #2e6da4; -} - -#cookie-notification .cn-btn-block { - display: block; -} - -#cookie-notification .cn-btn { - display: inline-block; - text-decoration: none; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} - -#cookie-notification .visible-xs-inline-block { - display: none !important; -} - -@media (max-width: 767px) { - #cookie-notification .hidden-xs { - display: none !important; - } - - #cookie-notification .visible-xs-inline-block { - display: inline-block !important; - } - - #cookie-notification .cn-btn-block { - display: block !important; - } -} - -#cookie-notification a:not(.cn-btn) { - color: #47C2FF !important; - display: inline-block; -} \ No newline at end of file diff --git a/css/ethplorer.css b/css/ethplorer.css deleted file mode 100644 index 679a1dd2..00000000 --- a/css/ethplorer.css +++ /dev/null @@ -1,1615 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,600,700&subset=latin,cyrillic); - -body { - padding: 0px; - background-color: #000; - min-height: 100vh; - height: 100%; -} - -.pager .page { - width: 20px; - text-align: center; - float: left; -} - -tr.paginationFooter td { - background: white; - padding-top:0px !important; - padding-bottom: 0px !important; - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; - text-align: right; -} - -tr.paginationFooter td ul.pagination { - margin-top: 8px; - margin-bottom: 4px; -} - -.nav-tabs.unclickable { - pointer-events: none; -} - -.navbar.navbar-inverse { - padding-bottom:0px; - padding-top:0px; - border: 0px; - border-radius: 0px; -} - -#ethplorer-note { - display:none; - width: 100%; - background-color: rgba(19,150,226,1); - padding: 10px; - margin-bottom: 20px; - margin-top: -20px; -} - -#ethplorer-note .ethplorer-note { - color: white; - text-align: center; - font-weight: 300; -} - -#ethplorer-note.warning { - background-color: rgba(255,0,0,1); -} - -#ethplorer-note .ethplorer-note img { - height: 35px; - margin-top: -10px; - margin-bottom: -10px; -} - -#ethplorer-note .ethplorer-note a { - color: white; - text-decoration: none; - border-bottom: 2px solid white; -} - -.table.unclickable { - opacity: 0.5; - pointer-events: none; -} - -#navbar { - min-height: 80px; -} - -#navbar .navbar-right { - padding-top: 14px; -} - -#error-reason { - padding-left: 0px; -} - -#error-with-details h3 { - margin: 0; - padding-top: 7px; - padding-bottom: 15px; -} - -.ethplorer-panel { - display: inline-block; - background: #1c1c1c; - color: #dedede; - border-radius: 5px; - padding: 15px; - font-size: 16px; -} - -#error-info { - margin: 0 auto; -} - -.navbar-inverse { - background-color: #fff; - padding-top: 8px; - padding-bottom: 8px; -} - -.navbar-nav { - margin-right: 0px; -} - -.navbar-header { - padding-left: 15px; -} - -.nav-tabs { - border-bottom: 10px solid #fff; -} - -.nav-tabs li a { - color: white; - border-bottom: 1px dashed white; -} - -.nav-tabs li a:hover { - color: black; -} - -.nav-tabs li a span.dashed { - border-bottom: 1px dashed white; -} - -.nav-tabs li a:hover span.dashed { - border-bottom: 1px dashed black; -} - -.nav-tabs li.active a span.dashed { - border-bottom: 0px dashed transparent; -} - -#topmenu li { - font-family: 'Open Sans', sans-serif; - font-size: 16px; - color: black; - font-weight: 600; - box-sizing: content-box; - -webkit-font-smoothing: antialiased; - padding: 16px; - cursor:pointer; -} - -#network { - color: white; - line-height: 34px; - margin-right: 30px; -} - -.content-page { - display: none; -} - -#address-token-details h3 { - max-width: 90%; -} - -.content-page h3 { - padding-left: 20px; - padding-top: 12px; - margin-bottom: 0; -} - -.content-page .block { - background-color: black; - border-radius: 8px; - margin-top: 20px; -} - -.content-page .block-header { - padding-bottom: 10px; - background-color:white; - border-top-left-radius: 8px; - border-top-right-radius: 8px; -} - -.content-page table.table td { - color: white; - border: 0 !important; - min-width: 120px; -} - -.content-page table.table td:first-child { - padding: 8px 8px 8px 28px; -} - -table.table.limit-width td:first-child, -table.table.limit-width td:nth-child(2) { - word-wrap: break-word; - max-width: 100px; -} - - -@media screen and (min-width: 500px) { - table.table.limit-width td:first-child{ - max-width: 200px; - } - table.table.limit-width td:nth-child(2) { - max-width: 200px; - } -} -@media screen and (min-width: 922px) { - table.table.limit-width td:first-child, - table.table.limit-width td:nth-child(2) { - max-width: 270px; /*tr width max 540px*/ - } -} - -#address-chainy-tx .table tr:nth-child(even), -#token-transfers-tab .table tr:nth-child(even), -#token-issuances-tab .table tr:nth-child(even), -#token-holders-tab .table tr:nth-child(even), -tr.even { - background: #0f0f0f; -} - -#address-chainy-tx .table tr:nth-child(odd), -#token-transfers-tab .table tr:nth-child(odd), -#token-issuances-tab .table tr:nth-child(odd), -#token-holders-tab .table tr:nth-child(odd), -tr.odd { - background: #202020; -} - -#address-token-balances .table tr td.text-right { - max-width: 250px; - overflow: hidden; -} - -.content-page .table tr.blue { - background-color: #1396e2 !important; -} - -.content-page .table tr.green { - background-color: #27ae60 !important; -} - -.content-page .table tr.red { - background-color: #c0392b !important; -} - -.block h3 { - margin-top: 0px; -} - -#loader { - margin-top: 90px; - padding: 40px; - width: 300px; - height: 300px; - border-radius: 150px; - margin-left: auto; - margin-right: auto; -} - -#loader #searchInProgressText { - font-size: 18px; - position: relative; - top: -80px; - color: #ddd; -} - -#transaction-tx-parsed, -#transaction-tx-input { - white-space: pre-wrap; /* Since CSS 2.1 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -.pre-switcher { - cursor: pointer; - position: absolute; - right: 52px; - font-size: 10px; -} - -pre.list-field { - padding-top: 16px; - max-height: 200px; - padding-right: 36px; -} - -#search { - margin-top: 8px; - margin-right: 15px !important; - width: 350px; - margin-left: 25px; -} - -.subnav { - background: #0f0f0f; - marign: 0px; -} - -.subnav .container { - padding: 8px; - color: white; - padding-left: 36px; -} - -a:not(.btn) { - text-decoration: underline; -} - -.token-logo { - max-width: 32px; - max-height: 32px; - margin: 8px; - margin-left:20px; -} - -.nav-tabs { - margin-top: 10px; -} - -.nav-tabs li a { - text-decoration: none; - border-radius: 8px 8px 0 0; -} - -#transaction-token-decimals small, -#address-token-decimals small { - color: #888; -} - -a.local-link, a.local-link:visited, a.local-link:hover { - color: white; -} - -.footer { - font-family: 'Open Sans', sans-serif; - padding-top:60px; - padding-bottom:75px; - background-color:#0d0d0d; - position: absolute; - width: 100%; - bottom: 0px; - overflow-x: auto; -} - -.footer .small-link { - color:#eeeeee !important; - text-decoration: none; - border-bottom: 2px solid #eeeeee; - box-shadow: inset 0px -1px 0px 0px #eeeeee; - -webkit-box-shadow: inset 0px -1px 0px 0px #eeeeee; - -moz-box-shadow: inset 0px -1px 0px 0px #eeeeee; - font-size: 12px; -} - -.footer-links li { - display: block; - margin-bottom: 10px; -} - -.footer-links li a{ - color: #ffffff; - font-weight: 600; - border-bottom: 2px solid #1396e2; - -webkit-box-shadow: inset 0px -1px 0px 0px #1396e2; - -moz-box-shadow: inset 0px -1px 0px 0px #1396e2; - box-shadow: inset 0px -1px 0px 0px #1396e2; - text-decoration: none; -} - -.footer-links ul { - -webkit-padding-start: 0px; -} - -.footer-donation { - color:#eeeeee; - /* overflow: hidden; - text-overflow: ellipsis; */ - word-wrap: break-word; -} - -.footer-links, -.footer-donation { - padding-right: 0px; -} - -#disqus_thread { - margin-top: 60px; - display: none; - padding-bottom: 320px; -} - -td.list-field { - white-space: nowrap; - overflow: hidden; - max-width: 1px; - width: 80%; - text-overflow: ellipsis; -} - -.address-balance, .token-related .blue td { - font-size: 20px; - white-space: normal; -} - -.navbar-logo { - float: left; - height: 50px; - padding: 25px 15px; - line-height: 20px; - width: 170px; - position: absolute; - z-index: 10000; - padding-left: 0px; -} - -.navbar-logo-extra { - float: left; - height: 10px; - line-height: 48px; - width: 40px; - position: absolute; - z-index: 10000; - padding-left: 175px; - padding-top: 20px; -} - -.navbar-logo-extra img { - width: 40px; -} - - -.navbar-logo img { - width: 170px; - cursor: pointer; -} - -.navbar-logo-small { - float: left; - height: 50px; - padding: 25px 15px; - line-height: 20px; - width: 32px; - position: absolute; - z-index: 10000; - padding-left: 0px; - display: none; -} - -.navbar-logo-small img { - height: 32px; - cursor: pointer; -} - -.table tr.last td:first-child { - border-bottom-left-radius: 8px; -} - -.table tr.last td:last-child { - border-bottom-right-radius: 8px; -} - -.multiop { - display: none; -} - -.multiop tr.selectable { - cursor: pointer; -} - -.multiop tr td:nth-child(1) { - max-width: 85px; -} - -.multiop tr td:nth-child(2) { - max-width: 50vw; - overflow: hidden; - text-overflow: ellipsis; -} - -.multiop tr td:nth-child(2), -.multiop tr td:nth-child(3), -.multiop tr td:nth-child(4) -{ - min-width: 65px; -} - -.multiop tr td:nth-child(4) { - max-width: 65px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.multiop tr td:nth-child(5){ - display: none; - max-width: 4px; -} - -.multiop tr.selectable:hover td span.dash_on_hover { - border-bottom: 1px dashed; -} - -a.dashed { - text-decoration: none; - border-bottom: 1px dashed; -} - -.multiop a { - color: white !important; -} - -.chainy { - display: none; -} - -.chainy-text { - font-size: 11px; - display: block; - margin-bottom: -7px; - opacity: 0.4; - overflow: hidden; - white-space: nowrap; -} - -.token-name a { - color: #333 !important; -} - -.address-token-inline { - display: none; -} - -#transfer-tx-message, -#transaction-tx-message, -#address-token-description { - white-space: normal !important; -} - -#qr-code-address { - display:inline-block; -} - -#ethplorer-path { - display: none; - padding: 16px; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100vw; - background-color: white; - border-radius: 8px; - text-align: center; - font-size: 22px; - margin-top: 10px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis -} - -#ethplorer-path .tx-pending { - padding-top: 10px; - margin: 0; -} - -#ethplorer-alert { - display: none; - padding: 16px; - overflow: hidden; - text-overflow: ellipsis; - max-width: 100vw; - background-color: #f8f577; - color: #ac0000; - border-radius: 8px; - text-align: center; - font-size: 22px; - margin-top: 10px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis -} - -#ethplorer-alert a { - color: #ac0000 !important; -} - - -#token-history-grouped-widget { - display: none; - overflow: hidden; - text-align: center; - white-space: nowrap; - overflow: hidden; -} - -.same-address { - opacity: 0.4; -} - -.incoming { - font-size: 16px; - color: #1e8c1e !important; -} - -.outgoing { - font-size: 16px; - color: #ae2525 !important; -} - -.self { - font-size: 16px; - color: #fff !important; -} - -.diff-up { - color: #1e8c1e !important; -} - -.diff-down { - color: #ae2525 !important; -} -#transfer-operation-value .diff-up, -#transfer-operation-value .diff-zero, -#transfer-operation-value .diff-down{ - padding-left: 6px; -} - -#transfer-operation-value .diff-up{ - color: #28d028 !important; - font-size: 0.9em; -} - -#transfer-operation-value .diff-down{ - color: #a92626 !important; - font-size: 0.9em; -} - -.tx-value-price { - font-size: 0.9em; - color: white; - opacity: 0.6; -} - -.balances-price { - color: rgba(255, 255, 255, 0.6); - font-size: 0.9em; - display: inline-block; - float: right; -} - -#address-balances-total { - color: rgba(0, 0, 0, 0.6); - font-size: 0.8em; - line-height: 1.6em; - display: block; - padding-right: 15px; - width: 100%; - position: relative; - top: -25px; - text-align: right; - margin-bottom: -30px; -} - -#address-balances-total-inner { - max-width: 250px; - display: inline-block; - white-space: nowrap; - text-overflow: ellipsis; - line-height: 1em; - overflow: hidden; - position: relative; - top: 2px; -} - -.total-supply-usd { - color: rgba(255, 255, 255, 0.6); -} - -.transfer-usd { - color: rgba(255, 255, 255, 0.6); - font-size: 0.8em; -} -.transfer-usd span{ - padding-left: 6px; -} -@media screen and (max-width: 1199px) and (min-width: 767px) { - .transfer-usd span{ - display: block; - } -} - -.hash-from-to, .cut-long-text { - max-width: 40vw; - overflow: hidden; - text-overflow: ellipsis -} -.cut-long-text { - max-width: 17vw; -} - -#address-token-transfers small, -#address-transfers small, -#address-issuances small, -#address-chainy-tx small -{ - margin-top: -10px; - display: block; - padding-left: 16px; - color: white; - margin-bottom: 20px; -} - -.export-csv { - float: right; - padding-right: 16px; -} - -.export-csv-spinner { - float: right; - padding-right: 16px; - display: none; -} - -#address-chainy-tx .table tr td:nth-child(4){ - white-space: nowrap; -} - -.pageSize { - float: left; - color: #333; - margin-top: 14px; -} - -#address-chainy-info, -#tab-issuances, -#tab-holders, -#address-token-transfers, -#address-issuances, -#address-token-holders { - display: none; -} - -#address-token-holders td.show_small { - padding-left: 0px !important; -} - -.holder_small { - min-height: 50px; - margin-top: -16px; - max-width: 60vw; - overflow: hidden; - text-overflow: ellipsis; -} - -.total-records { - float: right; - margin-top: -22px; - margin-right: 20px; -} - -#address-token-holders tr td:first-child { - max-width: 50px; - width: 50px; - text-align: right; - padding-left: 0px; -} - -tr.paginationFooter td { - padding-left: 20px !important; -} - -#address-token-holders tr td:nth-child(2) { - max-width: 250px; - width: 250px; - overflow: hidden; - text-overflow: ellipsis; -} - -#address-token-holders tr td:nth-child(3) { - min-width: 1px; -} - -#address-token-holders tr td:nth-child(4) { - max-width: 220px; - width: 220px; - overflow: hidden; - text-overflow: ellipsis; - text-align: right; - white-space: nowrap; -} - -#address-token-holders tr td:nth-child(5) { - width: 50%; - padding-right: 60px; -} - -#address-token-holders-totals { - color: white; - font-size: 13px; - text-align: center; -} - -.holder-gauge { - position: relative; - background-color: white; - opacity: 0.8; - height: 20px; - float: left; -} - -.holder-gauge-value { - position:relative; - width:0px; - height: 20px; - float: left; -} - - -#address-issuances tr td:last-child { - min-width: 200px; -} - -.tx-details-link { - font-size: 22px; - color: white !important; - cursor: pointer; - border-bottom: 1px dashed white; -} - -.tx-details-link, -.tx-details-link:hover, -.tx-details-link:visited, -.tx-details-link:active { - text-decoration: none; -} - -.tx-details-link.closed { - display: none; -} - -.tx-details-close { - top: 24px; - position: absolute; - right: 32px; - font-size: 30px; - color: #444; - cursor: pointer; -} - -.total-in-out-small { - font-size: 0.8em; - opacity: 0.4; - line-height: 14px; - padding-top: 4px; -} - -.filter-box { - z-index:200; -} - -#address-transfers { - z-index:100; -} - -.filter-box.in-tabs { - text-align: right; - height: 0px; - margin-top: -50px; -} - -.filter-box.in-tabs .filter-form{ - width: 300px; - float: right; -} - -.filer-mark { - /* color: black; */ - /* background-color: yellow; */ -} - -.filter-box.out-of-tabs{ - text-align: right; - height: 15px; - margin-top: 5px; -} - -.filter-clear { - width: 16px; - height: 16px; - position: absolute; - top: -3px; - right: 24px; - color: #7b1818; - cursor: pointer; - display: none; - font-size: 24px; -} - -_::-webkit-:host:not(:root:root), .filter-clear { - top: -6px; -} - -#filter-error { - color: #7b1818; - margin-top: 15px; - display: none; -} - -.filter-box.out-of-tabs .filter-clear { - right: 24px; -} - -#filter_list { - border-radius: 7px; - padding-left: 5px; - padding-right: 24px; - width: 240px; - border: 1px solid white; - padding-top: 2px; - padding-bottom: 2px; - background-color: black; - color: white; -} - -#filter_list.filled { - border-color: #7b1818; - color: #7b1818; -} - -.filtered-totals { - color: #7b1818; -} - -.filter-box.processing { - opacity: 0.6; - pointer-events: none; -} - -.ui-autocomplete { - max-width: 350px; - overflow: hidden; - border-radius: 4px; -} - -.ui-autocomplete li { - font-size: 12px; - white-space: nowrap; -} - -li.ui-menu-item.not-found { - opacity: 1 !important; - color: #aaa; - pointer-events: none; -} - -li.ui-menu-item.have-more { - opacity: 1 !important; - color: #aaa; - padding-top: 4px; - border-top: 1px dotted #aaa; - font-style: italic; - pointer-events: none; -} - -#filter_list:focus { - outline: none; - box-shadow: 0 0 0px #000; -} - -.notFoundRow td { - text-align: center !important; -} - -#search-quick-results { - z-index:100; - position: absolute; - background-color: white; - border:1px solid #aaa; - width: 350px; - display: none; - padding: 2px 8px; - border-radius: 4px; - margin-top: -1px; -} - -#search-quick-results .search-result { - color: #444; - overflow: hidden; - cursor: pointer; - white-space: nowrap; - text-overflow: ellipsis; -} - -#search-quick-results .search-result:hover { - background-color: #eee; -} - -#search-quick-results .search-more { - color: #aaa; - padding-top: 4px; - border-top: 1px dotted #aaa; - font-style: italic; -} - -.table-loading { - margin-top: -5px; - margin-right: -10px; -} - -/* Loader */ - -.loader-wrapper { - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto; - padding: 0 20px; - height: 100%; - } - - .dot-loader { - height: 15px; - position: relative; - padding: 8px; - width: 75px; - margin: 0 auto; - } - - .dot { - background: #b7b7b7; - border-radius: 50%; - float: left; - height: 15px; - opacity: 0.15; - position: relative; - left: 0; - top: 0; - -webkit-transform: scale(1); - transform: scale(1); - -webkit-animation-delay: 0.6s; - animation-delay: 0.6s; - width: 15px; - } - .dot:nth-child(1) { - -webkit-animation: dots-animation 1s 0.2s ease-in-out infinite; - animation: dots-animation 1s 0.2s ease-in-out infinite; - -webkit-animation-delay: 0.2s; - animation-delay: 0.2s; - left: 0px; - } - .dot:nth-child(2) { - -webkit-animation: dots-animation 1s 0.4s ease-in-out infinite; - animation: dots-animation 1s 0.4s ease-in-out infinite; - -webkit-animation-delay: 0.4s; - animation-delay: 0.4s; - left: 7.5px; - } - .dot:nth-child(3) { - -webkit-animation: dots-animation 1s 0.6s ease-in-out infinite; - animation: dots-animation 1s 0.6s ease-in-out infinite; - -webkit-animation-delay: 0.6s; - animation-delay: 0.6s; - left: 15px; - } - - @-webkit-keyframes dots-animation { - 0%, 70%, 100% { - opacity: 0.15; - -webkit-transform: scale(1); - transform: scale(1); - } - 35% { - opacity: 1; - -webkit-transform: scale(1); - transform: scale(1); - } -} - - @keyframes dots-animation { - 0%, 70%, 100% { - opacity: 0.15; - -webkit-transform: scale(1); - transform: scale(1); - } - 35% { - opacity: 1; - -webkit-transform: scale(1); - transform: scale(1); - } -} - -/* Loader end */ - -.cuttable-address { - white-space: nowrap; -} - -.new-mark { - color: #f71e1e; - font-size: 10px; - font-family: 'Open Sans'; - line-height: 1.55; - font-weight: 700; - position: absolute; - right: 5px; - top: 5px; -} - -@media screen and (max-width: 1199px) { - .footer-donation { - font-size:12.8px; - } - - #topmenu li { - padding-right: 8px; - } -} - -@media screen and (min-width: 640px) { - .nav-tabs li a { - font-size: 24px !important; - } -} - -@media screen and (max-width: 640px) { - .footer { - /* line-height: 18px; */ - font-size: 12px; - } - .footer .copyrights { - text-align: center; - position:relative; - width: 100%; - } -} -@media screen and (min-width: 992px) { - .multiop tr td:nth-child(3) { - white-space: nowrap !important; - } -} - -@media screen and (max-width: 991px) { - .tx-details-link, - #ethplorer-path { - font-size: 18px; - } - #qr-code-address { - font-size: 16px; - } - .address-token { - display: none; - } - .address-token-inline { - display: inline; - } - .footer-links, - .footer-donation { - font-size:12.3px; - } - .new-mark { - right: -10px; - } -} - -@media screen and (min-width: 400px) and (max-width: 991px) { - .hash-from-to, .cut-long-text { - padding-left: 20px; - max-width: 38vw; - } - - td.table-hash-field { - max-width: 26vw; - } -} - -@media screen and (max-width: 699px) { - .address-balance, .token-related .blue td { - font-size: 18px; - } - - .hash-from-to { - max-width: 56vw; - } - .cut-long-text { - max-width: 32vw; - } - - td.table-hash-field { - display: none; - } -} - -@media screen and (max-width: 499px) { - .nav-tabs li a { - padding-left:6px; - padding-right: 6px; - } - td.table-type-field { - display: none; - } - .footer-links, - .footer-donation { - font-size:12px; - } - #address-balances-total-inner { - max-width: 150px; - } -} - -@media screen and (max-width: 399px) { - #ethplorer-note { - margin-top: 0px; - } - - .total-records { - display: none; - } - .pagination-sm>li>a, .pagination-sm>li>span { - padding: 7px 5px; - font-size: 9px; - } - tr.paginationFooter td ul.pagination { - margin-right: 10px; - } - #address-issuances tr td:last-child { - min-width: 140px; - } - .address-balance, .token-related .blue td { - font-size: 16px; - } - #address-token-transfers td { - font-size: 11px; - } - #qr-code-address { - font-size: 12px; - } - #ethplorer-path { - font-size: 14px; - } - .table tr td:first-child { - max-width: 90px; - padding-left: 8px !important; - } - .table tr td:nth-child(2) { - /* text-align: right; */ - } - .table tr td { - font-size: 12px; - } - .block-header h3 { - font-size: 18px; - padding-left: 8px; - } - .navbar { - margin-bottom: 0px; - } - #address-balances-total { - font-size: 0.6em; - line-height: 2em; - padding-right: 5px; - } - .footer-links, - .footer-donation { - font-size:11px; - } -} - -.show_small { - display: none; -} - -a.token-update { - position: absolute; - right: 0px; - margin-right: 30px; - font-size: 14px; - top: 37px; - color: #337ab7 !important; -} - -.adsbygoogle { - display: block; - width: 900px; - height: 17px; - margin-left: auto; - margin-right: auto; -} - -@media screen and (max-width: 979px) { - .adsbygoogle { - width: 480px !important; - } -} - -@media screen and (max-width: 479px) { - .adsbygoogle { - display: none !important; - } - .new-mark { - right: -5px; - top: 0px; - } -} - -@media screen and (max-width: 991px) { - #topmenu li { - padding-right: 0px; - } - .navbar-logo { - display: none; - } - .navbar-logo-extra { - display: none; - } - .navbar-logo-small { - display: block; - } -} - -@media screen and (max-height: 1024px) { - #loader { - margin-top: -20px; - } -} - -@media screen and (max-width: 767px) { - - #loader { - margin-top: -40px; - } - - #disqus_thread { - padding-bottom: 430px; - } - - .navbar-nav>li { - float: left; - } - - .filter-box.in-tabs { - text-align: right; - height: 15px !important; - margin-top: 10px !important; - } - - .filter-box.in-tabs .filter-form { - width: 100%; - } - - .filter-box.in-tabs #filter_list { - width: 100%; - } - - .ui-autocomplete { - max-width: 100%; - } - - #qr-code-address { - font-size: 12px; - } - - #ethplorer-path { - font-size: 16px; - } - - .multiop tr td:nth-child(3), - .multiop tr td:nth-child(4), - .multiop tr td:nth-child(5) - { - display: none; - } - - .multiop tr td:nth-child(5){ - display: table-cell; - } - - #address-token-transfers .block { - max-width: 100vw; - overflow: hidden; - } - - .block-header h3 { - font-size: 20px; - } - - .hash-from-to{ - max-width: 75vw !important; - } - - #address-token-transfers td { - font-size: 12px; - } - - .hide-small { - display: none !important; - } - - .show_small { - display: initial; - } - - .address-token{ - display: none; - } - - #navbar { - height: 115px; - } - - #searchform { - position: absolute; - top: 35px; - right: 0px; - width: 100%; - } - - #search-quick-results, - #search { - width: 100%; - margin-left: 0px; - } - - #topmenu { - position: absolute; - right: 0px; - top: -4px; - } - - .token-history-grouped-widget { - padding: 0px !important; - } -} - -@media screen and (max-width: 479px) { - a.token-update { - display: none; - } - #topmenu li { - padding-left: 8px; - padding-bottom: 8px; - padding-top: 10px; - padding-right: 0px; - } -} - -@media screen and (max-width: 359px) { - #topmenu li { - padding-left: 10px; - padding-top: 13px; - font-size: 15px; - } - #address-balances-total { - font-size: 0.5em; - line-height: 2.5em; - } - #address-balances-total-inner { - max-width: 100px; - } -} - -@-webkit-keyframes minhand{ - 0%{-webkit-transform:rotate(0deg)} - 100%{-webkit-transform:rotate(360deg)} -} -@-moz-keyframes minhand{ - 0%{-moz-transform:rotate(0deg)} - 100%{-moz-transform:rotate(360deg)} -} -@keyframes minhand{ - 0%{transform:rotate(0deg)} - 100%{transform:rotate(360deg)} -} - -@-webkit-keyframes hrhand{ - 0%{-webkit-transform:rotate(0deg)} - 100%{-webkit-transform:rotate(360deg)} -} -@-moz-keyframes hrhand{ - 0%{-moz-transform:rotate(0deg)} - 100%{-moz-transform:rotate(360deg)} -} -@keyframes hrhand{ - 0%{transform:rotate(0deg)} - 100%{transform:rotate(360deg)} -} -.historical-price { - display: block; - font-size: 0.7em; - color: rgba(255, 255, 255, 0.4); -} -.mrgnl-10 { - margin-left: 10px; -} -/* Scrollable */ -.scrollable{ - position: relative; -} -.scrollwrapper{ - max-height: 280px; - overflow-y: auto; -} -#address-token-balances .scrollwrapper{ - max-height: 350px; -} -.scrollwrapper:after{ - content: ""; - position: absolute; - display: block; - left: 0; - width: 100%; - height: 60px; -} -.scrollwrapper.hide-bottom-gr:after{ - display: none; -} -.scrollwrapper:after{ - bottom: 0; - pointer-events: none; - content: ''; - background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); - background: -webkit-gradient(left bottom, left top, color-stop(0%, rgba(0,0,0,0)), color-stop(100%, rgba(0,0,0,9))); - background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); - background: -o-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); - background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); - background: linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,9)); -} - -.expand-btn{ - display: none; - font-size: 16px; - color: white !important; - opacity: 0.6; - cursor: pointer; - border-bottom: 1px dashed white; - /*text-transform:capitalize;*/ -} -.shift-up{ - position: relative; - top: -15px; -} - -.expand-btn, -.expand-btn:hover, -.expand-btn:visited, -.expand-btn:active { - text-decoration: none; -} - - -.expanded .scrollwrapper, -#address-token-balances .expanded .scrollwrapper { - max-height: none; -} - -.expanded .scrollwrapper:after{ - display: none; -} - -/* ^^^ Scrollable ^^^ */ - -#address-token-balances, .multiop { - margin-bottom: 20px; -} - -#address-token-balances table, .multiop table{ - margin-bottom: 0; -} - -.diff-span { - padding-right: 20px; - color: rgba(255, 255, 255, 0.6); -} -.diff-span span { - padding-left: 6px; -} -.diff-zero{ - color: rgba(255, 255, 255, 0.6); -} - -#page-create { - min-height: 650px; -} - -#cookie-notification { - position: fixed; - z-index: 1000; - width: 100%; - bottom: 0; - padding: 10px 0; - background: #eaeaea; -} - -#cookie-notification span { - padding-bottom: 7px; - display: inline-block; - margin-right: 10px; -} - -#address-balances-total { - pointer-events: none; -} - -.tooltip{ - font-size: 0.8em; -} diff --git a/css/font-awesome.min.css b/css/font-awesome.min.css deleted file mode 100644 index 540440ce..00000000 --- a/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/css/jquery-ui.min.css b/css/jquery-ui.min.css deleted file mode 100644 index 0e3d4642..00000000 --- a/css/jquery-ui.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2017-02-07 -* http://jqueryui.com -* Includes: core.css, autocomplete.css, menu.css -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0} \ No newline at end of file diff --git a/css/tilda-blocks-2.10.css b/css/tilda-blocks-2.10.css deleted file mode 100644 index 86baa843..00000000 --- a/css/tilda-blocks-2.10.css +++ /dev/null @@ -1 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,600,700&subset=latin,cyrillic);.t-body{margin:0}#allrecords{-webkit-font-smoothing:antialiased;background-color:none}#allrecords a{color:#ff8562;text-decoration:none}#allrecords a[href^=tel]{color:inherit;text-decoration:none}#allrecords ol{padding-left:22px}#allrecords ul{padding-left:20px}@media print{body,html{min-width:1200px;max-width:1200px;padding:0;margin:0 auto;border:none}}.t-text{font-family:'Georgia',serif;font-weight:300;color:#000}.t-text_xs{font-size:15px;line-height:1.55}.t-text_sm{font-size:18px;line-height:1.55}.t-text_md{font-size:20px;line-height:1.55}.t-text_lg{font-size:22px;line-height:1.55}.t-text_weight_plus{font-weight:400}.t-text-impact{font-family:'Georgia',serif;font-weight:300;color:#000}.t-text-impact_xs{font-size:26px;line-height:1.5}.t-text-impact_sm{font-size:32px;line-height:1.35}.t-text-impact_md{font-size:38px;line-height:1.35}.t-text-impact_lg{font-size:42px;line-height:1.23}.t-name{font-family:'Open Sans',sans-serif;font-weight:600;color:#000}.t-name_xs{font-size:16px;line-height:1.35}.t-name_sm{font-size:18px;line-height:1.35}.t-name_md{font-size:20px;line-height:1.35}.t-name_lg{font-size:22px;line-height:1.35}.t-name_xl{font-size:24px;line-height:1.35}.t-heading{font-family:'Open Sans',sans-serif;font-weight:600;color:#000}.t-heading_xs{font-size:26px;line-height:1.23}.t-heading_sm{font-size:28px;line-height:1.17}.t-heading_md{font-size:30px;line-height:1.17}.t-heading_lg{font-size:32px;line-height:1.17}.t-title{font-family:'Open Sans',sans-serif;font-weight:600;color:#000}.t-title_xxs{font-size:36px;line-height:1.23}.t-title_xs{font-size:42px;line-height:1.23}.t-title_sm{font-size:48px;line-height:1.23}.t-title_md{font-size:52px;line-height:1.23}.t-title_lg{font-size:64px;line-height:1.23}.t-title_xl{font-size:72px;line-height:1.17}.t-title_xxl{font-size:82px;line-height:1.17}.t-descr{font-family:'Open Sans',sans-serif;font-weight:300;color:#000}.t-descr_xxs{font-size:14px;line-height:1.55}.t-descr_xs{font-size:16px;line-height:1.55}.t-descr_sm{font-size:18px;line-height:1.55}.t-descr_md{font-size:20px;line-height:1.55}.t-descr_lg{font-size:22px;line-height:1.55}.t-descr_xl{font-size:24px;line-height:1.5}.t-descr_xxl{font-size:26px;line-height:1.45}.t-descr_xxxl{font-size:30px;line-height:1.45;letter-spacing:.45}.t-uptitle{font-family:'Open Sans',sans-serif;font-weight:600;color:#000;letter-spacing:2.5px}.t-uptitle_xs{font-size:12px}.t-uptitle_sm{font-size:14px}.t-uptitle_md{font-size:16px}.t-uptitle_lg{font-size:18px}.t-uptitle_xl{font-size:20px;letter-spacing:2px}.t-uptitle_xxl{font-size:22px;letter-spacing:2px}.t-uptitle_xxxl{font-size:24px;letter-spacing:2px}@media screen and (max-width:1200px){.t-text_xs{font-size:14px}.t-text_sm{font-size:16px}.t-text_md{font-size:18px}.t-text_lg{font-size:20px}.t-text-impact_md{font-size:30px}.t-descr_xxs{font-size:12px}.t-descr_xs{font-size:14px}.t-descr_sm{font-size:16px}.t-descr_md{font-size:18px}.t-descr_lg{font-size:20px}.t-descr_xl{font-size:22px}.t-descr_xxl{font-size:22px}.t-descr_xxxl{font-size:26px}.t-uptitle_md{font-size:14px}.t-uptitle_lg{font-size:16px}.t-uptitle_xl{font-size:18px}.t-uptitle_xxl{font-size:20px}.t-uptitle_xxxl{font-size:22px}.t-title_xxs{font-size:32px}.t-title_xs{font-size:38px}.t-title_sm{font-size:44px}.t-title_md{font-size:48px}.t-title_lg{font-size:60px}.t-title_xl{font-size:68px}.t-title_xxl{font-size:78px}.t-name_xs{font-size:14px}.t-name_sm{font-size:16px}.t-name_md{font-size:18px}.t-name_lg{font-size:20px}.t-name_xl{font-size:22px}.t-heading_xs{font-size:24px}.t-heading_sm{font-size:26px}.t-heading_md{font-size:28px}.t-heading_lg{font-size:30px}}@media screen and (max-width:640px){.t-text_xs{font-size:12px;line-height:1.45}.t-text_sm{font-size:14px;line-height:1.45}.t-text_md{font-size:16px;line-height:1.45}.t-text_lg{font-size:18px;line-height:1.45}.t-text-impact_sm{font-size:22px}.t-text-impact_md{font-size:26px}.t-text-impact_lg{font-size:28px}.t-descr_xs{font-size:12px;line-height:1.45}.t-descr_sm{font-size:14px;line-height:1.45}.t-descr_md{font-size:16px;line-height:1.45}.t-descr_lg{font-size:18px;line-height:1.45}.t-descr_xl{font-size:20px;line-height:1.4}.t-descr_xxl{font-size:20px}.t-descr_xxxl{font-size:22px}.t-uptitle_xs{font-size:10px}.t-uptitle_sm{font-size:10px}.t-uptitle_md{font-size:12px}.t-uptitle_lg{font-size:14px}.t-uptitle_xl{font-size:16px}.t-uptitle_xxl{font-size:18px}.t-uptitle_xxxl{font-size:20px}.t-title_xxs{font-size:28px}.t-title_xs{font-size:30px}.t-title_sm{font-size:30px}.t-title_md{font-size:30px}.t-title_lg{font-size:30px}.t-title_xl{font-size:32px}.t-title_xxl{font-size:36px}.t-name_xs{font-size:12px}.t-name_sm{font-size:14px}.t-name_md{font-size:16px}.t-name_lg{font-size:18px}.t-name_xl{font-size:20px}.t-heading_xs{font-size:22px}.t-heading_sm{font-size:24px}.t-heading_md{font-size:24px}.t-heading_lg{font-size:26px}}@media screen and (max-width:480px){.t-title_xl{font-size:30px}.t-title_xxl{font-size:30px}}.t-records{-webkit-font_smoothing:antialiased;background-color:none}.t-records a{color:#ff8562;text-decoration:none}.t-records a[href^=tel]{color:inherit;text-decoration:none}.t-records ol{padding-left:22px;margin-top:0;margin-bottom:10px}.t-records ul{padding-left:20px;margin-top:0;margin-bottom:10px}.t-cover{height:700px;width:100%;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;background-color:#000;background-repeat:no-repeat;background-position:center center;text-align:center;vertical-align:middle;position:relative;background-attachment:fixed;overflow:hidden}.t-cover__carrier{height:700px;width:100%;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-repeat:no-repeat;background-position:center center;text-align:center;vertical-align:middle;position:relative;background-attachment:fixed}.t-cover__carrier.loading{opacity:0}.t-cover__carrier[data-content-cover-bg=""].loading{opacity:1!important}.t-cover__carrier.loaded{opacity:1;transition:opacity 400ms}@media screen and (max-device-width:1024px){.t-cover{background-attachment:scroll}.t-cover__carrier{background-attachment:scroll}}@media print{.t-cover{background-attachment:scroll}.t-cover__carrier{background-attachment:scroll}}.t-cover__filter{height:700px;width:100%;position:absolute;top:0;left:0}.t-cover .t-container,.t-cover .t-container_100,.t-cover .t-container_10,.t-cover .t-container_8{position:absolute;top:0;left:0;bottom:0;right:0}.t-cover__wrapper{height:700px;display:table-cell;width:1200px}.t-cover__wrapper span.space{display:inline-block;height:100%;width:1px}@media screen and (max-width:640px){.t-cover{height:400px;background-attachment:fixed}.t-cover__carrier{background-attachment:scroll!important;background-size:cover;background-position:center center}.t-cover__filter{height:400px}.t-cover__wrapper{height:400px}}@-webkit-keyframes t-arrow-bottom{0%{-moz-transform:translateY(0);-ms-transform:translateY(0);-webkit-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}50%{-moz-transform:translateY(-7px);-ms-transform:translateY(-7px);-webkit-transform:translateY(-7px);-o-transform:translateY(-7px);transform:translateY(-7px)}55%{-moz-transform:translateY(-7px);-ms-transform:translateY(-7px);-webkit-transform:translateY(-7px);-o-transform:translateY(-7px);transform:translateY(-7px)}100%{-moz-transform:translateY(0);-ms-transform:translateY(0);-webkit-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@keyframes t-arrow-bottom{0%{-moz-transform:translateY(0);-ms-transform:translateY(0);-webkit-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}50%{-moz-transform:translateY(-7px);-ms-transform:translateY(-7px);-webkit-transform:translateY(-7px);-o-transform:translateY(-7px);transform:translateY(-7px)}55%{-moz-transform:translateY(-7px);-ms-transform:translateY(-7px);-webkit-transform:translateY(-7px);-o-transform:translateY(-7px);transform:translateY(-7px)}100%{-moz-transform:translateY(0);-ms-transform:translateY(0);-webkit-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}.t-cover__arrow-wrapper_animated{animation:t-arrow-bottom 1.7s infinite ease}.t-cover__arrow{position:absolute;z-index:9;bottom:40px;right:0;left:0;text-align:center}.t-cover__arrow-wrapper{display:inline-block;-webkit-transition:all ease-in-out 0.2s;-moz-transition:all ease-in-out 0.2s;-o-transition:all ease-in-out 0.2s;transition:all ease-in-out 0.2s;cursor:pointer}.t-cover__arrow-wrapper:hover{opacity:.7}.t-cover__arrow-svg{fill:#fff}@media screen and (max-width:640px){.t-cover__arrow_mobile{-moz-transform:scale(.7);-ms-transform:scale(.7);-webkit-transform:scale(.7);-o-transform:scale(.7);transform:scale(.7)}.t-cover__arrow{bottom:14px}}.t-btn{display:inline-block;font-family:'Open Sans',sans-serif;height:60px;border:0 none;font-size:16px;padding-left:60px;padding-right:60px;text-align:center;white-space:nowrap;vertical-align:middle;font-weight:700;background-image:none;cursor:pointer;-webkit-appearance:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.t-btn td{vertical-align:middle}.t-btn_sending{opacity:.5}@media screen and (max-width:640px){.t-btn{white-space:normal;padding-left:30px;padding-right:30px}}.t-btn_sm{height:40px;font-size:14px;padding-left:30px;padding-right:30px}.t-btn_lg{height:60px;font-size:22px;padding-left:70px;padding-right:70px}.t-btn_xl{height:80px;font-size:26px;padding-left:80px;padding-right:80px}.t-btn_xxl{height:100px;font-size:30px;padding-left:90px;padding-right:90px}@media screen and (max-width:640px){.t-btn_lg{font-size:18px;padding-left:40px;padding-right:40px}.t-btn_xl{font-size:22px;padding-left:50px;padding-right:50px}.t-btn_xxl{font-size:26px;padding-left:60px;padding-right:60px}}.t-submit{font-family:'Open Sans',sans-serif;text-align:center;height:60px;border:0 none;font-size:16px;padding-left:60px;padding-right:60px;-webkit-appearance:none;font-weight:700;white-space:nowrap;background-image:none;cursor:pointer;margin:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;outline:none}.t-submit_sending{opacity:.5}@media screen and (max-width:640px){.t-submit{white-space:normal;padding-left:30px;padding-right:30px}}.t-input{margin:0;font-family:'Open Sans',sans-serif;font-size:100%;height:60px;padding:0 20px;font-size:16px;line-height:1.33;width:100%;border:0 none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;outline:none}.t-input::-moz-focus-inner{padding:0;border:0}.t-input_bbonly{outline:none;padding-left:0!important;padding-right:0!important;border-top:0!important;border-right:0!important;border-left:0!important;background-color:transparent!important;border-radius:0!important}@media screen and (max-width:1200px){.t-screenmin-1200px{display:none}}@media screen and (max-width:980px){.t-screenmin-980px{display:none}}@media screen and (max-width:640px){.t-screenmin-640px{display:none}}@media screen and (max-width:480px){.t-screenmin-480px{display:none}}@media screen and (max-width:320px){.t-screenmin-320px{display:none}}@media screen and (min-width:321px){.t-screenmax-320px{display:none}}@media screen and (min-width:481px){.t-screenmax-480px{display:none}}@media screen and (min-width:641px){.t-screenmax-640px{display:none}}@media screen and (min-width:981px){.t-screenmax-980px{display:none}}@media screen and (min-width:1201px){.t-screenmax-1200px{display:none}}.t-hidden{display:none}.t-opacity_50{filter:alpha(opacity=50);KHTMLOpacity:.5;MozOpacity:.5;opacity:.5}.t-opacity_70{filter:alpha(opacity=70);KHTMLOpacity:.7;MozOpacity:.7;opacity:.7}.t-uppercase{text-transform:uppercase}.t-align_center{text-align:center}.t-align_left{text-align:left}.t-align_right{text-align:right}.t-margin_auto{margin-left:auto;margin-right:auto}.t-valign_middle{vertical-align:middle}.t-valign_top{vertical-align:top}.t-valign_bottom{vertical-align:bottom}.t-margin_left_auto{margin-right:0;margin-left:auto}.yashare-style .b-share-btn__facebook,.yashare-style .b-share-btn__twitter,.yashare-style .b-share-btn__vkontakte{background-color:transparent!important}.yashare-style .b-share__link{-webkit-border-radius:0px!important;border-radius:0px!important}.yashare-style-black-white .b-share-btn__wrap{background-color:#000!important;padding:5px!important}.yashare-style-transp-white .b-share-btn__wrap{padding:5px!important}.yashare-style-transp-white .b-share-counter{color:#fff;font-weight:700}.yashare-style-white-black .b-share-btn__wrap{background-color:#fff!important;padding:5px!important}.yashare-style-white-black .b-share-icon{background-image:url(//static.tildacdn.com/img/b-share_counter_large_white.png)!important}.yashare-style-transp-black .b-share-btn__wrap{padding:5px!important}.yashare-style-transp-black .b-share-icon{background-image:url(//static.tildacdn.com/img/b-share_counter_large_white.png)!important}.yashare-style-transp-black .b-share-counter{color:#000;font-weight:700}.ya-share2 ul{padding-left:0px!important}.carousel{position:relative}.carousel ol{padding-left:0px!important}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;line-height:1}.carousel-inner .widthauto{width:auto;max-width:100%;vertical-align:middle}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;opacity:.2;filter:alpha(opacity=20)}.carousel-control.right{right:0;left:auto}.carousel-control .carousel-control-left{position:absolute;top:48%;z-index:5;display:inline-block;left:20%;height:34px;width:21px;background:url(//static.tildacdn.com/img/aboutSliderControls.png) no-repeat}.carousel-control .carousel-control-left-white{position:absolute;top:48%;z-index:5;display:inline-block;left:20%;height:34px;width:21px;background:url(//static.tildacdn.com/img/aboutSliderControls_white.png) no-repeat}.carousel-control .carousel-control-right{position:absolute;top:48%;z-index:5;display:inline-block;right:20%;height:34px;width:21px;background:url(//static.tildacdn.com/img/aboutSliderControls.png) no-repeat;background-position:left bottom}.carousel-control .carousel-control-right-white{position:absolute;top:48%;z-index:5;display:inline-block;right:20%;height:34px;width:21px;background:url(//static.tildacdn.com/img/aboutSliderControls_white.png) no-repeat;background-position:left bottom}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators.dotsbottom{bottom:-60px}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;margin-left:5px;margin-right:5px;text-indent:-999px;cursor:pointer;background-color:#000;border:none;border-radius:10px}.carousel-indicators .active{width:10px;height:10px;margin:0;margin-left:4px;margin-right:4px;border:1px solid #000;border-radius:10px;background-color:transparent}.carousel-indicators li.white{background-color:#fff}.carousel-indicators li.white.active{border:1px solid #fff;border-radius:10px;background-color:transparent}.carousel-caption-imgs h6{font-family:'Georgia',serif;color:#000;font-weight:400;font-size:14px;line-height:28px;padding-top:28px;padding-bottom:0;text-align:center}.carousel-caption-imgs p{font-family:'Georgia',serif;color:#000;font-size:14px;line-height:28px;padding-top:14px;padding-bottom:14px;text-align:center}.carousel-title{font-family:'Open Sans',sans-serif;color:#000;font-size:18px;line-height:28px;padding-top:36px;padding-bottom:14px;text-align:center}.carousel-descr{font-family:'Georgia',serif;color:#000;font-size:14px;line-height:28px;padding-top:14px;padding-bottom:14px;text-align:center}@media screen and (min-width:768px){.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}@media screen and (max-width:960px){.carousel-control .carousel-control-left{left:10%}.carousel-control .carousel-control-left-white{left:10%}.carousel-control .carousel-control-right{right:10%}.carousel-control .carousel-control-right-white{right:10%}}.t-tildalabel{background-color:#000;color:#fff;width:100%;height:70px;font-family:Arial;font-size:14px}.t-tildalabel:hover .t-tildalabel__wrapper{opacity:1}.t-tildalabel_white{background-color:#fff;color:#000}.t-tildalabel_gray{background-color:#eee;color:#000}.t-tildalabel__wrapper{display:table;height:30px;width:270px;margin:0 auto;padding-top:20px;opacity:.4}.t-tildalabel__txtleft{display:table-cell;width:120px;height:30px;vertical-align:middle;text-align:right;padding-right:12px;font-weight:300;font-size:12px}.t-tildalabel__wrapimg{display:table-cell;width:30px;height:30px;vertical-align:middle}.t-tildalabel__img{width:30px;height:30px;vertical-align:middle}.t-tildalabel__txtright{display:table-cell;width:120px;height:30px;vertical-align:middle;padding-left:12px;font-weight:500;letter-spacing:2px}.t-tildalabel__link{color:#fff;text-decoration:none;vertical-align:middle}.t-tildalabel_white .t-tildalabel__link,.t-tildalabel_gray .t-tildalabel__link{color:#000}.t-carousel{position:relative}.t-carousel__inner{position:relative;overflow:hidden;margin:0 auto}.t-carousel__slides{position:relative}.t-carousel__inner>.t-carousel__item{position:relative;display:none;-webkit-transition:0 ease-in-out left;-moz-transition:0 ease-in-out left;-o-transition:0 ease-in-out left;transition:0 ease-in-out left}.t-carousel__inner>.t-carousel__item.t-carousel__animation_fast{-webkit-transition:.3s ease-in-out left;-moz-transition:.3s ease-in-out left;-o-transition:.3s ease-in-out left;transition:.3s ease-in-out left}.t-carousel__inner>.t-carousel__item.t-carousel__animation_slow{-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.t-carousel__item__wrapper{position:relative;margin:0 auto}.t-carousel__item__img{background-size:contain;background-repeat:no-repeat;background-position:center;position:absolute;top:0;right:0;bottom:0;left:0}.t-carousel_cover .t-carousel__item__img{background-size:cover}.t-carousel__inner>.active,.t-carousel__inner>.next,.t-carousel__inner>.prev{display:block}.t-carousel__inner>.active{left:0}.t-carousel__inner>.next,.t-carousel__inner>.prev{position:absolute;top:0;width:100%}.t-carousel__inner>.next{left:100%}.t-carousel__inner>.prev{left:-100%}.t-carousel__inner>.next.left,.t-carousel__inner>.prev.right{left:0}.t-carousel__inner>.active.left{left:-100%}.t-carousel__inner>.active.right{left:100%}.t-carousel__arrows__container{position:absolute;top:0;left:0;right:0;bottom:0;margin:0 auto;pointer-events:none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII=',sizingMethod='scale');background:none!important}.t-carousel__arrow_outsidesmall .t-carousel__arrow__wrapper_left{left:16px}.t-carousel__arrow_outsidesmall .t-carousel__arrow__wrapper_right{right:16px}.t-carousel__arrow_outsidemiddle .t-carousel__arrow__wrapper_left{left:20px}.t-carousel__arrow_outsidemiddle .t-carousel__arrow__wrapper_right{right:20px}.t-carousel__control{position:absolute;top:0;bottom:0;left:0;width:15%;-webkit-transition:all ease-in-out 0.3s;-moz-transition:all ease-in-out 0.3s;-o-transition:all ease-in-out 0.3s;transition:all ease-in-out 0.3s;pointer-events:auto}.t-carousel__control:hover{opacity:.6}.t-carousel__arrow{width:34px;height:34px;background:transparent;-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t-carousel__arrow.t-carousel__arrow_small{width:20px;height:20px}.t-carousel__arrow.t-carousel__arrow_large{width:54px;height:54px}.t-carousel__arrow__wrapper{-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-webkit-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);position:absolute;top:50%}.t-carousel__arrow__wrapper_left{left:30px}.t-carousel__arrow__wrapper_right{right:30px}.t-carousel__arrow_right{border-top:3px solid;border-right:3px solid}.t-carousel__arrow_right.t-carousel__arrow_light{border-top:1px solid;border-right:1px solid}.t-carousel__arrow_right.t-carousel__arrow_bold{border-top:6px solid;border-right:6px solid}.t-carousel__arrow_left{border-left:3px solid;border-bottom:3px solid}.t-carousel__arrow_left.t-carousel__arrow_light{border-left:1px solid;border-bottom:1px solid}.t-carousel__arrow_left.t-carousel__arrow_bold{border-left:6px solid;border-bottom:6px solid}.t-carousel__control.right{right:0;left:auto}@media screen and (max-width:768px){.t-carousel__control .t-carousel__arrow{width:12px;height:12px}.t-carousel-control{width:10%}.t-carousel__arrow__left{left:15px}.t-carousel__arrow__right{right:15px}}.t-carousel__indicators.carousel-indicators{z-index:15;text-align:center;list-style:none;position:relative;padding-left:0!important;margin:0 auto;padding:20px 0;bottom:auto;left:auto}.t-carousel__indicators.t-carousel__indicators_light{padding:15px 0 18px}.t-carousel__indicators.t-carousel__indicators_bold{padding:24px 0 21px}.t-carousel__indicators .t-carousel__indicator{display:inline-block;width:8px;height:8px;margin:0 6px;text-indent:-999px;cursor:pointer;background-color:#222;border:none;border-radius:10px;opacity:.4;-webkit-transition:.2s ease-in-out opacity;-moz-transition:.2s ease-in-out opacity;-o-transition:.2s ease-in-out opacity;transition:.2s ease-in-out opacity}@media screen and (max-width:640px){.t-carousel__indicators.carousel-indicators,.t-carousel__indicators.t-carousel__indicators_light,.t-carousel__indicators.t-carousel__indicators_bold{padding:15px 0}}.t-carousel__indicators.t-carousel__indicators_light .t-carousel__indicator{width:4px;height:4px;margin:0 5px}.t-carousel__indicators.t-carousel__indicators_bold .t-carousel__indicator{width:10px;height:10px;margin:0 6px}.t-carousel__indicators .t-carousel__indicator:hover{opacity:.8}.t-carousel__indicators .t-carousel__indicator.active{opacity:1}.t-carousel__indicators.t-carousel__indicators_inside{position:absolute;bottom:0;left:0;right:0}.t-carousel__caption-inside{display:none}.t-carousel__caption_wrapper{border-top:1px solid #eee;padding:14px 0}.t-carousel__descr{margin-top:5px;color:#777}.t-mbfix{opacity:.01;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0);position:fixed;width:100%;height:500px;background-color:white;top:0;left:0;z-index:10000;-webkit-transition:all 0.1s ease;transition:all 0.1s ease}.t-mbfix_hide{-webkit-transform:translateX(3000px);-ms-transform:translateX(3000px);transform:translateX(3000px)}.r_anim{-webkit-transition:opacity 0.5s;transition:opacity 0.5s}.r_hidden{opacity:0}.r_showed{opacity:1}@media screen and (min-width:960px){.t-animate,.t-animate_item_wait{opacity:0}}.t-item.t-animate{animation-duration:0.5s!important}@-webkit-keyframes t-animate_fadein{0%{opacity:0}100%{opacity:1}}@keyframes t-animate_fadein{0%{opacity:0}100%{opacity:1}}.t-animate_played .t-animate_fadein:not(.t-animate_item_wait){-webkit-animation:t-animate_fadein 1s cubic-bezier(.25,.46,.45,.94) both;animation:t-animate_fadein 1s cubic-bezier(.25,.46,.45,.94) both}@-webkit-keyframes t-animate_fadeinup{0%{opacity:0;-webkit-transform:translate3d(0,100px,0);transform:translate3d(0,100px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes t-animate_fadeinup{0%{opacity:0;-webkit-transform:translate3d(0,100px,0);transform:translate3d(0,100px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.t-animate_played .t-animate_fadeinup:not(.t-animate_item_wait){-webkit-animation:t-animate_fadeinup 1s cubic-bezier(.19,1,.22,1) both;animation:t-animate_fadeinup 1s cubic-bezier(.19,1,.22,1) both}@-webkit-keyframes t-animate_fadeindown{0%{opacity:0;-webkit-transform:translate3d(0,-100px,0);transform:translate3d(0,-100px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes t-animate_fadeindown{0%{opacity:0;-webkit-transform:translate3d(0,-100px,0);transform:translate3d(0,-100px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.t-animate_played .t-animate_fadeindown:not(.t-animate_item_wait){-webkit-animation:t-animate_fadeindown 1s cubic-bezier(.19,1,.22,1) both;animation:t-animate_fadeindown 1s cubic-bezier(.19,1,.22,1) both}@-webkit-keyframes t-animate_zoomin{0%{opacity:0;-webkit-transform:scale(.9);transform:scale(.9)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes t-animate_zoomin{0%{opacity:0;-webkit-transform:scale(.9);transform:scale(.9)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.t-animate_played .t-animate_zoomin:not(.t-animate_item_wait){-webkit-animation:t-animate_zoomin 1s cubic-bezier(.19,1,.22,1) both;animation:t-animate_zoomin 1s cubic-bezier(.19,1,.22,1) both}.t107{text-align:center}.t107__width{vertical-align:middle}.t107__widthauto{width:auto;max-width:100%;display:block;margin:0 auto}.t107__title{padding-top:28px;padding-bottom:28px;font-size:14px;line-height:28px}.t001__wrapper{padding-top:42px;padding-bottom:42px}.t001__uptitle{text-transform:uppercase;color:#fff;padding-bottom:60px;padding-top:30px}.t001__title{color:#fff;padding:24px 0 38px 0;letter-spacing:.5px}.t001__descr{color:#fff;padding:0 0 30px 0}.t001__descr_center{max-width:700px;margin:0 auto}.t001__descr_center a{color:#fff!important;font-weight:600}@media screen and (max-width:640px){.t001__title{padding-left:10px;padding-right:10px}.t001__uptitle{padding-left:10px;padding-right:10px}.t001__descr{padding-left:10px;padding-right:10px;font-size:14px;line-height:20px}}.t015__title{padding-top:8px;padding-bottom:3px}.t015__uptitle{text-transform:uppercase;padding-top:10px;padding-bottom:40px}.t015__descr{padding:41px 0 0 0}.t017__uptitle{padding-top:3px;padding-bottom:22px}.t017__title{padding-top:2px;padding-bottom:0}.t017__descr{padding-top:21px}.t021__line{width:100%;max-width:140px;margin-left:auto;margin-right:auto;height:1px;background-color:#000}.t021__text-impact{text-align:center;margin-top:44px;margin-bottom:54px}.t030__title{margin-bottom:15px}.t030__descr{margin-top:8px;padding-bottom:6px}.t032__wrapper{padding-top:42px;padding-bottom:42px}.t032__title{color:#fff;margin-bottom:50px}.t032__line{width:100%;height:1px;background-color:#fff}.t032__descr{color:#fff;margin-top:43px;padding:0 50px;margin-bottom:0}@media screen and (max-width:960px){.t032__line{max-width:160px;margin:0 auto}}@media screen and (max-width:640px){.t032 .t-cover__wrapper{display:block;width:100%}.t032__title{padding:0 10px}.t032__descr{padding:0 10px}}.t033 .t-container{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.t033__lineTop{border-top:4px solid #000;padding-left:0;width:100%;margin-top:1px}.t033__title{font-size:24px;color:#000;line-height:36px;padding-top:19px}.t033__descr{margin-top:-12px}@media screen and (max-width:960px){.t033 .t-container{display:-webkit-block;display:block}.t033__title{padding-bottom:40px}}@media screen and (max-width:640px){.t033__lineTop{width:100%}}.t037 .t-container{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.t037__title{font-family:'Open Sans',sans-serif;color:#000;font-weight:600;font-size:24px;line-height:28px;padding-right:50px;padding-top:7px;padding-bottom:7px}.t037__text{padding-top:8px;padding-bottom:6px}@media screen and (max-width:960px){.t037 .t-container{display:-webkit-block;display:block}.t037__title{padding-right:0}}@media screen and (max-width:640px){.t037__title{margin-bottom:20px;padding-right:0}}.t050__uptitle{padding-top:9px;padding-bottom:93px;text-transform:uppercase}.t050__descr{padding-top:50px;padding-bottom:9px}.t056__title{padding-top:8px;padding-bottom:9px}.t056__descr{font-size:18px;line-height:28px;letter-spacing:1px;padding-top:22px;padding-bottom:5px}.t029 .t-container{padding-top:3px;padding-bottom:5px}.t029 img{max-width:100%}.t075__wrapperleft{padding-left:0;padding-right:0}.t075__wrappercenter{padding-left:20px;padding-right:20px}.t075__img{margin-bottom:14px;width:100px;height:100px}.t075__img_circle{border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}.t075__textclass1 .t075__title{font-size:24px;line-height:30px;margin-bottom:25px;margin-top:18px}.t075__textclass1{font-size:16px;line-height:25px}.t075__textclass2 .t075__title{font-size:18px;line-height:21px;margin-bottom:25px;margin-top:12px}.t075__textclass2{font-size:13px;line-height:20px}.t075__textclass3 .t075__title{font-size:30px;line-height:40px;margin-bottom:25px;margin-top:12px}.t075__textclass3{font-size:16px;line-height:25px}@media screen and (max-width:960px){.t075__textclass1,.t075__textclass2,.t075__textclass3{margin-bottom:45px}}.t004{padding-top:8px;padding-bottom:6px}.t004__text-column-count_2{column-count:2;column-gap:40px;-moz-column-count:2;-moz-column-gap:40px;-webkit-column-count:2;-webkit-column-gap:40px}.t004__text-column-count_3{column-count:3;column-gap:40px;-moz-column-count:3;-moz-column-gap:40px;-webkit-column-count:3;-webkit-column-gap:40px}.t004__text-column-count_4{column-count:4;column-gap:40px;-moz-column-count:4;-moz-column-gap:40px;-webkit-column-count:4;-webkit-column-gap:40px}.t004__initial-letter:first-child::first-letter{font-size:100px;float:left;margin:-30px 20px -30px 0}.t004 table{border-collapse:collapse;font-size:1em;width:100%}.t004 table td,.t004 table th{padding:5px;border:1px solid #ddd;vertical-align:top}.t004 table thead td,.t004 table th{font-weight:700;border-bottom-color:#888}@media screen and (max-width:1200px){.t004__text-column-count_2,.t004__text-column-count_3,.t004__text-column-count_4{column-gap:20px;-moz-column-gap:20px;-webkit-column-gap:20px}}@media screen and (max-width:960px){.t004__text-column-count_2,.t004__text-column-count_3,.t004__text-column-count_4{column-count:1;column-gap:0;-moz-column-count:1;-moz-column-gap:0;-webkit-column-count:1;-webkit-column-gap:0}}@media screen and (max-width:640px){.t004 h1{font-size:28px;line-height:35px}}.t113{width:100%;height:50px;position:absolute;z-index:990}.t113__space{width:100%;height:50px;position:relative}.t113__fixed{position:fixed;top:0}.t113__logo{font-size:20px;margin-top:13px;margin-left:20px;padding-right:50px;float:left}.t113__img{margin-left:20px;padding-right:50px;float:left}.t113__list{list-style-type:none;padding-left:10px!important;padding-top:16px;padding-right:10px;padding-bottom:0;margin:0}.t113__list_item{clear:both;font-family:'Open Sans',sans-serif;font-size:14px;display:inline;padding-left:15px;padding-right:15px;margin:0;color:#000}.t113 a{text-decoration:none;color:#ff8562}.t113__list_item .t-active{opacity:.7}@media screen and (max-width:640px){.t113__list_item{display:block;text-align:center;padding:10px}.t113__fixed{position:relative}.t113{position:relative;height:auto;text-align:center}.t113__logo{float:inherit;text-align:center;margin:0;padding:20px}.t113__img{float:inherit;margin:0 auto;padding:20px}}.t123__centeredContainer{text-align:center}.t135__img{max-width:100%}@media screen and (max-width:640px){.t135{position:relative!important;text-align:center;padding:30px;top:0px!important;right:0px!important;left:0px!important;z-index:1!important}}@media screen and (max-width:640px){.t141{position:relative!important;text-align:center;padding:20px;top:0px!important;right:0px!important}}.t145__title{font-size:30px;line-height:34px;font-weight:700;padding-top:8px;padding-bottom:6px;margin-right:20px}.t145__line{margin-top:14px;margin-bottom:14px;border:0;border-top:3px solid #000;margin-right:20px}.t145__text{padding-top:4px;padding-bottom:6px;font-size:16px;line-height:25px;margin-right:20px}@media screen and (max-width:960px){.t145 .t145__col{margin-top:20px;margin-bottom:20px}}.t149 a{text-decoration:none;color:#ff8562}.t149__title{margin-top:20px;margin-bottom:0}.t149__subtitle{margin-top:4px;margin-bottom:0;opacity:.5}.t149__sp{margin-bottom:20px}.t149__descr{font-size:16px;line-height:24px;margin-top:40px}.t149__img{width:100%}.t149__img.t149__circle{width:70%;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%;border:1px solid rgba(0,0,0,.07)}.t149__textwrapper{display:table;width:100%}.t149__floatbeaker_lr3{display:none}@media screen and (max-width:960px){.t149__col.t-col_4,.t149__col.t-col_6{width:100%;max-width:580px;display:table;vertical-align:middle;margin:0 auto 50px;float:none}.t149__col.t-col_4:last-child,.t149__col.t-col_6:last-child{margin-bottom:0!important}.t149__col.t-col_4 .t149__img,.t149__col.t-col_6 .t149__img{display:table-cell;width:100%;vertical-align:middle}.t149__col.t-col_4 .t149__img.t149__circle,.t149__col.t-col_6 .t149__img.t149__circle{width:100%}.t149__col.t-col_4 .t149__textwrapper,.t149__col.t-col_6 .t149__textwrapper{display:table-cell;width:50%;vertical-align:middle;padding-left:30px}.t149__col.t-col_3{max-width:320px;display:inline;float:left;margin-bottom:60px}.t149__floatbeaker_lr3{display:block;width:100%;content:" ";clear:both}.t149__col.t-col_3 .t149__title{font-size:16px;line-height:24px}.t149__col.t-col_3 .t149__subtitle{font-size:14px;line-height:24px}}@media screen and (max-width:660px){.t149__col.t-col_3,.t149__col.t-col_4,.t149__col.t-col_6{max-width:480px;display:table;vertical-align:middle;margin:0 auto;margin-bottom:40px;float:none}.t149__img{display:table-cell;width:100%;vertical-align:middle}.t149__img.t149__circle{width:100%}.t149__textwrapper{display:table-cell;width:50%;vertical-align:middle}.t149__col.t-col_3 .t149__textwrapper{padding-left:30px}}@media screen and (max-width:480px){.t149__col.t-col_3,.t149__col.t-col_4,.t149__col.t-col_6{max-width:320px;width:100%;display:block;float:none}.t149__img{display:block}.t149__img.t149__circle{max-width:70%;margin:0 auto}.t149__col.t-col_3 .t149__textwrapper,.t149__col.t-col_4 .t149__textwrapper,.t149__col.t-col_6 .t149__textwrapper,.t149__textwrapper{display:block;width:100%;margin-bottom:30px;padding-left:0}}.t160{text-align:center;padding-bottom:20px}.t160__img{border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%;width:150px;max-width:150px;height:150px;padding-top:17px;padding-bottom:14px}.t160__title{text-align:center;padding-top:8px;padding-bottom:5px}.t160__descr{text-align:center;padding-top:0;padding-bottom:6px;letter-spacing:2px}.t160__text{padding-top:30px;padding-bottom:30px;font-size:22px;line-height:1.55}@media screen and (max-width:960px){.t160__wrapper{padding:0 20px}}@media screen and (max-width:640px){.t160__text{font-size:18px;line-height:1.45}}@media screen and (max-width:480px){.t160__text{font-size:16px;padding-left:10px;padding-right:10px}}.t161 .t-col_2{max-width:100px}.t161 .t-col_6,.t161 .t-col_8,.t161 .t-col_10{width:auto}.t161__img{width:80px;height:80px;border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%;margin-top:9px}.t161 .t161__wrapper{display:table;height:80px}.t161__textwrapper{display:table-cell;vertical-align:middle}.t161__descr{padding-bottom:20px}.t161__text{padding-bottom:22px}@media screen and (max-width:960px){.t161 .t-col_6{max-width:62%}.t161 .t161__blockimgthumb{width:100%;max-width:100%;text-align:center;padding-bottom:20px}.t161 .t161__wrapper{margin:0 20px}}.t162 h2{padding-top:4px;padding-bottom:14px;font-family:'Open Sans',sans-serif;font-size:22px;color:#000;font-weight:600;line-height:34px;cursor:pointer}.t162__subtitle{font-style:italic;font-family:'Georgia',serif;font-size:14px;color:#000;line-height:28px;font-weight:400;margin-top:-12px;padding-bottom:12px;cursor:pointer}.t162__text{font-family:'Georgia',serif;color:#000;font-size:18px;line-height:1.55;padding-bottom:56px;padding-top:28px}.t165 .t-container{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.t165__vmiddle{margin-top:auto;margin-bottom:auto}.t165__vtop{margin-bottom:auto}.t165__vbottom{margin-top:auto}.t165__left{text-align:left}.t165__center{text-align:center}.t165__right{text-align:right}.t165__textwrapper{padding-right:20px}.t165__uptitle{padding:0;margin:0;margin-bottom:14px}.t165__title{padding:0;margin:0;padding-bottom:28px}.t165__text{filter:alpha(opacity=85);KHTMLOpacity:.85;MozOpacity:.85;opacity:.85}.t165__img{float:right;width:100%}.t165__img_circle{border-radius:50%;-moz-border-radius:50%;-webkit-border-radius:50%}@media screen and (max-width:640px){.t165 .t-container{display:-webkit-block;display:block}.t165__img{float:none}.t165__col-top{margin-bottom:30px}}.t166 .t-container{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.t166__textsmall{padding-top:11px;padding-bottom:7px}.t166__text{padding-top:8px;padding-bottom:6px}@media screen and (max-width:960px){.t166 .t-container{display:-webkit-block;display:block}}.t169__text{font-size:60px;line-height:90px;margin:0 100px}@media screen and (max-width:640px){.t169__text{font-size:28px;line-height:36px;margin:0 20px}}.t173__ul{text-align:center;list-style-type:none;padding-left:10px!important;padding-top:16px;padding-right:10px;padding-bottom:0;margin:0}.t173__li{clear:both;font-family:'Open Sans',sans-serif;color:#000;font-size:14px;display:inline;padding-left:15px;padding-right:15px;margin:0;font-weight:600}.t173 a{text-decoration:none}.t173__copyright{text-align:center;font-family:'Open Sans',sans-serif;font-size:14px;color:#000;filter:alpha(opacity=70);KHTMLOpacity:.7;MozOpacity:.7;opacity:.7;padding-top:40px;padding-bottom:10px}@media screen and (max-width:640px){.t173 li{display:block;margin:20px auto}}.t142__submit-overflowed{line-height:1.1!important}.t142__text{display:table-cell;vertical-align:middle;height:50px}.t142__wrapone{position:relative;right:50%;float:right}.t142__wraptwo{position:relative;z-index:1;right:-50%}.t142__submit{font-family:'Open Sans',sans-serif;text-align:center;height:50px;line-height:50px;border:0 none;font-size:16px;padding-left:60px;padding-right:60px;-webkit-appearance:none;font-weight:700;background:none;cursor:pointer;box-sizing:content-box}.t142__submit_size_sm{height:40px;line-height:40px;font-size:14px;padding-left:30px;padding-right:30px}.t142__submit_size_lg{height:60px;line-height:60px;font-size:22px;padding-left:70px;padding-right:70px}.t142__submit_size_xl{height:80px;line-height:80px;font-size:26px;padding-left:80px;padding-right:80px}.t142__submit_size_xxl{height:100px;line-height:100px;font-size:30px;padding-left:90px;padding-right:90px}@media screen and (max-width:640px){.t142__submit{white-space:normal;padding-left:30px;padding-right:30px;margin-left:20px;margin-right:20px;-webkit-border-radius:0}.t142__submit_size_lg,.t142__submit_size_xl,.t142__submit_size_xxl{height:60px;line-height:60px;font-size:18px;padding-left:40px;padding-right:40px}.t142__submit_size_lg .t142__text,.t142__submit_size_xl .t142__text,.t142__submit_size_xxl .t142__text{height:60px}}.t181{text-align:left}.t181__wrapper{padding-top:42px;padding-bottom:42px}.t181__title{color:#fff;padding:24px 0 38px 0;letter-spacing:1px}.t181__descr{color:#fff;padding:0 0 30px 0}.t181 .t-btn:nth-child(2){margin-left:10px}@media screen and (max-width:640px){.t181 .t-btn:nth-child(2){margin-left:0}.t181 .t-btn{margin:5px;margin-left:0}}.t182{text-align:center}.t182__wrapper{padding-top:42px;padding-bottom:42px}.t182__title{color:#fff;padding:24px 0 24px 0;letter-spacing:1px}.t182__descr{color:#fff;padding:15px 0 30px 0}.t182__buttons{margin-top:45px}.t182 .t-btn:nth-child(2){margin-left:10px}@media screen and (max-width:640px){.t182__title{font-size:30px;line-height:30px;padding-left:10px;padding-right:10px}.t182__descr{padding-left:10px;padding-right:10px;font-size:14px;line-height:20px}.t182 .t-btn{margin:7px 3px}}.t183__wrapper{padding-top:42px;padding-bottom:42px}.t183__uptitle{color:#fff;padding-bottom:20px;padding-top:10px}.t183__title{color:#fff;padding:24px 0 24px 0;letter-spacing:1px}.t183__buttons{margin-top:45px}.t183 .t-btn:nth-child(2){margin-left:10px}@media screen and (max-width:640px){.t183__title{padding-left:10px;padding-right:10px}.t183__uptitle{padding-left:10px;padding-right:10px}.t183 .t-btn:nth-child(2){margin-left:5px}.t183 .t-btn{margin:5px}}.t186__wrapper{display:table}.t186__blockinput{display:table-cell;vertical-align:middle;height:100%;width:100%;padding-right:20px}.t186__input{background-color:transparent;-webkit-appearance:none;border-radius:0}.t186__blockbutton{display:table-cell;vertical-align:middle;height:100%}.t186__form-bottom-text{margin-top:30px;text-align:center}@media screen and (max-width:640px){.t186__wrapper{display:block}.t186__blockinput{display:block;width:100%;padding-bottom:10px}.t186__blockbutton{display:block;width:100%;padding-bottom:20px}.t186 .t-submit{width:100%}}.t186__blockinput-errors{background:#f66 none repeat scroll 0 0}.js-error-control-box .t186__input{font-family:'Georgia',serif;border:1px solid red!important}.t186__blockinput-errors-text{font-family:'Georgia',serif;color:#ff7;box-sizing:border-box;padding:0 10px 10px 10px}.t186__blockinput-errors-item{font-family:'Georgia',serif;padding-top:10px;display:none}.t186__blockinput-errorbox{font-family:'Georgia',serif;background:#f66 none repeat scroll 0 0;color:#ff7;padding:10px;text-align:center;margin-bottom:20px}.t186__blockinput-success{text-align:center;background:#FFF;color:#222;padding:20px;font-family:'Georgia',serif;border:2px solid #2D2;margin-bottom:20px}.t186A__wrapper{display:table}.t186A__blockinput{display:table-cell;vertical-align:middle;height:100%;width:50%;padding-right:20px}.t186A__blockbutton{display:table-cell;vertical-align:middle;height:100%}.t186A__form-bottom-text{margin-top:30px;text-align:center}@media screen and (max-width:640px){.t186A__wrapper{display:block}.t186A__blockinput{display:block;width:100%;padding-bottom:10px}.t186A__blockbutton{display:block;width:100%;padding-bottom:20px}.t186A .t-submit{width:100%}}.t186A__blockinput-errors{background:#f66 none repeat scroll 0 0}.js-error-control-box .t186A__input{font-family:'Georgia',serif;border:1px solid red!important}.t186A__blockinput-errors-text{color:#ff7;font-family:'Georgia',serif;box-sizing:border-box;padding:0 10px 10px 10px}.t186A__blockinput-errors-item{font-family:'Georgia',serif;padding-top:10px;display:none}.t186A__blockinput-errorbox{font-family:'Georgia',serif;background:#f66 none repeat scroll 0 0;color:#ff7;padding:10px;text-align:center;margin-bottom:20px}.t186A__blockinput-success{text-align:center;background:#FFF;color:#222;padding:20px;font-family:'Georgia',serif;border:2px solid #2D2;margin-bottom:20px}.t188__wrapone{position:relative;right:50%;float:right}.t188__wraptwo{position:relative;z-index:1;right:-50%}.t188__sociallinkimg{display:inline-block;padding-left:5px;padding-right:5px}.t188__imgwrapper{background-size:contain;background-repeat:no-repeat;background-position:center}.t203__wrapper{display:table;padding-top:60px;padding-bottom:60px;margin-left:-60px;margin-right:-60px}.t203__textwrapper{display:block;text-align:left;background-color:#fff;padding-left:60px;padding-right:60px;padding-top:60px;padding-bottom:60px}.t203__title{padding-top:20px;padding-bottom:20px}.t203__text{padding-bottom:20px;padding-top:20px}@media screen and (max-width:720px){.t203__wrapper{padding-top:0;padding-bottom:0;margin-left:0;margin-right:0}.t203__textwrapper{margin:20px 0;padding:20px}}.t204__burger{position:fixed;z-index:5000000;width:60px;height:60px;top:30px;right:30px;background-color:#000;cursor:pointer}.t204__burger-icon{position:relative;display:inline-block;margin:28px 12px;width:36px;height:3px;background:#fff;vertical-align:middle}.t204__burger-icon:before,.t204__burger-icon:after{position:absolute;left:0;width:100%;height:3px;background:#fff;content:''}.t204__burger-icon:before{top:-9px}.t204__burger-icon:after{bottom:-9px}.t204__menu{box-sizing:border-box;background-color:#000;color:#fff;position:fixed;z-index:5000002;width:380px;height:100vh;top:0;right:0;overflow-y:auto;overflow-x:hidden;visibility:hidden}.t204__closelayer{background-color:#000;position:fixed;top:0;left:0;z-index:5000001;width:100%;height:100vh;filter:alpha(opacity=50);KHTMLOpacity:.5;MozOpacity:.5;opacity:.5;visibility:hidden}.t204__item{display:table;margin:40px auto;width:300px}.t204__item:hover .t204__item_img{opacity:.7}.t204__item:hover .t204__item_text a{color:#ff8562!important}.t204__item_img{display:table-cell;width:85px;height:85px;padding-right:20px}.t204__item_img a{border:solid #222 1px;margin:0;display:block;width:85px;height:85px;background-size:cover}.t204__item_text{display:table-cell;width:100%;vertical-align:middle;color:#fff;font-size:18px}.t204__item_text a{color:#fff!important}@media screen and (max-width:640px){.t204__burger{position:static;text-align:right;top:0;right:0;width:100%}.t204__menu{width:100%;height:auto;position:absolute;top:60px}}.t216__wrapper{padding-top:42px;padding-bottom:42px;position:relative;z-index:1}.t216__blocklogo{padding-bottom:30px;padding-top:30px}.t216__logo{width:auto;max-width:100%;vertical-align:middle}.t216__title{color:#fff;padding:24px 0 38px 0;letter-spacing:.5px}.t216__descr{color:#fff;padding:0 0 30px 0}.t216__descr_center{max-width:700px;margin:0 auto}.t216__descr_center a{color:#fff!important;font-weight:600}@media screen and (max-width:640px){.t216__title{padding-left:10px;padding-right:10px;box-sizing:border-box}.t216__descr{padding-left:10px;padding-right:10px;font-size:14px;line-height:20px;box-sizing:border-box}}.t219{text-align:center;padding:0 2px}.t219__butwrapper{margin:0 auto}.t219__blocktitle{padding-bottom:50px}@media screen and (max-width:640px){.t219{padding:0 20px}}.t264__wrapper{padding:20px;background:#f8f8f8}.t264__title{margin-bottom:19px;border-bottom:1px solid #eee;padding-bottom:8px}.t264__descr{color:#888;margin-bottom:20px}@media screen and (max-width:500px){.t264__title{margin-bottom:10px}.t264__descr{margin-bottom:11px}}.t269__mainblock{margin:0 auto}.t269__uptitle{color:#fff;position:absolute;top:80px;left:0;right:0}.t269__uptitle_mobile{display:none}.t269__title{color:#fff;margin-bottom:24px;padding-top:20px}.t269__descr{color:#fff;margin-bottom:44px}.t269__input-container{max-width:600px;margin:0 auto}.t269__blockinput{display:table-cell;vertical-align:middle;height:100%;width:100%;padding-right:20px}.t269__input{height:56px;outline:none}.t269__submit{height:56px;padding-left:40px;padding-right:40px}.t269__blockinput input{background-color:transparent;-webkit-appearance:none;border-radius:0}.t269__wrapper{display:table;-webkit-transition:all ease-in-out 0.2s;-moz-transition:all ease-in-out 0.2s;-o-transition:all ease-in-out 0.2s;transition:all ease-in-out 0.2s}.t269__blockinput.js-error-control-box .t269__input{border:1px solid red!important}.t269__blockinput-errors-text{color:#ff7;box-sizing:border-box;padding:0 10px 10px 10px;font-family:'Georgia',serif}.t269__blockinput-errors-item{padding-top:10px;display:none;font-family:'Georgia',serif}.t269__blockinput-errorbox{background:#f66 none repeat scroll 0 0;color:#ff7;padding:1px 10px;text-align:center;margin-bottom:20px;font-family:'Georgia',serif;margin-top:20px}.t269__hint{color:#fff;margin-top:20px;max-width:600px;margin:20px auto 0}.t269__blockinput-success{text-align:center;color:#fff;padding:20px;font-family:'Georgia',serif}.t269__success-message{color:#fff}.t269 .js-send-form-success .t269__wrapper{display:none}@media screen and (max-width:680px){.t269__blockinput{display:block;padding-right:0;width:100%}.t269__descr{margin-bottom:32px}.t269__uptitle_desktop{display:none}.t269__uptitle_mobile{display:block}.t269__uptitle{position:initial;top:40px;font-size:16px!important}.t269__mainwrapper{padding:0 20px}.t269__input-container{max-width:320px}.t269__input{width:100%;margin-bottom:18px;height:42px;font-size:14px;padding-left:14px}.t269__submit{width:100%;height:42px;font-size:14px}.t269__wrapper{display:block}}.t282_opened{height:100vh;min-height:100vh;overflow:hidden}.t282__container{width:100%;z-index:99999;position:fixed;top:0;right:0;left:0}.t282__beforeready{visibility:hidden}.t282_opened .t282__container{position:fixed!important;top:0!important;right:0!important;left:0!important}.t282__container.t282__positionfixed{position:fixed;top:0;right:0;left:0}.t282__container.t282__positionstatic{position:relative;top:auto;right:auto;left:auto}.t282__container.t282__positionabsolute{position:absolute}.t282__col-12{max-width:1160px}.t282__container__bg,.t282__container__bg_opened{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;-webkit-transition:all ease-in-out .1s;-moz-transition:all ease-in-out .1s;-o-transition:all ease-in-out .1s;transition:all ease-in-out .1s}.t282__container__bg_opened{opacity:0;background:#fff}.t282_opened .t282__container__bg_opened{opacity:1}.t282_opened .t282__container__bg{opacity:0!important}.t282__menu__content{position:relative;margin:0 auto;padding:0 40px}.t282__logo__container{display:table;height:100px}.t282__logo__content{display:table-cell;vertical-align:middle}.t282__logo{position:relative;z-index:1;display:block;-webkit-transition:all ease-in-out .2s;-moz-transition:all ease-in-out .2s;-o-transition:all ease-in-out .2s;transition:all ease-in-out .2s}.t282__logo:hover{opacity:.8}.t282__logo__img{display:block;height:100%}.t282__burger{position:absolute;width:28px;height:20px;top:50%;margin-top:-10px;right:40px;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.5s ease-in-out;-moz-transition:.5s ease-in-out;-o-transition:.5s ease-in-out;transition:.5s ease-in-out;cursor:pointer;z-index:999}.t282__big .t282__burger{width:42px;height:32px;margin-top:-16px}.t282__small .t282__burger{width:22px;height:14px;margin-top:-7px}.t282__burger span{display:block;position:absolute;width:100%;opacity:1;left:0;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.3s ease-in-out;-moz-transition:.3s ease-in-out;-o-transition:.3s ease-in-out;transition:.3s ease-in-out;height:3px;background-color:#000}.t282__big .t282__burger span{height:5px}.t282__small .t282__burger span{height:2px}.t282__burger span:nth-child(1){top:0}.t282__burger span:nth-child(2),.t282__burger span:nth-child(3){top:8px}.t282__big .t282__burger span:nth-child(2),.t282__big .t282__burger span:nth-child(3){top:13px}.t282__small .t282__burger span:nth-child(2),.t282__small .t282__burger span:nth-child(3){top:6px}.t282__burger span:nth-child(4){top:16px}.t282__big .t282__burger span:nth-child(4){top:26px}.t282__small .t282__burger span:nth-child(4){top:12px}.t282_opened .t282__burger span:nth-child(1){top:8px;width:0%;left:50%}.t282_opened .t282__small .t282__burger span:nth-child(1){top:6px}.t282_opened .t282__big .t282__burger span:nth-child(1){top:6px}.t282_opened .t282__burger span:nth-child(2){-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t282_opened .t282__burger span:nth-child(3){-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.t282_opened .t282__burger span:nth-child(4){top:8px;width:0%;left:50%}.t282_opened .t282__big .t282__burger span:nth-child(4){top:18px}.t282_opened .t282__small .t282__burger span:nth-child(4){top:6px}.t282__menu__content{z-index:15}.t282__menu__container{position:fixed;right:0;left:0;-webkit-transition:.5s cubic-bezier(0,1,.5,1);-moz-transition:.5s cubic-bezier(0,1,.5,1);-o-transition:.5s cubic-bezier(0,1,.5,1);transition:.5s cubic-bezier(0,1,.5,1);-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0);z-index:2;z-index:9999}.t282__menu__container.t282__closed{top:0!important}.t282__menu_static .t282__menu__container{bottom:0;overflow:scroll}.t282__menu__container.t282__closed{-webkit-transform:translateY(-200%);-moz-transform:translateY(-100%);-o-transform:translateY(-100%);transform:translateY(-100%)}.t282__menu__wrapper{text-align:center;background:#fff;width:100%}.t282__overlay{position:fixed;top:0;left:0;right:0;bottom:0;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out;cursor:pointer;z-index:999;background:black;opacity:.6}.t282__overlay.t282__closed{opacity:0;z-index:-1}.t282__menu__item{display:block;margin-bottom:20px;color:#222}.t282__menu__item:last-child{margin-bottom:0}.t282__menu__item.t-active{opacity:.7}.t282__menu{padding:30px 20px 30px}.t282__menu__items{padding:5px 0 55px}.t282__descr{max-width:540px;margin:0 auto}.t282__share{margin-top:22px}.t282 .t-sociallinks__item,.t282__social__item{display:inline-block;margin:0 3px}.t282 .t-sociallinks__wrapper,.t282__social__wrapper{margin-top:22px}.t282__lang{margin-top:20px}@media screen and (max-width:1200px){.t282__menu__content{padding:0 20px}.t282__burger{right:20px}}@media screen and (max-width:660px){.t282__burger{right:20px}.t282__menu__content{padding:0 20px}}.t282 .ya-share2__container_size_m .ya-share2__icon{width:28px;height:28px}.t282 .ya-share2__container_size_m .ya-share2__counter{line-height:28px}.t282__black-white .ya-share2__badge{background-color:#111!important}.t282__transp-white .ya-share2__badge{background-color:transparent!important}.t282__transp-white .ya-share2__container_size_m .ya-share2__counter:before{display:none}.t282__transp-white .ya-share2__container_size_m .ya-share2__counter{padding-left:0!important;margin-top:2px}.t282__white-black .ya-share2__badge{background-color:#fff!important}.t282__white-black .ya-share2__container_size_m .ya-share2__item_service_facebook .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE1LjEgMjN2LTguMjFoMi43NzNsLjQxNS0zLjJIMTUuMVY5LjU0N2MwLS45MjcuMjYtMS41NTggMS41OTYtMS41NThsMS43MDQtLjAwMlY1LjEyNkEyMi43ODcgMjIuNzg3IDAgMCAwIDE1LjkxNyA1QzEzLjQ2IDUgMTEuNzggNi40OTIgMTEuNzggOS4yM3YyLjM2SDl2My4yaDIuNzhWMjNoMy4zMnoiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.t282__white-black .ya-share2__container_size_m .ya-share2__counter{color:#222}.t282__white-black .ya-share2__counter:before{background-color:#222}.t282__white-black .ya-share2__container_size_m .ya-share2__item_service_vkontakte .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0Ljg4MyAxOS4zOTZzLjMyNS0uMDM2LjQ5LS4yMThjLjE1NC0uMTY3LjE1LS40OC4xNS0uNDhzLS4wMjMtMS40NjguNjQ4LTEuNjg0Yy42Ni0uMjEzIDEuNTEgMS40MTggMi40MDggMi4wNDYuNjguNDc0IDEuMTk3LjM3IDEuMTk3LjM3bDIuNDA0LS4wMzRzMS4yNTYtLjA4LjY2LTEuMDg0Yy0uMDUtLjA4Mi0uMzQ4LS43NDMtMS43ODgtMi4xMDItMS41MDctMS40MjMtMS4zMDUtMS4xOTIuNTEtMy42NTMgMS4xMDYtMS40OTggMS41NDgtMi40MTIgMS40MS0yLjgwNC0uMTMyLS4zNzMtLjk0NS0uMjc1LS45NDUtLjI3NWwtMi43MDYuMDE3cy0uMi0uMDI4LS4zNS4wNjNjLS4xNDQuMDg4LS4yMzguMjk1LS4yMzguMjk1cy0uNDI4IDEuMTYtMSAyLjE0NmMtMS4yMDQgMi4wOC0xLjY4NiAyLjE5LTEuODgzIDIuMDYtLjQ2LS4zLS4zNDUtMS4yMS0uMzQ1LTEuODU1IDAtMi4wMTcuMy0yLjg1Ny0uNTg2LTMuMDc1LS4yOTUtLjA3Mi0uNTEyLS4xMi0xLjI2NC0uMTI4LS45NjYtLjAxLTEuNzgzLjAwMy0yLjI0Ni4yMzQtLjMwOC4xNTMtLjU0Ni40OTUtLjQuNTE0LjE3OC4wMjUuNTgzLjExLjc5OC40MS4yNzcuMzgyLjI2OCAxLjI0NC4yNjggMS4yNDRzLjE2IDIuMzczLS4zNzMgMi42NjhjLS4zNjUuMjAyLS44NjUtLjIxLTEuOTQtMi4wOTgtLjU1LS45NjctLjk2Ni0yLjAzNi0uOTY2LTIuMDM2cy0uMDgtLjItLjIyMy0uMzA2Yy0uMTczLS4xMy0uNDE2LS4xNy0uNDE2LS4xN2wtMi41Ny4wMTZzLS4zODguMDEtLjUzLjE4MmMtLjEyNS4xNTItLjAxLjQ2Ni0uMDEuNDY2czIuMDE0IDQuNzkgNC4yOTQgNy4yMDJjMi4wOSAyLjIxNCA0LjQ2NSAyLjA2OCA0LjQ2NSAyLjA2OGgxLjA3NnoiICBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.t282__white-black .ya-share2__container_size_m .ya-share2__item_service_twitter .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIzIDguNzNhNy4zOCA3LjM4IDAgMCAxLTIuMTIuNTgzIDMuNzA2IDMuNzA2IDAgMCAwIDEuNjIzLTIuMDQzIDcuMzk3IDcuMzk3IDAgMCAxLTIuMzQ2Ljg5NiAzLjY5MyAzLjY5MyAwIDAgMC02LjI5MyAzLjM2OCAxMC40ODUgMTAuNDg1IDAgMCAxLTcuNjEtMy44NThjLS4zMi41NDUtLjUgMS4xOC0uNSAxLjg1NiAwIDEuMjguNjUgMi40MSAxLjY0MiAzLjA3M2EzLjY4MyAzLjY4MyAwIDAgMS0xLjY3My0uNDYydi4wNDdjMCAxLjc4OCAxLjI3MyAzLjI4IDIuOTYyIDMuNjJhMy43MTggMy43MTggMCAwIDEtMS42NjcuMDYzIDMuNjk3IDMuNjk3IDAgMCAwIDMuNDUgMi41NjRBNy40MSA3LjQxIDAgMCAxIDUgMTkuOTY3YTEwLjQ1MyAxMC40NTMgMCAwIDAgNS42NiAxLjY1OGM2Ljc5NCAwIDEwLjUwOC01LjYyNiAxMC41MDgtMTAuNTA1IDAtLjE2LS4wMDMtLjMyLS4wMS0uNDc4QTcuNTA3IDcuNTA3IDAgMCAwIDIzIDguNzMyeiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.t282__white-black .ya-share2__container_size_m .ya-share2__item_service_odnoklassniki .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIxNTBweCIgaGVpZ2h0PSIxNTBweCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE1MCAxNTAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjx0aXRsZT5TaGFwZTwvdGl0bGU+PGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+PGcgaWQ9IldlbGNvbWUiPjxwYXRoIGlkPSJTaGFwZSIgZmlsbD0iIzIyMjIyMiIgZD0iTTc0Ljk5Nyw0Ni4wMTFjLTQuOTAzLDAuMDA2LTguODc1LDMuOTc5LTguODgzLDguODgzYzAsNC44OTQsMy45ODUsOC44NzksOC44ODMsOC44NzljNC45MDMtMC4wMDgsOC44NzUtMy45NzksOC44OC04Ljg3OUM4My44NzksNDkuOTg5LDc5LjksNDYuMDE3LDc0Ljk5Nyw0Ni4wMTFMNzQuOTk3LDQ2LjAxMXogTTc0Ljk5Nyw3Ni4zMzhjLTExLjgzOC0wLjAxLTIxLjQzNy05LjYwNi0yMS40NDgtMjEuNDQ0YzAuMDA4LTExLjg0Niw5LjYwNC0yMS40NDIsMjEuNDQ4LTIxLjQ1NWMxMS44NDUsMC4wMSwyMS40NTEsOS42MDksMjEuNDU2LDIxLjQ1NUM5Ni40MzgsNjYuNzM0LDg2LjgzOCw3Ni4zMyw3NC45OTcsNzYuMzM4TDc0Ljk5Nyw3Ni4zMzh6IE02Ni4zMiw5My44MzZjLTQuNDEyLTEuMDAyLTguNjI0LTIuNzQ4LTEyLjQ1NS01LjE1NGMtMi45MzktMS44NS0zLjgyMy01LjczNC0xLjk3My04LjY2OGMxLjg0OC0yLjk0MSw1LjcyOC0zLjgyMiw4LjY2Ni0xLjk3NWM4LjgzNCw1LjUyMywyMC4wNTIsNS41MjMsMjguODg2LDBjMS45MDEtMS4xOTUsNC4yOTctMS4yODcsNi4yODQtMC4yNDJjMS45ODQsMS4wNDksMy4yNiwzLjA3OCwzLjM0Miw1LjMyNGMwLjA4NywyLjI0LTEuMDI3LDQuMzYzLTIuOTMsNS41NjFjLTMuODM0LDIuNDA2LTguMDQ5LDQuMTQ4LTEyLjQ1Nyw1LjE1NGwxMS45OTQsMTJjMi40NTEsMi40NTcsMi40NDYsNi40MzYtMC4wMTEsOC44OTNjLTIuNDU2LDIuNDQ1LTYuNDM0LDIuNDQ1LTguODg2LTAuMDEybC0xMS43NzktMTEuNzg5bC0xMS43ODUsMTEuNzg5Yy0yLjQ1NSwyLjQ1Ny02LjQzNiwyLjQ1Ny04Ljg4OSwwYy0yLjQ1NC0yLjQ1NS0yLjQ1NC02LjQzNCwwLTguODkxTDY2LjMyLDkzLjgzNkw2Ni4zMiw5My44MzZ6Ii8+PC9nPjwvc3ZnPg==);background-size:28px 28px}.t282__transp-black .ya-share2__badge{background-color:transparent!important}.t282__transp-black .ya-share2__container_size_m .ya-share2__item_service_facebook .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE1LjEgMjN2LTguMjFoMi43NzNsLjQxNS0zLjJIMTUuMVY5LjU0N2MwLS45MjcuMjYtMS41NTggMS41OTYtMS41NThsMS43MDQtLjAwMlY1LjEyNkEyMi43ODcgMjIuNzg3IDAgMCAwIDE1LjkxNyA1QzEzLjQ2IDUgMTEuNzggNi40OTIgMTEuNzggOS4yM3YyLjM2SDl2My4yaDIuNzhWMjNoMy4zMnoiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==)}.t282__transp-black .ya-share2__container_size_m .ya-share2__counter{color:#222;padding-left:0!important;margin-top:2px}.t282__transp-black .ya-share2__counter:before{display:none}.t282__transp-black .ya-share2__container_size_m .ya-share2__item_service_vkontakte .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0Ljg4MyAxOS4zOTZzLjMyNS0uMDM2LjQ5LS4yMThjLjE1NC0uMTY3LjE1LS40OC4xNS0uNDhzLS4wMjMtMS40NjguNjQ4LTEuNjg0Yy42Ni0uMjEzIDEuNTEgMS40MTggMi40MDggMi4wNDYuNjguNDc0IDEuMTk3LjM3IDEuMTk3LjM3bDIuNDA0LS4wMzRzMS4yNTYtLjA4LjY2LTEuMDg0Yy0uMDUtLjA4Mi0uMzQ4LS43NDMtMS43ODgtMi4xMDItMS41MDctMS40MjMtMS4zMDUtMS4xOTIuNTEtMy42NTMgMS4xMDYtMS40OTggMS41NDgtMi40MTIgMS40MS0yLjgwNC0uMTMyLS4zNzMtLjk0NS0uMjc1LS45NDUtLjI3NWwtMi43MDYuMDE3cy0uMi0uMDI4LS4zNS4wNjNjLS4xNDQuMDg4LS4yMzguMjk1LS4yMzguMjk1cy0uNDI4IDEuMTYtMSAyLjE0NmMtMS4yMDQgMi4wOC0xLjY4NiAyLjE5LTEuODgzIDIuMDYtLjQ2LS4zLS4zNDUtMS4yMS0uMzQ1LTEuODU1IDAtMi4wMTcuMy0yLjg1Ny0uNTg2LTMuMDc1LS4yOTUtLjA3Mi0uNTEyLS4xMi0xLjI2NC0uMTI4LS45NjYtLjAxLTEuNzgzLjAwMy0yLjI0Ni4yMzQtLjMwOC4xNTMtLjU0Ni40OTUtLjQuNTE0LjE3OC4wMjUuNTgzLjExLjc5OC40MS4yNzcuMzgyLjI2OCAxLjI0NC4yNjggMS4yNDRzLjE2IDIuMzczLS4zNzMgMi42NjhjLS4zNjUuMjAyLS44NjUtLjIxLTEuOTQtMi4wOTgtLjU1LS45NjctLjk2Ni0yLjAzNi0uOTY2LTIuMDM2cy0uMDgtLjItLjIyMy0uMzA2Yy0uMTczLS4xMy0uNDE2LS4xNy0uNDE2LS4xN2wtMi41Ny4wMTZzLS4zODguMDEtLjUzLjE4MmMtLjEyNS4xNTItLjAxLjQ2Ni0uMDEuNDY2czIuMDE0IDQuNzkgNC4yOTQgNy4yMDJjMi4wOSAyLjIxNCA0LjQ2NSAyLjA2OCA0LjQ2NSAyLjA2OGgxLjA3NnoiICBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=)}.t282__transp-black .ya-share2__container_size_m .ya-share2__item_service_twitter .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMjIyIiB2aWV3Qm94PSIwIDAgMjggMjgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIzIDguNzNhNy4zOCA3LjM4IDAgMCAxLTIuMTIuNTgzIDMuNzA2IDMuNzA2IDAgMCAwIDEuNjIzLTIuMDQzIDcuMzk3IDcuMzk3IDAgMCAxLTIuMzQ2Ljg5NiAzLjY5MyAzLjY5MyAwIDAgMC02LjI5MyAzLjM2OCAxMC40ODUgMTAuNDg1IDAgMCAxLTcuNjEtMy44NThjLS4zMi41NDUtLjUgMS4xOC0uNSAxLjg1NiAwIDEuMjguNjUgMi40MSAxLjY0MiAzLjA3M2EzLjY4MyAzLjY4MyAwIDAgMS0xLjY3My0uNDYydi4wNDdjMCAxLjc4OCAxLjI3MyAzLjI4IDIuOTYyIDMuNjJhMy43MTggMy43MTggMCAwIDEtMS42NjcuMDYzIDMuNjk3IDMuNjk3IDAgMCAwIDMuNDUgMi41NjRBNy40MSA3LjQxIDAgMCAxIDUgMTkuOTY3YTEwLjQ1MyAxMC40NTMgMCAwIDAgNS42NiAxLjY1OGM2Ljc5NCAwIDEwLjUwOC01LjYyNiAxMC41MDgtMTAuNTA1IDAtLjE2LS4wMDMtLjMyLS4wMS0uNDc4QTcuNTA3IDcuNTA3IDAgMCAwIDIzIDguNzMyeiIgZmlsbC1ydWxlPSJldmVub2RkIi8+PC9zdmc+)}.t282__transp-black .ya-share2__container_size_m .ya-share2__item_service_odnoklassniki .ya-share2__icon{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSIxNTBweCIgaGVpZ2h0PSIxNTBweCIgdmlld0JveD0iMCAwIDE1MCAxNTAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE1MCAxNTAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjx0aXRsZT5TaGFwZTwvdGl0bGU+PGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+PGcgaWQ9IldlbGNvbWUiPjxwYXRoIGlkPSJTaGFwZSIgZmlsbD0iIzIyMjIyMiIgZD0iTTc0Ljk5Nyw0Ni4wMTFjLTQuOTAzLDAuMDA2LTguODc1LDMuOTc5LTguODgzLDguODgzYzAsNC44OTQsMy45ODUsOC44NzksOC44ODMsOC44NzljNC45MDMtMC4wMDgsOC44NzUtMy45NzksOC44OC04Ljg3OUM4My44NzksNDkuOTg5LDc5LjksNDYuMDE3LDc0Ljk5Nyw0Ni4wMTFMNzQuOTk3LDQ2LjAxMXogTTc0Ljk5Nyw3Ni4zMzhjLTExLjgzOC0wLjAxLTIxLjQzNy05LjYwNi0yMS40NDgtMjEuNDQ0YzAuMDA4LTExLjg0Niw5LjYwNC0yMS40NDIsMjEuNDQ4LTIxLjQ1NWMxMS44NDUsMC4wMSwyMS40NTEsOS42MDksMjEuNDU2LDIxLjQ1NUM5Ni40MzgsNjYuNzM0LDg2LjgzOCw3Ni4zMyw3NC45OTcsNzYuMzM4TDc0Ljk5Nyw3Ni4zMzh6IE02Ni4zMiw5My44MzZjLTQuNDEyLTEuMDAyLTguNjI0LTIuNzQ4LTEyLjQ1NS01LjE1NGMtMi45MzktMS44NS0zLjgyMy01LjczNC0xLjk3My04LjY2OGMxLjg0OC0yLjk0MSw1LjcyOC0zLjgyMiw4LjY2Ni0xLjk3NWM4LjgzNCw1LjUyMywyMC4wNTIsNS41MjMsMjguODg2LDBjMS45MDEtMS4xOTUsNC4yOTctMS4yODcsNi4yODQtMC4yNDJjMS45ODQsMS4wNDksMy4yNiwzLjA3OCwzLjM0Miw1LjMyNGMwLjA4NywyLjI0LTEuMDI3LDQuMzYzLTIuOTMsNS41NjFjLTMuODM0LDIuNDA2LTguMDQ5LDQuMTQ4LTEyLjQ1Nyw1LjE1NGwxMS45OTQsMTJjMi40NTEsMi40NTcsMi40NDYsNi40MzYtMC4wMTEsOC44OTNjLTIuNDU2LDIuNDQ1LTYuNDM0LDIuNDQ1LTguODg2LTAuMDEybC0xMS43NzktMTEuNzg5bC0xMS43ODUsMTEuNzg5Yy0yLjQ1NSwyLjQ1Ny02LjQzNiwyLjQ1Ny04Ljg4OSwwYy0yLjQ1NC0yLjQ1NS0yLjQ1NC02LjQzNCwwLTguODkxTDY2LjMyLDkzLjgzNkw2Ni4zMiw5My44MzZ6Ii8+PC9nPjwvc3ZnPg==);background-size:28px 28px}.t338__logo{margin-bottom:55px;max-width:280px;width:100%}.t338__title{color:#fff;margin-bottom:50px}.t338__descr{color:#fff;margin-bottom:63px}.t338__btn{border-radius:100px;font-size:14px;height:50px;padding-right:34px;padding-left:34px;color:#fff}.t389{overflow:hidden}.t389__maincontainer{width:100%;height:80px;display:table}.t389__content{padding:2px 40px 0;display:table-cell;vertical-align:middle}.t389__col{display:table-cell;vertical-align:middle}.t389__col_center{width:100%;padding:0 16px}.t389__list{list-style-type:none;padding-left:0!important;margin-bottom:0!important}.t389__list_item{display:inline-block;margin:0 15px}.t389__copyright,.t389__scroll{width:250px}.t389__typo{font-size:14px;color:#222}.t389__col_mobile{display:none}.t389_scrolltop{position:relative;padding-right:12px}.t389__icon{position:absolute;right:0;top:2px}@media screen and (max-width:1200px){.t389__content{padding:2px 20px 0}.t389__col,.t389__copyright,.t389__scroll{width:230px}.t389__col_center{width:100%}}@media screen and (max-width:960px){.t389__col,.t389__copyright,.t389__scroll{width:100%;display:block;text-align:center}.t389__maincontainer{display:block}.t389__content{display:block}.t389__col_mobile{display:block}.t389__col_hiddenmobile{display:none}.t389__maincontainer{height:auto!important;padding:40px 0}.t389__col{margin-bottom:20px;padding:0}.t389__list_item{margin:0 10px 4px}.t389__col:last-child{margin-bottom:0}}@media screen and (max-width:670px){.t389__typo{font-size:12px}}.t396__iframe{z-index:10000;background-color:#fff;width:100vw;height:100vh;position:fixed;top:0;left:0;border:0}.t396__body_overflow_hidden{overflow:hidden}.t396__display_none{display:none}.t396__artboard{position:relative;width:100%;height:100vh;overflow:hidden}.t396__artboard.rendering .tn-elem{visibility:hidden}.t396__artboard.rendered .tn-elem{visibility:visible}.t396__carrier{position:absolute;left:0;top:0;z-index:0;width:100%;height:100vh}.t396__filter{position:absolute;left:0;top:0;z-index:0;width:100%;height:100vh}.t396__elem{position:absolute;box-sizing:border-box;display:table}.t396 .tn-atom{display:table-cell;vertical-align:middle;width:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%}.t396 a.tn-atom{text-decoration:none}.t396 .tn-atom__img{width:100%;display:block}.t396__ui{position:absolute;top:16px;left:196px;background-color:#fa876b;color:#000!important;height:30px;line-height:30px;width:100px;z-index:1000;text-align:center;border-radius:3px;display:none;font-size:14px}.t411__mainblock{margin:0 auto;padding:0 20px;box-sizing:border-box;position:relative;z-index:2}.t411__content{padding:30px 0}.t411__hide{display:none!important}.t411__col{display:inline-block;padding-right:32px;margin-right:30px;position:relative}.t411__col:after{content:' ';position:absolute;top:0;right:0;bottom:0;opacity:.2;background:#fff;width:1px}.t411__col:last-child:after{display:none}.t411__col:last-child{margin-right:0;padding-right:0}.t411__number{color:#fff}.t411__text{color:#fff;padding-bottom:7px}.t411__logo{margin-bottom:45px;max-width:280px;width:100%}.t411__textwrapper{margin:0 auto 55px}.t411__uptitle,.t411__title,.t411__descr,.t411__descr-second{color:#fff}.t411__uptitle{margin-bottom:18px}.t411__descr{margin-top:18px}.t411__hint{color:#fff;margin-top:45px}.t411__descr-second{margin:0 auto 25px}.t411__formwrapper{max-width:600px;margin:50px auto 0}.t411__blockinput{display:table-cell;vertical-align:middle;height:100%;width:100%;padding-right:20px}.t411__input{height:56px;outline:none}.t411__submit{height:56px;padding-left:40px;padding-right:40px}.t411__blockinput input{-webkit-appearance:none;border-radius:0}.t411__wrapper{display:table;-webkit-transition:all ease-in-out 0.2s;-moz-transition:all ease-in-out 0.2s;-o-transition:all ease-in-out 0.2s;transition:all ease-in-out 0.2s}.t411__blockinput.js-error-control-box .t411__input{border:1px solid red!important}.t411__blockinput-errors-text{color:#ff7;box-sizing:border-box;padding:0 10px 10px 10px;font-family:'Georgia',serif}.t411__blockinput-errors-item{padding-top:10px;display:none;font-family:'Georgia',serif}.t411__blockinput-errorbox{background:#f66 none repeat scroll 0 0;color:#ff7;padding:1px 10px;text-align:center;margin-bottom:20px;font-family:'Georgia',serif;margin-top:20px}.t411__blockinput-success{text-align:center;color:#fff;padding:20px;font-family:'Georgia',serif}.t411__success-message{color:#fff}.t411 .js-send-form-success .t411__wrapper{display:none}@media screen and (max-width:640px){.t411__blockinput{display:block;padding-right:0;width:100%}.t411__input-container{max-width:320px;margin:0 auto}.t411__input{width:100%;margin-bottom:18px;height:42px;font-size:14px;padding-left:14px}.t411__submit{width:100%;height:42px;font-size:14px}.t411__wrapper{display:block}.t411__col{padding-right:20px;margin-right:13px}.t411__logo{margin-bottom:25px}.t411__textwrapper{margin-bottom:35px}.t411__formwrapper{margin-top:35px}.t411__hint{margin-top:35px}}@media screen and (max-width:400px){.t411__number{font-size:24px}}.t420__descr ul{padding:0!important;margin:0}.t420__descr li{display:block;margin-bottom:10px}.t420__descr li:last-child{margin-bottom:0}.t420__title{margin-bottom:14px;color:#fff}.t420__title a,.t420__descr a{color:inherit!important}.t420__floatbeaker_lr3{display:none}.t420__title_uppercase{letter-spacing:1px;text-transform:uppercase}.t420__logo{display:block;max-width:120px;width:100%}.t420 .t-sociallinks__item,.t420__right_social_links_item{display:inline-block;margin-right:4px;-webkit-transition:opacity ease-in-out 0.2s;-moz-transition:opacity ease-in-out 0.2s;-o-transition:opacity ease-in-out 0.2s;transition:opacity ease-in-out 0.2s}.t420 .t-sociallinks__item:hover,.t420__right_social_links_item:hover{opacity:.9}.t420 .t-sociallinks__item:last-child,.t420__right_social_links_item:last-child{margin-right:0}.t420 .t-sociallinks,.t420__right_social_links{margin-top:30px}.t420__text{color:#525252;margin-top:21px;font-size:12px}@media screen and (max-width:960px){.t420__col.t-col_3{max-width:320px;display:inline;float:left;margin-bottom:30px}.t420__floatbeaker_lr3{display:block;width:100%;content:" ";clear:both}}@media screen and (max-width:640px){.t420__col.t-col_3{max-width:50%;width:100%}}@media screen and (max-width:420px){.t420__col.t-col_3{max-width:100%;width:100%}}.t454__imglogo{height:auto;display:block}.t454__linewrapper{position:absolute;bottom:0;width:100%}.t454__horizontalline{margin:0;border:0;background-color:#C2C2C2;height:1px;right:0;bottom:0;margin:0 40px 0 40px}.t454__leftmenuwrapper,.t454__rightmenuwrapper{display:inline-table;height:100%;vertical-align:middle}.t454__leftmenuwrapper .t454__list,.t454__rightmenuwrapper .t454__list{display:table-cell;vertical-align:middle}.t454__logowrapper{position:absolute;left:50%;transform:translateX(-50%);display:table;height:inherit;z-index:100}.t454__logowrapper2{display:table-cell;vertical-align:middle;position:relative;z-index:100}.t454__imglogo{max-width:300px}.t454__leftwrapper,.t454__rightwrapper{width:50%;box-sizing:border-box;position:absolute;height:100%}.t454__leftwrapper{text-align:right;padding-right:200px;padding-left:40px;left:0}.t454__rightwrapper{text-align:left;padding-left:200px;padding-right:40px;right:0}@media screen and (max-width:1200px){.t454__leftwrapper{padding-left:20px}.t454__rightwrapper{padding-right:20px}}.t454{width:100%;height:80px;z-index:990;position:fixed;top:0;box-shadow:0 1px 3px rgba(0,0,0,0);-webkit-transition:background-color 300ms linear;-moz-transition:background-color 300ms linear;-o-transition:background-color 300ms linear;-ms-transition:background-color 300ms linear;transition:background-color 300ms linear}.t454__beforeready{visibility:hidden}.t454 ul{margin:0}.t454__maincontainer{width:100%;height:80px;display:table;position:relative}.t454__maincontainer.t454__c12collumns{max-width:1200px;margin:0 auto}.t454__logo{display:inline-block;font-size:24px;font-weight:400;white-space:nowrap}.t454__list{list-style-type:none;margin:0;padding:0!important}.t454__list_item{clear:both;font-family:'Open Sans',sans-serif;font-size:16px;display:inline;padding-left:15px;padding-right:15px;margin:0;color:#000;white-space:nowrap}.t454__list_item .t-active{opacity:.7}.t454__list_item:first-child{padding-left:0}.t454__list_item:last-child{padding-right:0}.t454 a,#allrecords .t454 a{text-decoration:none;color:#000}.t454.t454__positionabsolute{position:absolute}.t454.t454__positionfixed{position:fixed}.t454.t454__positionstatic{position:static}.t454__mobile{display:none}@media screen and (max-width:980px){.t454.t454__hidden{display:none;height:100%}.t454__mobile{background-color:#111;display:block}.t454__mobile_text{color:#fff}.t454__mobile_container{padding:20px;position:relative}.t454__burger{position:absolute;top:50%;margin-top:-10px;right:20px;width:28px;height:20px;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.5s ease-in-out;-moz-transition:.5s ease-in-out;-o-transition:.5s ease-in-out;transition:.5s ease-in-out;cursor:pointer;z-index:9999}.t454__burger span{display:block;position:absolute;width:100%;opacity:1;left:0;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.25s ease-in-out;-moz-transition:.25s ease-in-out;-o-transition:.25s ease-in-out;transition:.25s ease-in-out;height:3px;background-color:#fff}.t454__burger span:nth-child(1){top:0}.t454__burger span:nth-child(2),.t454__burger span:nth-child(3){top:8px}.t454__burger span:nth-child(4){top:16px}.t454_opened .t454__burger span:nth-child(1){top:8px;width:0%;left:50%}.t454_opened .t454__burger span:nth-child(2){-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t454_opened .t454__burger span:nth-child(3){-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.t454_opened .t454__burger span:nth-child(4){top:8px;width:0%;left:50%}.t454__linewrapper{display:none}.t454{position:static;text-align:center;display:block;margin:0;padding:0;height:auto!important}.t454__maincontainer{padding:20px 0 40px 0}.t454.t454__positionabsolute,.t454.t454__positionfixed,.t454.t454__positionstatic{position:static}.t454__imglogo{width:auto!important;box-sizing:border-box;padding:20px;margin:0 auto}.t454__imglogomobile.t454__imglogo{width:100%!important}.t454__rightcontainer{display:table;position:static;float:none;text-align:center;margin:0 auto}.t454__logo{text-align:center;margin:20px}.t454 img{float:inherit}.t454 .t454__list_item{display:block;text-align:center;padding:10px!important;white-space:normal}.t454__logo{white-space:normal;padding:0}.t454__logowrapper{position:static;display:table;width:100%;padding:20px;box-sizing:border-box;transform:none}.t454__logowrapper2{display:block;position:static}.t454__leftwrapper,.t454__rightwrapper,.rightmenuwrapper{position:static;padding:0!important;width:100%}.t454__rightmenuwrapper,.t454__leftmenuwrapper,.t454__leftmenuwrapper .t454__list,.t454__rightmenuwrapper .t454__list{display:block}}.t456__imglogo{height:auto;display:block}.t456__linewrapper{position:absolute;bottom:0;left:0;width:100%}.t456__horizontalline{margin:0;border:0;background-color:#C2C2C2;height:1px;right:0;bottom:0;margin:0 40px 0 40px}.t456__imglogo{max-width:300px}.t456__leftwrapper{display:table-cell;vertical-align:middle;padding-left:40px}.t456__rightwrapper{display:table-cell;vertical-align:middle;padding-right:40px;width:100%}.t456__menualign_left{text-align:left}.t456__menualign_right{text-align:right}.t456__menualign_center{text-align:center}@media screen and (max-width:1200px){.t456__leftwrapper{padding-left:20px}.t456__rightwrapper{padding-right:20px}}.t456{width:100%;height:80px;z-index:990;position:fixed;top:0;box-shadow:0 1px 3px rgba(0,0,0,0);-webkit-transition:background-color 300ms linear;-moz-transition:background-color 300ms linear;-o-transition:background-color 300ms linear;-ms-transition:background-color 300ms linear;transition:background-color 300ms linear}.t456__beforeready{visibility:hidden}.t456 ul{margin:0}.t456__maincontainer{width:100%;height:80px;display:table;position:relative}.t456__maincontainer.t456__c12collumns{max-width:1200px;margin:0 auto}.t456__logo{display:inline-block;font-size:24px;font-weight:400;white-space:nowrap;padding-right:30px}.t456__list{list-style-type:none;margin:0;padding:0!important}.t456__list_item{clear:both;font-family:'Open Sans',sans-serif;font-size:16px;display:inline;padding-left:15px;padding-right:15px;margin:0;color:#000;white-space:nowrap}.t456__list_item .t-active{opacity:.7}.t456__list_item:first-child{padding-left:0}.t456__list_item:last-child{padding-right:0}.t456 a,#allrecords .t456 a{text-decoration:none;color:#000}.t456.t456__positionabsolute{position:absolute}.t456.t456__positionfixed{position:fixed}.t456.t456__positionstatic{position:static}.t456__mobile{display:none}@media screen and (max-width:980px){.t456__linewrapper{display:none}.t456{position:static;text-align:center;display:block;margin:0;padding:0;height:auto!important}.t456.t456__positionabsolute,.t456.t456__positionfixed,.t456.t456__positionstatic{position:static}.t456__imglogo{width:auto!important;box-sizing:border-box;padding:20px;margin:0 auto}.t456__imglogomobile.t456__imglogo{width:100%!important}.t456__logo{text-align:center;margin:20px}.t456 img{float:inherit}.t456 .t456__list_item{display:block;text-align:center;padding:10px!important;white-space:normal}.t456__logo{white-space:normal;padding:0}.t456__logowrapper{position:static;display:block;width:100%}.t456__logowrapper2{display:block;position:static}.t456__leftwrapper,.t456__rightwrapper{width:100%;display:block}.t456__leftwrapper{padding:20px;box-sizing:border-box}.t456__rightwrapper{padding:20px 0}.t456__list{display:block;padding:0!important}.t456.t456__hidden{display:none;height:100%}.t456__mobile{background-color:#111;display:block}.t456__mobile_text{color:#fff}.t456__mobile_container{padding:20px;position:relative}.t456__burger{position:absolute;top:50%;margin-top:-10px;right:20px;width:28px;height:20px;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.5s ease-in-out;-moz-transition:.5s ease-in-out;-o-transition:.5s ease-in-out;transition:.5s ease-in-out;cursor:pointer;z-index:9999}.t456__burger span{display:block;position:absolute;width:100%;opacity:1;left:0;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-o-transform:rotate(0deg);transform:rotate(0deg);-webkit-transition:.25s ease-in-out;-moz-transition:.25s ease-in-out;-o-transition:.25s ease-in-out;transition:.25s ease-in-out;height:3px;background-color:#fff}.t456__burger span:nth-child(1){top:0}.t456__burger span:nth-child(2),.t456__burger span:nth-child(3){top:8px}.t456__burger span:nth-child(4){top:16px}.t456_opened .t456__burger span:nth-child(1){top:8px;width:0%;left:50%}.t456_opened .t456__burger span:nth-child(2){-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t456_opened .t456__burger span:nth-child(3){-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.t456_opened .t456__burger span:nth-child(4){top:8px;width:0%;left:50%}} \ No newline at end of file diff --git a/css/tilda-blocks-2.8.css b/css/tilda-blocks-2.8.css deleted file mode 100644 index 842b7642..00000000 --- a/css/tilda-blocks-2.8.css +++ /dev/null @@ -1,3677 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,600,700&subset=latin,cyrillic); -.t-body { - margin: 0px; -} -#allrecords { - -webkit-font-smoothing: antialiased; - background-color: none; -} -#allrecords a { - color: #ff8562; - text-decoration: none; -} -#allrecords a[href^=tel] { - color: inherit; - text-decoration: none; -} -#allrecords ol { - padding-left: 22px; -} -#allrecords ul { - padding-left: 20px; -} -@media print { - body, - html { - min-width: 1200px; - max-width: 1200px; - padding: 0; - margin: 0 auto; - border: none; - } -} -.t-text { - font-family: 'Georgia', serif; - font-weight: 300; - color: #000000; -} -.t-text_xs { - font-size: 15px; - line-height: 1.55; -} -.t-text_sm { - font-size: 18px; - line-height: 1.55; -} -.t-text_md { - font-size: 20px; - line-height: 1.55; -} -.t-text_lg { - font-size: 22px; - line-height: 1.55; -} -.t-text_weight_plus { - font-weight: 400; -} -.t-text-impact { - font-family: 'Georgia', serif; - font-weight: 300; - color: #000000; -} -.t-text-impact_xs { - font-size: 26px; - line-height: 1.50; -} -.t-text-impact_sm { - font-size: 32px; - line-height: 1.35; -} -.t-text-impact_md { - font-size: 38px; - line-height: 1.35; -} -.t-text-impact_lg { - font-size: 42px; - line-height: 1.23; -} -.t-name { - font-family: 'Open Sans', sans-serif; - font-weight: 600; - color: #000000; -} -.t-name_xs { - font-size: 16px; - line-height: 1.35; -} -.t-name_sm { - font-size: 18px; - line-height: 1.35; -} -.t-name_md { - font-size: 20px; - line-height: 1.35; -} -.t-name_lg { - font-size: 22px; - line-height: 1.35; -} -.t-name_xl { - font-size: 24px; - line-height: 1.35; -} -.t-heading { - font-family: 'Open Sans', sans-serif; - font-weight: 600; - color: #000000; -} -.t-heading_xs { - font-size: 26px; - line-height: 1.23; -} -.t-heading_sm { - font-size: 28px; - line-height: 1.17; -} -.t-heading_md { - font-size: 30px; - line-height: 1.17; -} -.t-heading_lg { - font-size: 32px; - line-height: 1.17; -} -.t-title { - font-family: 'Open Sans', sans-serif; - font-weight: 600; - color: #000000; -} -.t-title_xxs { - font-size: 36px; - line-height: 1.23; -} -.t-title_xs { - font-size: 42px; - line-height: 1.23; -} -.t-title_sm { - font-size: 48px; - line-height: 1.23; -} -.t-title_md { - font-size: 52px; - line-height: 1.23; -} -.t-title_lg { - font-size: 64px; - line-height: 1.23; -} -.t-title_xl { - font-size: 72px; - line-height: 1.17; -} -.t-title_xxl { - font-size: 82px; - line-height: 1.17; -} -.t-descr { - font-family: 'Open Sans', sans-serif; - font-weight: 300; - color: #000000; -} -.t-descr_xxs { - font-size: 14px; - line-height: 1.55; -} -.t-descr_xs { - font-size: 16px; - line-height: 1.55; -} -.t-descr_sm { - font-size: 18px; - line-height: 1.55; -} -.t-descr_md { - font-size: 20px; - line-height: 1.55; -} -.t-descr_lg { - font-size: 22px; - line-height: 1.55; -} -.t-descr_xl { - font-size: 24px; - line-height: 1.50; -} -.t-descr_xxl { - font-size: 26px; - line-height: 1.45; -} -.t-descr_xxxl { - font-size: 30px; - line-height: 1.45; - letter-spacing: 0.45; -} -.t-uptitle { - font-family: 'Open Sans', sans-serif; - font-weight: 600; - color: #000000; - letter-spacing: 2.5px; -} -.t-uptitle_xs { - font-size: 12px; -} -.t-uptitle_sm { - font-size: 14px; -} -.t-uptitle_md { - font-size: 16px; -} -.t-uptitle_lg { - font-size: 18px; -} -.t-uptitle_xl { - font-size: 20px; - letter-spacing: 2px; -} -.t-uptitle_xxl { - font-size: 22px; - letter-spacing: 2px; -} -.t-uptitle_xxxl { - font-size: 24px; - letter-spacing: 2px; -} -@media screen and (max-width: 1200px) { - .t-text_xs { - font-size: 14px; - } - .t-text_sm { - font-size: 16px; - } - .t-text_md { - font-size: 18px; - } - .t-text_lg { - font-size: 20px; - } - .t-text-impact_md { - font-size: 30px; - } - .t-descr_xxs { - font-size: 12px; - } - .t-descr_xs { - font-size: 14px; - } - .t-descr_sm { - font-size: 16px; - } - .t-descr_md { - font-size: 18px; - } - .t-descr_lg { - font-size: 20px; - } - .t-descr_xl { - font-size: 22px; - } - .t-descr_xxl { - font-size: 22px; - } - .t-descr_xxxl { - font-size: 26px; - } - .t-uptitle_md { - font-size: 14px; - } - .t-uptitle_lg { - font-size: 16px; - } - .t-uptitle_xl { - font-size: 18px; - } - .t-uptitle_xxl { - font-size: 20px; - } - .t-uptitle_xxxl { - font-size: 22px; - } - .t-title_xxs { - font-size: 32px; - } - .t-title_xs { - font-size: 38px; - } - .t-title_sm { - font-size: 44px; - } - .t-title_md { - font-size: 48px; - } - .t-title_lg { - font-size: 60px; - } - .t-title_xl { - font-size: 68px; - } - .t-title_xxl { - font-size: 78px; - } - .t-name_xs { - font-size: 14px; - } - .t-name_sm { - font-size: 16px; - } - .t-name_md { - font-size: 18px; - } - .t-name_lg { - font-size: 20px; - } - .t-name_xl { - font-size: 22px; - } - .t-heading_xs { - font-size: 24px; - } - .t-heading_sm { - font-size: 26px; - } - .t-heading_md { - font-size: 28px; - } - .t-heading_lg { - font-size: 30px; - } -} -@media screen and (max-width: 640px) { - .t-text_xs { - font-size: 12px; - line-height: 1.45; - } - .t-text_sm { - font-size: 14px; - line-height: 1.45; - } - .t-text_md { - font-size: 16px; - line-height: 1.45; - } - .t-text_lg { - font-size: 18px; - line-height: 1.45; - } - .t-text-impact_sm { - font-size: 22px; - } - .t-text-impact_md { - font-size: 26px; - } - .t-text-impact_lg { - font-size: 28px; - } - .t-descr_xs { - font-size: 12px; - line-height: 1.45; - } - .t-descr_sm { - font-size: 14px; - line-height: 1.45; - } - .t-descr_md { - font-size: 16px; - line-height: 1.45; - } - .t-descr_lg { - font-size: 18px; - line-height: 1.45; - } - .t-descr_xl { - font-size: 20px; - line-height: 1.40; - } - .t-descr_xxl { - font-size: 20px; - } - .t-descr_xxxl { - font-size: 22px; - } - .t-uptitle_xs { - font-size: 10px; - } - .t-uptitle_sm { - font-size: 10px; - } - .t-uptitle_md { - font-size: 12px; - } - .t-uptitle_lg { - font-size: 14px; - } - .t-uptitle_xl { - font-size: 16px; - } - .t-uptitle_xxl { - font-size: 18px; - } - .t-uptitle_xxxl { - font-size: 20px; - } - .t-title_xxs { - font-size: 28px; - } - .t-title_xs { - font-size: 30px; - } - .t-title_sm { - font-size: 30px; - } - .t-title_md { - font-size: 30px; - } - .t-title_lg { - font-size: 30px; - } - .t-title_xl { - font-size: 32px; - } - .t-title_xxl { - font-size: 36px; - } - .t-name_xs { - font-size: 12px; - } - .t-name_sm { - font-size: 14px; - } - .t-name_md { - font-size: 16px; - } - .t-name_lg { - font-size: 18px; - } - .t-name_xl { - font-size: 20px; - } - .t-heading_xs { - font-size: 22px; - } - .t-heading_sm { - font-size: 24px; - } - .t-heading_md { - font-size: 24px; - } - .t-heading_lg { - font-size: 26px; - } -} -@media screen and (max-width: 480px) { - .t-title_xl { - font-size: 30px; - } - .t-title_xxl { - font-size: 30px; - } -} -.t-records { - -webkit-font_smoothing: antialiased; - background-color: none; -} -.t-records a { - color: #ff8562; - text-decoration: none; -} -.t-records a[href^=tel] { - color: inherit; - text-decoration: none; -} -.t-records ol { - padding-left: 22px; - margin-top: 0px; - margin-bottom: 10px; -} -.t-records ul { - padding-left: 20px; - margin-top: 0px; - margin-bottom: 10px; -} -.t-cover { - height: 700px; - width: 100%; - -webkit-background-size: cover; - -moz-background-size: cover; - -o-background-size: cover; - background-size: cover; - background-color: #000; - background-repeat: no-repeat; - background-position: center center; - text-align: center; - vertical-align: middle; - position: relative; - background-attachment: fixed; - overflow: hidden; -} -.t-cover__carrier { - height: 700px; - width: 100%; - background-size: cover; - -webkit-background-size: cover; - -moz-background-size: cover; - -o-background-size: cover; - background-repeat: no-repeat; - background-position: center center; - text-align: center; - vertical-align: middle; - position: relative; - background-attachment: fixed; -} -.t-cover__carrier.loading { - opacity: 0; -} -.t-cover__carrier[data-content-cover-bg=""].loading { - opacity: 1 !important; -} -.t-cover__carrier.loaded { - opacity: 1; - transition: opacity 400ms; -} -@media screen and (max-device-width: 1024px) { - .t-cover { - background-attachment: scroll; - } - .t-cover__carrier { - background-attachment: scroll; - } -} -@media print { - .t-cover { - background-attachment: scroll; - } - .t-cover__carrier { - background-attachment: scroll; - } -} -.t-cover__filter { - height: 700px; - width: 100%; - position: absolute; - top: 0; - left: 0; -} -.t-cover .t-container, -.t-cover .t-container_100, -.t-cover .t-container_10, -.t-cover .t-container_8 { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; -} -.t-cover__wrapper { - height: 700px; - display: table-cell; - width: 1200px; -} -.t-cover__wrapper span.space { - display: inline-block; - height: 100%; - width: 1px; -} -@media screen and (max-width: 640px) { - .t-cover { - height: 400px; - background-attachment: fixed; - } - .t-cover__carrier { - background-attachment: scroll !important; - background-size: cover; - background-position: center center; - } - .t-cover__filter { - height: 400px; - } - .t-cover__wrapper { - height: 400px; - } -} -@-webkit-keyframes t-arrow-bottom { - 0% { - -moz-transform: translateY(0); - -ms-transform: translateY(0); - -webkit-transform: translateY(0); - -o-transform: translateY(0); - transform: translateY(0); - } - 50% { - -moz-transform: translateY(-7px); - -ms-transform: translateY(-7px); - -webkit-transform: translateY(-7px); - -o-transform: translateY(-7px); - transform: translateY(-7px); - } - 55% { - -moz-transform: translateY(-7px); - -ms-transform: translateY(-7px); - -webkit-transform: translateY(-7px); - -o-transform: translateY(-7px); - transform: translateY(-7px); - } - 100% { - -moz-transform: translateY(0); - -ms-transform: translateY(0); - -webkit-transform: translateY(0); - -o-transform: translateY(0); - transform: translateY(0); - } -} -@keyframes t-arrow-bottom { - 0% { - -moz-transform: translateY(0); - -ms-transform: translateY(0); - -webkit-transform: translateY(0); - -o-transform: translateY(0); - transform: translateY(0); - } - 50% { - -moz-transform: translateY(-7px); - -ms-transform: translateY(-7px); - -webkit-transform: translateY(-7px); - -o-transform: translateY(-7px); - transform: translateY(-7px); - } - 55% { - -moz-transform: translateY(-7px); - -ms-transform: translateY(-7px); - -webkit-transform: translateY(-7px); - -o-transform: translateY(-7px); - transform: translateY(-7px); - } - 100% { - -moz-transform: translateY(0); - -ms-transform: translateY(0); - -webkit-transform: translateY(0); - -o-transform: translateY(0); - transform: translateY(0); - } -} -.t-cover__arrow-wrapper_animated { - animation: t-arrow-bottom 1.7s infinite ease; -} -.t-cover__arrow { - position: absolute; - z-index: 9; - bottom: 40px; - right: 0; - left: 0; - text-align: center; -} -.t-cover__arrow-wrapper { - display: inline-block; - -webkit-transition: all ease-in-out 0.2s; - -moz-transition: all ease-in-out 0.2s; - -o-transition: all ease-in-out 0.2s; - transition: all ease-in-out 0.2s; - cursor: pointer; -} -.t-cover__arrow-wrapper:hover { - opacity: .7; -} -.t-cover__arrow-svg { - fill: #fff; -} -@media screen and (max-width: 640px) { - .t-cover__arrow_mobile { - -moz-transform: scale(.7); - -ms-transform: scale(.7); - -webkit-transform: scale(.7); - -o-transform: scale(.7); - transform: scale(.7); - } - .t-cover__arrow { - bottom: 14px; - } -} -.t-btn { - display: inline-block; - font-family: 'Open Sans', sans-serif; - height: 60px; - border: 0 none; - font-size: 16px; - padding-left: 60px; - padding-right: 60px; - text-align: center; - white-space: nowrap; - vertical-align: middle; - font-weight: bold; - background-image: none; - cursor: pointer; - -webkit-appearance: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.t-btn td { - vertical-align: middle; -} -@media screen and (max-width: 640px) { - .t-btn { - white-space: normal; - padding-left: 30px; - padding-right: 30px; - } -} -.t-btn_sm { - height: 40px; - font-size: 14px; - padding-left: 30px; - padding-right: 30px; -} -.t-btn_lg { - height: 60px; - font-size: 22px; - padding-left: 70px; - padding-right: 70px; -} -@media screen and (max-width: 640px) { - .t-btn_lg { - font-size: 18px; - padding-left: 40px; - padding-right: 40px; - } -} -.t-submit { - font-family: 'Open Sans', sans-serif; - text-align: center; - height: 60px; - border: 0 none; - font-size: 16px; - padding-left: 60px; - padding-right: 60px; - -webkit-appearance: none; - font-weight: bold; - white-space: nowrap; - background-image: none; - cursor: pointer; - margin: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -@media screen and (max-width: 640px) { - .t-submit { - white-space: normal; - padding-left: 30px; - padding-right: 30px; - } -} -.t-input { - margin: 0; - font-family: 'Open Sans', sans-serif; - font-size: 100%; - height: 60px; - padding: 0px 20px; - font-size: 16px; - line-height: 1.33; - width: 100%; - border: 0 none; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.t-input::-moz-focus-inner { - padding: 0; - border: 0; -} -.t-input_bbonly { - outline: none; - padding-left: 0 !important; - padding-right: 0 !important; - border-top: 0 !important; - border-right: 0 !important; - border-left: 0 !important; - background-color: transparent !important; - border-radius: 0 !important; -} -@media screen and (max-width: 1200px) { - .t-screenmin-1200px { - display: none; - } -} -@media screen and (max-width: 980px) { - .t-screenmin-980px { - display: none; - } -} -@media screen and (max-width: 640px) { - .t-screenmin-640px { - display: none; - } -} -@media screen and (max-width: 480px) { - .t-screenmin-480px { - display: none; - } -} -@media screen and (max-width: 320px) { - .t-screenmin-320px { - display: none; - } -} -@media screen and (min-width: 321px) { - .t-screenmax-320px { - display: none; - } -} -@media screen and (min-width: 481px) { - .t-screenmax-480px { - display: none; - } -} -@media screen and (min-width: 641px) { - .t-screenmax-640px { - display: none; - } -} -@media screen and (min-width: 981px) { - .t-screenmax-980px { - display: none; - } -} -@media screen and (min-width: 1201px) { - .t-screenmax-1200px { - display: none; - } -} -.t-hidden { - display: none; -} -.t-opacity_50 { - filter: alpha(opacity=50); - KHTMLOpacity: 0.50; - MozOpacity: 0.50; - opacity: 0.50; -} -.t-opacity_70 { - filter: alpha(opacity=70); - KHTMLOpacity: 0.70; - MozOpacity: 0.70; - opacity: 0.70; -} -.t-uppercase { - text-transform: uppercase; -} -.t-align_center { - text-align: center; -} -.t-align_left { - text-align: left; -} -.t-align_right { - text-align: right; -} -.t-margin_auto { - margin-left: auto; - margin-right: auto; -} -.t-valign_middle { - vertical-align: middle; -} -.t-valign_top { - vertical-align: top; -} -.t-valign_bottom { - vertical-align: bottom; -} -.t-margin_left_auto { - margin-right: 0; - margin-left: auto; -} -.yashare-style .b-share-btn__facebook, -.yashare-style .b-share-btn__twitter, -.yashare-style .b-share-btn__vkontakte { - background-color: transparent !important; -} -.yashare-style .b-share__link { - -webkit-border-radius: 0px !important; - border-radius: 0px !important; -} -.yashare-style-black-white .b-share-btn__wrap { - background-color: #000 !important; - padding: 5px !important; -} -.yashare-style-transp-white .b-share-btn__wrap { - padding: 5px !important; -} -.yashare-style-transp-white .b-share-counter { - color: #fff; - font-weight: bold; -} -.yashare-style-white-black .b-share-btn__wrap { - background-color: #fff !important; - padding: 5px !important; -} -.yashare-style-white-black .b-share-icon { - background-image: url("//static.tildacdn.com/img/b-share_counter_large_white.png") !important; -} -.yashare-style-transp-black .b-share-btn__wrap { - padding: 5px !important; -} -.yashare-style-transp-black .b-share-icon { - background-image: url("//static.tildacdn.com/img/b-share_counter_large_white.png") !important; -} -.yashare-style-transp-black .b-share-counter { - color: #000; - font-weight: bold; -} -.ya-share2 ul { - padding-left: 0px !important; -} -.carousel { - position: relative; -} -.carousel ol { - padding-left: 0px !important; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - height: auto; - line-height: 1; -} -.carousel-inner .widthauto { - width: auto; - max-width: 100%; - vertical-align: middle; -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - opacity: 0.2; - filter: alpha(opacity=20); -} -.carousel-control.right { - right: 0; - left: auto; -} -.carousel-control .carousel-control-left { - position: absolute; - top: 48%; - z-index: 5; - display: inline-block; - left: 20%; - height: 34px; - width: 21px; - background: url(//static.tildacdn.com/img/aboutSliderControls.png) no-repeat; -} -.carousel-control .carousel-control-left-white { - position: absolute; - top: 48%; - z-index: 5; - display: inline-block; - left: 20%; - height: 34px; - width: 21px; - background: url(//static.tildacdn.com/img/aboutSliderControls_white.png) no-repeat; -} -.carousel-control .carousel-control-right { - position: absolute; - top: 48%; - z-index: 5; - display: inline-block; - right: 20%; - height: 34px; - width: 21px; - background: url(//static.tildacdn.com/img/aboutSliderControls.png) no-repeat; - background-position: left bottom; -} -.carousel-control .carousel-control-right-white { - position: absolute; - top: 48%; - z-index: 5; - display: inline-block; - right: 20%; - height: 34px; - width: 21px; - background: url(//static.tildacdn.com/img/aboutSliderControls_white.png) no-repeat; - background-position: left bottom; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators.dotsbottom { - bottom: -60px; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - margin-left: 5px; - margin-right: 5px; - text-indent: -999px; - cursor: pointer; - background-color: #000000; - border: none; - border-radius: 10px; -} -.carousel-indicators .active { - width: 10px; - height: 10px; - margin: 0; - margin-left: 4px; - margin-right: 4px; - border: 1px solid #000000; - border-radius: 10px; - background-color: transparent; -} -.carousel-indicators li.white { - background-color: #fff; -} -.carousel-indicators li.white.active { - border: 1px solid #fff; - border-radius: 10px; - background-color: transparent; -} -.carousel-caption-imgs h6 { - font-family: 'Georgia', serif; - color: #000000; - font-weight: normal; - font-size: 14px; - line-height: 28px; - padding-top: 28px; - padding-bottom: 0px; - text-align: center; -} -.carousel-caption-imgs p { - font-family: 'Georgia', serif; - color: #000000; - font-size: 14px; - line-height: 28px; - padding-top: 14px; - padding-bottom: 14px; - text-align: center; -} -.carousel-title { - font-family: 'Open Sans', sans-serif; - color: #000000; - font-size: 18px; - line-height: 28px; - padding-top: 36px; - padding-bottom: 14px; - text-align: center; -} -.carousel-descr { - font-family: 'Georgia', serif; - color: #000000; - font-size: 14px; - line-height: 28px; - padding-top: 14px; - padding-bottom: 14px; - text-align: center; -} -@media screen and (min-width: 768px) { - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after { - display: table; - content: " "; -} -.clearfix:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -@media screen and (max-width: 960px) { - .carousel-control .carousel-control-left { - left: 10%; - } - .carousel-control .carousel-control-left-white { - left: 10%; - } - .carousel-control .carousel-control-right { - right: 10%; - } - .carousel-control .carousel-control-right-white { - right: 10%; - } -} -.t-tildalabel { - background-color: #000; - color: #fff; - width: 100%; - height: 70px; - font-family: Arial; - font-size: 14px; -} -.t-tildalabel:hover .t-tildalabel__wrapper { - opacity: 1; -} -.t-tildalabel_white { - background-color: #fff; - color: #000; -} -.t-tildalabel_gray { - background-color: #eee; - color: #000; -} -.t-tildalabel__wrapper { - display: table; - height: 30px; - width: 270px; - margin: 0 auto; - padding-top: 20px; - opacity: 0.4; -} -.t-tildalabel__txtleft { - display: table-cell; - width: 120px; - height: 30px; - vertical-align: middle; - text-align: right; - padding-right: 12px; - font-weight: 300; - font-size: 12px; -} -.t-tildalabel__wrapimg { - display: table-cell; - width: 30px; - height: 30px; - vertical-align: middle; -} -.t-tildalabel__img { - width: 30px; - height: 30px; - vertical-align: middle; -} -.t-tildalabel__txtright { - display: table-cell; - width: 120px; - height: 30px; - vertical-align: middle; - padding-left: 12px; - font-weight: 500; - letter-spacing: 2px; -} -.t-tildalabel__link { - color: #fff; - text-decoration: none; - vertical-align: middle; -} -.t-tildalabel_white .t-tildalabel__link, -.t-tildalabel_gray .t-tildalabel__link { - color: #000; -} -.t-carousel { - position: relative; -} -.t-carousel__inner { - position: relative; - overflow: hidden; - margin: 0 auto; -} -.t-carousel__slides { - position: relative; -} -.t-carousel__inner > .t-carousel__item { - position: relative; - display: none; - -webkit-transition: 0 ease-in-out left; - -moz-transition: 0 ease-in-out left; - -o-transition: 0 ease-in-out left; - transition: 0 ease-in-out left; -} -.t-carousel__inner > .t-carousel__item.t-carousel__animation_fast { - -webkit-transition: .3s ease-in-out left; - -moz-transition: .3s ease-in-out left; - -o-transition: .3s ease-in-out left; - transition: .3s ease-in-out left; -} -.t-carousel__inner > .t-carousel__item.t-carousel__animation_slow { - -webkit-transition: .6s ease-in-out left; - -moz-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.t-carousel__item__wrapper { - position: relative; - margin: 0 auto; -} -.t-carousel__item__img { - background-size: contain; - background-repeat: no-repeat; - background-position: center; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} -.t-carousel_cover .t-carousel__item__img { - background-size: cover; -} -.t-carousel__inner > .active, -.t-carousel__inner > .next, -.t-carousel__inner > .prev { - display: block; -} -.t-carousel__inner > .active { - left: 0; -} -.t-carousel__inner > .next, -.t-carousel__inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.t-carousel__inner > .next { - left: 100%; -} -.t-carousel__inner > .prev { - left: -100%; -} -.t-carousel__inner > .next.left, -.t-carousel__inner > .prev.right { - left: 0; -} -.t-carousel__inner > .active.left { - left: -100%; -} -.t-carousel__inner > .active.right { - left: 100%; -} -.t-carousel__arrows__container { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin: 0 auto; - pointer-events: none; - filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII=',sizingMethod='scale'); - background: none !important; -} -.t-carousel__arrow_outsidesmall .t-carousel__arrow__wrapper_left { - left: 16px; -} -.t-carousel__arrow_outsidesmall .t-carousel__arrow__wrapper_right { - right: 16px; -} -.t-carousel__arrow_outsidemiddle .t-carousel__arrow__wrapper_left { - left: 20px; -} -.t-carousel__arrow_outsidemiddle .t-carousel__arrow__wrapper_right { - right: 20px; -} -.t-carousel__control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - -webkit-transition: all ease-in-out 0.3s; - -moz-transition: all ease-in-out 0.3s; - -o-transition: all ease-in-out 0.3s; - transition: all ease-in-out 0.3s; - pointer-events: auto; -} -.t-carousel__control:hover { - opacity: .6; -} -.t-carousel__arrow { - width: 34px; - height: 34px; - background: transparent; - -moz-transform: rotate(45deg); - -ms-transform: rotate(45deg); - -webkit-transform: rotate(45deg); - -o-transform: rotate(45deg); - transform: rotate(45deg); -} -.t-carousel__arrow.t-carousel__arrow_small { - width: 20px; - height: 20px; -} -.t-carousel__arrow.t-carousel__arrow_large { - width: 54px; - height: 54px; -} -.t-carousel__arrow__wrapper { - -moz-transform: translateY(-50%); - -ms-transform: translateY(-50%); - -webkit-transform: translateY(-50%); - -o-transform: translateY(-50%); - transform: translateY(-50%); - position: absolute; - top: 50%; -} -.t-carousel__arrow__wrapper_left { - left: 30px; -} -.t-carousel__arrow__wrapper_right { - right: 30px; -} -.t-carousel__arrow_right { - border-top: 3px solid; - border-right: 3px solid; -} -.t-carousel__arrow_right.t-carousel__arrow_light { - border-top: 1px solid; - border-right: 1px solid; -} -.t-carousel__arrow_right.t-carousel__arrow_bold { - border-top: 6px solid; - border-right: 6px solid; -} -.t-carousel__arrow_left { - border-left: 3px solid; - border-bottom: 3px solid; -} -.t-carousel__arrow_left.t-carousel__arrow_light { - border-left: 1px solid; - border-bottom: 1px solid; -} -.t-carousel__arrow_left.t-carousel__arrow_bold { - border-left: 6px solid; - border-bottom: 6px solid; -} -.t-carousel__control.right { - right: 0; - left: auto; -} -@media screen and (max-width: 768px) { - .t-carousel__control .t-carousel__arrow { - width: 12px; - height: 12px; - } - .t-carousel-control { - width: 10%; - } - .t-carousel__arrow__left { - left: 15px; - } - .t-carousel__arrow__right { - right: 15px; - } -} -.t-carousel__indicators.carousel-indicators { - z-index: 15; - text-align: center; - list-style: none; - position: relative; - padding-left: 0 !important; - margin: 0 auto; - padding: 20px 0; - bottom: auto; - left: auto; -} -.t-carousel__indicators.t-carousel__indicators_light { - padding: 15px 0 18px; -} -.t-carousel__indicators.t-carousel__indicators_bold { - padding: 24px 0 21px; -} -.t-carousel__indicators .t-carousel__indicator { - display: inline-block; - width: 8px; - height: 8px; - margin: 0 6px; - text-indent: -999px; - cursor: pointer; - background-color: #222; - border: none; - border-radius: 10px; - opacity: .4; - -webkit-transition: .2s ease-in-out opacity; - -moz-transition: .2s ease-in-out opacity; - -o-transition: .2s ease-in-out opacity; - transition: .2s ease-in-out opacity; -} -@media screen and (max-width: 640px) { - .t-carousel__indicators.carousel-indicators, - .t-carousel__indicators.t-carousel__indicators_light, - .t-carousel__indicators.t-carousel__indicators_bold { - padding: 15px 0; - } -} -.t-carousel__indicators.t-carousel__indicators_light .t-carousel__indicator { - width: 4px; - height: 4px; - margin: 0 5px; -} -.t-carousel__indicators.t-carousel__indicators_bold .t-carousel__indicator { - width: 10px; - height: 10px; - margin: 0 6px; -} -.t-carousel__indicators .t-carousel__indicator:hover { - opacity: .8; -} -.t-carousel__indicators .t-carousel__indicator.active { - opacity: 1; -} -.t-carousel__indicators.t-carousel__indicators_inside { - position: absolute; - bottom: 0; - left: 0; - right: 0; -} -.t-carousel__caption-inside { - display: none; -} -.t-carousel__caption_wrapper { - border-top: 1px solid #eee; - padding: 14px 0; -} -.t-carousel__descr { - margin-top: 5px; - color: #777; -} -.t-mbfix { - opacity: 0.01; - -webkit-transform: translateX(0px); - -ms-transform: translateX(0px); - transform: translateX(0px); - position: fixed; - width: 100%; - height: 500px; - background-color: white; - top: 0px; - left: 0px; - z-index: 10000; - -webkit-transition: all 0.1s ease; - transition: all 0.1s ease; -} -.t-mbfix_hide { - -webkit-transform: translateX(3000px); - -ms-transform: translateX(3000px); - transform: translateX(3000px); -} -.t107 { - text-align: center; -} -.t107__width { - vertical-align: middle; -} -.t107__widthauto { - width: auto; - max-width: 100%; - display: block; - margin: 0 auto; -} -.t107__title { - padding-top: 28px; - padding-bottom: 28px; - font-size: 14px; - line-height: 28px; -} -.t102__title { - font-size: 104px; - color: #fff; - margin: 74px 0 54px 0; - text-transform: uppercase; -} -.t102__descr { - color: #fff; - padding: 0 220px; -} -@media screen and (max-width: 1024px) { - .t102__title { - font-size: 70px; - line-height: 70px; - margin-top: 30px; - } - .t102__descr { - padding: 0 120px; - } -} -@media screen and (max-width: 640px) { - .t102__title { - font-size: 34px; - line-height: 38px; - margin-top: 30px; - } - .t102__descr { - padding: 0 10px; - } -} -.t001__wrapper { - padding-top: 42px; - padding-bottom: 42px; -} -.t001__uptitle { - text-transform: uppercase; - color: #ffffff; - padding-bottom: 60px; - padding-top: 30px; -} -.t001__title { - color: #fff; - padding: 24px 0px 38px 0px; - letter-spacing: 0.5px; -} -.t001__descr { - color: #fff; - padding: 0px 0px 30px 0px; -} -.t001__descr_center { - max-width: 700px; - margin: 0 auto; -} -.t001__descr_center a { - color: #fff !important; - font-weight: 600; -} -@media screen and (max-width: 640px) { - .t001__title { - padding-left: 10px; - padding-right: 10px; - } - .t001__uptitle { - padding-left: 10px; - padding-right: 10px; - } - .t001__descr { - padding-left: 10px; - padding-right: 10px; - font-size: 14px; - line-height: 20px; - } -} -.t015__title { - padding-top: 8px; - padding-bottom: 3px; -} -.t015__uptitle { - text-transform: uppercase; - padding-top: 10px; - padding-bottom: 40px; -} -.t015__descr { - padding: 41px 0px 0px 0px; -} -.t017__uptitle { - padding-top: 3px; - padding-bottom: 22px; -} -.t017__title { - padding-top: 2px; - padding-bottom: 0px; -} -.t017__descr { - padding-top: 21px; -} -.t021__line { - width: 100%; - max-width: 140px; - margin-left: auto; - margin-right: auto; - height: 1px; - background-color: #000000; -} -.t021__text-impact { - text-align: center; - margin-top: 44px; - margin-bottom: 54px; -} -.t030__title { - margin-bottom: 15px; -} -.t030__descr { - margin-top: 8px; - padding-bottom: 6px; -} -.t033 .t-container { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; -} -.t033__lineTop { - border-top: 4px solid #000000; - padding-left: 0; - width: 100%; - margin-top: 1px; -} -.t033__title { - font-size: 24px; - color: #000000; - line-height: 36px; - padding-top: 19px; -} -.t033__descr { - margin-top: -12px; -} -@media screen and (max-width: 960px) { - .t033 .t-container { - display: -webkit-block; - display: block; - } - .t033__title { - padding-bottom: 40px; - } -} -@media screen and (max-width: 640px) { - .t033__lineTop { - width: 100%; - } -} -.t037 .t-container { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; -} -.t037__title { - font-family: 'Open Sans', sans-serif; - color: #000000; - font-weight: 600; - font-size: 24px; - line-height: 28px; - padding-right: 50px; - padding-top: 7px; - padding-bottom: 7px; -} -.t037__text { - padding-top: 8px; - padding-bottom: 6px; -} -@media screen and (max-width: 960px) { - .t037 .t-container { - display: -webkit-block; - display: block; - } - .t037__title { - padding-right: 0px; - } -} -@media screen and (max-width: 640px) { - .t037__title { - margin-bottom: 20px; - padding-right: 0; - } -} -.t050__uptitle { - padding-top: 9px; - padding-bottom: 93px; - text-transform: uppercase; -} -.t050__descr { - padding-top: 50px; - padding-bottom: 9px; -} -.t029 .t-container { - padding-top: 3px; - padding-bottom: 5px; -} -.t029 img { - max-width: 100%; -} -.t075__wrapperleft { - padding-left: 0px; - padding-right: 0px; -} -.t075__wrappercenter { - padding-left: 20px; - padding-right: 20px; -} -.t075__img { - margin-bottom: 14px; - width: 100px; - height: 100px; -} -.t075__img_circle { - border-radius: 50%; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; -} -.t075__textclass1 .t075__title { - font-size: 24px; - line-height: 30px; - margin-bottom: 25px; - margin-top: 18px; -} -.t075__textclass1 { - font-size: 16px; - line-height: 25px; -} -.t075__textclass2 .t075__title { - font-size: 18px; - line-height: 21px; - margin-bottom: 25px; - margin-top: 12px; -} -.t075__textclass2 { - font-size: 13px; - line-height: 20px; -} -.t075__textclass3 .t075__title { - font-size: 30px; - line-height: 40px; - margin-bottom: 25px; - margin-top: 12px; -} -.t075__textclass3 { - font-size: 16px; - line-height: 25px; -} -@media screen and (max-width: 960px) { - .t075__textclass1, - .t075__textclass2, - .t075__textclass3 { - margin-bottom: 45px; - } -} -.t004 { - padding-top: 8px; - padding-bottom: 6px; -} -.t004__text-column-count_2 { - column-count: 2; - column-gap: 40px; - -moz-column-count: 2; - -moz-column-gap: 40px; - -webkit-column-count: 2; - -webkit-column-gap: 40px; -} -.t004__text-column-count_3 { - column-count: 3; - column-gap: 40px; - -moz-column-count: 3; - -moz-column-gap: 40px; - -webkit-column-count: 3; - -webkit-column-gap: 40px; -} -.t004__text-column-count_4 { - column-count: 4; - column-gap: 40px; - -moz-column-count: 4; - -moz-column-gap: 40px; - -webkit-column-count: 4; - -webkit-column-gap: 40px; -} -.t004__initial-letter:first-child::first-letter { - font-size: 100px; - float: left; - margin: -30px 20px -30px 0; -} -.t004 table { - border-collapse: collapse; - font-size: 1em; - width: 100%; -} -.t004 table td, -.t004 table th { - padding: 5px; - border: 1px solid #ddd; - vertical-align: top; -} -.t004 table thead td, -.t004 table th { - font-weight: bold; - border-bottom-color: #888; -} -@media screen and (max-width: 1200px) { - .t004__text-column-count_2, - .t004__text-column-count_3, - .t004__text-column-count_4 { - column-gap: 20px; - -moz-column-gap: 20px; - -webkit-column-gap: 20px; - } -} -@media screen and (max-width: 960px) { - .t004__text-column-count_2, - .t004__text-column-count_3, - .t004__text-column-count_4 { - column-count: 1; - column-gap: 0px; - -moz-column-count: 1; - -moz-column-gap: 0px; - -webkit-column-count: 1; - -webkit-column-gap: 0px; - } -} -@media screen and (max-width: 640px) { - .t004 h1 { - font-size: 28px; - line-height: 35px; - } -} -.t113 { - width: 100%; - height: 50px; - position: absolute; - z-index: 990; -} -.t113__space { - width: 100%; - height: 50px; - position: relative; -} -.t113__fixed { - position: fixed; - top: 0; -} -.t113__logo { - font-size: 20px; - margin-top: 13px; - margin-left: 20px; - padding-right: 50px; - float: left; -} -.t113__img { - margin-left: 20px; - padding-right: 50px; - float: left; -} -.t113__list { - list-style-type: none; - padding-left: 10px !important; - padding-top: 16px; - padding-right: 10px; - padding-bottom: 0px; - margin: 0px; -} -.t113__list_item { - clear: both; - font-family: 'Open Sans', sans-serif; - font-size: 14px; - display: inline; - padding-left: 15px; - padding-right: 15px; - margin: 0px; - color: #000000; -} -.t113 a { - text-decoration: none; - color: #ff8562; -} -.t113__list_item .t-active { - opacity: 0.7; -} -@media screen and (max-width: 640px) { - .t113__list_item { - display: block; - text-align: center; - padding: 10px; - } - .t113__fixed { - position: relative; - } - .t113 { - position: relative; - height: auto; - text-align: center; - } - .t113__logo { - float: inherit; - text-align: center; - margin: 0px; - padding: 20px; - } - .t113__img { - float: inherit; - margin: 0px auto; - padding: 20px; - } -} -.t123__centeredContainer { - text-align: center; -} -.t135__img { - max-width: 100%; -} -@media screen and (max-width: 640px) { - .t135 { - position: relative !important; - text-align: center; - padding: 30px; - top: 0px !important; - right: 0px !important; - left: 0px !important; - z-index: 1 !important; - } -} -@media screen and (max-width: 640px) { - .t141 { - position: relative !important; - text-align: center; - padding: 20px; - top: 0px !important; - right: 0px !important; - } -} -.t145__title { - font-size: 30px; - line-height: 34px; - font-weight: bold; - padding-top: 8px; - padding-bottom: 6px; - margin-right: 20px; -} -.t145__line { - margin-top: 14px; - margin-bottom: 14px; - border: 0; - border-top: 3px solid #000000; - margin-right: 20px; -} -.t145__text { - padding-top: 4px; - padding-bottom: 6px; - font-size: 16px; - line-height: 25px; - margin-right: 20px; -} -@media screen and (max-width: 960px) { - .t145 .t145__col { - margin-top: 20px; - margin-bottom: 20px; - } -} -.t149 a { - text-decoration: none; - color: #ff8562; -} -.t149__title { - margin-top: 20px; - margin-bottom: 0px; -} -.t149__subtitle { - margin-top: 4px; - margin-bottom: 0px; - opacity: 0.5; -} -.t149__sp { - margin-bottom: 20px; -} -.t149__descr { - font-size: 16px; - line-height: 24px; - margin-top: 40px; -} -.t149__img { - width: 100%; -} -.t149__img.t149__circle { - width: 70%; - border-radius: 50%; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border: 1px solid rgba(0,0,0,0.07); -} -.t149__textwrapper { - display: table; - width: 100%; -} -.t149__floatbeaker_lr3 { - display: none; -} -@media screen and (max-width: 960px) { - .t149__col.t-col_4, - .t149__col.t-col_6 { - width: 100%; - max-width: 580px; - display: table; - vertical-align: middle; - margin: 0 auto 50px; - float: none; - } - .t149__col.t-col_4:last-child, - .t149__col.t-col_6:last-child { - margin-bottom: 0 !important; - } - .t149__col.t-col_4 .t149__img, - .t149__col.t-col_6 .t149__img { - display: table-cell; - width: 100%; - vertical-align: middle; - } - .t149__col.t-col_4 .t149__img.t149__circle, - .t149__col.t-col_6 .t149__img.t149__circle { - width: 100%; - } - .t149__col.t-col_4 .t149__textwrapper, - .t149__col.t-col_6 .t149__textwrapper { - display: table-cell; - width: 50%; - vertical-align: middle; - padding-left: 30px; - } - .t149__col.t-col_3 { - max-width: 320px; - display: inline; - float: left; - margin-bottom: 60px; - } - .t149__floatbeaker_lr3 { - display: block; - width: 100%; - content: " "; - clear: both; - } - .t149__col.t-col_3 .t149__title { - font-size: 16px; - line-height: 24px; - } - .t149__col.t-col_3 .t149__subtitle { - font-size: 14px; - line-height: 24px; - } -} -@media screen and (max-width: 660px) { - .t149__col.t-col_3, - .t149__col.t-col_4, - .t149__col.t-col_6 { - max-width: 480px; - display: table; - vertical-align: middle; - margin: 0 auto; - margin-bottom: 40px; - float: none; - } - .t149__img { - display: table-cell; - width: 100%; - vertical-align: middle; - } - .t149__img.t149__circle { - width: 100%; - } - .t149__textwrapper { - display: table-cell; - width: 50%; - vertical-align: middle; - } - .t149__col.t-col_3 .t149__textwrapper { - padding-left: 30px; - } -} -@media screen and (max-width: 480px) { - .t149__col.t-col_3, - .t149__col.t-col_4, - .t149__col.t-col_6 { - max-width: 320px; - width: 100%; - display: block; - float: none; - } - .t149__img { - display: block; - } - .t149__img.t149__circle { - max-width: 70%; - margin: 0 auto; - } - .t149__col.t-col_3 .t149__textwrapper, - .t149__col.t-col_4 .t149__textwrapper, - .t149__col.t-col_6 .t149__textwrapper, - .t149__textwrapper { - display: block; - width: 100%; - margin-bottom: 30px; - padding-left: 0; - } -} -.t160 { - text-align: center; - padding-bottom: 20px; -} -.t160__img { - border-radius: 50%; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - width: 150px; - max-width: 150px; - height: 150px; - padding-top: 17px; - padding-bottom: 14px; -} -.t160__title { - text-align: center; - padding-top: 8px; - padding-bottom: 5px; -} -.t160__descr { - text-align: center; - padding-top: 0px; - padding-bottom: 6px; - letter-spacing: 2px; -} -.t160__text { - padding-top: 30px; - padding-bottom: 30px; - font-size: 22px; - line-height: 1.55; -} -@media screen and (max-width: 960px) { - .t160__wrapper { - padding: 0 20px; - } -} -@media screen and (max-width: 640px) { - .t160__text { - font-size: 18px; - line-height: 1.45; - } -} -@media screen and (max-width: 480px) { - .t160__text { - font-size: 16px; - padding-left: 10px; - padding-right: 10px; - } -} -.t161 .t-col_2 { - max-width: 100px; -} -.t161 .t-col_6, -.t161 .t-col_8, -.t161 .t-col_10 { - width: auto; -} -.t161__img { - width: 80px; - height: 80px; - border-radius: 50%; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - margin-top: 9px; -} -.t161 .t161__wrapper { - display: table; - height: 80px; -} -.t161__textwrapper { - display: table-cell; - vertical-align: middle; -} -.t161__descr { - padding-bottom: 20px; -} -.t161__text { - padding-bottom: 22px; -} -@media screen and (max-width: 960px) { - .t161 .t-col_6 { - max-width: 62%; - } - .t161 .t161__blockimgthumb { - width: 100%; - max-width: 100%; - text-align: center; - padding-bottom: 20px; - } - .t161 .t161__wrapper { - margin: 0 20px; - } -} -.t162 h2 { - padding-top: 4px; - padding-bottom: 14px; - font-family: 'Open Sans', sans-serif; - font-size: 22px; - color: #000000; - font-weight: 600; - line-height: 34px; - cursor: pointer; -} -.t162__subtitle { - font-style: italic; - font-family: 'Georgia', serif; - font-size: 14px; - color: #000000; - line-height: 28px; - font-weight: normal; - margin-top: -12px; - padding-bottom: 12px; - cursor: pointer; -} -.t162__text { - font-family: 'Georgia', serif; - color: #000000; - font-size: 18px; - line-height: 1.55; - padding-bottom: 56px; - padding-top: 28px; -} -.t165 .t-container { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; -} -.t165__vmiddle { - margin-top: auto; - margin-bottom: auto; -} -.t165__vtop { - margin-bottom: auto; -} -.t165__vbottom { - margin-top: auto; -} -.t165__left { - text-align: left; -} -.t165__center { - text-align: center; -} -.t165__right { - text-align: right; -} -.t165__textwrapper { - padding-right: 20px; -} -.t165__uptitle { - padding: 0px; - margin: 0px; - margin-bottom: 14px; -} -.t165__title { - padding: 0px; - margin: 0px; - padding-bottom: 28px; -} -.t165__text { - filter: alpha(opacity=85); - KHTMLOpacity: 0.85; - MozOpacity: 0.85; - opacity: 0.85; -} -.t165__img { - float: right; - width: 100%; -} -.t165__img_circle { - border-radius: 50%; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; -} -@media screen and (max-width: 640px) { - .t165 .t-container { - display: -webkit-block; - display: block; - } - .t165__img { - float: none; - } - .t165__col-top { - margin-bottom: 30px; - } -} -.t166 .t-container { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; -} -.t166__textsmall { - padding-top: 11px; - padding-bottom: 7px; -} -.t166__text { - padding-top: 8px; - padding-bottom: 6px; -} -@media screen and (max-width: 960px) { - .t166 .t-container { - display: -webkit-block; - display: block; - } -} -.t169__text { - font-size: 60px; - line-height: 90px; - margin: 0px 100px; -} -@media screen and (max-width: 640px) { - .t169__text { - font-size: 28px; - line-height: 36px; - margin: 0px 20px; - } -} -.t173__ul { - text-align: center; - list-style-type: none; - padding-left: 10px !important; - padding-top: 16px; - padding-right: 10px; - padding-bottom: 0px; - margin: 0px; -} -.t173__li { - clear: both; - font-family: 'Open Sans', sans-serif; - color: #000000; - font-size: 14px; - display: inline; - padding-left: 15px; - padding-right: 15px; - margin: 0px; - font-weight: 600; -} -.t173 a { - text-decoration: none; -} -.t173__copyright { - text-align: center; - font-family: 'Open Sans', sans-serif; - font-size: 14px; - color: #000000; - filter: alpha(opacity=70); - KHTMLOpacity: 0.70; - MozOpacity: 0.70; - opacity: 0.70; - padding-top: 40px; - padding-bottom: 10px; -} -@media screen and (max-width: 640px) { - .t173 li { - display: block; - margin: 20px auto; - } -} -.t142__submit-overflowed { - line-height: 1.1 !important; -} -.t142__text { - display: table-cell; - vertical-align: middle; - height: 50px; -} -.t142__wrapone { - position: relative; - right: 50%; - float: right; -} -.t142__wraptwo { - position: relative; - z-index: 1; - right: -50%; -} -.t142__submit { - font-family: 'Open Sans', sans-serif; - text-align: center; - height: 50px; - line-height: 50px; - border: 0 none; - font-size: 16px; - padding-left: 60px; - padding-right: 60px; - -webkit-appearance: none; - font-weight: bold; - background: none; - cursor: pointer; -} -.t142__submit_size_sm { - height: 40px; - line-height: 40px; - font-size: 14px; - padding-left: 30px; - padding-right: 30px; -} -.t142__submit_size_lg { - height: 60px; - line-height: 60px; - font-size: 22px; - padding-left: 70px; - padding-right: 70px; -} -.t142__submit_size_xl { - height: 80px; - line-height: 80px; - font-size: 26px; - padding-left: 80px; - padding-right: 80px; -} -.t142__submit_size_xxl { - height: 100px; - line-height: 100px; - font-size: 30px; - padding-left: 90px; - padding-right: 90px; -} -@media screen and (max-width: 640px) { - .t142__submit { - white-space: normal; - padding-left: 30px; - padding-right: 30px; - margin-left: 20px; - margin-right: 20px; - -webkit-border-radius: 0px; - } - .t142__submit_size_lg, - .t142__submit_size_xl, - .t142__submit_size_xxl { - height: 60px; - line-height: 60px; - font-size: 18px; - padding-left: 40px; - padding-right: 40px; - } - .t142__submit_size_lg .t142__text, - .t142__submit_size_xl .t142__text, - .t142__submit_size_xxl .t142__text { - height: 60px; - } -} -.t181 { - text-align: left; -} -.t181__wrapper { - padding-top: 42px; - padding-bottom: 42px; -} -.t181__title { - color: #fff; - padding: 24px 0px 38px 0px; - letter-spacing: 1px; -} -.t181__descr { - color: #fff; - padding: 0px 0px 30px 0px; -} -.t181 .t-btn:nth-child(2) { - margin-left: 10px; -} -@media screen and (max-width: 640px) { - .t181 .t-btn:nth-child(2) { - margin-left: 0px; - } - .t181 .t-btn { - margin: 5px; - margin-left: 0px; - } -} -.t182 { - text-align: center; -} -.t182__wrapper { - padding-top: 42px; - padding-bottom: 42px; -} -.t182__title { - color: #fff; - padding: 24px 0px 24px 0px; - letter-spacing: 1px; -} -.t182__descr { - color: #fff; - padding: 15px 0px 30px 0px; -} -.t182__buttons { - margin-top: 45px; -} -.t182 .t-btn:nth-child(2) { - margin-left: 10px; -} -@media screen and (max-width: 640px) { - .t182__title { - font-size: 30px; - line-height: 30px; - padding-left: 10px; - padding-right: 10px; - } - .t182__descr { - padding-left: 10px; - padding-right: 10px; - font-size: 14px; - line-height: 20px; - } - .t182 .t-btn { - margin: 7px 3px; - } -} -.t183__wrapper { - padding-top: 42px; - padding-bottom: 42px; -} -.t183__uptitle { - text-transform: uppercase; - color: #ffffff; - padding-bottom: 20px; - padding-top: 10px; -} -.t183__title { - color: #fff; - padding: 24px 0px 24px 0px; - letter-spacing: 1px; -} -.t183__buttons { - margin-top: 45px; -} -.t183 .t-btn:nth-child(2) { - margin-left: 10px; -} -@media screen and (max-width: 640px) { - .t183__title { - padding-left: 10px; - padding-right: 10px; - } - .t183__uptitle { - padding-left: 10px; - padding-right: 10px; - } - .t183 .t-btn:nth-child(2) { - margin-left: 5px; - } - .t183 .t-btn { - margin: 5px; - } -} -.t186A__wrapper { - display: table; -} -.t186A__blockinput { - display: table-cell; - vertical-align: middle; - height: 100%; - width: 50%; - padding-right: 20px; -} -.t186A__blockbutton { - display: table-cell; - vertical-align: middle; - height: 100%; -} -@media screen and (max-width: 640px) { - .t186A__wrapper { - display: block; - } - .t186A__blockinput { - display: block; - width: 100%; - padding-bottom: 10px; - } - .t186A__blockbutton { - display: block; - width: 100%; - padding-bottom: 20px; - } - .t186A__submit { - width: 100%; - } -} -.t186A__blockinput-errors { - background: #ff6666 none repeat scroll 0px 0px; -} -.js-error-control-box .t186A__input { - font-family: 'Georgia', serif; - border: 1px solid #FF0000 !important; -} -.t186A__blockinput-errors-text { - color: #ffff77; - font-family: 'Georgia', serif; - box-sizing: border-box; - padding: 0px 10px 10px 10px; -} -.t186A__blockinput-errors-item { - font-family: 'Georgia', serif; - padding-top: 10px; - display: none; -} -.t186A__blockinput-errorbox { - font-family: 'Georgia', serif; - background: #ff6666 none repeat scroll 0px 0px; - color: #ffff77; - padding: 10px; - text-align: center; - margin-bottom: 20px; -} -.t186A__blockinput-success { - text-align: center; - background: #FFF; - color: #222; - padding: 20px; - font-family: 'Georgia', serif; - border: 2px solid #22DD22; - margin-bottom: 20px; -} -.t188__wrapone { - position: relative; - right: 50%; - float: right; -} -.t188__wraptwo { - position: relative; - z-index: 1; - right: -50%; -} -.t188__sociallinkimg { - display: inline-block; - padding-left: 5px; - padding-right: 5px; -} -.t188__imgwrapper { - background-size: contain; - background-repeat: no-repeat; - background-position: center; -} -.t203__wrapper { - display: table; - padding-top: 60px; - padding-bottom: 60px; - margin-left: -60px; - margin-right: -60px; -} -.t203__textwrapper { - display: block; - text-align: left; - background-color: #fff; - padding-left: 60px; - padding-right: 60px; - padding-top: 60px; - padding-bottom: 60px; -} -.t203__title { - padding-top: 20px; - padding-bottom: 20px; -} -.t203__text { - padding-bottom: 20px; - padding-top: 20px; -} -@media screen and (max-width: 720px) { - .t203__wrapper { - padding-top: 0px; - padding-bottom: 0px; - margin-left: 0px; - margin-right: 0px; - } - .t203__textwrapper { - margin: 20px 0px; - padding: 20px; - } -} -.t204__burger { - position: fixed; - z-index: 5000000; - width: 60px; - height: 60px; - top: 30px; - right: 30px; - background-color: #000; - cursor: pointer; -} -.t204__burger-icon { - position: relative; - display: inline-block; - margin: 28px 12px; - width: 36px; - height: 3px; - background: #fff; - vertical-align: middle; -} -.t204__burger-icon:before, -.t204__burger-icon:after { - position: absolute; - left: 0; - width: 100%; - height: 3px; - background: #fff; - content: ''; -} -.t204__burger-icon:before { - top: -9px; -} -.t204__burger-icon:after { - bottom: -9px; -} -.t204__menu { - box-sizing: border-box; - background-color: #000; - color: #fff; - position: fixed; - z-index: 5000002; - width: 380px; - height: 100vh; - top: 0px; - right: 0px; - overflow-y: auto; - overflow-x: hidden; - visibility: hidden; -} -.t204__closelayer { - background-color: #000; - position: fixed; - top: 0px; - left: 0px; - z-index: 5000001; - width: 100%; - height: 100vh; - filter: alpha(opacity=50); - KHTMLOpacity: 0.50; - MozOpacity: 0.50; - opacity: 0.50; - visibility: hidden; -} -.t204__item { - display: table; - margin: 40px auto; - width: 300px; -} -.t204__item:hover .t204__item_img { - opacity: 0.7; -} -.t204__item:hover .t204__item_text a { - color: #ff8562 !important; -} -.t204__item_img { - display: table-cell; - width: 85px; - height: 85px; - padding-right: 20px; -} -.t204__item_img a { - border: solid #222 1px; - margin: 0; - display: block; - width: 85px; - height: 85px; - background-size: cover; -} -.t204__item_text { - display: table-cell; - width: 100%; - vertical-align: middle; - color: #fff; - font-size: 18px; -} -.t204__item_text a { - color: #fff !important; -} -@media screen and (max-width: 640px) { - .t204__burger { - position: static; - text-align: right; - top: 0; - right: 0; - width: 100%; - } - .t204__menu { - width: 100%; - height: auto; - position: absolute; - top: 60px; - } -} -.t216__wrapper { - padding-top: 42px; - padding-bottom: 42px; -} -.t216__blocklogo { - padding-bottom: 30px; - padding-top: 30px; -} -.t216__logo { - width: auto; - max-width: 100%; - vertical-align: middle; -} -.t216__title { - color: #fff; - padding: 24px 0px 38px 0px; - letter-spacing: 0.5px; -} -.t216__descr { - color: #fff; - padding: 0px 0px 30px 0px; -} -.t216__descr_center { - max-width: 700px; - margin: 0 auto; -} -.t216__descr_center a { - color: #fff !important; - font-weight: 600; -} -@media screen and (max-width: 640px) { - .t216__title { - padding-left: 10px; - padding-right: 10px; - } - .t216__descr { - padding-left: 10px; - padding-right: 10px; - font-size: 14px; - line-height: 20px; - } -} -.t219 { - text-align: center; - padding: 0 2px; -} -.t219__butwrapper { - margin: 0 auto; -} -.t219__blocktitle { - padding-bottom: 50px; -} -@media screen and (max-width: 640px) { - .t219 { - padding: 0 20px; - } -} -.t269__mainblock { - margin: 0 auto; -} -.t269__uptitle { - color: #fff; - position: absolute; - top: 80px; - left: 0; - right: 0; -} -.t269__title { - color: #fff; - margin-bottom: 24px; - padding-top: 20px; -} -.t269__descr { - color: #fff; - margin-bottom: 44px; -} -.t269__input-container { - max-width: 600px; - margin: 0 auto; -} -.t269__blockinput { - display: table-cell; - vertical-align: middle; - height: 100%; - width: 100%; - padding-right: 20px; -} -.t269__input { - height: 56px; - outline: none; -} -.t269__submit { - height: 56px; - padding-left: 40px; - padding-right: 40px; -} -.t269__blockinput input { - background-color: transparent; - -webkit-appearance: none; - border-radius: 0; -} -.t269__wrapper { - display: table; - -webkit-transition: all ease-in-out 0.2s; - -moz-transition: all ease-in-out 0.2s; - -o-transition: all ease-in-out 0.2s; - transition: all ease-in-out 0.2s; -} -.t269__blockinput.js-error-control-box .t269__input { - border: 1px solid #FF0000 !important; -} -.t269__blockinput-errors-text { - color: #ffff77; - box-sizing: border-box; - padding: 0px 10px 10px 10px; - font-family: 'Georgia', serif; -} -.t269__blockinput-errors-item { - padding-top: 10px; - display: none; - font-family: 'Georgia', serif; -} -.t269__blockinput-errorbox { - background: #ff6666 none repeat scroll 0px 0px; - color: #ffff77; - padding: 1px 10px; - text-align: center; - margin-bottom: 20px; - font-family: 'Georgia', serif; - margin-top: 20px; -} -.t269__hint { - color: #fff; - margin-top: 20px; - max-width: 600px; - margin: 20px auto 0; -} -.t269__blockinput-success { - text-align: center; - color: #fff; - padding: 20px; - font-family: 'Georgia', serif; -} -.t269__success-message { - color: #fff; -} -.t269 .js-send-form-success .t269__wrapper { - display: none; -} -@media screen and (max-width: 680px) { - .t269__blockinput { - display: block; - padding-right: 0; - width: 100%; - } - .t269__descr { - margin-bottom: 32px; - } - .t269__uptitle { - top: 40px; - font-size: 16px !important; - } - .t269__mainwrapper { - padding: 0 20px; - } - .t269__input-container { - max-width: 320px; - } - .t269__input { - width: 100%; - margin-bottom: 18px; - height: 42px; - font-size: 14px; - padding-left: 14px; - } - .t269__submit { - width: 100%; - height: 42px; - font-size: 14px; - } - .t269__wrapper { - display: block; - } -} -.t338__logo { - margin-bottom: 55px; - max-width: 280px; - width: 100%; -} -.t338__title { - color: #fff; - margin-bottom: 50px; -} -.t338__descr { - color: #fff; - margin-bottom: 63px; -} -.t338__btn { - border-radius: 100px; - font-size: 14px; - height: 50px; - padding-right: 34px; - padding-left: 34px; - color: #fff; -} -.t389__maincontainer { - width: 100%; - height: 80px; - display: table; -} -.t389__content { - padding: 2px 40px 0; - display: table-cell; - vertical-align: middle; -} -.t389__col { - display: table-cell; - vertical-align: middle; -} -.t389__col_center { - width: 100%; - padding: 0 16px; -} -.t389__list { - list-style-type: none; - padding-left: 0 !important; - margin-bottom: 0 !important; -} -.t389__list_item { - display: inline-block; - margin: 0 15px; -} -.t389__copyright, -.t389__scroll { - width: 250px; -} -.t389__typo { - font-size: 14px; - color: #222; -} -.t389__col_mobile { - display: none; -} -.t389_scrolltop { - position: relative; - padding-right: 12px; -} -.t389__icon { - position: absolute; - right: 0; - top: 2px; -} -@media screen and (max-width: 1200px) { - .t389__content { - padding: 2px 20px 0; - } - .t389__col, - .t389__copyright, - .t389__scroll { - width: 230px; - } - .t389__col_center { - width: 100%; - } -} -@media screen and (max-width: 960px) { - .t389__col, - .t389__copyright, - .t389__scroll { - width: 100%; - display: block; - text-align: center; - } - .t389__maincontainer { - display: block; - } - .t389__content { - display: block; - } - .t389__col_mobile { - display: block; - } - .t389__col_hiddenmobile { - display: none; - } - .t389__maincontainer { - height: auto !important; - padding: 40px 0; - } - .t389__col { - margin-bottom: 20px; - padding: 0; - } - .t389__list_item { - margin: 0 10px 4px; - } - .t389__col:last-child { - margin-bottom: 0; - } -} -@media screen and (max-width: 670px) { - .t389__typo { - font-size: 12px; - } -} -.t396__iframe { - z-index: 10000; - background-color: #fff; - width: 100vw; - height: 100vh; - position: fixed; - top: 0px; - left: 0px; - border: 0px; -} -.t396__body_overflow_hidden { - overflow: hidden; -} -.t396__display_none { - display: none; -} -.t396__artboard { - position: relative; - width: 100%; - height: 100vh; - overflow: hidden; -} -.t396__carrier { - position: absolute; - left: 0px; - top: 0px; - z-index: 0; - width: 100%; - height: 100vh; -} -.t396__filter { - position: absolute; - left: 0px; - top: 0px; - z-index: 0; - width: 100%; - height: 100vh; -} -.t396__elem { - position: absolute; - box-sizing: border-box; - display: table; -} -.t396 .tn-atom { - display: table-cell; - vertical-align: middle; - width: 100%; -} -.t396 a.tn-atom { - text-decoration: none; -} -.t396 .tn-atom__img { - width: 100%; - display: block; -} -.t396__ui { - position: absolute; - top: 16px; - left: 196px; - background-color: #fa876b; - color: #000 !important; - height: 30px; - line-height: 30px; - width: 100px; - z-index: 1000; - text-align: center; - border-radius: 3px; - display: none; - font-size: 14px; -} -.t411__mainblock { - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; - position: relative; - z-index: 2; -} -.t411__content { - padding: 30px 0; -} -.t411__hide { - display: none !important; -} -.t411__col { - display: inline-block; - padding-right: 32px; - margin-right: 30px; - position: relative; -} -.t411__col:after { - content: ' '; - position: absolute; - top: 0; - right: 0; - bottom: 0; - opacity: .2; - background: #fff; - width: 1px; -} -.t411__col:last-child:after { - display: none; -} -.t411__col:last-child { - margin-right: 0; - padding-right: 0; -} -.t411__number { - color: #fff; -} -.t411__text { - color: #fff; - padding-bottom: 7px; -} -.t411__logo { - margin-bottom: 45px; - max-width: 280px; - width: 100%; -} -.t411__textwrapper { - margin: 0 auto 55px; -} -.t411__uptitle, -.t411__title, -.t411__descr, -.t411__descr-second { - color: #fff; -} -.t411__uptitle { - margin-bottom: 18px; -} -.t411__descr { - margin-top: 18px; -} -.t411__hint { - color: #fff; - margin-top: 45px; -} -.t411__descr-second { - margin: 0 auto 25px; -} -.t411__formwrapper { - max-width: 600px; - margin: 50px auto 0; -} -.t411__blockinput { - display: table-cell; - vertical-align: middle; - height: 100%; - width: 100%; - padding-right: 20px; -} -.t411__input { - height: 56px; - outline: none; -} -.t411__submit { - height: 56px; - padding-left: 40px; - padding-right: 40px; -} -.t411__blockinput input { - -webkit-appearance: none; - border-radius: 0; -} -.t411__wrapper { - display: table; - -webkit-transition: all ease-in-out 0.2s; - -moz-transition: all ease-in-out 0.2s; - -o-transition: all ease-in-out 0.2s; - transition: all ease-in-out 0.2s; -} -.t411__blockinput.js-error-control-box .t411__input { - border: 1px solid #FF0000 !important; -} -.t411__blockinput-errors-text { - color: #ffff77; - box-sizing: border-box; - padding: 0px 10px 10px 10px; - font-family: 'Georgia', serif; -} -.t411__blockinput-errors-item { - padding-top: 10px; - display: none; - font-family: 'Georgia', serif; -} -.t411__blockinput-errorbox { - background: #ff6666 none repeat scroll 0px 0px; - color: #ffff77; - padding: 1px 10px; - text-align: center; - margin-bottom: 20px; - font-family: 'Georgia', serif; - margin-top: 20px; -} -.t411__blockinput-success { - text-align: center; - color: #fff; - padding: 20px; - font-family: 'Georgia', serif; -} -.t411__success-message { - color: #fff; -} -.t411 .js-send-form-success .t411__wrapper { - display: none; -} -@media screen and (max-width: 640px) { - .t411__blockinput { - display: block; - padding-right: 0; - width: 100%; - } - .t411__input-container { - max-width: 320px; - margin: 0 auto; - } - .t411__input { - width: 100%; - margin-bottom: 18px; - height: 42px; - font-size: 14px; - padding-left: 14px; - } - .t411__submit { - width: 100%; - height: 42px; - font-size: 14px; - } - .t411__wrapper { - display: block; - } - .t411__col { - padding-right: 20px; - margin-right: 13px; - } - .t411__logo { - margin-bottom: 25px; - } - .t411__textwrapper { - margin-bottom: 35px; - } - .t411__formwrapper { - margin-top: 35px; - } - .t411__hint { - margin-top: 35px; - } -} -@media screen and (max-width: 400px) { - .t411__number { - font-size: 24px; - } -} -.t454__imglogo { - height: auto; - display: block; -} -.t454__linewrapper { - position: absolute; - bottom: 0; - width: 100%; -} -.t454__horizontalline { - margin: 0; - border: 0; - background-color: #C2C2C2; - height: 1px; - right: 0; - bottom: 0; - margin: 0 40px 0 40px; -} -.t454__leftmenuwrapper, -.t454__rightmenuwrapper { - display: inline-table; - height: 100%; - vertical-align: middle; -} -.t454__leftmenuwrapper .t454__list, -.t454__rightmenuwrapper .t454__list { - display: table-cell; - vertical-align: middle; -} -.t454__logowrapper { - position: absolute; - left: 50%; - display: table; - height: inherit; -} -.t454__logowrapper2 { - display: table-cell; - vertical-align: middle; - position: relative; - left: -50%; - z-index: 100; -} -.t454__imglogo { - max-width: 300px; -} -.t454__leftwrapper, -.t454__rightwrapper { - width: 50%; - box-sizing: border-box; - position: absolute; - height: 100%; -} -.t454__leftwrapper { - text-align: right; - padding-right: 200px; - padding-left: 40px; - left: 0; -} -.t454__rightwrapper { - text-align: left; - padding-left: 200px; - padding-right: 40px; - right: 0; -} -@media screen and (max-width: 1200px) { - .t454__leftwrapper { - padding-left: 20px; - } - .t454__rightwrapper { - padding-right: 20px; - } -} -.t454 { - width: 100%; - height: 80px; - z-index: 990; - position: fixed; - top: 0; - box-shadow: 0px 1px 3px rgba(0,0,0,0); - -webkit-transition: background-color 300ms linear; - -moz-transition: background-color 300ms linear; - -o-transition: background-color 300ms linear; - -ms-transition: background-color 300ms linear; - transition: background-color 300ms linear; -} -.t454__beforeready { - visibility: hidden; -} -.t454 ul { - margin: 0px; -} -.t454__maincontainer { - width: 100%; - height: 80px; - display: table; - position: relative; -} -.t454__maincontainer.t454__c12collumns { - max-width: 1200px; - margin: 0 auto; -} -.t454__logo { - display: inline-block; - font-size: 24px; - font-weight: 400; - white-space: nowrap; -} -.t454__list { - list-style-type: none; - margin: 0px; - padding: 0 !important; -} -.t454__list_item { - clear: both; - font-family: 'Open Sans', sans-serif; - font-size: 16px; - display: inline; - padding-left: 15px; - padding-right: 15px; - margin: 0px; - color: #000000; - white-space: nowrap; -} -.t454__list_item .t-active { - opacity: 0.7; -} -.t454__list_item:first-child { - padding-left: 0; -} -.t454__list_item:last-child { - padding-right: 0; -} -.t454 a, -#allrecords .t454 a { - text-decoration: none; - color: #000000; -} -.t454.t454__positionabsolute { - position: absolute; -} -.t454.t454__positionfixed { - position: fixed; -} -.t454.t454__positionstatic { - position: static; -} -.t454__mobile { - display: none; -} -@media screen and (max-width: 980px) { - .t454.t454__hidden { - display: none; - height: 100%; - } - .t454__mobile { - background-color: #111; - display: block; - } - .t454__mobile_text { - color: #fff; - } - .t454__mobile_container { - padding: 20px; - position: relative; - } - .t454__burger { - position: absolute; - top: 50%; - margin-top: -10px; - right: 20px; - width: 28px; - height: 20px; - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - transform: rotate(0deg); - -webkit-transition: .5s ease-in-out; - -moz-transition: .5s ease-in-out; - -o-transition: .5s ease-in-out; - transition: .5s ease-in-out; - cursor: pointer; - z-index: 9999; - } - .t454__burger span { - display: block; - position: absolute; - width: 100%; - opacity: 1; - left: 0; - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - transform: rotate(0deg); - -webkit-transition: .25s ease-in-out; - -moz-transition: .25s ease-in-out; - -o-transition: .25s ease-in-out; - transition: .25s ease-in-out; - height: 3px; - background-color: #fff; - } - .t454__burger span:nth-child(1) { - top: 0px; - } - .t454__burger span:nth-child(2), - .t454__burger span:nth-child(3) { - top: 8px; - } - .t454__burger span:nth-child(4) { - top: 16px; - } - .t454_opened .t454__burger span:nth-child(1) { - top: 8px; - width: 0%; - left: 50%; - } - .t454_opened .t454__burger span:nth-child(2) { - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -o-transform: rotate(45deg); - transform: rotate(45deg); - } - .t454_opened .t454__burger span:nth-child(3) { - -webkit-transform: rotate(-45deg); - -moz-transform: rotate(-45deg); - -o-transform: rotate(-45deg); - transform: rotate(-45deg); - } - .t454_opened .t454__burger span:nth-child(4) { - top: 8px; - width: 0%; - left: 50%; - } - .t454__linewrapper { - display: none; - } - .t454 { - position: static; - text-align: center; - display: block; - margin: 0; - padding: 0; - height: auto !important; - } - .t454__maincontainer { - padding: 20px 0 40px 0; - } - .t454.t454__positionabsolute, - .t454.t454__positionfixed, - .t454.t454__positionstatic { - position: static; - } - .t454__imglogo { - width: auto !important; - box-sizing: border-box; - padding: 20px; - margin: 0 auto; - } - .t454__imglogomobile.t454__imglogo { - width: 100% !important; - } - .t454__rightcontainer { - display: table; - position: static; - float: none; - text-align: center; - margin: 0 auto; - } - .t454__logo { - text-align: center; - margin: 20px; - } - .t454 img { - float: inherit; - } - .t454 .t454__list_item { - display: block; - text-align: center; - padding: 10px !important; - white-space: normal; - } - .t454__logo { - white-space: normal; - padding: 0px; - } - .t454__logowrapper { - position: static; - display: table; - width: 100%; - padding: 20px; - box-sizing: border-box; - } - .t454__logowrapper2 { - display: block; - position: static; - } - .t454__leftwrapper, - .t454__rightwrapper, - .rightmenuwrapper { - position: static; - padding: 0 !important; - width: 100%; - } - .t454__rightmenuwrapper, - .t454__leftmenuwrapper, - .t454__leftmenuwrapper .t454__list, - .t454__rightmenuwrapper .t454__list { - display: block; - } -} diff --git a/css/tilda-custom.css b/css/tilda-custom.css deleted file mode 100644 index 5bea168b..00000000 --- a/css/tilda-custom.css +++ /dev/null @@ -1,89 +0,0 @@ -a, a:hover, a:visited { - text-decoration: underline !important; - color: white !important; -} - -a.external, a.external:hover, a.external:visited { - text-decoration: underline !important; - color: #1396e2 !important; -} - -a.t-btn { - color: black !important; -} - -.disclaimer { - font-size: 22px; -} -@media screen and (min-width: 640px) and (max-width: 1200px) { - - .disclaimer { - font-size: 18px; - } - - .t269__title { - margin-top: 40px; - } -} - -@media screen and (max-width: 980px){ - .t269__title { - font-size: 50px; - } - .t454__maincontainer { - padding: 0 !important; - } -} - -@media screen and (max-width: 639px) { - .t269__title { - font-size: 40px; - } - .disclaimer { - font-size: 14px; - } -} - -@media screen and (max-width: 400px) { - .t269__title { - font-size: 30px; - } - .t415__number { - font-size: 24px; - } -} - -@media screen and (max-width: 360px) { - .t269__mainwrapper { - padding: 0 10px; - } -} - -#ui-id-1 { - margin-top: 4px !important; -} - -.ui-autocomplete { - overflow: hidden; - border-radius: 4px; -} - -.ui-autocomplete li { - font-size: 16px; - white-space: nowrap; -} - -li.ui-menu-item.not-found { - opacity: 1 !important; - color: #aaa; - pointer-events: none; -} - -li.ui-menu-item.have-more { - opacity: 1 !important; - color: #aaa; - padding-top: 4px; - border-top: 1px dotted #aaa; - font-style: italic; - pointer-events: none; -} diff --git a/css/tilda-grid-3.0.min.css b/css/tilda-grid-3.0.min.css deleted file mode 100644 index 69ee01bd..00000000 --- a/css/tilda-grid-3.0.min.css +++ /dev/null @@ -1 +0,0 @@ -.t-clear,.t-container:after,.t-container_100:after,.t-container_10:after,.t-container_8:after{clear:both}*,:after,:before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}a,b,blockquote,center,code,div,h1,h2,h3,h4,h5,h6,i,img,p,pre,span,table,td,th,tr,u,video{margin:0;padding:0;border:0}.t-row{margin:0}.t-container,.t-container_10,.t-container_8{margin-left:auto;margin-right:auto;padding:0;width:100%}.t-container{max-width:1200px}.t-container.flexx,.t-container_flex{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.t-container_100{width:100%;padding:0}.t-container_10{max-width:1000px}.t-container_8{max-width:800px}.t-container:after,.t-container:before,.t-container_100:after,.t-container_100:before,.t-container_10:after,.t-container_10:before,.t-container_8:after,.t-container_8:before{display:table;content:" "}.t-col{display:inline;float:left;margin-left:20px;margin-right:20px;width:100%}.t-col.flexx,.t-col_flex{align-items:stretch;height:inherit;margin-top:auto;margin-bottom:auto}.t-col_1{max-width:60px}.t-col_2{max-width:160px}.t-col_3{max-width:260px}.t-col_4{max-width:360px}.t-col_5{max-width:460px}.t-col_6{max-width:560px}.t-col_7{max-width:660px}.t-col_8{max-width:760px}.t-col_9{max-width:860px}.t-col_10{max-width:960px}.t-col_11{max-width:1060px}.t-col_12{max-width:1160px}.t-col_100{max-width:100vw}.t-prefix_1{padding-left:100px}.t-prefix_2{padding-left:200px}.t-prefix_3{padding-left:300px}.t-prefix_4{padding-left:400px}.t-prefix_5{padding-left:500px}.t-prefix_6{padding-left:600px}.t-prefix_7{padding-left:700px}.t-prefix_8{padding-left:800px}.t-prefix_9{padding-left:900px}.t-prefix_10{padding-left:1000px}.t-prefix_11{padding-left:1100px}.t-prefix_12{padding-left:1200px}.t-width{width:100%}.t-width_1{max-width:60px}.t-width_2{max-width:160px}.t-width_3{max-width:260px}.t-width_4{max-width:360px}.t-width_5{max-width:460px}.t-width_6{max-width:560px}.t-width_7{max-width:660px}.t-width_8{max-width:760px}.t-width_9{max-width:860px}.t-width_10{max-width:960px}.t-width_11{max-width:1060px}.t-width_12{max-width:1160px}.t-width_100{max-width:100%}.t-cell{display:table-cell;vertical-align:middle;height:100%;margin-left:0;margin-right:0}.t-cell_25{width:25vw}.t-cell_33{width:33.3333333vw}.t-cell_50{width:50vw}.t-cell_100{width:100vw}@media screen and (max-width:1200px){.t-container{max-width:960px;padding:0}.t-container_10{max-width:780px}.t-container_8{max-width:640px}.t-col{display:inline;float:left;margin-left:10px;margin-right:10px;width:100%}.t-col_1{max-width:60px}.t-col_2{max-width:140px}.t-col_3{max-width:220px}.t-col_4{max-width:300px}.t-col_5{max-width:380px}.t-col_6{max-width:460px}.t-col_7{max-width:540px}.t-col_8{max-width:620px}.t-col_9{max-width:700px}.t-col_10{max-width:780px}.t-col_11{max-width:860px}.t-col_12{max-width:940px}.t-prefix_1{padding-left:80px}.t-prefix_2{padding-left:160px}.t-prefix_3{padding-left:240px}.t-prefix_4{padding-left:320px}.t-prefix_5{padding-left:400px}.t-prefix_6{padding-left:480px}.t-prefix_7{padding-left:560px}.t-prefix_8{padding-left:640px}.t-prefix_9{padding-left:720px}.t-prefix_10{padding-left:800px}.t-prefix_11{padding-left:880px}.t-prefix_12{padding-left:960px}.t-width_1{max-width:60px}.t-width_2{max-width:140px}.t-width_3{max-width:220px}.t-width_4{max-width:300px}.t-width_5{max-width:380px}.t-width_6{max-width:460px}.t-width_7{max-width:540px}.t-width_8{max-width:620px}.t-width_9{max-width:700px}.t-width_10{max-width:780px}.t-width_11{max-width:860px}.t-width_12{max-width:940px}.t-width_100{max-width:100%}}@media screen and (max-width:960px){.t-col,.t-container.flexx,.t-container_flex{display:block}.t-container{max-width:640px}.t-col,.t-col_1,.t-col_10,.t-col_11,.t-col_12,.t-col_2,.t-col_3,.t-col_4,.t-col_5,.t-col_6,.t-col_7,.t-col_8,.t-col_9{width:100%;max-width:100%}.t-col{float:none;padding-left:20px;padding-right:20px;margin:0;box-sizing:border-box}.t-prefix_1,.t-prefix_10,.t-prefix_11,.t-prefix_12,.t-prefix_2,.t-prefix_3,.t-prefix_4,.t-prefix_5,.t-prefix_6,.t-prefix_7,.t-prefix_8,.t-prefix_9{padding-left:none}} \ No newline at end of file diff --git a/css/tilda-zoom-1.0.min.css b/css/tilda-zoom-1.0.min.css deleted file mode 100644 index 8eb03a3a..00000000 --- a/css/tilda-zoom-1.0.min.css +++ /dev/null @@ -1 +0,0 @@ -.t-zoomer__show_fixed{max-height:100%;max-width:100%;overflow:hidden}.t-zoomer__wrapper{position:fixed;top:0;left:0;right:0;bottom:0;z-index:-1;opacity:0;-webkit-transition:all ease-in-out .2s;-moz-transition:all ease-in-out .2s;-o-transition:all ease-in-out .2s;transition:all ease-in-out .2s}.t-zoomer__show .t-zoomer__wrapper{z-index:9999999;opacity:1}.t-zoomer__container{text-align:center;position:absolute;top:0;right:0;left:0;bottom:0}.t-zoomer__bg{position:absolute;top:0;right:0;left:0;bottom:0;background:#fff;cursor:-webkit-zoom-out;cursor:zoom-out}.t-zoomer__comments{position:absolute;right:0;bottom:0;left:0;display:block;height:auto}.t-zoomer__descr{z-index:3;text-align:center;padding:14px 20px 0;background:transparent;max-width:700px;margin:0 auto}.t-zoomable{cursor:-webkit-zoom-in;cursor:zoom-in}.t-zoomer__show .t-zoomable,.t-zoomer__show .t-carousel__zoomer__inner{cursor:-webkit-zoom-out;cursor:zoom-out}.t-zoomer__container{z-index:99999999}.t-carousel__zoomed,.t-carousel__zoomer__slides,.t-carousel__zoomer__inner,.t-carousel__zoomer__item,.t-carousel__zoomer__wrapper{position:absolute;top:0;right:0;bottom:0;left:0}.t-carousel__zoomer__inner{top:15px;right:15px;bottom:15px;left:15px}.t-carousel__zoomer__img{position:absolute;top:0;bottom:0;left:0;right:0;max-width:100%;max-height:100%;margin:auto;overflow:auto}.t-carousel__zoomer__item{height:100%;display:none}.t-zoomer__close{position:fixed;right:10px;top:12px;width:29px;height:32px;cursor:pointer;-webkit-transition:opacity ease-in-out 0.3s;-moz-transition:opacity ease-in-out 0.3s;-o-transition:opacity ease-in-out 0.3s;transition:opacity ease-in-out 0.3s;z-index:999999999999}.t-zoomer__close:hover{opacity:.7}.t-zoomer__close-line{position:absolute;left:15px;height:26px;width:2px;background-color:#222}.t-zoomer__close-line-first{-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t-zoomer__close-line-second{-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-webkit-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.t-carousel__zoomer__control{position:absolute;top:0;bottom:0;left:0;width:15%;-webkit-transition:opacity ease-in-out 0.3s;-moz-transition:opacity ease-in-out 0.3s;-o-transition:opacity ease-in-out 0.3s;transition:opacity ease-in-out 0.3s;cursor:pointer;z-index:99}.t-carousel__zoomer__control_right{left:auto;right:0}.t-carousel__zoomer__control:hover{opacity:.6}.t-carousel__zoomer__arrow{width:20px;height:20px;background:transparent;-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.t-carousel__zoomer__arrow__wrapper{-moz-transform:translateY(-50%);-ms-transform:translateY(-50%);-webkit-transform:translateY(-50%);-o-transform:translateY(-50%);transform:translateY(-50%);position:absolute;top:50%}.t-carousel__zoomer__arrow__wrapper_left{left:18px}.t-carousel__zoomer__arrow__wrapper_right{right:18px}.t-carousel__zoomer__arrow_right{border-top:2px solid;border-right:2px solid}.t-carousel__zoomer__arrow_left{border-left:2px solid;border-bottom:2px solid}@media screen and (max-width:768px){.t-carousel__zoomer__control .t-carousel__zoomer__arrow{width:12px;height:12px}.t-carousel__zoomer-control{width:10%}.t-carousel__zoomer__arrow__left{left:15px}.t-carousel__zoomer__arrow__right{right:15px}} \ No newline at end of file diff --git a/extensions/CryptoKitties/css/styles.css b/extensions/CryptoKitties/css/styles.css deleted file mode 100644 index 17a345f2..00000000 --- a/extensions/CryptoKitties/css/styles.css +++ /dev/null @@ -1,82 +0,0 @@ -.ck-kitty { - display:inline-block; - vertical-align:top; - height:200px; - width:200px; - border:1px solid white; - border-radius:6px; - color:white; - text-align:center; - margin-bottom:32px; -} - -.ck-kitty-dashed { - border-style: dashed; -} - -#ck-symbol { - display:inline-block; - vertical-align:top; - width:70px; - height:200px; - line-height:200px; - color:white; - font-size:64px; -} - -.ck-show-small { - display:none; -} - -#ck-full td, -#ck-address-block tr.last td { - text-align: center; -} - -#ck-full .ck-kitty, -#ck-address-block tr.last td .ck-kitty { - margin-left: 10px; - margin-right: 10px; -} - -#ck-address-block tr.last td .ck-link { - cursor: pointer; - text-decoration: none !important; - border-bottom: 1px dashed #47C2FF; -} - -#ck-full td, -#ck-address-block tr.last td { - padding-top:20px; -} - -#ck-loading { - color: white; -} - -.ck-full-close { - top: 24px; - position: absolute; - right: 32px; - font-size: 30px; - color: #444; - cursor: pointer; -} - -@media screen and (min-width: 992px) and (max-width: 1200px) { - .ck-has-kitties { - clear: left !important; - width: 100% !important; - } -} - -@media screen and (max-width: 550px) { - .ck-show-small { - display:inline; - } - - #ck-symbol { - height:72px; - line-height:64px; - } -} \ No newline at end of file diff --git a/extensions/CryptoKitties/css/tipr.css b/extensions/CryptoKitties/css/tipr.css deleted file mode 100644 index af1c968e..00000000 --- a/extensions/CryptoKitties/css/tipr.css +++ /dev/null @@ -1,86 +0,0 @@ -/* -Tipr 3.2 -Copyright (c) 2017 Tipue -Tipr is released under the MIT License -http://www.tipue.com/tipr -*/ - - -.tipr_content -{ - font: 300 11px/1.7 'Roboto Condensed', sans-serif; - color: #777; - text-transform: uppercase; - letter-spacing: 1px; - background-color: #f3f3f3; - padding: 7px 14px 6px 14px; -} -.tipr_container_below -{ - display: none; - position: absolute; - margin-top: 7px; - z-index: 1000; -} -.tipr_container_above -{ - display: none; - position: absolute; - margin-top: -67px; - z-index: 1000; -} -.tipr_point_above, .tipr_point_below -{ - position: relative; - background: #f3f3f3; - border: 1px solid #f3f3f3; - border-radius: 1px; -} -.tipr_point_above:after, .tipr_point_above:before -{ - position: absolute; - pointer-events: none; - border: solid transparent; - top: 100%; - content: ""; - height: 0; - width: 0; -} -.tipr_point_above:after -{ - border-top-color: #f3f3f3; - border-width: 8px; - left: 50%; - margin-left: -8px; -} -.tipr_point_above:before -{ - border-top-color: #f3f3f3; - border-width: 9px; - left: 50%; - margin-left: -9px; -} -.tipr_point_below:after, .tipr_point_below:before -{ - position: absolute; - pointer-events: none; - border: solid transparent; - bottom: 100%; - content: ""; - height: 0; - width: 0; -} -.tipr_point_below:after -{ - border-bottom-color: #f3f3f3; - border-width: 8px; - left: 50%; - margin-left: -8px; -} -.tipr_point_below:before -{ - border-bottom-color: #f3f3f3; - border-width: 9px; - left: 50%; - margin-left: -9px; -} \ No newline at end of file diff --git a/extensions/CryptoKitties/img/stroller.png b/extensions/CryptoKitties/img/stroller.png deleted file mode 100644 index ab44fc1eaca60da1b006fdc3d589dd25fd06de54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 274823 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

    b-$%C69pjN1us@u13Fc8~#Vgm~1i^O!M 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 CryptoKitties...

    '); - $('#address-token-balances').parent().after('
    ') - $.getJSON('/extensions/CryptoKitties/service.php', {action:"getAddress", address:address}, function(data){ - $('#ck-loading').hide(); - $('#ck-address-block tr.last td').empty(); - if(data && data.total){ - Ethplorer.Extensions.CryptoKitties.data = data; - $('#address-token-balances').parent().append('

    CryptoKitties

    '); - for(var i=0; i< data.kitties.length; i++){ - if(i
    "); - Ethplorer.Extensions.CryptoKitties.showKittyData('ck-' + i, data.kitties[i], false); - } - $('#ck-full td').append("
    "); - Ethplorer.Extensions.CryptoKitties.showKittyData('ck-' + i + '-f', data.kitties[i], false); - } - if(data.total > limit){ - $('#ck-address-block tr.last td').append(''); - $('.ck-link').click(function(){ - $('#ck-address-block').hide(); - $('#ck-full').show(); - }); - $('.ck-full-close').click(function(){ - $('#ck-address-block').show(); - $('#ck-full').hide(); - }); - if(data.total > 20){ - $('#ck-full table').after("
    Last 20 of " + data.total + " kitties shown
    "); - } - } - } - }); - }, - onTxDetails: function(txData){ - var oTx = txData.tx; - if(oTx.to && (Ethplorer.Extensions.CryptoKitties.contract === oTx.to) && oTx.method){ - Ethplorer.Extensions.CryptoKitties.gaSendEvent('CK-txDetails'); - var p = oTx.method.replace('(', ' ').replace(',', ' ').replace(')', '').split(' '); - var cmd = p[0]; - $('.token-operation-type').text(cmd); - var m1 = ['giveBirth', 'createSaleAuction'] - if(m1.indexOf(p[0]) >= 0){ - var data = oTx.input.slice(8).substr(0,64).replace(/^0+/, ''); - var id = parseInt(data, 16); - if(id){ - $('#token-information-block').addClass('text-center'); - $('#token-information-block').html('
    '); - Ethplorer.Extensions.CryptoKitties.showKitty('ck-1', id); - } - } - var m2 = ['bidOnSiringAuction', 'breedWithAuto'] - if(m2.indexOf(p[0]) >= 0){ - var data1 = oTx.input.slice(8).substr(0,64).replace(/^0+/, ''); - var data2 = oTx.input.slice(8).substr(64,64).replace(/^0+/, ''); - var id1 = parseInt(data1, 16); - var id2 = parseInt(data2, 16); - if(id1 && id2){ - $('#token-information-block').addClass('text-center'); - $('#token-information-block').empty(); - $('#token-information-block').append('

    '); - $('#token-information-block').append('

    '); - $('#token-information-block').append('
    '); - Ethplorer.Extensions.CryptoKitties.showKitty('ck-1', id1); - Ethplorer.Extensions.CryptoKitties.showKitty('ck-2', id2); - var symbol = '?'; - if('breedWithAuto' == p[0]){ - $("#ck-symbol").css('color', 'red'); - symbol = '❤'; - } - $("#ck-symbol").html(symbol); - } - } - if(Ethplorer.Extensions.CryptoKitties.show){ - $('#token-information-block, #token-operation-block').addClass('ck-has-kitties'); - } - if(oTx.receipt && oTx.receipt.logs && oTx.receipt.logs.length){ - for(var i=0; i"); - var block = parseInt(oLog.data.substr(64 * 3 + 2), 16); - var currentBlock = oTx.blockNumber + oTx.confirmations; - var blocksTillBirth = block - currentBlock; - var msg = ""; - if(blocksTillBirth > 0){ - msg = "A new kitty should be born in " + blocksTillBirth + " blocks"; - $('#token-information-block').append('
    '); - $("#ck-3").html(""); - $('#ck-3').append("
    " + msg + "
    "); - setInterval(function(){ - var cnt = parseInt($('.ck-counter:eq(0)').text()); - if(cnt > 0){ - cnt--; - $('.ck-counter').text(cnt); - } - }, 15000); - }else{ - var matronId = parseInt(oLog.data.substr(64 + 2, 64), 16); - var sireId = parseInt(oLog.data.substr(64 * 2 + 2, 64), 16); - var matron = Ethplorer.Extensions.CryptoKitties.data[matronId]; - Ethplorer.Extensions.CryptoKitties.i = setInterval(function(_m, _s){ - return function(){ - if(Ethplorer.Extensions.CryptoKitties.data[_m] && Ethplorer.Extensions.CryptoKitties.data[_s]){ - clearInterval(Ethplorer.Extensions.CryptoKitties.i); - var matron = Ethplorer.Extensions.CryptoKitties.data[_m]; - if(matron && matron.children && matron.children.length){ - var kitty = false; - if(1 === matron.children.length){ - kitty = matron.children[0]; - } - if(kitty){ - $('#token-information-block').append('
    '); - Ethplorer.Extensions.CryptoKitties.showKittyData('ck-3', kitty, false); - $('#ck-3 span').append('
    born on block ' + $('.ck-block').text()); - } - } - } - } - }(matronId, sireId), 1000); - msg = "Kitty born on block " + block + ''; - } - $('#operation-status').before(infoTR); - infoTR.find("td:eq(1)").html(msg); - break; - } - } - } - } - }, - showKitty: function(containerId, id){ - Ethplorer.Extensions.CryptoKitties.show = true; - $('#' + containerId).html("Loading..."); - $.getJSON('/extensions/CryptoKitties/service.php', {action:"getKitty", id:id}, function(data){ - Ethplorer.Extensions.CryptoKitties.data[id] = data; - Ethplorer.Extensions.CryptoKitties.showKittyData(containerId, data, true); - }); - }, - showKittyData: function(containerId, data, tooltip){ - var bgColors = { - coral: "#c5eefa", - babyblue: "#dcebfc", - topaz: "#d1eeeb", - mintgreen: "#cdf5d4", - limegreen: "#d9f5cb", - babypuke: "#eff1e0", - chestnut: "#efe1da", - strawberry: "#fcdede", - pumpkin: "#fae1ca", - gold: "#faf4cf", - sizzurp: "#dfdffa", - bubblegum: "#fadff4", - violet: "#ede2f5", - thundergrey: "#eee9e8" - }; - if(data["color"] && bgColors[data["color"]]){ - $('#' + containerId).css("background-color", bgColors[data["color"]]); - } - var img = $(''); - if(tooltip){ - img.attr("data-tip", data["bio"] ? data["bio"] : ""); - img.addClass('tip'); - } - $('#' + containerId).html(img); - $('#' + containerId).append("Kitty " + data["id"] + " - Gen " + data["generation"] + ""); - if(tooltip){ - $('.tip').tipr(); - } - } -}; diff --git a/extensions/CryptoKitties/js/tipr.min.js b/extensions/CryptoKitties/js/tipr.min.js deleted file mode 100644 index e8d539fe..00000000 --- a/extensions/CryptoKitties/js/tipr.min.js +++ /dev/null @@ -1,10 +0,0 @@ -(function($){$.fn.tipr=function(options){var set=$.extend({'speed':200,'mode':'below','space':70},options);return this.each(function(){var mouseY=-1;$(document).on('mousemove',function(event) -{mouseY=event.clientY;});var viewY=$(window).height();$(this).hover(function() -{var d_m=set.mode;$(window).on('resize',function() -{viewY=$(window).height();});if(viewY-mouseY
    '+$(this).attr('data-tip')+'
    ';$(this).after(out);var w_t=$(tipr_cont).outerWidth();var w_e=$(this).width();var m_l=(w_e / 2)-(w_t / 2);$(tipr_cont).css('margin-left',m_l+'px');$(this).removeAttr('title alt');$(tipr_cont).fadeIn(set.speed);},function() -{$(tipr_cont).remove();});});};})(jQuery); \ No newline at end of file diff --git a/extensions/CryptoKitties/service.php b/extensions/CryptoKitties/service.php deleted file mode 100644 index 11423d99..00000000 --- a/extensions/CryptoKitties/service.php +++ /dev/null @@ -1,44 +0,0 @@ - 'memcached')); - -$oCache = $es->getCache(); - -$api = "https://api.cryptokitties.co/kitties"; - -if(isset($_GET["action"]) && ("getKitty" === $_GET["action"])){ - $id = isset($_GET["id"]) ? (int)$_GET["id"] : false; - if($id){ - $cacheId = "ck-kitty-" . $id; - $result = $oCache->get($cacheId, FALSE, TRUE, 600); - if(!$result){ - $result = file_get_contents($api . "/" . $id); - $oCache->save($cacheId, $result); - } - if($result){ - echo $result; - die(); - } - } -} - -if(isset($_GET["action"]) && ("getAddress" === $_GET["action"])){ - $address = isset($_GET["address"]) ? strtolower(preg_replace("/[^a-fA-F0-9x]/", "", $_GET["address"])) : false; - if($address){ - $cacheId = "ck-kitty-" . $address; - $result = $oCache->get($cacheId, FALSE, TRUE, 600); - if(!$result){ - $result = file_get_contents($api . "?owner_wallet_address=" . $address . '&limit=20'); - $oCache->save($cacheId, $result); - } - if($result){ - echo $result; - die(); - } - } -} - -// ?owner_wallet_address= - -echo '{"error":"Invalid Request"}'; \ No newline at end of file diff --git a/favicon-16x16.png b/favicon-16x16.png deleted file mode 100644 index 5af256cd69608de21122c70fc15025290d1e510a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 599 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+ueoXe|!I#{XiaP zfk$L90|U1(2s1Lwnj--eWH0gbb!C6RF2l=htk%44Hc;rfr;B5V#`)5V`?XsOMc6)^ ze;r<~aL6I3OQ_j3(0p-rkdcSiUDnC_52OUREuC^OZ5Q`Oi5s5NqS=^V{*&N%z1Di; zi@o=+*Uo)ubH4c8<)4m5W;xj(^L?tqOl5-tCzM;5Eqv!3r@OX3($z1_)6Q3};JL@_ z6Z;lTeAX1(f9${ncJ`>rpVoxWHjD~2lRq{0Tc7}eqyP%H2zEpp0@haX3pqEukTq8Cy&nOiTJTUc4xd$I_#u!2j2 y$>9`c<;@`qr*B+2apcSqnIr6{8$1?x=`p+#7cBYYWI7dS1%s!npUXO@geCx3D%;Tj diff --git a/favicon-32x32.png b/favicon-32x32.png deleted file mode 100644 index 1ebd5510bc93fb052777ae54ce6339ecd170e6ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-G$+Qd;gjJKptm- zM`SSr1Gg{;GcwGYBLNg-FY)wsWq-gf!^>@~*1T>u0|VnbPZ!4!kK=Q%*m{TtNF4h( zKaN{-vcpNG><)ts2bbzQEB%_l!PI#$J^9`<9__te{eJV@@0S0c&zb(YNXTeqz+5eP)u$_?-q&tckFS|{ z+o>WUvyQR-ub9)Nmo*=*#&NB;75|lcLR7yfP@>pjuj0dHtvgxY%sM2b$C=Fcv}yWF zpRl4Qr67Je8qlc|gEu8MbyQ+D)-*#PQzalAM zrQ`SV+;z2{44?MtyR><3P5ai6mEW>lEBH2hFZWt5W0T4=OA4~8uK(Y9#HOc{hfy(L z)~%R#`wTM5qxM{5UwC|0iS)K#N;clcUq!82=YLDvvGDP+*41KXin`{APl{48Vx6)> zugB8p^v(CvFD$$xv+9%6kBrYfucG!k&Hq~b@Ir#eiy*^L&C+0rQVZ!hEya_ZR#z@? z*v$FRYnkG_l||oM;{UgmEnj~~S$p%*#JP40!?$|%w=!B69b9;FMZs~?M5oP7G0a`D zVrsrz=9hT$)7D1boFyt=akR{00i$`l>h($ diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index aa9c043f052b38482c386c1eaef9f7f6bc627f09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmdU$36NCP6^0)Qj379OQC#U!5RjO-qfo{sI-n*oafO5!jRjJ;#Y)8`WE(BiiJF9z ziJHX-m84P#Bp53eBrIW5h(Re)1QeYa27?v+!_;dx#|Ls0JLd9P8|k5uhbx_jO|C=5e~F5Wjm z^;sF5OSqs;sBS&w;ZRG` z1805;S|jHFtK?6CqhYmEulCt+5Y&o%6-Rc0`M!(%HI8#*$iL;Ze@Ol|=mvXRPQ-zY zV7@DT5bD50e%=o9+w|Tf-w1nC>KXjcU_L3;ouxGs7Oj^#;OefTJTR=-MP<$DRB-3? z4a(52`CFjanjVLayI1~8c_MVBG%(mRV7@Dz z1%08I=>ED7+_S2M^6AAo#?;;mJHG|j_ZKM-i(r2Mx{E?K=2QMu1RLe5PNw5-F#kKq zUsi^(k@QhqXLfW?-wpdiwd70;w}FkRHP8&@#x&Q_H|5xSkNhQ24LKB}{{Zt{>EA*1 z<%-tg@4&UWj`GlQ4HoF9`Ta4td#;u82&hz!#lRYHpW#oG`&4S!>3=zS#f~+1x;R2*fRl@16j6{uLWl zdLJB&jRhgQ4^i#`amo~oY2TXvuaMW?i$fGsy61!L+%LvqIIyAfej}LgT0=JlZE+;} z4Sxb=U+FTaneppPjE;W0lkJyy+YBzzAa=i0*8#IZ#^3?-*g|tg6=SN^r+ld|K+d zy$W4-AL*T;!v;x5y_;u%dW*ozqX}*zG0si(92927e9aztSf`--HT@ z?vbB?+h-}|IPMY5M3xii@iLe{y8o~5#7ZM=+Z}zqFJ9P*epfWfUpH>qM0r@Af%{Xp z5bRl%{u1L%WMeD}(OY2JO%N4y(x$h@0Q9j;P*o*ljV{8A~GbkR={xq4lw`2sowpMtVPEipA-iut`7VDK6RHmdbOO@x>sD_ zKEtDw>uT9)$2Y|T?t95*%Aa=H_l0Z{Czrz-7`HDtoX5w5snhqTs+~7}R#>Qhrpafu z`hGf@OH+v;t0>uV?;L+J1 zSve%$FE5Ju&w;TJ_cuFC7M1hR*b0i z+M5f~(fXJKamWyitOMC?hfz>S6iaLX>9)WbP>J-Rv&FqB^4FJOOfiAhhkRH7S~um2 z-i_@Wzzp)eOEAKlI z;0q8{^e(ssWJCYnHWW&gTTxU$p?z2GnRXL>?b}8(`BLR-6zzA{Uf-|Ojv>8oQMUVG zYN)NVqW1C=py${8p9@iCI2~RA*;oTQr=!T(DC;~|f9<0v(MwPC9|`*IA{`G=MRTsb zqw#gF>bERawBGezslI=Ja?fJT*}nrjn@KgN#pDPSEH-H&e^RjyMcOrYnnOK{=2UZA zNVHGx0O_XTJ5Z@;?lgz8sX5hMR7lRE;Xfc_9HKdF1=)QX4u`Pxq2ezfop)g@ z#3{F6OnX^p`j7G$o=Dvu(D*+G-2-uo=2CaR?7t3Yg2`Yq>p^WVz;RFwxd5XUhs-5^ zAn0!U1!(LPTm#h-&FKSRV_ijFzjN3ps;VaLTyJ8OwP3%=h^meHNyC#U+FH}tT9ZHg zq)JsweX%|dG`4sO^6g2gt0p6{+y-yMMO7Q6uwmU#pMyr|QCO|>7JV(qexlK5gj6EO zj_JPNzKRbe?Y_SXrtk3mL`pPelIf;&_OG8vH~Ew@N!5w0j&z0kZ3EenJt6xVN9c0} zG7R^0u{XfS|DQ~|taQpz=M|GHQIOwXaTIkHZGp*7UB2vRsoV&6fjeiK%kROfQ0Oet&!yOKKIFS! z>#5g0xDfKa`{?~mG3D2wkbH@T?a-JoAUc>bL}7fGpDOQ>id7y%f%7^ diff --git a/go.php b/go.php deleted file mode 100644 index d8bd2414..00000000 --- a/go.php +++ /dev/null @@ -1,23 +0,0 @@ -0){ - $sLink = $_GET["link"]; - $fp = @fopen(dirname(__FILE__) . "/service/log/go-links.log", "a+"); - if($fp){ - $t = date('Y-m-d H:i:s')." - ".$sLink." - ".@getenv("REMOTE_ADDR")." - ".@getenv("HTTP_REFERER"). " - ".@getenv("HTTP_USER_AGENT")."\r\n"; - @fwrite($fp, $t); - } -} - -header("HTTP/1.1 301 Moved Permanently"); -header("Location: " . $sLink); - -?> - \ No newline at end of file diff --git a/index.php b/index.php deleted file mode 100644 index 6464fd41..00000000 --- a/index.php +++ /dev/null @@ -1,878 +0,0 @@ - $part){ - $rParts[$i] = strtolower($part); -} -if(3 === count($rParts)){ - if(('tx' === $rParts[1]) && $es->isValidTransactionHash($rParts[2])){ - $header = "Transaction hash: " . $rParts[2]; - $error = FALSE; - $aTxInfo = $es->getTransactionInfo($rParts[2]); - if(isset($aTxInfo['token']) && isset($aTxInfo['token']['name'])){ - $title .= $aTxInfo['token']['name'] . ' token transfer'; - if(isset($aTxInfo['opValue'])){ - $title .= ' for ' . $aTxInfo['opValue']; - } - if(isset($aTxInfo['token']['symbol'])){ - $title .= ' [' . $aTxInfo['token']['symbol'] . ']'; - } - $title .= ' - ' . $rParts[2] . ' - transaction hash | by Ethplorer'; - }else if(isset($aTxInfo['tx']) && isset($aTxInfo['tx']['value'])){ - $title .= 'Ethereum transaction for ' . $aTxInfo['tx']['value'] . ' [ETH] - ' . $rParts[2] . ' - transaction hash | by Ethplorer'; - } - } - if(('address' === $rParts[1]) && $es->isValidAddress($rParts[2])){ - $header = "Address: " . $rParts[2]; - $address = $rParts[2]; - $error = FALSE; - $aAddressInfo = $es->getAddressInfo($rParts[2]); - $checksumAddress = $es->getChecksumAddress($rParts[2]); - if(isset($aAddressInfo['token'])){ - if(isset($aAddressInfo['token']['symbol'])){ - $title .= '[' . $aAddressInfo['token']['symbol'] . ']'; - } - if(isset($aAddressInfo['token']['name'])){ - $title .= ' ' . $aAddressInfo['token']['name']; - if(strpos($aAddressInfo['token']['name'], ' Token') === false){ - $title .= ' Token'; - } - $title .= ' viewer'; - } - if(isset($aAddressInfo['token']['price']) && isset($aAddressInfo['token']['price']['rate'])){ - $title .= ' and price chart'; - } - $title .= ' - Ethereum contract address ' . $checksumAddress . ' | Ethplorer'; - $aAddressInfo['title'] = $title; - }else if(isset($aAddressInfo['contract'])){ - $title .= $checksumAddress . ' - ethereum contract explorer - Ethplorer'; - }else{ - $title .= $checksumAddress . ' - ethereum address history, charts and balances explorer - Ethplorer'; - } - } - if(('token' === $rParts[1]) && $es->isValidAddress($rParts[2])){ - $header = "Token address: " . $rParts[2]; - $error = FALSE; - } -} -if($error){ - header('HTTP/1.0 404 Not Found', true, 404); - if(isset($rParts[1]) && !$rParts[1]){ - header('Location:/'); - die(); - } -} -$testWidget = true; -if(isset($_GET['test'])){ - $testWidget = true; -} -$debugEnabled = false; -if(isset($_GET['debug']) && $_GET['debug']){ - $debugId = $_GET['debug']; - $debugEnabled = true; -} - -$withEth = false; -if((isset($_GET['withEth']) && (bool)$_GET['withEth']) || (isset($_GET['witheth']) && (bool)$_GET['witheth'])){ - $withEth = true; -} - -$hasNotes = isset($aConfig['adv']) && count($aConfig['adv']); - -$sentryURL = false; -if(isset($aConfig['sentry']) && is_array($aConfig['sentry'])){ - $aSentry = $aConfig['sentry']; - $https = isset($aSentry['https']) ? !!$aSentry['https'] : false; - $url = isset($aSentry['url']) ? $aSentry['url'] : false; - $key = isset($aSentry['key']) ? $aSentry['key'] : false; - if($url && $key){ - $protocol = $https ? "https" : "http"; - $sentryURL = $protocol . "://" . $key . "@" . $url; - } -} - -function includeLocal($name){ - if(file_exists(__DIR__ . '/index.' . $name . '.local.php')) require_once(__DIR__ . '/index.' . $name . '.local.php'); -} - -$csvExport = ''; -if(is_array($rParts) && isset($rParts[2])){ - $csvExport = ' Export...Export as CSV'; -} -if(!$title){ - $title = 'Ethplorer'; - if($header){ - $title .= ": " . $header; - } -} -?> - - - <?=$title?> - - - - - $aExtension){ - $cv = isset($aExtension['version']) ? (int)$aExtension['version'] : false; - if(isset($aExtension['css'])){ - $aExtension['js'] = (array)$aExtension['js']; - foreach($aExtension['css'] as $js){ - $jsf = "/extensions/" . $extName . "/" . $js; - if(file_exists(dirname(__FILE__) . $jsf)){ - echo ' ' . "\n"; - } - } - } - } - } ?> - - - - - - - - - - - - - - - - - - $aExtension){ - $cv = isset($aExtension['version']) ? (int)$aExtension['version'] : false; - if(isset($aExtension['js'])){ - $aExtension['js'] = (array)$aExtension['js']; - foreach($aExtension['js'] as $js){ - $jsf = "/extensions/" . $extName . "/" . $js; - if(file_exists(dirname(__FILE__) . $jsf)){ - echo ' ' . "\n"; - } - } - } - } - } ?> - - - - - - - - - - - -
    - -
    -
    -
    -
    - - -
    -

    ERROR

    -

    Invalid request

    -
    - - -
    -
    -
    -
    -
    -
    -
    -
    -
    search in progress...
    -
    - -
    -

    -

    -
    - -
    -
    -

    -
    -
    -
    - -
    - -
    -

    -
    - - -
    -

    -
    - - -
    - -
    - - - - - - - - - - - -
    - -
    -
    -
    - -
    - - -
    -

    -
    - -
    -
    -
    -
    -
    -

    Internal operations

    -
    -
    -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    URL
    SHA256 Hash
    Filename
    Filesize
    Data
    Short Link
    -
    - -
    - - -
    - -
    - -
    -
    -
    -

    Information

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Created At
    Creator
    Create Tx
    Balance
    Total In
    Total Out
    Transactions
    Transactions
    -
    -
    -
    -
    -
    -

    Balances -
    -

    -
    -
    -
    - Expand -
    -
    -
    -
    - -

    Chainy Information

    -
    - - - - -
    - Chainy is a smart contract which allows to create and read different kind of data in Ethereum blockchain: -

    - AEON short links
    - Irreplaceable short URLs (similar to bit.ly but impossible to change) -

    - Proof of Existence + Files
    - Permanent proof of existence of the document (file) together with link to the file at one page -

    - Broadcast Messages
    - Public text message on the Ethereum blockchain. Also may be encrypted -

    - Read more: https://chainy.link
    - Post your data: https://chainy.link/add -
    -
    -
    -

    Token Information

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Symbol
    Price
    Total Supply
    Decimals
    Owner
    Transfers
    Issuances
    Holders
    -
    -
    -
    - -
    -
    -
    - -
    ×
    -
    -
    -
    -
    -
    -
    -
    -

    Token Transfers

    -
    -
    -
    -
    - * all dates are displayed for timezone -
    -
    -
    -
    -
    -
    -

    Token Issuances

    -
    -
    -
    -
    - * all dates are displayed for timezone -
    -
    -
    -
    -
    -
    -

    Token Holders

    -
    -
    -
    -
    -
    -
    -
    -
    - - -
    - -
    -
    -
    - -
    - - -
    -



    - - - - diff --git a/js/ace.js b/js/ace.js deleted file mode 100644 index b4b7a55c..00000000 --- a/js/ace.js +++ /dev/null @@ -1,14 +0,0 @@ -(function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE="",e=function(){return this}();!e&&typeof window!="undefined"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!="undefined")return;var t=function(e,n,r){if(typeof e!="string"){t.original?t.original.apply(this,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t=="string"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)==="[object Array]"){var o=[];for(var u=0,a=t.length;u1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n=0?parseFloat((i.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]):parseFloat((i.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&window.navigator.product==="Gecko",t.isOldGecko=t.isGecko&&parseInt((i.match(/rv:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isTouchPad=i.indexOf("TouchPad")>=0,t.isChromeOS=i.indexOf(" CrOS ")>=0}),define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function a(e,t,n){var a=u(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState("OS")||t.getModifierState("Win"))&&(a|=8);if(s.altGr){if((3&a)==3)return;s.altGr=0}if(n===18||n===17){var f="location"in t?t.location:t.keyLocation;if(n===17&&f===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&a===3&&f===2){var l=t.timeStamp-o;l<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1),a&8&&n>=91&&n<=93&&(n=-1);if(!a&&n===13){var f="location"in t?t.location:t.keyLocation;if(f===3){e(t,a,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&a&8){e(t,a,n);if(t.defaultPrevented)return;a&=-9}return!!a||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,a,n):!1}function f(){s=Object.create(null)}var r=e("./keys"),i=e("./useragent"),s=null,o=0;t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n.call(e,window.event)};n._wrapper=r,e.attachEvent("on"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent("on"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type=="dblclick"?0:e.type=="contextmenu"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,n,r){function i(e){n&&n(e),r&&r(e),t.removeListener(document,"mousemove",n,!0),t.removeListener(document,"mouseup",i,!0),t.removeListener(document,"dragstart",i,!0)}return t.addListener(document,"mousemove",n,!0),t.addListener(document,"mouseup",i,!0),t.addListener(document,"dragstart",i,!0),i},t.addTouchMoveListener=function(e,n){if("ontouchmove"in e){var r,i;t.addListener(e,"touchstart",function(e){var t=e.changedTouches[0];r=t.clientX,i=t.clientY}),t.addListener(e,"touchmove",function(e){var t=1,s=e.changedTouches[0];e.wheelX=-(s.clientX-r)/t,e.wheelY=-(s.clientY-i)/t,r=s.clientX,i=s.clientY,n(e)})}},t.addMouseWheelListener=function(e,n){"onmousewheel"in e?t.addListener(e,"mousewheel",function(e){var t=8;e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),n(e)}):"onwheel"in e?t.addListener(e,"wheel",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=(e.deltaX||0)*5,e.wheelY=(e.deltaY||0)*5}n(e)}):t.addListener(e,"DOMMouseScroll",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)})},t.addMultiMouseDownListener=function(e,n,r,s){function c(e){t.getButton(e)!==0?o=0:e.detail>1?(o++,o>4&&(o=1)):o=1;if(i.isIE){var c=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||c)o=1;f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),o==1&&(u=e.clientX,a=e.clientY)}e._clicks=o,r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}function h(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)}var o=0,u,a,f,l={2:"dblclick",3:"tripleclick",4:"quadclick"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,"mousedown",c),i.isOldIE&&t.addListener(e,"dblclick",h)})};var u=!i.isMac||!i.isOpera||"KeyboardEvent"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[u(e)]},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var o=null;r(e,"keydown",function(e){o=e.keyCode}),r(e,"keypress",function(e){return a(n,e,o)})}else{var u=null;r(e,"keydown",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=a(n,e,e.keyCode);return u=e.defaultPrevented,t}),r(e,"keypress",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)}),r(e,"keyup",function(e){s[e.keyCode]=null}),s||(f(),r(window,"focus",f))}};if(typeof window=="object"&&window.postMessage&&!i.isOldIE){var l=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+l;t.addListener(n,"message",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())}),n.postMessage(r,"*")}}t.nextFrame=typeof window=="object"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=53&&O()},I=o.delayedCall(j,50);r.addListener(n,"compositionstart",B),i.isGecko?r.addListener(n,"text",function(){I.schedule()}):(r.addListener(n,"keyup",function(){I.schedule()}),r.addListener(n,"keydown",function(){I.schedule()})),r.addListener(n,"compositionend",F),this.getElement=function(){return n},this.setReadOnly=function(e){n.readOnly=e},this.onContextMenu=function(e){L=!0,b(t.selection.isEmpty()),t._emit("nativecontextmenu",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,o){if(!o&&i.isOldIE)return;p||(p=n.style.cssText),n.style.cssText=(o?"z-index:100000;":"")+"height:"+n.style.height+";"+(i.isIE?"opacity:0.1;":"");var u=t.container.getBoundingClientRect(),a=s.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){n.style.left=e.clientX-l-2+"px",n.style.top=Math.min(e.clientY-f-2,c)+"px"};h(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(q),i.isWin&&!i.isOldIE&&r.capture(t.container,h,R)},this.onContextMenuClose=R;var q,U=function(e){t.textInput.onContextMenu(e),R()};r.addListener(n,"mouseup",U),r.addListener(n,"mousedown",function(e){e.preventDefault(),R()}),r.addListener(t.renderer.scroller,"contextmenu",U),r.addListener(n,"contextmenu",U)};t.TextInput=f}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";function u(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler("mousedown",this.onMouseDown.bind(e)),t.setDefaultHandler("dblclick",this.onDoubleClick.bind(e)),t.setDefaultHandler("tripleclick",this.onTripleClick.bind(e)),t.setDefaultHandler("quadclick",this.onQuadClick.bind(e)),t.setDefaultHandler("mousewheel",this.onMouseWheel.bind(e)),t.setDefaultHandler("touchmove",this.onTouchMove.bind(e));var n=["select","startSelect","selectEnd","selectAllEnd","selectByWordsEnd","selectByLinesEnd","dragWait","dragWaitEnd","focusWait"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,"getLineRange"),e.selectByWords=this.extendSelectionBy.bind(e,"getWordRange")}function a(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function f(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e("../lib/dom"),i=e("../lib/event"),s=e("../lib/useragent"),o=0;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var r=this.editor,i=e.getButton();if(i!==0){var s=r.getSelectionRange(),o=s.isEmpty();r.$blockScrolling++,(o||i==1)&&r.selection.moveToPosition(n),r.$blockScrolling--,i==2&&r.textInput.onContextMenu(e.domEvent);return}this.mousedownEvent.time=Date.now();if(t&&!r.isFocused()){r.focus();if(this.$focusTimout&&!this.$clickSelection&&!r.inMultiSelectMode){this.setState("focusWait"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;n.$blockScrolling++,this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.renderer.scroller.setCapture&&n.renderer.scroller.setCapture(),n.setStyle("ace_selecting"),this.setState("select"),n.$blockScrolling--},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);t.$blockScrolling++;if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=f(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);n.$blockScrolling++;if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=f(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.$blockScrolling--,n.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle("ace_selecting"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=a(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>o||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState("select")):(i=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=i,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=e.domEvent.timeStamp,n=t-(this.$lastScrollTime||0),r=this.editor,i=r.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(i||n<200)return this.$lastScrollTime=t,r.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()},this.onTouchMove=function(e){var t=e.domEvent.timeStamp,n=t-(this.$lastScrollTime||0),r=this.editor,i=r.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(i||n<200)return this.$lastScrollTime=t,r.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()}}).call(u.prototype),t.DefaultHandlers=u}),define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"],function(e,t,n){"use strict";function s(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}var r=e("./lib/oop"),i=e("./lib/dom");(function(){this.$init=function(){return this.$element=i.createElement("div"),this.$element.className="ace_tooltip",this.$element.style.display="none",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){i.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+"px",this.getElement().style.top=t+"px"},this.setClassName=function(e){i.addCssClass(this.getElement(),e)},this.show=function(e,t,n){e!=null&&this.setText(e),t!=null&&n!=null&&this.setPosition(t,n),this.isOpen||(this.getElement().style.display="block",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display="none",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth}}).call(s.prototype),t.Tooltip=s}),define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"],function(e,t,n){"use strict";function u(e){function l(){var r=u.getDocumentPosition().row,s=n.$annotations[r];if(!s)return c();var o=t.session.getLength();if(r==o){var a=t.renderer.pixelToScreenCoordinates(0,u.y).row,l=u.$pos;if(a>t.session.documentToScreenRow(l.row,l.column))return c()}if(f==s)return;f=s.text.join("
    "),i.setHtml(f),i.show(),t._signal("showGutterTooltip",i),t.on("mousewheel",c);if(e.$tooltipFollowsMouse)h(u);else{var p=u.domEvent.target,d=p.getBoundingClientRect(),v=i.getElement().style;v.left=d.right+"px",v.top=d.bottom+"px"}}function c(){o&&(o=clearTimeout(o)),f&&(i.hide(),f=null,t._signal("hideGutterTooltip",i),t.removeEventListener("mousewheel",c))}function h(e){i.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler("guttermousedown",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i=="foldWidgets")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState("selectByLines"),e.captureMouse(r),r.preventDefault()});var o,u,f;e.editor.setDefaultHandler("guttermousemove",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,"ace_fold-widget"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t;if(o)return;o=setTimeout(function(){o=null,u&&!e.isMousePressed?l():c()},50)}),s.addListener(t.renderer.$gutter,"mouseout",function(e){u=null;if(!f||o)return;o=setTimeout(function(){o=null,c()},50)}),t.on("changeSession",c)}function a(e){o.call(this,e)}var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/event"),o=e("../tooltip").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=u}),define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){"use strict";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.$blockScrolling+=1,t.moveCursorToPosition(e),t.$blockScrolling-=1,S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,"ace_selection",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,"mousemove",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.$blockScrolling+=1,t.selection.fromOrientedRange(m),t.$blockScrolling-=1,t.isFocused()&&!w&&t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,"mousemove",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e=="text/plain"||e=="Text"})}function _(e){var t=["copy","copymove","all","uninitialized"],n=["move","copymove","linkmove","all","uninitialized"],r=s.isMac?e.altKey:e.ctrlKey,i="uninitialized";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o="none";return r&&t.indexOf(i)>=0?o="copy":n.indexOf(i)>=0?o="move":t.indexOf(i)>=0&&(o="copy"),o}var t=e.editor,n=r.createElement("img");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",s.isOpera&&(n.style.cssText="width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;");var f=["dragWait","dragWaitEnd","startDrag","dragReadyEnd","onMouseDrag"];f.forEach(function(t){e[t]=this[t]},this),t.addEventListener("mousedown",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?"copy":"copyMove",s.isOpera&&(t.container.appendChild(n),n.scrollTop=0),i.setDragImage&&i.setDragImage(n,0,0),s.isOpera&&t.container.removeChild(n),i.clearData(),i.setData("Text",t.session.getTextRange()),w=!0,this.setState("drag")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n=="move"&&t.session.remove(t.getSelectionRange()),t.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle("")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case"move":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case"copy":m=t.moveText(m,g,!0)}else{var r=n.getData("Text");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,"dragstart",this.onDragStart.bind(e)),i.addListener(c,"dragend",this.onDragEnd.bind(e)),i.addListener(c,"dragenter",this.onDragEnter.bind(e)),i.addListener(c,"dragover",this.onDragOver.bind(e)),i.addListener(c,"dragleave",this.onDragLeave.bind(e)),i.addListener(c,"drop",this.onDrop.bind(e));var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e("../lib/dom"),i=e("../lib/event"),s=e("../lib/useragent"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.editor.renderer.setCursorStyle(""),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle("ace_dragging");var n=s.isWin?"default":"move";e.renderer.setCursorStyle(n),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state=="dragReady"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state==="dragWait"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;"unselectable"in o&&(o.unselectable="on");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState("dragWait")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define("ace/lib/net",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("./dom");t.get=function(e,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement("script");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState=="loaded"||i.readyState=="complete")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement("a");return t.href=e,t.href}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o1&&(i=n[n.length-2]);var o=a[t+"Path"];return o==null?o=a.basePath:r=="/"&&(t=r=""),o&&o.slice(-1)!="/"&&(o+="/"),o+t+r+i+this.get("suffix")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i&&!t.$loading[n])return r&&r(i);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var a=function(){e([n],function(e){t._emit("load.module",{name:n,module:e});var r=t.$loading[n];t.$loading[n]=null,r.forEach(function(t){t&&t(e)})})};if(!t.get("packaged"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=f}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop_handler","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event"),i=e("../lib/useragent"),s=e("./default_handlers").DefaultHandlers,o=e("./default_gutter_handler").GutterHandler,u=e("./mouse_event").MouseEvent,a=e("./dragdrop_handler").DragdropHandler,f=e("../config"),l=function(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus()},u=e.renderer.getMouseEventTarget();r.addListener(u,"click",this.onMouseEvent.bind(this,"click")),r.addListener(u,"mousemove",this.onMouseMove.bind(this,"mousemove")),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,"onMouseEvent"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel")),r.addTouchMoveListener(e.container,this.onTouchMove.bind(this,"touchmove"));var f=e.renderer.$gutter;r.addListener(f,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),r.addListener(f,"click",this.onMouseEvent.bind(this,"gutterclick")),r.addListener(f,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),r.addListener(f,"mousemove",this.onMouseEvent.bind(this,"guttermousemove")),r.addListener(u,"mousedown",n),r.addListener(f,"mousedown",n),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,"mousedown",n),r.addListener(e.renderer.scrollBarH.element,"mousedown",n)),e.on("mousemove",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle("default"):s.setCursorStyle("")})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.onTouchMove=function(e,t){var n=new u(t,this.editor);n.speed=1,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor.renderer;n.$keepTextAreaAtCursor&&(n.$keepTextAreaAtCursor=null);var s=this,o=function(e){if(!e)return;if(i.isWebKit&&!e.which&&s.releaseMouse)return s.releaseMouse();s.x=e.clientX,s.y=e.clientY,t&&t(e),s.mouseEvent=new u(e,s.editor),s.$mouseMoved=!0},a=function(e){clearInterval(l),f(),s[s.state+"End"]&&s[s.state+"End"](e),s.state="",n.$keepTextAreaAtCursor==null&&(n.$keepTextAreaAtCursor=!0,n.$moveTextAreaToCursor()),s.isMousePressed=!1,s.$onCaptureMouseMove=s.releaseMouse=null,e&&s.onMouseEvent("mouseup",e)},f=function(){s[s.state]&&s[s.state](),s.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type=="dblclick")return setTimeout(function(){a(e)});s.$onCaptureMouseMove=o,s.releaseMouse=r.capture(this.editor.container,o,a);var l=setInterval(f,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!="contextmenu")return;this.editor.off("nativecontextmenu",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on("nativecontextmenu",e)}}).call(l.prototype),f.defineOptions(l.prototype,"mouseHandler",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=l}),define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,n){"use strict";function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on("gutterclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold("...",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){"use strict";var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;typeof e=="function"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||""}).filter(Boolean).join(" ")},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command=="null"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:"insertstring"},o=u.exec("insertstring",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal("keyboardActivity",s),o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(s.prototype),t.KeyBinding=s}),define("ace/range",["require","exports","module"],function(e,t,n){"use strict";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.rowt.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(e.column-n,e.column).split(" ").length-1==n?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column);t===0&&(this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var r=this.session.screenToDocumentPosition(n.row+e,n.column);e!==0&&t===0&&r.row===this.lead.row&&r.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[r.row]&&(r.row>0||e>0)&&r.row++,this.moveCursorTo(r.row,r.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define("ace/tokenizer",["require","exports","module","ace/config"],function(e,t,n){"use strict";var r=e("./config"),i=2e3,s=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:"text"},o="g",u=[];for(var a=0;a1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\d/.test(f.regex)?l=f.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!="string"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push("$")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp("("+r.join(")|(")+")|($)",o)}};(function(){this.$setMaxTokenCount=function(e){i=e|0},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n=="string")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;il){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;yi){c>2*e.length&&this.reportError("infinite loop with in ace tokenizer",{startState:t,line:e});while(l1&&n[0]!==r&&n.unshift("#tmp",r),{tokens:f,state:n.length?n:r}},this.reportError=r.reportError}).call(s.prototype),t.Tokenizer=s}),define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../lib/lang"),i=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{defaultToken:"text"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}}}).call(r.prototype),t.TokenIterator=r}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},h=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){c(n);var a=n.getSelectionRange(),l=r.doc.getTextRange(a);if(l!==""&&l!=="{"&&n.getWrapBehavioursEnabled())return h(a,l,"{","}");if(p.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){c(n);var d=u.substring(s.column,s.column+1);if(d=="}"){var v=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(v!==null&&p.isAutoInsertedClosing(s,u,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(i=="\n"||i=="\r\n"){c(n);var m="";p.isMaybeInsertedClosing(s,u)&&(m=o.stringRepeat("}",f.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var d=u.substring(s.column,s.column+1);if(d==="}"){var g=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!g)return null;var y=this.$getIndent(r.getLine(g.row))}else{if(!m){p.clearMaybeInsertedClosing();return}var y=this.$getIndent(u)}var b=y+r.getTabString();return{text:"\n"+b+"\n"+y+m,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"(",")");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"[","]");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;c(n);var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return h(o,u,s,s);if(!u){var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column),p=f.substring(a.column,a.column+1),d=r.getTokenAt(a.row,a.column),v=r.getTokenAt(a.row,a.column+1);if(l=="\\"&&d&&/escape/.test(d.type))return null;var m=d&&/string|escape/.test(d.type),g=!v||/string|escape/.test(v.type),y;if(p==s)y=m!==g,y&&/string\.end/.test(v.type)&&(y=!1);else{if(m&&!g)return null;if(m&&g)return null;var b=r.$mode.tokenRe;b.lastIndex=0;var w=b.test(l);b.lastIndex=0;var E=b.test(l);if(w||E)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;y=!0}return{text:y?s+s:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(p,i),t.CstyleBehaviour=p}),define("ace/unicode",["require","exports","module"],function(e,t,n){"use strict";function r(e){var n=/\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n,"\\u$&")}t.packages={},r({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Ll:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",Lo:"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048906DE20DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",So:"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"})}),define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour/cstyle","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"],function(e,t,n){"use strict";var r=e("../tokenizer").Tokenizer,i=e("./text_highlight_rules").TextHighlightRules,s=e("./behaviour/cstyle").CstyleBehaviour,o=e("../unicode"),u=e("../lib/lang"),a=e("../token_iterator").TokenIterator,f=e("../range").Range,l=function(){this.HighlightRules=i};(function(){this.$defaultBehaviour=new s,this.tokenRe=new RegExp("^["+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]|\\s])+","g"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules(this.$highlightRuleConfig),this.$tokenizer=new r(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart="",this.blockComment="",this.toggleCommentLines=function(e,t,n,r){function w(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}var i=t.doc,s=!0,o=!0,a=Infinity,f=t.getTabSize(),l=!1;if(!this.lineCommentStart){if(!this.blockComment)return!1;var c=this.blockComment.start,h=this.blockComment.end,p=new RegExp("^(\\s*)(?:"+u.escapeRegExp(c)+")"),d=new RegExp("(?:"+u.escapeRegExp(h)+")\\s*$"),v=function(e,t){if(g(e,t))return;if(!s||/\S/.test(e))i.insertInLine({row:t,column:e.length},h),i.insertInLine({row:t,column:a},c)},m=function(e,t){var n;(n=e.match(d))&&i.removeInLine(t,e.length-n[0].length,e.length),(n=e.match(p))&&i.removeInLine(t,n[1].length,n[0].length)},g=function(e,n){if(p.test(e))return!0;var r=t.getTokens(n);for(var i=0;i2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\S/);n!==-1?(ne.length&&(E=e.length)}),a==Infinity&&(a=E,s=!1,o=!1),l&&a%f!=0&&(a=Math.floor(a/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new a(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,l=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new f(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new a(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new f(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);l.start.row==c&&(l.start.column+=h),l.end.row==c&&(l.end.column+=h),t.selection.fromOrientedRange(l)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);var n=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"];for(var t=0;t=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n=="undefined"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.columnthis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal("change",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(""),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action=="insert"?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,s<=r&&n.fireUpdateEvent(s,r)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action=="remove")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+""!=r.state+""?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,n){"use strict";function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error("Trying to add fold to FoldRow that doesn't have a matching row");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},this.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.rowr)break;l.start.row==r&&l.start.column>=t.column&&(l.start.column!=t.column||!this.$insertRight)&&(l.start.column+=o,l.start.row+=s);if(l.end.row==r&&l.end.column>=t.column){if(l.end.column==t.column&&this.$insertRight)continue;l.end.column==t.column&&o>0&&al.start.column&&l.end.column==u[a+1].start.column&&(l.end.column-=o),l.end.column+=o,l.end.row+=s}}if(s!=0&&a=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i=t){u=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u0&&(this.removeFolds(p),p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?(n=new r(0,0,this.getLength(),0),t=!0):typeof e=="number"?n=new r(e,0,e,this.getLine(e).length):"row"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRangeList(n);if(t)this.removeFolds(i);else{var s=i;while(s.length)this.expandFolds(s),s=this.getFoldsInRangeList(n)}if(i.length)return i},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o="";return e.walk(function(e,t,n,u){if(t=e){i=s.end.row;try{var o=this.addFold("...",s);o&&(o.collapseChildren=n)}catch(u){}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==e)return;this.$foldStyle=e,e=="manual"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off("change",this.$updateFoldWidgets),this.off("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets),this._signal("changeAnnotation");if(!e||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets),this.on("tokenizerUpdate",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s=="start"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=" ace_invalid")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n==="end"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold("...",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold("...",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action=="remove")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e("../range").Range,i=e("./fold_line").FoldLine,s=e("./fold").Fold,o=e("../token_iterator").TokenIterator;t.Folding=u}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){"use strict";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren").replace(/\b(?:end)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren").replace(/\b(?:start|begin)\b/,"(?:start|begin|end)")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}r.implement(this,o),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(" ",this.getTabSize()):" "},this.setUseSoftTabs=function(e){this.setOption("useSoftTabs",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption("tabSize",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption("overwrite",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._signal("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._signal("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(oe&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;ao){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group=="doc"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;re.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,l=s.start,o=l.row-a.row,u=l.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},this.indentRows=function(e,t,n){n=n.replace(/\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new f(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new f(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$useWrapMode&&this._signal("changeWrapMode")},this.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n==="remove"){this[t?"$wrapData":"$rowLengthCache"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n==="remove"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var r=this.doc.getAllLines(),i=this.getTabSize(),s=this.$wrapData,o=this.$wrapLimit,a,f,l=e;t=Math.min(t,r.length-1);while(l<=t)f=this.getFoldLine(l,f),f?(a=[],f.walk(function(e,t,i,s){var o;if(e!=null){o=this.$getDisplayTokens(e,a.length),o[0]=n;for(var f=1;fr-b){var w=a+r-b;if(e[w-1]>=p&&e[w]>=p){y(w);continue}if(e[w]==n||e[w]==u){for(w;w!=a-1;w--)if(e[w]==n)break;if(w>a){y(w);continue}w=a+r;for(w;w>2)),a-1);while(w>E&&e[w]E&&e[w]E&&e[w]==l)w--}else while(w>E&&e[w]E){y(++w);continue}w=a+r,e[w]==t&&w--,y(w-b)}return s},this.$getDisplayTokens=function(n,r){var i=[],s;r=r||0;for(var o=0;o39&&u<48||u>57&&u<64?i.push(l):u>=4352&&m(u)?i.push(e,t):i.push(e)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i=4352&&m(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]=0)var o=a[f],r=this.$docRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:Infinity;while(o<=e){u=this.getRowLength(r);if(o+u>e||r>=h)break;o+=u,r++,r>d&&(r=p.end.row+1,p=this.getNextFoldLine(r,p),d=p?p.start.row:Infinity),c&&(this.$docRowCache.push(r),this.$screenRowCache.push(o))}if(p&&p.start.row<=r)n=this.getFoldDisplayLine(p),r=p.start.row;else{if(o+u<=e||r>h)return{row:h,column:this.getLine(h).length};n=this.getLine(r),p=null}var v=0;if(this.$useWrapMode){var m=this.$wrapData[r];if(m){var g=Math.floor(e-o);s=m[g],g>0&&m.length&&(v=m.indent,i=m[g-1]||m[m.length-1],n=n.substring(i))}}return i+=this.$getStringScreenWidth(n,t-v)[1],this.$useWrapMode&&i>=s&&(i=s-1),p?p.idxToPosition(i):{row:r,column:i}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return{row:r,column:v+this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;ro&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},this.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;sn)break}return[r,s]}},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()}}).call(p.prototype),e("./edit_session/folding").Folding.call(p.prototype),e("./edit_session/bracket_match").BracketMatch.call(p.prototype),s.defineOptions(p.prototype,"session",{wrap:{set:function(e){!e||e=="off"?e=!1:e=="free"?e=!0:e=="printMargin"?e=-1:typeof e=="string"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e=="number"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?"printMargin":this.getWrapLimitRange().min?this.$wrap:"free":"off"},handlesSet:!0},wrapMethod:{set:function(e){e=e=="auto"?this.$mode.type!="text":e!="text",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:"auto"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal("changeBreakpoint")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal("changeTabSize")},initialValue:4,handlesSet:!0},overwrite:{set:function(e){this._signal("changeOverwrite")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=p}),define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){"use strict";function u(e,t){function n(e){return/\w/.test(e)||t.regExp?"\\b":""}return n(e[0])+e+n(e[e.length-1])}var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i){if(!e.start){var o=e.offset+(i||0);r=new s(n,o,n,o+e.length);if(!e.length&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start))return r=null,!1}else r=e;return!0}),r},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;hv)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;gE&&o[h].end.row==n.end.row)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g=0;u--)if(i(o[u],t,s))return!0};else var u=function(e,t,s){var o=r.getMatchOffsets(e,n);for(var u=0;u=o;r--)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=u,o=s.row;r>=o;r--)if(n(e.getLine(r),r))return}:function(n){var r=s.row,i=e.getLine(r).substr(s.column);if(n(i,r,s.column))return;for(r+=1;r<=u;r++)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=o,u=s.row;r<=u;r++)if(n(e.getLine(r),r))return};return{forEach:a}}}).call(o.prototype),t.Search=o}),define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"],function(e,t,n){"use strict";function o(e,t){this.platform=t||(i.isMac?"mac":"win"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function u(e,t){o.call(this,e,t),this.$singleCommand=!1}var r=e("../lib/keys"),i=e("../lib/useragent"),s=r.KEY_MODS;u.prototype=o.prototype,function(){function e(e){return typeof e=="object"&&e.bindKey&&e.bindKey.position||0}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var n=e&&(typeof e=="string"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},this.bindKey=function(e,t,n){typeof e=="object"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t=="function")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split("|").forEach(function(e){var r="";if(e.indexOf(" ")!=-1){var i=e.split(/\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=s[t.hashId]+t.key;r+=(r?" ":"")+n,this._addCommandToBinding(r,"chainKeys")},this),r+=" "}var o=this.parseKeys(e),u=s[o.hashId]+o.key;this._addCommandToBinding(r+u,t,n)},this)},this._addCommandToBinding=function(t,n,r){var i=this.commandKeyBinding,s;if(!n)delete i[t];else if(!i[t]||this.$singleCommand)i[t]=n;else{Array.isArray(i[t])?(s=i[t].indexOf(n))!=-1&&i[t].splice(s,1):i[t]=[i[t]],typeof r!="number"&&(r||n.isDefault?r=-100:r=e(n));var o=i[t];for(s=0;sr)break}o.splice(s,0,n)}},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n});if(typeof n!="object")return;n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)return typeof console!="undefined"&&console.error("invalid modifier "+t[o]+" in "+e),!1;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=s[t]+n;return this.commandKeyBinding[r]},this.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=s[t]+n,o=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=" "+i,o=this.commandKeyBinding[e.$keyChain]||o);if(o)if(o=="chainKeys"||o[o.length-1]=="chainKeys")return e.$keyChain=e.$keyChain||i,{command:"null"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=""}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:o}},this.getStatusText=function(e,t){return t.$keyChain||""}}.call(o.prototype),t.HashHandler=o,t.MultiHashHandler=u}),define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../keyboard/hash_handler").MultiHashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){i.call(this,t,e),this.byName=this.commands,this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit("exec",i),this._signal("afterExec",i),i.returnValue===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"],function(e,t,n){"use strict";function o(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),i=e("../config"),s=e("../range").Range;t.commands=[{name:"showSettingsMenu",bindKey:o("Ctrl-,","Command-,"),exec:function(e){i.loadModule("ace/ext/settings_menu",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:"goToNextError",bindKey:o("Alt-E","F4"),exec:function(e){i.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,1)})},scrollIntoView:"animate",readOnly:!0},{name:"goToPreviousError",bindKey:o("Alt-Shift-E","Shift-F4"),exec:function(e){i.loadModule("ace/ext/error_marker",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:"animate",readOnly:!0},{name:"selectall",bindKey:o("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:o(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:o("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:o("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"unfold",bindKey:o("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleFoldWidget",bindKey:o("F2","F2"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"toggleParentFoldWidget",bindKey:o("Alt-F2","Alt-F2"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"foldall",bindKey:o(null,"Ctrl-Command-Option-0"),exec:function(e){e.session.foldAll()},scrollIntoView:"center",readOnly:!0},{name:"foldOther",bindKey:o("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:"center",readOnly:!0},{name:"unfoldall",bindKey:o("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},scrollIntoView:"center",readOnly:!0},{name:"findnext",bindKey:o("Ctrl-K","Command-G"),exec:function(e){e.findNext()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"findprevious",bindKey:o("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},multiSelectAction:"forEach",scrollIntoView:"center",readOnly:!0},{name:"selectOrFindNext",bindKey:o("Alt-K","Ctrl-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:"selectOrFindPrevious",bindKey:o("Alt-Shift-K","Ctrl-Shift-G"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:"find",bindKey:o("Ctrl-F","Command-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:o("Ctrl-Shift-Home","Command-Shift-Home|Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotostart",bindKey:o("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectup",bindKey:o("Shift-Up","Shift-Up|Ctrl-Shift-P"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golineup",bindKey:o("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttoend",bindKey:o("Ctrl-Shift-End","Command-Shift-End|Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"gotoend",bindKey:o("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0,scrollIntoView:"animate",aceCommandGroup:"fileJump"},{name:"selectdown",bindKey:o("Shift-Down","Shift-Down|Ctrl-Shift-N"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"golinedown",bindKey:o("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordleft",bindKey:o("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordleft",bindKey:o("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolinestart",bindKey:o("Alt-Shift-Left","Command-Shift-Left|Ctrl-Shift-A"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolinestart",bindKey:o("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectleft",bindKey:o("Shift-Left","Shift-Left|Ctrl-Shift-B"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoleft",bindKey:o("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectwordright",bindKey:o("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotowordright",bindKey:o("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selecttolineend",bindKey:o("Alt-Shift-Right","Command-Shift-Right|Shift-End|Ctrl-Shift-E"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotolineend",bindKey:o("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectright",bindKey:o("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"gotoright",bindKey:o("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:o(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:o("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:o(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:o("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:o("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"togglerecording",bindKey:o("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:o("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:o("Ctrl-P","Ctrl-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"selecttomatching",bindKey:o("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"expandToMatching",bindKey:o("Ctrl-Shift-M","Ctrl-Shift-M"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:"forEach",scrollIntoView:"animate",readOnly:!0},{name:"passKeysToBrowser",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:"copy",exec:function(e){},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"paste",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:"cursor"},{name:"removeline",bindKey:o("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},scrollIntoView:"cursor",multiSelectAction:"forEachLine"},{name:"duplicateSelection",bindKey:o("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"sortlines",bindKey:o("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},scrollIntoView:"selection",multiSelectAction:"forEachLine"},{name:"togglecomment",bindKey:o("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"toggleBlockComment",bindKey:o("Ctrl-Shift-/","Command-Shift-/"),exec:function(e){e.toggleBlockComment()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"modifyNumberUp",bindKey:o("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:o("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:"cursor",multiSelectAction:"forEach"},{name:"replace",bindKey:o("Ctrl-H","Command-Option-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:o("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:o("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:o("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()},scrollIntoView:"cursor"},{name:"movelinesup",bindKey:o("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()},scrollIntoView:"cursor"},{name:"copylinesdown",bindKey:o("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()},scrollIntoView:"cursor"},{name:"movelinesdown",bindKey:o("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()},scrollIntoView:"cursor"},{name:"del",bindKey:o("Delete","Delete|Ctrl-D|Shift-Delete"),exec:function(e){e.remove("right")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"backspace",bindKey:o("Shift-Backspace|Backspace","Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"cut_or_delete",bindKey:o("Shift-Delete",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove("left")},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolinestart",bindKey:o("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removetolineend",bindKey:o("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordleft",bindKey:o("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"removewordright",bindKey:o("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"outdent",bindKey:o("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"indent",bindKey:o("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach",scrollIntoView:"selectionPart"},{name:"blockoutdent",bindKey:o("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"blockindent",bindKey:o("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEachLine",scrollIntoView:"selectionPart"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"splitline",bindKey:o(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"transposeletters",bindKey:o("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:"cursor"},{name:"touppercase",bindKey:o("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"tolowercase",bindKey:o("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach",scrollIntoView:"cursor"},{name:"expandtoline",bindKey:o("Ctrl-Shift-L","Command-Shift-L"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:"forEach",scrollIntoView:"cursor",readOnly:!0},{name:"joinlines",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\n\s*/," ").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=" "+c),f+=c}i.row+10?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:"forEach",readOnly:!0},{name:"invertSelection",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o0&&this.$blockScrolling--;var n=t&&t.scrollIntoView;if(n){switch(n){case"center-animate":n="animate";case"center":this.renderer.scrollCursorIntoView(null,.5);break;case"animate":case"cursor":this.renderer.scrollCursorIntoView();break;case"selectionPart":var r=this.selection.getRange(),i=this.renderer.layerConfig;(r.start.row>=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n=="animate"&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=["backspace","del","insertstring"],this.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name=="insertstring"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\s/.test(i)||/\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!="always"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},this.setKeyboardHandler=function(e,t){if(e&&typeof e=="string"){this.$keybindingId=e;var n=this;g.loadModule(["keybinding",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off("change",this.$onDocumentChange),this.session.off("changeMode",this.$onChangeMode),this.session.off("tokenizerUpdate",this.$onTokenizerUpdate),this.session.off("changeTabSize",this.$onChangeTabSize),this.session.off("changeWrapLimit",this.$onChangeWrapLimit),this.session.off("changeWrapMode",this.$onChangeWrapMode),this.session.off("changeFold",this.$onChangeFold),this.session.off("changeFrontMarker",this.$onChangeFrontMarker),this.session.off("changeBackMarker",this.$onChangeBackMarker),this.session.off("changeBreakpoint",this.$onChangeBreakpoint),this.session.off("changeAnnotation",this.$onChangeAnnotation),this.session.off("changeOverwrite",this.$onCursorChange),this.session.off("changeScrollTop",this.$onScrollTopChange),this.session.off("changeScrollLeft",this.$onScrollLeftChange);var n=this.session.getSelection();n.off("changeCursor",this.$onCursorChange),n.off("changeSelection",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal("changeSession",{session:e,oldSession:t}),this.curOp=null,t&&t._signal("changeEditor",{oldEditor:this}),e&&e._signal("changeEditor",{editor:this})},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption("fontSize")||i.computedStyle(this.container,"fontSize")},this.setFontSize=function(e){this.setOption("fontSize",e)},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=t.findMatchingBracket(e.getCursorPosition());if(n)var r=new p(n.row,n.column,n.row,n.column+1);else if(t.$mode.getMatching)var r=t.$mode.getMatching(e.session);r&&(t.$bracketHighlight=t.addMarker(r,"ace_bracket","text"))},50)},this.$highlightTags=function(){if(this.$highlightTagPending)return;var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=e.getCursorPosition(),r=new y(e.session,n.row,n.column),i=r.getCurrentToken();if(!i||!/\b(?:tag-open|tag-name)/.test(i.type)){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}if(i.type.indexOf("tag-open")!=-1){i=r.stepForward();if(!i)return}var s=i.value,o=0,u=r.stepBackward();if(u.value=="<"){do u=i,i=r.stepForward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="=0)}else{do i=u,u=r.stepBackward(),i&&i.value===s&&i.type.indexOf("tag-name")!==-1&&(u.value==="<"?o++:u.value==="1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new p(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,"ace_active-line","screenLine"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\w\d]/.test(o)||r<=s&&/[\w\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\w\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit("changeMode",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e,t){var n={text:e,event:t};this.commands.exec("paste",this,n)},this.$handlePaste=function(e){typeof e=="string"&&(e={text:e}),this._signal("paste",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var n=t.split(/\r\n|\r|\n/),r=this.selection.rangeList.ranges;if(n.length>r.length||n.length<2||!n[1])return this.commands.exec("insertstring",this,t);for(var i=r.length;i--;){var s=r[i];s.isEmpty()||this.session.remove(s),this.session.insert(s.start,n[i])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),"insertion",this,n,e);s&&(e!==s.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=s.text)}e==" "&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()){var o=new p.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e=="\n"||e=="\r\n"){var u=n.getLine(i.row);if(i.column>u.search(/\S|$/)){var a=u.substr(i.column).search(/\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e),h=n.insert(i,e);s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(n.getDocument().isNewLine(e)){var d=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},d)}c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]=="\n"){var o=n.getLine(t.end.row);/^\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;tt.toLowerCase()?1:0});var r=new p(0,0,0,0);for(var i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new p(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&np+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new y(this.session,n.row,n.column),i=r.getCurrentToken(),s=i||r.stepForward();if(!s)return;var o,u=!1,a={},f=n.column-s.start,l,c={")":"(","(":"(","]":"[","[":"[","{":"{","}":"{"};do{if(s.value.match(/[{}()\[\]]/g))for(;f=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement("div"));var i=this.$scrollAnchor;i.style.cssText="position:absolute",this.container.insertBefore(i,this.container.firstChild);var s=this.on("changeSelection",function(){r=!0}),o=this.renderer.on("beforeRender",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on("afterRender",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.topwindow.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+"px",i.style.left=s.left+"px",i.style.height=o.lineHeight+"px",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off("changeSelection",s),this.renderer.off("afterRender",u),this.renderer.off("beforeRender",o)}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!="wide",i.setCssClass(t.element,"ace_slim-cursors",/slim/.test(e))}}).call(b.prototype),g.defineOptions(b.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.keybindingId},handlesSet:!0},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",showLineNumbers:"renderer",showGutter:"renderer",displayIndentGuides:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",tabSize:"session",wrap:"session",indentedSoftWrap:"session",foldStyle:"session",mode:"session"}),t.Editor=b}),define("ace/undomanager",["require","exports","module"],function(e,t,n){"use strict";var r=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines.length==1?null:e.lines,text:e.lines.length==1?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function n(e,t){var n=new Array(e.length);for(var r=0;r0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return this.dirtyCounter===0},this.$serializeDeltas=function(t){return n(t,e)},this.$deserializeDeltas=function(e){return n(e,t)}}).call(r.prototype),t.UndoManager=r}),define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e&&e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;to&&(v=s.end.row+1,s=t.getNextFoldLine(v,s),o=s?s.start.row:Infinity);if(v>i){while(this.$cells.length>d+1)p=this.$cells.pop(),this.element.removeChild(p.element);break}p=this.$cells[++d],p||(p={element:null,textNode:null,foldWidget:null},p.element=r.createElement("div"),p.textNode=document.createTextNode(""),p.element.appendChild(p.textNode),this.element.appendChild(p.element),this.$cells[d]=p);var m="ace_gutter-cell ";a[v]&&(m+=a[v]),f[v]&&(m+=f[v]),this.$annotations[v]&&(m+=this.$annotations[v].className),p.element.className!=m&&(p.element.className=m);var g=t.getRowLength(v)*e.lineHeight+"px";g!=p.element.style.height&&(p.element.style.height=g);if(u){var y=u[v];y==null&&(y=u[v]=t.getFoldWidget(v))}if(y){p.foldWidget||(p.foldWidget=r.createElement("span"),p.element.appendChild(p.foldWidget));var m="ace_fold-widget ace_"+y;y=="start"&&v==o&&vn.right-t.right)return"foldWidgets"}}).call(u.prototype),t.Gutter=u}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+i.start.column*e.characterWidth;r.renderer(t,i,o,s,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,i,r.clazz,e):r.type=="screenLine"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type=="text"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.drawSingleLineMarker(t,i,r.clazz+" ace_start"+" ace_br15",e)}this.element.innerHTML=t.join("")},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,n,i,s,o){var u=this.session,a=n.start.row,f=n.end.row,l=a,c=0,h=0,p=u.getScreenLastRowColumn(l),d=new r(l,n.start.column,l,h);for(;l<=f;l++)d.start.row=d.end.row=l,d.start.column=l==a?n.start.column:u.getRowWrapIndent(l),d.end.column=p,c=h,h=p,p=l+1p,l==f),s,l==f?0:1,o)},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth;i=i||"",e.push("
    "),u=this.$getTop(t.end.row,r);var f=t.end.column*r.characterWidth;e.push("
    "),o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var l=(t.start.column?1:0)|(t.end.column?0:8);e.push("
    ")},this.drawSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;e.push("
    ")},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),e.push("
    ")},this.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;e.push("
    ")}}).call(s.prototype),t.Marker=s}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){r.implement(this,u),this.EOF_CHAR="\u00b6",this.EOL_CHAR_LF="\u00ac",this.EOL_CHAR_CRLF="\u00a4",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="\u2014",this.SPACE_CHAR="\u00b7",this.$padding=0,this.$updateEolChar=function(){var e=this.session.doc.getNewLineCharacter()=="\n"?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=e)return this.EOL_CHAR=e,!0},this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n"+s.stringRepeat(this.TAB_CHAR,n)+""):t.push(s.stringRepeat(" ",n));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var r="ace_indent-guide",i="",o="";if(this.showInvisibles){r+=" ace_invisible",i=" ace_invisible_space",o=" ace_invisible_tab";var u=s.stringRepeat(this.SPACE_CHAR,this.tabSize),a=s.stringRepeat(this.TAB_CHAR,this.tabSize)}else var u=s.stringRepeat(" ",this.tabSize),a=u;this.$tabStrings[" "]=""+u+"",this.$tabStrings[" "]=""+a+""}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),i=Math.min(n,e.lastRow),s=this.element.childNodes,o=0;for(var u=e.firstRow;uf&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),f=a?a.start.row:Infinity);if(u>i)break;var l=s[o++];if(l){var c=[];this.$renderLine(c,u,!this.$useLineGroups(),u==f?a:!1),l.style.height=e.lineHeight*this.session.getRowLength(u)+"px",l.innerHTML=c.join("")}u++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRowt.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement("div"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join("");if(this.$useLineGroups())a.className="ace_line_group",r.appendChild(a),a.style.height=e.lineHeight*this.session.getRowLength(s)+"px";else while(a.firstChild)r.appendChild(a.firstChild);s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,i=n,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>r)break;this.$useLineGroups()&&t.push("
    "),this.$renderLine(t,i,!1,i==o?s:!1),this.$useLineGroups()&&t.push("
    "),i++}this.element.innerHTML=t.join("")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF\uFFF9-\uFFFC])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?""+s.stringRepeat(i.SPACE_CHAR,e.length)+"":e;if(e=="&")return"&";if(e=="<")return"<";if(e==">")return">";if(e==" "){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e=="\u3000"){var f=i.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",l=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,""+l+""}return r?""+i.SPACE_CHAR+"":(t+=1,""+e+"")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f="ace_"+n.type.replace(/\./g," ace_"),l="";n.type=="fold"&&(l=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("",a,"")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);return r<=0||r>=n?t:t[0]==" "?(r-=r%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[" "],r/this.tabSize)),t.substr(r)):t[0]==" "?(e.push(s.stringRepeat(this.$tabStrings[" "],r)),t.substr(r)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,o=0,u=n[0],a=0;for(var f=0;f=u)a=this.$renderToken(e,a,l,c.substring(0,u-i)),c=c.substring(u-i),i=u,r||e.push("
    ","
    "),e.push(s.stringRepeat("\u00a0",n.indent)),o++,a=0,u=n[o]||Number.MAX_VALUE;c.length!=0&&(i+=c.length,a=this.$renderToken(e,a,l,c))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),n||e.push("
    ")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../lib/dom"),i,s=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),i===undefined&&(i=!("opacity"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=(i?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.visibility=e?"":"hidden"},this.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.opacity=e?"":"0"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&!i&&(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking"),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+n.column*this.config.characterWidth,i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=0,i=t.length;ne.height+e.offset||s.top<0)&&n>1)continue;var o=(this.cursors[r++]||this.addCursor()).style;this.drawCursor?this.drawCursor(o,s,e,t[n],this.session):(o.left=s.left+"px",o.top=s.top+"px",o.width=e.characterWidth+"px",o.height=e.lineHeight+"px")}while(this.cursors.length>r)this.removeCursor();var u=this.session.getOverwrite();this.$setOverwrite(u),this.$pixelPos=s,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(s.prototype),t.Cursor=s}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=32768,a=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,"scroll",this.onScroll.bind(this)),s.addListener(this.element,"mousedown",s.preventDefault)};(function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e,this.coeff=1}}).call(a.prototype);var f=function(e,t){a.call(this,e),this.scrollTop=0,this.scrollHeight=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px"};r.inherits(f,a),function(){this.classSuffix="-v",this.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit("scroll",{data:this.scrollTop})}this.skipEvent=!1},this.getWidth=function(){return this.isVisible?this.width:0},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=this.setScrollHeight=function(e){this.scrollHeight=e,e>u?(this.coeff=u/e,e=u):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)}}.call(f.prototype);var l=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};r.inherits(l,a),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(l.prototype),t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){"use strict";var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending&&this.changes){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=0,f=t.FontMetrics=function(e){this.el=i.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),a||this.$testFractionalRect(),this.$measureNode.innerHTML=s.stringRepeat("X",a),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){r.implement(this,u),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=i.createElement("div");this.$setMeasureNodeStyles(e.style),e.style.width="0.2px",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;t>0&&t<1?a=50:a=100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height="auto",e.left=e.top="0px",e.visibility="hidden",e.position="absolute",e.whiteSpace="pre",o.isIE<8?e["font-family"]="inherit":e.font="inherit",e.overflow=t?"hidden":"visible"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(a===50){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var n={height:e.height,width:e.width/a}}else var n={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/a};return n.width===0||n.height===0?null:n},this.$measureCharWidth=function(e){this.$main.innerHTML=s.stringRepeat(e,a);var t=this.$main.getBoundingClientRect();return t.width/a},this.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(f.prototype)}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./config"),o=e("./lib/useragent"),u=e("./layer/gutter").Gutter,a=e("./layer/marker").Marker,f=e("./layer/text").Text,l=e("./layer/cursor").Cursor,c=e("./scrollbar").HScrollBar,h=e("./scrollbar").VScrollBar,p=e("./renderloop").RenderLoop,d=e("./layer/font_metrics").FontMetrics,v=e("./lib/event_emitter").EventEmitter,m='.ace_editor {position: relative;overflow: hidden;font: 12px/normal \'Monaco\', \'Menlo\', \'Ubuntu Mono\', \'Consolas\', \'source-code-pro\', monospace;direction: ltr;text-align: left;}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;min-width: 100%;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \'\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC");}.ace_scrollbar {position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;text-indent: -1em;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: inherit;color: inherit;z-index: 1000;opacity: 1;text-indent: 0;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-webkit-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_editor.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII="),url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC");}.ace_tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block; }.ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");}.ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");}.ace_dark .ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-webkit-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-webkit-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_br1 {border-top-left-radius : 3px;}.ace_br2 {border-top-right-radius : 3px;}.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}';i.importCssString(m,"ace_editor.css");var g=function(e,t){var n=this;this.container=e||i.createElement("div"),this.$keepTextAreaAtCursor=!o.isOldIE,i.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);var r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new d(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new p(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode)},this.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar()},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null},this.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var i=0,s=this.$size,o={width:s.width,height:s.height,scrollerHeight:s.scrollerHeight,scrollerWidth:s.scrollerWidth};r&&(e||s.height!=r)&&(s.height=r,i|=this.CHANGE_SIZE,s.scrollerHeight=s.height,this.$horizScroll&&(s.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+"px",i|=this.CHANGE_SCROLL);if(n&&(e||s.width!=n)){i|=this.CHANGE_SIZE,s.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+"px",s.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+"px",this.scroller.style.bottom=this.scrollBarH.getHeight()+"px";if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)i|=this.CHANGE_FULL}return s.$dirty=!n||!r,i&&this._signal("resize",o),i},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption("animatedScroll",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption("showInvisibles",e)},this.getShowInvisibles=function(){return this.getOption("showInvisibles")},this.getDisplayIndentGuides=function(){return this.getOption("displayIndentGuides")},this.setDisplayIndentGuides=function(e){this.setOption("displayIndentGuides",e)},this.setShowPrintMargin=function(e){this.setOption("showPrintMargin",e)},this.getShowPrintMargin=function(){return this.getOption("showPrintMargin")},this.setPrintMarginColumn=function(e){this.setOption("printMarginColumn",e)},this.getPrintMarginColumn=function(){return this.getOption("printMarginColumn")},this.getShowGutter=function(){return this.getOption("showGutter")},this.setShowGutter=function(e){return this.setOption("showGutter",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var n=this.session.selection.getCursor();n.column=0,e=this.$cursorLayer.getPixelPosition(n,!0),t*=this.session.getRowLength(n.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=t+"px"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;var r=this.textarea.style,i=this.lineHeight;if(t<0||t>e.height-i){r.top=r.left="0";return}var s=this.characterWidth;if(this.$composition){var o=this.textarea.value.replace(/^\x01+/,"");s*=this.session.$getStringScreenWidth(o)[0]+2,i+=2}n-=this.scrollLeft,n>this.$size.scrollerWidth-s&&(n=this.$size.scrollerWidth-s),n+=this.gutterWidth,r.height=i+"px",r.width=s+"px",r.left=Math.min(n,this.$size.scrollerWidth-s)+"px",r.top=Math.min(t,this.$size.height-i)+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender");var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-this.layerConfig.firstRow)*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-n.offset+"px",this.content.style.marginTop=-n.offset+"px",this.content.style.width=n.width+2*this.$padding+"px",this.content.style.height=n.minHeight+"px"}e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+"px",this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left");if(e&this.CHANGE_FULL){this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this._signal("afterRender");return}if(e&this.CHANGE_SCROLL){e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),this._signal("afterRender");return}e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal("afterRender")},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||r!=this.$vScroll){r!=this.$vScroll&&(this.$vScroll=r,this.scrollBarV.setVisible(r));var i=this.container.clientWidth;this.container.style.height=n+"px",this.$updateCachedSize(!0,this.$gutterWidth,i,n),this.desiredHeight=n,this._signal("autosize")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=this.scrollTop%this.lineHeight,l=t.scrollerHeight+this.lineHeight,c=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=c;var h=this.scrollMargin;this.session.setScrollTop(Math.max(-h.top,Math.min(this.scrollTop,i-t.scrollerHeight+h.bottom))),this.session.setScrollLeft(Math.max(-h.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+h.right)));var p=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+c<0||this.scrollTop>h.top),d=a!==p;d&&(this.$vScroll=p,this.scrollBarV.setVisible(p));var v=Math.ceil(l/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-f)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),l=t.scrollerHeight+e.getRowLength(g)*w+b,f=this.scrollTop-y*w;var S=0;this.layerConfig.width!=s&&(S=this.CHANGE_H_SCROLL);if(u||d)S=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),d&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:l,maxHeight:i,offset:f,gutterOffset:w?Math.max(0,Math.ceil((f+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},S},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(ts?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-ui?(i=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},this.pixelToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=(e+this.scrollLeft-n.left-this.$padding)/this.characterWidth,i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),s=Math.round(r);return{row:i,column:s,side:r-s>0?1:-1}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=Math.round((e+this.scrollLeft-n.left-this.$padding)/this.characterWidth),i=(t+this.scrollTop-n.top)/this.lineHeight;return this.session.screenToDocumentPosition(i,Math.max(r,0))},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+Math.round(r.column*this.characterWidth),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this.setTheme=function(e,t){function o(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw new Error("couldn't load module "+e+" or it didn't call define");i.importCssString(r.cssText,r.cssClass,n.container.ownerDocument),n.theme&&i.removeCssClass(n.container,n.theme.cssClass);var s="padding"in r?r.padding:"padding"in(n.theme||{})?4:n.$padding;n.$padding&&s!=n.$padding&&n.setPadding(s),n.$theme=r.cssClass,n.theme=r,i.addCssClass(n.container,r.cssClass),i.setCssClass(n.container,"ace_dark",r.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent("themeLoaded",{theme:r}),t&&t()}var n=this;this.$themeId=e,n._dispatchEvent("themeChange",{theme:e});if(!e||typeof e=="string"){var r=e||this.$options.theme.initialValue;s.loadModule(["theme",r],o)}else o(e)},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){i.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){i.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),s.defineOptions(g.prototype,"renderer",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){typeof e=="number"&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?"block":"none",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){i.setCssClass(this.$gutter,"ace_fade-fold-widgets",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?"":"none",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){typeof e=="number"&&(e+="px"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},maxPixelHeight:{set:function(e){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(e){e=+e||0;if(this.$scrollPastEnd==e)return;this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:"./theme/textmate",handlesSet:!0}}),t.VirtualRenderer=g}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/net"),s=e("../lib/event_emitter").EventEmitter,o=e("../config"),u=function(t,n,r,i){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl);if(o.get("packaged")||!e.toUrl)i=i||o.moduleUrl(n,"worker");else{var s=this.$normalizePath;i=i||s(e.toUrl("ace/worker/worker.js",null,"_"));var u={};t.forEach(function(t){u[t]=s(e.toUrl(t,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}try{this.$worker=new Worker(i)}catch(a){if(!(a instanceof window.DOMException))throw a;var f=this.$workerBlob(i),l=window.URL||window.webkitURL,c=l.createObjectURL(f);this.$worker=new Worker(c),l.revokeObjectURL(c)}this.$worker.postMessage({init:!0,tlns:u,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case"event":this._signal(t.name,{data:t.data});break;case"call":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id]);break;case"error":this.reportError(t.data);break;case"log":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return i.qualifyURL(e)},this.terminate=function(){this._signal("terminate",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){console.error(n.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),e.action=="insert"?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;if(!e)return;this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e})},this.$workerBlob=function(e){var t="importScripts('"+i.qualifyURL(e)+"');";try{return new Blob([t],{type:"application/javascript"})}catch(n){var r=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,s=new r;return s.append(t),s.getBlob("application/javascript")}}}).call(u.prototype);var a=function(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},o.loadModule(["worker",t],function(e){r=new e[n](u);while(a.messageBuffer.length)f()})};a.prototype=u.prototype,t.UIWorkerClient=a,t.WorkerClient=u}),define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){"use strict";var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action==="insert")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action==="remove")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},this.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n1&&!this.inMultiSelectMode&&(this._signal("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal("removeRange",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column0)d--;if(d>0){var m=0;while(r[m].isEmpty())m++}for(var g=d;g>=m;g--)r[g].isEmpty()&&r.splice(g,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit("changeSelection")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction=="forEach"?r=n.forEachSelection(t,e.args):t.multiSelectAction=="forEachLine"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges();var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e="";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join("\n")+"\n"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),io?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(" ",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),st[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off("addRange",this.$onAddRange),n.multiSelect.off("removeRange",this.$onRemoveRange),n.multiSelect.off("multiSelect",this.$onMultiSelect),n.multiSelect.off("singleSelect",this.$onSingleSelect),n.multiSelect.lead.off("change",this.$checkMultiselectChange),n.multiSelect.anchor.off("change",this.$checkMultiselectChange)),t&&(t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),t.multiSelect.lead.on("change",this.$checkMultiselectChange),t.multiSelect.anchor.on("change",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e("./config").defineOptions(d.prototype,"editor",{enableMultiselect:{set:function(e){m(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",o)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",o))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../../range").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?"start":t=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?"end":""},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++tf){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}),define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on("change",this.updateOnChange),this.session.on("changeFold",this.updateOnFold),this.session.on("changeEditor",this.$onChangeEditor)}var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./range").Range;(function(){this.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets))},this.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off("beforeRender",this.measureWidgets),t.renderer.off("afterRender",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},this.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action=="add";for(var u=i+1;u0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+"px";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+"px";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+"px",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+"px"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+"px":u.el.style.right=""}}}).call(o.prototype),t.LineWidgets=o}),define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,n){"use strict";function o(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=o(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var u=r[i];if(!u||!n)return;if(u.row===t){do u=r[i+=n];while(u&&u.row===t);if(!u)return r.slice()}var a=[];t=u.row;do a[n<0?"unshift":"push"](u),u=r[i+=n];while(u&&u.row==t);return a.length&&a}var r=e("../line_widgets").LineWidgets,i=e("../lib/dom"),s=e("../range").Range;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),o=s.row,a=n.widgetManager.getWidgetsAtRow(o).filter(function(e){return e.type=="errorMarker"})[0];a?a.destroy():o-=t;var f=u(n,o,t),l;if(f){var c=f[0];s.column=(c.pos&&typeof c.column!="number"?c.pos.sc:c.column)||0,s.row=c.row,l=e.renderer.$gutterLayer.$annotations[s.row]}else{if(a)return;l={text:["Looks good!"],className:"ace_ok"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var h={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement("div"),type:"errorMarker"},p=h.el.appendChild(i.createElement("div")),d=h.el.appendChild(i.createElement("div"));d.className="error_widget_arrow "+l.className;var v=e.renderer.$cursorLayer.getPixelPosition(s).left;d.style.left=v+e.renderer.gutterWidth-5+"px",h.el.className="error_widget_wrapper",p.className="error_widget "+l.className,p.innerHTML=l.text.join("
    "),p.appendChild(i.createElement("div"));var m=function(e,t,n){if(t===0&&(n==="esc"||n==="return"))return h.destroy(),{command:"null"}};h.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off("changeSelection",h.destroy),e.off("changeSession",h.destroy),e.off("mouseup",h.destroy),e.off("change",h.destroy)},e.keyBinding.addKeyboardHandler(m),e.on("changeSelection",h.destroy),e.on("changeSession",h.destroy),e.on("mouseup",h.destroy),e.on("change",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; }","")}),define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"],function(e,t,n){"use strict";e("./lib/fixoldbrowsers");var r=e("./lib/dom"),i=e("./lib/event"),s=e("./editor").Editor,o=e("./edit_session").EditSession,u=e("./undomanager").UndoManager,a=e("./virtual_renderer").VirtualRenderer;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./multi_select"),e("./mode/folding/fold_mode"),e("./theme/textmate"),e("./ext/error_marker"),t.config=e("./config"),t.require=e,typeof define=="function"&&(t.define=define),t.edit=function(e){if(typeof e=="string"){var n=e;e=document.getElementById(n);if(!e)throw new Error("ace.edit can't find div #"+n)}if(e&&e.env&&e.env.editor instanceof s)return e.env.editor;var o="";if(e&&/input|textarea/i.test(e.tagName)){var u=e;o=u.value,e=r.createElement("pre"),u.parentNode.replaceChild(e,u)}else e&&(o=r.getInnerText(e),e.innerHTML="");var f=t.createEditSession(o),l=new s(new a(e));l.setSession(f);var c={document:f,editor:l,onResize:l.resize.bind(l,null)};return u&&(c.textarea=u),i.addListener(window,"resize",c.onResize),l.on("destroy",function(){i.removeListener(window,"resize",c.onResize),c.editor.container.env=null}),l.container.env=l.env=c,l},t.createEditSession=function(e,t){var n=new o(e,t);return n.setUndoManager(new u),n},t.EditSession=o,t.UndoManager=u,t.version="1.2.6"}); - (function() { - window.require(["ace/ace"], function(a) { - if (a) { - a.config.init(true); - a.define = window.define; - } - if (!window.ace) - window.ace = a; - for (var key in a) if (a.hasOwnProperty(key)) - window.ace[key] = a[key]; - }); - })(); - \ No newline at end of file diff --git a/js/bignumber.js b/js/bignumber.js deleted file mode 100644 index a90e7a34..00000000 --- a/js/bignumber.js +++ /dev/null @@ -1,4 +0,0 @@ -/* bignumber.js v2.4.0 https://github.com/MikeMcl/bignumber.js/LICENCE */ -!function(e){"use strict";function n(e){function a(e,n){var t,r,i,o,u,s,f=this;if(!(f instanceof a))return j&&L(26,"constructor call without new",e),new a(e,n);if(null!=n&&H(n,2,64,M,"base")){if(n=0|n,s=e+"",10==n)return f=new a(e instanceof a?e:s),U(f,P+f.e+1,B);if((o="number"==typeof e)&&0*e!=0||!new RegExp("^-?"+(t="["+b.slice(0,n)+"]+")+"(?:\\."+t+")?$",37>n?"i":"").test(s))return g(f,s,o,n);o?(f.s=0>1/e?(s=s.slice(1),-1):1,j&&s.replace(/^0\.0*|\./,"").length>15&&L(M,N,e),o=!1):f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1,s=D(s,10,n,f.s)}else{if(e instanceof a)return f.s=e.s,f.e=e.e,f.c=(e=e.c)?e.slice():e,void(M=0);if((o="number"==typeof e)&&0*e==0){if(f.s=0>1/e?(e=-e,-1):1,e===~~e){for(r=0,i=e;i>=10;i/=10,r++);return f.e=r,f.c=[e],void(M=0)}s=e+""}else{if(!p.test(s=e+""))return g(f,s,o);f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1}}for((r=s.indexOf("."))>-1&&(s=s.replace(".","")),(i=s.search(/e/i))>0?(0>r&&(r=i),r+=+s.slice(i+1),s=s.substring(0,i)):0>r&&(r=s.length),i=0;48===s.charCodeAt(i);i++);for(u=s.length;48===s.charCodeAt(--u););if(s=s.slice(i,u+1))if(u=s.length,o&&j&&u>15&&(e>S||e!==m(e))&&L(M,N,f.s*e),r=r-i-1,r>z)f.c=f.e=null;else if(G>r)f.c=[f.e=0];else{if(f.e=r,f.c=[],i=(r+1)%y,0>r&&(i+=y),u>i){for(i&&f.c.push(+s.slice(0,i)),u-=y;u>i;)f.c.push(+s.slice(i,i+=y));s=s.slice(i),i=y-s.length}else i-=u;for(;i--;s+="0");f.c.push(+s)}else f.c=[f.e=0];M=0}function D(e,n,t,i){var o,u,f,c,h,g,p,d=e.indexOf("."),m=P,w=B;for(37>t&&(e=e.toLowerCase()),d>=0&&(f=J,J=0,e=e.replace(".",""),p=new a(t),h=p.pow(e.length-d),J=f,p.c=s(l(r(h.c),h.e),10,n),p.e=p.c.length),g=s(e,t,n),u=f=g.length;0==g[--f];g.pop());if(!g[0])return"0";if(0>d?--u:(h.c=g,h.e=u,h.s=i,h=C(h,p,m,w,n),g=h.c,c=h.r,u=h.e),o=u+m+1,d=g[o],f=n/2,c=c||0>o||null!=g[o+1],c=4>w?(null!=d||c)&&(0==w||w==(h.s<0?3:2)):d>f||d==f&&(4==w||c||6==w&&1&g[o-1]||w==(h.s<0?8:7)),1>o||!g[0])e=c?l("1",-m):"0";else{if(g.length=o,c)for(--n;++g[--o]>n;)g[o]=0,o||(++u,g.unshift(1));for(f=g.length;!g[--f];);for(d=0,e="";f>=d;e+=b.charAt(g[d++]));e=l(e,u)}return e}function F(e,n,t,i){var o,u,s,c,h;if(t=null!=t&&H(t,0,8,i,v)?0|t:B,!e.c)return e.toString();if(o=e.c[0],s=e.e,null==n)h=r(e.c),h=19==i||24==i&&k>=s?f(h,s):l(h,s);else if(e=U(new a(e),n,t),u=e.e,h=r(e.c),c=h.length,19==i||24==i&&(u>=n||k>=u)){for(;n>c;h+="0",c++);h=f(h,u)}else if(n-=s,h=l(h,u),u+1>c){if(--n>0)for(h+=".";n--;h+="0");}else if(n+=u-c,n>0)for(u+1==c&&(h+=".");n--;h+="0");return e.s<0&&o?"-"+h:h}function _(e,n){var t,r,i=0;for(u(e[0])&&(e=e[0]),t=new a(e[0]);++ie||e>t||e!=c(e))&&L(r,(i||"decimal places")+(n>e||e>t?" out of range":" not an integer"),e),!0}function I(e,n,t){for(var r=1,i=n.length;!n[--i];n.pop());for(i=n[0];i>=10;i/=10,r++);return(t=r+t*y-1)>z?e.c=e.e=null:G>t?e.c=[e.e=0]:(e.e=t,e.c=n),e}function L(e,n,t){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][e]+"() "+n+": "+t);throw r.name="BigNumber Error",M=0,r}function U(e,n,t,r){var i,o,u,s,f,l,c,a=e.c,h=R;if(a){e:{for(i=1,s=a[0];s>=10;s/=10,i++);if(o=n-i,0>o)o+=y,u=n,f=a[l=0],c=f/h[i-u-1]%10|0;else if(l=d((o+1)/y),l>=a.length){if(!r)break e;for(;a.length<=l;a.push(0));f=c=0,i=1,o%=y,u=o-y+1}else{for(f=s=a[l],i=1;s>=10;s/=10,i++);o%=y,u=o-y+i,c=0>u?0:f/h[i-u-1]%10|0}if(r=r||0>n||null!=a[l+1]||(0>u?f:f%h[i-u-1]),r=4>t?(c||r)&&(0==t||t==(e.s<0?3:2)):c>5||5==c&&(4==t||r||6==t&&(o>0?u>0?f/h[i-u]:0:a[l-1])%10&1||t==(e.s<0?8:7)),1>n||!a[0])return a.length=0,r?(n-=e.e+1,a[0]=h[(y-n%y)%y],e.e=-n||0):a[0]=e.e=0,e;if(0==o?(a.length=l,s=1,l--):(a.length=l+1,s=h[y-o],a[l]=u>0?m(f/h[i-u]%h[u])*s:0),r)for(;;){if(0==l){for(o=1,u=a[0];u>=10;u/=10,o++);for(u=a[0]+=s,s=1;u>=10;u/=10,s++);o!=s&&(e.e++,a[0]==O&&(a[0]=1));break}if(a[l]+=s,a[l]!=O)break;a[l--]=0,s=1}for(o=a.length;0===a[--o];a.pop());}e.e>z?e.c=e.e=null:e.et?null!=(e=i[t++]):void 0};return f(n="DECIMAL_PLACES")&&H(e,0,E,2,n)&&(P=0|e),r[n]=P,f(n="ROUNDING_MODE")&&H(e,0,8,2,n)&&(B=0|e),r[n]=B,f(n="EXPONENTIAL_AT")&&(u(e)?H(e[0],-E,0,2,n)&&H(e[1],0,E,2,n)&&(k=0|e[0],$=0|e[1]):H(e,-E,E,2,n)&&(k=-($=0|(0>e?-e:e)))),r[n]=[k,$],f(n="RANGE")&&(u(e)?H(e[0],-E,-1,2,n)&&H(e[1],1,E,2,n)&&(G=0|e[0],z=0|e[1]):H(e,-E,E,2,n)&&(0|e?G=-(z=0|(0>e?-e:e)):j&&L(2,n+" cannot be zero",e))),r[n]=[G,z],f(n="ERRORS")&&(e===!!e||1===e||0===e?(M=0,H=(j=!!e)?x:o):j&&L(2,n+w,e)),r[n]=j,f(n="CRYPTO")&&(e===!!e||1===e||0===e?(V=!(!e||!h),e&&!V&&j&&L(2,"crypto unavailable",h)):j&&L(2,n+w,e)),r[n]=V,f(n="MODULO_MODE")&&H(e,0,9,2,n)&&(W=0|e),r[n]=W,f(n="POW_PRECISION")&&H(e,0,E,2,n)&&(J=0|e),r[n]=J,f(n="FORMAT")&&("object"==typeof e?X=e:j&&L(2,n+" not an object",e)),r[n]=X,r},a.max=function(){return _(arguments,T.lt)},a.min=function(){return _(arguments,T.gt)},a.random=function(){var e=9007199254740992,n=Math.random()*e&2097151?function(){return m(Math.random()*e)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(e){var t,r,i,o,u,s=0,f=[],l=new a(q);if(e=null!=e&&H(e,0,E,14)?0|e:P,o=d(e/y),V)if(h&&h.getRandomValues){for(t=h.getRandomValues(new Uint32Array(o*=2));o>s;)u=131072*t[s]+(t[s+1]>>>11),u>=9e15?(r=h.getRandomValues(new Uint32Array(2)),t[s]=r[0],t[s+1]=r[1]):(f.push(u%1e14),s+=2);s=o/2}else if(h&&h.randomBytes){for(t=h.randomBytes(o*=7);o>s;)u=281474976710656*(31&t[s])+1099511627776*t[s+1]+4294967296*t[s+2]+16777216*t[s+3]+(t[s+4]<<16)+(t[s+5]<<8)+t[s+6],u>=9e15?h.randomBytes(7).copy(t,s):(f.push(u%1e14),s+=7);s=o/7}else j&&L(14,"crypto unavailable",h);if(!s)for(;o>s;)u=n(),9e15>u&&(f[s++]=u%1e14);for(o=f[--s],e%=y,o&&e&&(u=R[y-e],f[s]=m(o/u)*u);0===f[s];f.pop(),s--);if(0>s)f=[i=0];else{for(i=-1;0===f[0];f.shift(),i-=y);for(s=1,u=f[0];u>=10;u/=10,s++);y>s&&(i-=y-s)}return l.e=i,l.c=f,l}}(),C=function(){function e(e,n,t){var r,i,o,u,s=0,f=e.length,l=n%A,c=n/A|0;for(e=e.slice();f--;)o=e[f]%A,u=e[f]/A|0,r=c*o+u*l,i=l*o+r%A*A+s,s=(i/t|0)+(r/A|0)+c*u,e[f]=i%t;return s&&e.unshift(s),e}function n(e,n,t,r){var i,o;if(t!=r)o=t>r?1:-1;else for(i=o=0;t>i;i++)if(e[i]!=n[i]){o=e[i]>n[i]?1:-1;break}return o}function r(e,n,t,r){for(var i=0;t--;)e[t]-=i,i=e[t]1;e.shift());}return function(i,o,u,s,f){var l,c,h,g,p,d,w,v,N,b,S,R,A,E,D,F,_,x=i.s==o.s?1:-1,I=i.c,L=o.c;if(!(I&&I[0]&&L&&L[0]))return new a(i.s&&o.s&&(I?!L||I[0]!=L[0]:L)?I&&0==I[0]||!L?0*x:x/0:NaN);for(v=new a(x),N=v.c=[],c=i.e-o.e,x=u+c+1,f||(f=O,c=t(i.e/y)-t(o.e/y),x=x/y|0),h=0;L[h]==(I[h]||0);h++);if(L[h]>(I[h]||0)&&c--,0>x)N.push(1),g=!0;else{for(E=I.length,F=L.length,h=0,x+=2,p=m(f/(L[0]+1)),p>1&&(L=e(L,p,f),I=e(I,p,f),F=L.length,E=I.length),A=F,b=I.slice(0,F),S=b.length;F>S;b[S++]=0);_=L.slice(),_.unshift(0),D=L[0],L[1]>=f/2&&D++;do{if(p=0,l=n(L,b,F,S),0>l){if(R=b[0],F!=S&&(R=R*f+(b[1]||0)),p=m(R/D),p>1)for(p>=f&&(p=f-1),d=e(L,p,f),w=d.length,S=b.length;1==n(d,b,w,S);)p--,r(d,w>F?_:L,w,f),w=d.length,l=1;else 0==p&&(l=p=1),d=L.slice(),w=d.length;if(S>w&&d.unshift(0),r(b,d,S,f),S=b.length,-1==l)for(;n(L,b,F,S)<1;)p++,r(b,S>F?_:L,S,f),S=b.length}else 0===l&&(p++,b=[0]);N[h++]=p,b[0]?b[S++]=I[A]||0:(b=[I[A]],S=1)}while((A++=10;x/=10,h++);U(v,u+(v.e=h+c*y-1)+1,s,g)}else v.e=c,v.r=+g;return v}}(),g=function(){var e=/^(-?)0([xbo])(?=\w[\w.]*$)/i,n=/^([^.]+)\.$/,t=/^\.([^.]+)$/,r=/^-?(Infinity|NaN)$/,i=/^\s*\+(?=[\w.])|^\s+|\s+$/g;return function(o,u,s,f){var l,c=s?u:u.replace(i,"");if(r.test(c))o.s=isNaN(c)?null:0>c?-1:1;else{if(!s&&(c=c.replace(e,function(e,n,t){return l="x"==(t=t.toLowerCase())?16:"b"==t?2:8,f&&f!=l?e:n}),f&&(l=f,c=c.replace(n,"$1").replace(t,"0.$1")),u!=c))return new a(c,l);j&&L(M,"not a"+(f?" base "+f:"")+" number",u),o.s=null}o.c=o.e=null,M=0}}(),T.absoluteValue=T.abs=function(){var e=new a(this);return e.s<0&&(e.s=1),e},T.ceil=function(){return U(new a(this),this.e+1,2)},T.comparedTo=T.cmp=function(e,n){return M=1,i(this,new a(e,n))},T.decimalPlaces=T.dp=function(){var e,n,r=this.c;if(!r)return null;if(e=((n=r.length-1)-t(this.e/y))*y,n=r[n])for(;n%10==0;n/=10,e--);return 0>e&&(e=0),e},T.dividedBy=T.div=function(e,n){return M=3,C(this,new a(e,n),P,B)},T.dividedToIntegerBy=T.divToInt=function(e,n){return M=4,C(this,new a(e,n),0,1)},T.equals=T.eq=function(e,n){return M=5,0===i(this,new a(e,n))},T.floor=function(){return U(new a(this),this.e+1,3)},T.greaterThan=T.gt=function(e,n){return M=6,i(this,new a(e,n))>0},T.greaterThanOrEqualTo=T.gte=function(e,n){return M=7,1===(n=i(this,new a(e,n)))||0===n},T.isFinite=function(){return!!this.c},T.isInteger=T.isInt=function(){return!!this.c&&t(this.e/y)>this.c.length-2},T.isNaN=function(){return!this.s},T.isNegative=T.isNeg=function(){return this.s<0},T.isZero=function(){return!!this.c&&0==this.c[0]},T.lessThan=T.lt=function(e,n){return M=8,i(this,new a(e,n))<0},T.lessThanOrEqualTo=T.lte=function(e,n){return M=9,-1===(n=i(this,new a(e,n)))||0===n},T.minus=T.sub=function(e,n){var r,i,o,u,s=this,f=s.s;if(M=10,e=new a(e,n),n=e.s,!f||!n)return new a(NaN);if(f!=n)return e.s=-n,s.plus(e);var l=s.e/y,c=e.e/y,h=s.c,g=e.c;if(!l||!c){if(!h||!g)return h?(e.s=-n,e):new a(g?s:NaN);if(!h[0]||!g[0])return g[0]?(e.s=-n,e):new a(h[0]?s:3==B?-0:0)}if(l=t(l),c=t(c),h=h.slice(),f=l-c){for((u=0>f)?(f=-f,o=h):(c=l,o=g),o.reverse(),n=f;n--;o.push(0));o.reverse()}else for(i=(u=(f=h.length)<(n=g.length))?f:n,f=n=0;i>n;n++)if(h[n]!=g[n]){u=h[n]0)for(;n--;h[r++]=0);for(n=O-1;i>f;){if(h[--i]0?(s=u,r=l):(o=-o,r=f),r.reverse();o--;r.push(0));r.reverse()}for(o=f.length,n=l.length,0>o-n&&(r=l,l=f,f=r,n=o),o=0;n;)o=(f[--n]=f[n]+l[n]+o)/O|0,f[n]%=O;return o&&(f.unshift(o),++s),I(e,f,s)},T.precision=T.sd=function(e){var n,t,r=this,i=r.c;if(null!=e&&e!==!!e&&1!==e&&0!==e&&(j&&L(13,"argument"+w,e),e!=!!e&&(e=null)),!i)return null;if(t=i.length-1,n=t*y+1,t=i[t]){for(;t%10==0;t/=10,n--);for(t=i[0];t>=10;t/=10,n++);}return e&&r.e+1>n&&(n=r.e+1),n},T.round=function(e,n){var t=new a(this);return(null==e||H(e,0,E,15))&&U(t,~~e+this.e+1,null!=n&&H(n,0,8,15,v)?0|n:B),t},T.shift=function(e){var n=this;return H(e,-S,S,16,"argument")?n.times("1e"+c(e)):new a(n.c&&n.c[0]&&(-S>e||e>S)?n.s*(0>e?0:1/0):n)},T.squareRoot=T.sqrt=function(){var e,n,i,o,u,s=this,f=s.c,l=s.s,c=s.e,h=P+4,g=new a("0.5");if(1!==l||!f||!f[0])return new a(!l||0>l&&(!f||f[0])?NaN:f?s:1/0);if(l=Math.sqrt(+s),0==l||l==1/0?(n=r(f),(n.length+c)%2==0&&(n+="0"),l=Math.sqrt(n),c=t((c+1)/2)-(0>c||c%2),l==1/0?n="1e"+c:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+c),i=new a(n)):i=new a(l+""),i.c[0])for(c=i.e,l=c+h,3>l&&(l=0);;)if(u=i,i=g.times(u.plus(C(s,u,h,1))),r(u.c).slice(0,l)===(n=r(i.c)).slice(0,l)){if(i.el&&(m=b,b=S,S=m,o=l,l=g,g=o),o=l+g,m=[];o--;m.push(0));for(w=O,v=A,o=g;--o>=0;){for(r=0,p=S[o]%v,d=S[o]/v|0,s=l,u=o+s;u>o;)c=b[--s]%v,h=b[s]/v|0,f=d*c+h*p,c=p*c+f%v*v+m[u]+r,r=(c/w|0)+(f/v|0)+d*h,m[u--]=c%w;m[u]=r}return r?++i:m.shift(),I(e,m,i)},T.toDigits=function(e,n){var t=new a(this);return e=null!=e&&H(e,1,E,18,"precision")?0|e:null,n=null!=n&&H(n,0,8,18,v)?0|n:B,e?U(t,e,n):t},T.toExponential=function(e,n){return F(this,null!=e&&H(e,0,E,19)?~~e+1:null,n,19)},T.toFixed=function(e,n){return F(this,null!=e&&H(e,0,E,20)?~~e+this.e+1:null,n,20)},T.toFormat=function(e,n){var t=F(this,null!=e&&H(e,0,E,21)?~~e+this.e+1:null,n,21);if(this.c){var r,i=t.split("."),o=+X.groupSize,u=+X.secondaryGroupSize,s=X.groupSeparator,f=i[0],l=i[1],c=this.s<0,a=c?f.slice(1):f,h=a.length;if(u&&(r=o,o=u,u=r,h-=r),o>0&&h>0){for(r=h%o||o,f=a.substr(0,r);h>r;r+=o)f+=s+a.substr(r,o);u>0&&(f+=s+a.slice(r)),c&&(f="-"+f)}t=l?f+X.decimalSeparator+((u=+X.fractionGroupSize)?l.replace(new RegExp("\\d{"+u+"}\\B","g"),"$&"+X.fractionGroupSeparator):l):f}return t},T.toFraction=function(e){var n,t,i,o,u,s,f,l,c,h=j,g=this,p=g.c,d=new a(q),m=t=new a(q),w=f=new a(q);if(null!=e&&(j=!1,s=new a(e),j=h,(!(h=s.isInt())||s.lt(q))&&(j&&L(22,"max denominator "+(h?"out of range":"not an integer"),e),e=!h&&s.c&&U(s,s.e+1,1).gte(q)?s:null)),!p)return g.toString();for(c=r(p),o=d.e=c.length-g.e-1,d.c[0]=R[(u=o%y)<0?y+u:u],e=!e||s.cmp(d)>0?o>0?d:m:s,u=z,z=1/0,s=new a(c),f.c[0]=0;l=C(s,d,0,1),i=t.plus(l.times(w)),1!=i.cmp(e);)t=w,w=i,m=f.plus(l.times(i=m)),f=i,d=s.minus(l.times(i=d)),s=i;return i=C(e.minus(t),w,0,1),f=f.plus(i.times(m)),t=t.plus(i.times(w)),f.s=m.s=g.s,o*=2,n=C(m,w,o,B).minus(g).abs().cmp(C(f,t,o,B).minus(g).abs())<1?[m.toString(),w.toString()]:[f.toString(),t.toString()],z=u,n},T.toNumber=function(){return+this},T.toPower=T.pow=function(e,n){var t,r,i,o=m(0>e?-e:+e),u=this;if(null!=n&&(M=23,n=new a(n)),!H(e,-S,S,23,"exponent")&&(!isFinite(e)||o>S&&(e/=0)||parseFloat(e)!=e&&!(e=NaN))||0==e)return t=Math.pow(+u,e),new a(n?t%n:t);for(n?e>1&&u.gt(q)&&u.isInt()&&n.gt(q)&&n.isInt()?u=u.mod(n):(i=n,n=null):J&&(t=d(J/y+2)),r=new a(q);;){if(o%2){if(r=r.times(u),!r.c)break;t?r.c.length>t&&(r.c.length=t):n&&(r=r.mod(n))}if(o=m(o/2),!o)break;u=u.times(u),t?u.c&&u.c.length>t&&(u.c.length=t):n&&(u=u.mod(n))}return n?r:(0>e&&(r=q.div(r)),i?r.mod(i):t?U(r,J,B):r)},T.toPrecision=function(e,n){return F(this,null!=e&&H(e,1,E,24,"precision")?0|e:null,n,24)},T.toString=function(e){var n,t=this,i=t.s,o=t.e;return null===o?i?(n="Infinity",0>i&&(n="-"+n)):n="NaN":(n=r(t.c),n=null!=e&&H(e,2,64,25,"base")?D(l(n,o),0|e,10,i):k>=o||o>=$?f(n,o):l(n,o),0>i&&t.c[0]&&(n="-"+n)),n},T.truncated=T.trunc=function(){return U(new a(this),this.e+1,1)},T.valueOf=T.toJSON=function(){var e,n=this,t=n.e;return null===t?n.toString():(e=r(n.c),e=k>=t||t>=$?f(e,t):l(e,t),n.s<0?"-"+e:e)},null!=e&&a.config(e),a}function t(e){var n=0|e;return e>0||e===n?n:n-1}function r(e){for(var n,t,r=1,i=e.length,o=e[0]+"";i>r;){for(n=e[r++]+"",t=y-n.length;t--;n="0"+n);o+=n}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function i(e,n){var t,r,i=e.c,o=n.c,u=e.s,s=n.s,f=e.e,l=n.e;if(!u||!s)return null;if(t=i&&!i[0],r=o&&!o[0],t||r)return t?r?0:-s:u;if(u!=s)return u;if(t=0>u,r=f==l,!i||!o)return r?0:!i^t?1:-1;if(!r)return f>l^t?1:-1;for(s=(f=i.length)<(l=o.length)?f:l,u=0;s>u;u++)if(i[u]!=o[u])return i[u]>o[u]^t?1:-1;return f==l?0:f>l^t?1:-1}function o(e,n,t){return(e=c(e))>=n&&t>=e}function u(e){return"[object Array]"==Object.prototype.toString.call(e)}function s(e,n,t){for(var r,i,o=[0],u=0,s=e.length;s>u;){for(i=o.length;i--;o[i]*=n);for(o[r=0]+=b.indexOf(e.charAt(u++));rt-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/t|0,o[r]%=t)}return o.reverse()}function f(e,n){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(0>n?"e":"e+")+n}function l(e,n){var t,r;if(0>n){for(r="0.";++n;r+="0");e=r+e}else if(t=e.length,++n>t){for(r="0",n-=t;--n;r+="0");e+=r}else t>n&&(e=e.slice(0,n)+"."+e.slice(n));return e}function c(e){return e=parseFloat(e),0>e?d(e):m(e)}var a,h,g,p=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,d=Math.ceil,m=Math.floor,w=" not a boolean or binary digit",v="rounding mode",N="number type has more than 15 significant digits",b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",O=1e14,y=14,S=9007199254740991,R=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],A=1e7,E=1e9;if("undefined"!=typeof crypto&&(h=crypto),a=n(),a["default"]=a.BigNumber=a,"function"==typeof define&&define.amd)define(function(){return a});else if("undefined"!=typeof module&&module.exports){if(module.exports=a,!h)try{h=require("crypto")}catch(D){}}else e||(e="undefined"!=typeof self?self:Function("return this")()),e.BigNumber=a}(this); - -BigNumber.config({ ERRORS: false }); diff --git a/js/bootstrap.min.js b/js/bootstrap.min.js deleted file mode 100755 index 7f21c1eb..00000000 --- a/js/bootstrap.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * Bootstrap v3.0.2 by @fat and @mdo - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat. - */ - -if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/js/cookie-notify.js b/js/cookie-notify.js deleted file mode 100644 index 358cfd96..00000000 --- a/js/cookie-notify.js +++ /dev/null @@ -1,26 +0,0 @@ -$('head').append(''); -$(document).ready(function() { - var template = $(''); - - // checking cookie - var matches = document.cookie.match(new RegExp("(?:^|; )agree_to_use=([^;]*)")); - var agreeToUseCookie = matches && decodeURIComponent(matches[1]); - if (!agreeToUseCookie) { - setTimeout(function() { - $('body').append(template); - $('.agree-using-cookies').on('click', function() { - var date = new Date(); - date.setFullYear(date.getFullYear() + 2); // + 2 years - document.cookie = 'agree_to_use=' + Date.now() + '; path=/; expires=' + date.toUTCString(); - $('#cookie-notification').hide(); - return false; - }); - }, 200); - } -}); \ No newline at end of file diff --git a/js/ethplorer-note.js b/js/ethplorer-note.js deleted file mode 100644 index 5eaf441a..00000000 --- a/js/ethplorer-note.js +++ /dev/null @@ -1,72 +0,0 @@ -/*! - * Copyright 2017 Everex https://everex.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -EthplorerNote = { - service: "/service/service.php", - next: 0, - notes: [], - init: function(container){ - EthplorerNote.container = container; - if((document.location.host !== 'ethplorer.io') && (document.location.host.indexOf('ethplorer') < 0)){ - EthplorerNote.service = '//ethplorer.io' + EthplorerNote.service; - } - var inner = $('
    '); - inner.addClass('ethplorer-note'); - EthplorerNote.container.append(inner); - EthplorerNote.inner = inner; - EthplorerNote.loadNotes(); - }, - loadNotes: function(){ - $.getJSON(EthplorerNote.service, {notes: 1}, function(data, status, xhr){ - if(('undefined' !== typeof(data)) && data.length){ - EthplorerNote.notes = data; - EthplorerNote.showNext(); - } - }); - }, - showNext: function(){ - if(!EthplorerNote.notes.length){ - return; - } - if(EthplorerNote.next >= EthplorerNote.notes.length){ - EthplorerNote.next = 0; - } - - EthplorerNote.container.show(); - - var note = EthplorerNote.notes[EthplorerNote.next]; - if(note.warning){ - EthplorerNote.container.addClass('warning'); - }else{ - EthplorerNote.container.removeClass('warning'); - } - EthplorerNote.inner.fadeOut(500, function(_data){ - return function(){ - var link = "/go.php?link=" + _data.link; - EthplorerNote.inner.html(_data.html.replace(/\%link\%/g, link)); - if(_data.image){ - var img = $(''); - img.attr('src', _data.image); - EthplorerNote.inner.prepend(img); - } - EthplorerNote.inner.fadeIn(800); - } - }(note)); - - EthplorerNote.next++; - setTimeout(EthplorerNote.showNext, 15000); - } -}; \ No newline at end of file diff --git a/js/ethplorer-search.js b/js/ethplorer-search.js deleted file mode 100644 index a394b4b3..00000000 --- a/js/ethplorer-search.js +++ /dev/null @@ -1,76 +0,0 @@ -/*! - * Copyright 2017 Everex https://everex.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -EthplorerSearch = { - data: {}, - service: "/service/service.php", - searchCache: {}, - init: function(form, el, cb){ - EthplorerSearch.form = form; - EthplorerSearch.el = el; - EthplorerSearch.cb = cb; - EthplorerSearch.form.submit(function(e){ - if('function' === typeof(EthplorerSearch.cb)){ - EthplorerSearch.cb(EthplorerSearch.el.val(), true); - } - e.preventDefault(); - }); - EthplorerSearch.el.autocomplete({ - source: function(request, response){ - var search = request.term; - if(search in EthplorerSearch.searchCache){ - response(EthplorerSearch.searchCache[search]); - return; - } - $.getJSON(EthplorerSearch.service, {search: search}, function(data, status, xhr){ - if(!data.total){ - data.results = [false]; - }else{ - if(data.total > data.results.length){ - data.results.push({more: (data.total - data.results.length)}); - } - } - EthplorerSearch.searchCache[search] = data.results; - response(data.results); - }); - }, - minLength: 1, - select: function(event, ui){ - if('undefined' !== typeof(ui.item[2])){ - if('undefined' !== typeof(Ethplorer)){ - Ethplorer.gaSendEvent('userAction', 'searchHeader', ui.item[2]); - } - document.location.href = '/address/' + ui.item[2] + '?from=search'; - } - } - }) - .autocomplete( "instance" )._renderItem = function(ul, res){ - if(!res) return; - if('undefined' !== typeof(res[0])){ - var address = res[2]; - var text = (res[0] ? $('').text(res[0]).html() : "") + (res[1] ? (' (' + res[1] + ')') : ''); - text = text.replace(new RegExp(EthplorerSearch.el.val(), 'ig'), "$&"); - address = address.replace(new RegExp(EthplorerSearch.el.val(), 'ig'), "$&"); - text += (' ' + address + '') - return $('
  • ').append(text).appendTo(ul); - } - if('undefined' !== typeof(res.more)){ - return $('
  • ').append(res.more + ' results more...').appendTo(ul); - } - return $('
  • ').append('No results').appendTo(ul); - }; - } -}; diff --git a/js/ethplorer.js b/js/ethplorer.js deleted file mode 100644 index eaa3d59d..00000000 --- a/js/ethplorer.js +++ /dev/null @@ -1,2571 +0,0 @@ -/*! - * Copyright 2016 Everex https://everex.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -Ethplorer = { - debug: false, - debugId: "", - data: {}, - pageSize: 10, - service: /*"https://ethplorer.io/service/service.php",*/ "/service/service.php", - filter: '', - ethPrice: {rate: 0, diff: 0}, - searchCache: {}, - saveData: function(){}, - Config: {testnet: false}, - Extensions: {}, - handlers: {}, - init: function(){ - if('undefined' !== typeof(ethplorerConfig)){ - Ethplorer.Config = ethplorerConfig; - } - Ethplorer.isProd = ('ethplorer.io' === document.location.host); - Ethplorer.showHistoricalPrice = true; // sessionStorage.getItem("enableHistoricalPrice") === 'true'; - BigNumber.config({ ERRORS: false }); - Ethplorer.Nav.init(); - Ethplorer.Storage.init(); - Ethplorer.pageSize = Ethplorer.Storage.get('pageSize', 10); - if(Ethplorer.pageSize > 10){ - Ethplorer.Nav.set('pageSize', Ethplorer.pageSize); - } - if(Ethplorer.Nav.get('pageSize')){ - Ethplorer.pageSize = Ethplorer.Nav.get('pageSize'); - } - if(Ethplorer.Nav.get('filter')){ - var filter = Ethplorer.Nav.get('filter'); - if(filter){ - filter = filter.toLowerCase(); - if(Ethplorer.checkFilter(filter)){ - Ethplorer.filter = filter; - Ethplorer.Nav.set('filter', Ethplorer.filter); - $('.filter-clear').show(); - $('#filter_list').val(Ethplorer.filter); - $('#filter_list').addClass('filled'); - }else{ - Ethplorer.Nav.del('filter'); - } - } - } - Ethplorer.maxListSize = 0; - Ethplorer.showTx = Ethplorer.Storage.get('showTx', 'all'); - var showTxHash = window.location.hash.substr(1); - if(showTxHash){ - aShowTxHash = showTxHash.split('='); - if(aShowTxHash.length > 1 && (aShowTxHash[0] == 'showTx') && (['all', 'eth', 'tokens'].indexOf(aShowTxHash[1]) >= 0)){ - Ethplorer.showTx = aShowTxHash[1]; - Ethplorer.Storage.set('showTx', aShowTxHash[1]); - } - } - Ethplorer.route(); - $('#network').text(Ethplorer.Config.testnet ? 'Test' : 'Modern'); - $('.navbar-nav li[data-page]').click(function(){ - if($(this).hasClass('active')) return; - if(!$('#loader:visible').length){ - $('.content-page:visible').hide(); - $('#' + $(this).attr('data-page')).show(); - $('.navbar-nav li').removeClass('active'); - $(this).addClass('active'); - } - }); - $(document).on('click', '.tx-details-link', function(){ - Ethplorer.Storage.set('tx-details-block', 'open'); - $('.tx-details-link').addClass('closed'); - $('#tx-details-block').show(); - $("#tx-details-block").find("tr:visible:odd").addClass("odd"); - $("#tx-details-block").find("tr:visible:even").addClass("even"); - $("#tx-details-block").find("tr:visible:last").addClass("last"); - }); - $(document).on('click', '.tx-details-close', function(){ - Ethplorer.Storage.set('tx-details-block', 'closed'); - $('.tx-details-link').removeClass('closed'); - $('#tx-details-block').hide(); - }); - $(document).on('click', '[data-toggle="tab"]', function(){ - Ethplorer.Nav.set('tab', $(this).parent().attr('id')); - var activeTab = Ethplorer.getActiveTab(); - if(activeTab){ - if(activeTab != 'transfers'){ - $('#showTxChecks').hide(); - }else{ - $('#showTxChecks').show(); - } - } - if(Ethplorer.data) Ethplorer.showFilter(Ethplorer.data); - }); - $('.download').click(function(){ - var date = new Date(); - var hashDate = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(); - var href = $(this).attr("href"); - if(href.indexOf('&hash') == -1){ - href += '&hash=' + md5($(this).attr("href") + hashDate); - } - var showTx = Ethplorer.Storage.get('showTx', 'all'); - if(showTx){ - href += '&showTx=' + showTx; - } - - $(this).attr("href", href); - /*$('.export-csv').hide(); - $('.export-csv-spinner').show(); - Ethplorer.downloadData($(this).attr('data-address'));*/ - }); - if(Ethplorer.Nav.get('tab')){ - $('#' + Ethplorer.Nav.get('tab') +' a').click(); - } - $('.filter-clear').click(function(){ - $('#filter_list').val(''); - $('.filter-form').trigger('submit'); - }); - $('.filter-form').submit(function(e){ - e.preventDefault(); - var filter = $('#filter_list').val().toLowerCase(); - if(Ethplorer.filter != filter){ - if(filter){ - if(Ethplorer.checkFilter(filter)){ - $('.filter-clear').show(); - Ethplorer.Nav.set('filter', filter); - Ethplorer.Nav.del('transfers'); - $('#filter_list').addClass('filled'); - }else{ - if(!$('#filter-error').length){ - var errDiv = $('
    '); - errDiv.addClass("col-xs-12 text-right"); - errDiv.text('Invalid filter value'); - $('.filter-box').after(errDiv); - $('#filter-error').show(500, function(){ - setTimeout(function(){ - $('#filter-error').hide(500, function(){ - $('#filter-error').remove(); - }); - }, 3000); - }); - } - return; - } - }else{ - $('.filter-clear').hide(); - $('#filter_list').removeClass('filled'); - Ethplorer.Nav.del('filter'); - } - Ethplorer.filter = filter; - Ethplorer.showTableLoader(); - $('#filter_list').attr('disabled', true) - - // Reload active tab, set other tabs as need to reload - Ethplorer.reloadTab(false, true); - } - }); - $('.nav-tabs li a').click(function(){ - var tabName = $(this).parent().attr('id').replace('tab-', ''); - if(('undefined' !== typeof(Ethplorer.reloadTabs)) && (Ethplorer.reloadTabs.indexOf(tabName) >= 0)){ - Ethplorer.reloadTab(tabName, false); - } - setTimeout(function(){ - $("table").find("tr:visible:last").addClass("last"); - }, 300); - }); - var blockStatus = Ethplorer.Storage.get('tx-details-block', 'open'); - if('open' === blockStatus){ - $('.tx-details-link').addClass('closed'); - $('#tx-details-block').show(); - }else{ - $('.tx-details-link').removeClass('closed'); - $('#tx-details-block').hide(); - } - - // @see ethplorer-search.js - // @todo extension - if('undefined' !== typeof(EthplorerSearch)){ - EthplorerSearch.init($('#search-form'), $('#search'), Ethplorer.search); - } - - // @see ethplorer-adv.js - // @todo extension - if('undefined' !== typeof(EthplorerNote)){ - EthplorerNote.init($('#ethplorer-note')); - } - - // Initialize extensions - if(Ethplorer.Extensions){ - for(var ext in Ethplorer.Extensions){ - Ethplorer.Extensions[ext].init(); - } - } - - // implement save to file function - /*Ethplorer.saveData = function(data, name, mimetype){ - var file = new File([data], name, {type: mimetype + ";charset=utf-8"}); - saveAs(file); - saveAs( - new Blob( - [data] - , {type: mimetype} - ) - , name - ); - }; - - var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; - if(Blob && URL){ - Ethplorer.saveData = function(data, name, mimetype){ - var blob, url; - if(!mimetype) mimetype = 'application/octet-stream'; - if('download' in document.createElement('a')){ - blob = new Blob([data], {type: mimetype}); - url = URL.createObjectURL(blob); - var link = document.createElement('a'); - link.setAttribute('href', url); - link.setAttribute('download', name || 'ethplorer.data'); - var event = document.createEvent('MouseEvents'); - event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); - link.dispatchEvent(event); - } - setTimeout(function(){ URL.revokeObjectURL(url); }, 250); - }; - }else if(!/\bMSIE\b/.test(navigator.userAgent)){ - Ethplorer.saveData = function(data, name, mimetype){ - if(!mimetype) mimetype = 'application/octet-stream'; - window.open("data:" + mimetype + "," + encodeURIComponent(data), '_blank', ''); - }; - }*/ - this.Utils.initScrollable(); - }, - getActiveTab: function(){ - var tab = ($('.nav-tabs:visible li.active').length) ? $('.nav-tabs:visible li.active').attr('id').replace('tab-', '') : false; - if(!tab){ - if($('#address-transfers:visible').length){ - tab = 'transfers'; - } - if($('#address-chainy-tx:visible').length){ - tab = 'chainy'; - } - } - return tab; - }, - reloadTab: function(name, reloadOthers){ - var tabs = ['transfers', 'issuances', 'chainy', 'holders']; - if(!name){ // Get active tab if name not set - name = Ethplorer.getActiveTab(); - } - if(tabs.indexOf(name) < 0){ - return; - } - var methodName = 'draw' + name[0].toUpperCase() + name.substr(1); - if('undefined' !== typeof(Ethplorer[methodName])){ - Ethplorer.showTableLoader(); - Ethplorer.loadAddressData(Ethplorer.currentAddress, {refresh: name}, Ethplorer[methodName]); - } - if(reloadOthers){ - Ethplorer.reloadTabs = tabs; - } - if(('undefined' !== typeof(Ethplorer.reloadTabs)) && (Ethplorer.reloadTabs.indexOf(name) >= 0)){ - delete Ethplorer.reloadTabs[Ethplorer.reloadTabs.indexOf(name)]; - } - }, - checkFilter: function(filter){ - return (!filter || /^[0-9a-fx]+$/.test(filter)); - }, - route: function(){ - var pathData = Ethplorer.Utils.parsePath(); - switch(pathData.cmd){ - case 'tx': - Ethplorer.getTxDetails(pathData.arg); - break; - case 'address': - Ethplorer.getAddressDetails(pathData.arg); - break; - case 'search': - Ethplorer.search(pathData.arg); - break; - default: - Ethplorer.error('Invalid request'); - } - }, - error: function(message, addationalInfo = ''){ - Ethplorer.hideLoader(); - $('.content-page').hide(); - if (addationalInfo.length) { - $('#error-with-details').show(); - $('#error').hide(); - $('#error-with-details .error-title').text(message); - $('#error-with-details .error-details').html(addationalInfo); - } else { - $('#error').show(); - $('#error-with-details').hide(); - $('#error-reason').text(message); - } - $('#error').show(); - $('#ethplorer-path').hide(); - }, - getTxErrorReason: function(reason){ - var aReasons = { - out_of_gas: 'Out of gas' - }; - return ('undefined' !== typeof(aReasons[reason])) ? aReasons[reason] : reason; - }, - getTxDetails: function (txHash, abi){ - Ethplorer.showLoader(); - - // Check TX hash format first - txHash = txHash.toLowerCase(); - if(!/^0x[0-9a-f]{64}$/i.test(txHash)){ - Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-invalid-hash'); - Ethplorer.error('Invalid transaction hash'); - return; - } - var requestData = {data: txHash}; - if(Ethplorer.debug){ - requestData.debugId = Ethplorer.debugId; - } - var stopCheckingPendingAt = Date.now() + 1800000; // after 30 minutes - function loadTxDetails(showResult = true) { - $.getJSON(Ethplorer.service, requestData) - .done(function(_txHash){ - return function(data){ - if(data.debug){ - Ethplorer.requestDebug = data.debug; - } - if(data.ethPrice){ - Ethplorer.ethPrice = data.ethPrice; - } - if(showResult) { - // if transaction is pending need send ga event - if (data.pending) { - Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-pending'); - } - Ethplorer.showTxDetails(_txHash, data); - } else if (!data.pending) { - // Transaction not pending anymore. Reloading the view. - location.reload(); - } - // is transaction is pending - if(data.pending && stopCheckingPendingAt > Date.now()){ - setTimeout(function() { - loadTxDetails(false); - }, 30000); // every 30 seconds - } - } - if(data.ethPrice){ - Ethplorer.ethPrice = data.ethPrice; - } - Ethplorer.showTxDetails(_txHash, data); - }(txHash)) - .fail(function() { - // Try send request again after 30 seconds - setTimeout(function() { - loadTxDetails(false); - }, 30000); - }); - } - loadTxDetails(); - }, - knownContracts: [], - dataFields: {}, - showOpDetails: function(oTx, op){ - var titleAdd = ''; - var oToken = Ethplorer.prepareToken(op.token); - var tokenName = ('N/A' !== oToken.name) ? oToken.name : '[ERC20]'; - titleAdd += (tokenName + ' '); - $('.token-name:eq(0)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, tokenName, false)); - $('.token-name:eq(1)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, oToken.name , false)); - var txData = {tx: oTx, operation: op, token: oToken}; - - $('.token-related td.list-field').empty(); - Ethplorer.fillValues('transaction', txData, ['token', 'token.timestamp', 'token.contract', 'token.symbol', 'token.price', 'token.decimals', 'token.owner']); - var totalSupply = oToken.totalSupply; - if(oToken.price && oToken.price.rate){ - var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); - if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - if(pf < 1e+12){ - pf = Ethplorer.Utils.formatNum(pf, true, 2, true); - }else{ - pf = "--"; - } - totalSupply = totalSupply + '
    $ ' + pf + ''; - $('#transaction-token-totalSupply').html(totalSupply); - } - } - - if(oToken.estimatedDecimals){ - $('#transaction-token-decimals').append(' (estimated)'); - } - - $('#transfer-tx-timestamp').html($('#transaction-tx-timestamp').html()); - - if($('#transaction-tx-message').html()){ - $('#transfer-tx-message').html($('#transaction-tx-message').html()); - $('#transaction-tx-message').html('') - } - var oOperation = txData.operation; - // Temporary workaround - if(oOperation.type == 'Mint'){ - oOperation.type = 'Issuance'; - } - - var valFloat = parseFloat(Ethplorer.Utils.toBig(oOperation.value).toString()); - if('undefined' !== typeof(oOperation.formatted)){ - if(Ethplorer.Utils.isSafari()){ - oOperation.value = valFloat; - }else{ - oOperation.value = Ethplorer.Utils.toBig(oOperation.value).div(Math.pow(10, oToken.decimals)); - } - oOperation.value = Ethplorer.Utils.formatNum(oOperation.value, true, oToken.decimals, true, true); - oOperation.value = oToken.symbol ? (oOperation.value + ' ' + oToken.symbol) : oOperation.value; - oOperation.formatted = true; - } - var value = oOperation.value; - if(oToken.symbol && (value.toString().indexOf(oToken.symbol) < 0)){ - value = value + ' ' + oToken.symbol; - } - if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; - value += getHistDiffPriceString(op.usdPrice, oToken.price.rate); - } - $('#transfer-operation-value').html(value); - - $('#historical-price').html(getHistUsdPriceString(op.usdPrice, valFloat)); - - - titleAdd += oOperation.type; - $('.token-operation-type').text(oOperation['type']); - Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); - if(oTx.blockNumber){ - $('#txTokenStatus')[oOperation.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); - $('#txTokenStatus').html(oOperation.success ? 'Success' : 'Failed' + (oOperation.failedReason ? (': ' + Ethplorer.getTxErrorReason(oOperation.failedReason)) : '')); - $('#operation-status').addClass(oOperation.success ? 'green' : 'red'); - } - //document.title = 'Ethplorer: ' + (titleAdd ? (titleAdd + ' -') : ''); - Ethplorer.Utils.hideEmptyFields(); - }, - showTxDetails: function(txHash, txData){ - // $('#ethplorer-path').html('

    Transaction hash: ' + txHash + '

    '); - $('#ethplorer-path').show(); - if (txData.pending && txData.tx && txData.tx.blockNumber) { - $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Processing transaction  

    ') - } else if (txData.pending) { - $('#ethplorer-path').html($('#ethplorer-path').text() + '

    Pending transaction  

    ') - } - - $('.list-field').empty(); - $('#transaction-tx-hash').html(Ethplorer.Utils.getEtherscanLink(txHash)); - $('.token-related')[txData.token ? 'show' : 'hide'](); - $('#tx-status, #operation-status').removeClass('green red'); - - var oTx = txData.tx; - if(false === oTx){ - Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-not-found'); - Ethplorer.error( - 'Transaction not found', - 'If transaction was created recently, it may not have reached mempool yet.
    Wait a minute and try to refresh the page.' - ); - return; - } - - Ethplorer.knownContracts = txData.contracts ? txData.contracts : []; - - if(oTx.blockNumber && !txData.pending){ - $('#txEthStatus')[oTx.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txEthStatus')[oTx.success ? 'addClass' : 'removeClass']('text-success'); - $('#txEthStatus').html(oTx.success ? 'Success' : 'Failed' + (oTx.failedReason ? (': ' + Ethplorer.getTxErrorReason(oTx.failedReason)) : '')); - $('#tx-status').addClass(oTx.success ? 'green' : 'red'); - } else if (oTx.blockNumber && txData.pending) { - $('#txEthStatus').removeClass('text-danger text-success'); - $('#txEthStatus').html('Processing'); - } else { - $('#txEthStatus').removeClass('text-danger text-success'); - $('#txEthStatus').html('Pending'); - } - - var titleAdd = ''; - - $('#tx-parsed').hide(); - if(oTx.input && oTx.input.length){ - oTx.input = oTx.input.toUpperCase().replace(/^0x/i, ''); - Ethplorer.dataFields['transaction-tx-input'] = { - hex: oTx.input, - ascii: Ethplorer.Utils.hex2ascii(oTx.input) - }; - var obj = Ethplorer.Utils.parseJData(oTx.input); - var isChainy = false; - // QUESTION: need explanation - if(oTx.to && ('0xf3763c30dd6986b53402d41a8552b8f7f6a6089b' === oTx.to)){ - var input = Ethplorer.Utils.hex2ascii(oTx.input.substring(136).replace(/0+$/, '')); - try { - obj = JSON.parse(input); - }catch(e){ - // console.log(e.message); - // console.log(input); - } - Ethplorer.dataFields['transaction-tx-input']['ascii'] = input; - if(('undefined' !== typeof(obj['id'])) && ('CHAINY' === obj['id'])){ - // Chainy transaction - var chainyTypes = { - 'R': 'Redirect', - 'T': 'Text', - 'H': 'Hash', - 'L': ('undefined' !== typeof(obj['url'])) ? 'File Link' : 'File Hash', - 'E': 'Encrypted' - }; - titleAdd = 'Chainy ' + chainyTypes[obj['type']]; - $('#chainy-op').text(chainyTypes[obj['type']]); - if('undefined' !== typeof(obj['url'])){ - $('#chainy-url').html(' ' + obj['url'] + ''); - } - var aFields = ['hash', 'filename', 'filesize', 'description']; - for(var f = 0; f < aFields.length; f++){ - var fld = aFields[f]; - if('undefined' !== typeof(obj[fld])){ - $('#chainy-' + fld).text(obj[fld]); - } - } - var log = oTx.receipt && oTx.receipt.logs && oTx.receipt.logs.length ? oTx.receipt.logs[0] : false; - if(log && log.topics && log.topics.length && (0 === log.topics[0].indexOf("0xdad5c"))){ - try { - var data = log.data.slice(194).replace(/0+$/, ''); - var link = Ethplorer.Utils.hex2ascii(data); - $('#chainy-link').html(' ' + link + ''); - }catch(e){} - } - $('.chainy').show(); - isChainy = true; - } - } - if(false !== obj){ - $('#transaction-tx-parsed').text(JSON.stringify(obj, null, 4)); - $('#tx-parsed').show(); - if(obj.description){ - var msg = obj.description; - if(obj.link){ - msg = msg + ' ' + obj.link; - } - var msgid = isChainy ? "#chainy-message" : '#transaction-tx-message'; - msg = $('').text(msg).html(); - msg = msg.replace(/http[s]?\:\/\/[^\s]*/g, '$&'); - msg = msg.replace(/~~~(.*)~~~\n?/g, '

    $1

    '); - msg = msg.replace(/\n/g, '
    '); - $(msgid).html(msg); - } - } - } - if(txData.tx.gasPrice){ - txData.tx.gasPrice = parseFloat(Ethplorer.Utils.toBig(txData.tx.gasPrice).toString()); - if (!txData.pending) { - txData.tx.cost = txData.tx.gasUsed ? txData.tx.gasPrice * txData.tx.gasUsed : 0; - } - } - Ethplorer.fillValues('transaction', txData, ['tx', 'tx.from', 'tx.to', 'tx.creates', 'tx.value', 'tx.timestamp', 'tx.gasLimit', 'tx.gasUsed', 'tx.gasPrice', 'tx.fee', 'tx.nonce', 'tx.blockNumber', 'tx.confirmations', 'tx.input', 'tx.cost', 'tx.method']); - - if(txData.token){ - var oToken = Ethplorer.prepareToken(txData.token); - var tokenName = ('N/A' !== oToken.name) ? oToken.name : '[ERC20]'; - titleAdd += (tokenName + ' '); - $('.token-name:eq(0)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, tokenName, false)); - $('.token-name:eq(1)').html(Ethplorer.Utils.getEthplorerLink(oToken.address, oToken.name , false)); - - if(oToken.image){ - var img = Ethplorer.Utils.getEthplorerLink(oToken.address, '##IMG##', false); - $('.token-related:eq(1) .block-header').find('img').remove(); - $('.token-related:eq(1) .block-header').prepend( - img.replace('##IMG##', '') - ); - } - - txData.token = oToken; - - Ethplorer.fillValues('transaction', txData, ['token', 'token.timestamp', 'token.contract', 'token.symbol', 'token.price', 'token.decimals', 'token.owner', 'token.totalSupply']); - var totalSupply = oToken.totalSupply; - if(oToken.price && oToken.price.rate){ - var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); - if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - if(pf < 1e+12){ - pf = Ethplorer.Utils.formatNum(pf, true, 2, true); - }else{ - pf = "--"; - } - totalSupply = totalSupply + '
    $ ' + pf + ''; - $('#transaction-token-totalSupply').html(totalSupply); - } - } - - if(oToken.estimatedDecimals){ - $('#transaction-token-decimals').append(' (estimated)'); - } - - if($('#transaction-tx-message').html()){ - $('#transfer-tx-message').html($('#transaction-tx-message').html()); - $('#transaction-tx-message').html('') - } - - if(txData.operations && txData.operations.length){ - txData.operation = txData.operations[txData.operations.length - 1]; - var multiop = txData.operations.length > 1; - for(var i=0; i'; - }else if(op.from && op.to){ - var from = 'from ' + op.from + ''; - var to = 'to ' + op.to + ''; - opParties = from + '
    ' + to; - } - if(multiop){ - var row = $( - '' + - 'Details' + - '' + op.type.toString().toUpperCase() + - ' ' + op.value + ' ' + op.symbol + '' + - '
    ' + opParties + '
    ' + - '' + op.value + '' + - '' + op.symbol + '' + - '' + - '' - ); - row[0].operation = op; - row.click(function(_tx){ - return function(){ - if($(this).hasClass('selectable')){ - $(this).removeClass('selectable'); - $('.multiop .blue').addClass('selectable'); - $('.multiop .blue').removeClass('blue'); - $(this).addClass('blue'); - $('.token-related').animate({opacity:0.1}, 250, function(){ - $('.token-related').animate({opacity:1}, 250); - }); - setTimeout(function(__tx, _op){ - return function(){ - Ethplorer.showOpDetails(__tx, _op); - }; - }(_tx, this.operation), 250); - Ethplorer.Nav.set('opIdx', ('undefined' !== typeof(this.operation.priority)) ? this.operation.priority : this.operation.index) - } - }; - }(oTx)); - $('.multiop table').append(row); - } - } - if(multiop){ - $('.multiop table tr').addClass('selectable'); - $('.multiop table tr:eq(0)').removeClass('selectable').addClass('blue'); - $('.multiop .block-header h3').text(txData.operations.length + ' internal operations found'); - $('.multiop').show(); - } - - var oOperation = txData.operation; - // Temporary workaround - if(oOperation.type == 'Mint'){ - oOperation.type = 'Issuance'; - } - titleAdd += oOperation.type; - $('.token-operation-type').text(oOperation.type); - Ethplorer.fillValues('transfer', txData, ['operation', 'operation.from', 'operation.to']); - if(oOperation.value){ - var value = oOperation.value; - if(oToken.symbol && (value.toString().indexOf(oToken.symbol) < 0)){ - value = value + ' ' + oToken.symbol; - } - if(valFloat && oToken.price && oToken.price.rate){ - value = value + '
    $ ' + Ethplorer.Utils.formatNum(oToken.price.rate * valFloat, true, 2, true, true) + ''; - value += getHistDiffPriceString(oOperation.usdPrice, oToken.price.rate); - } - $('#transfer-operation-value').html(value); - $('#historical-price').html(getHistUsdPriceString(oOperation.usdPrice, valFloat)); - } - - if(oTx.blockNumber && !txData.pending){ - $('#txTokenStatus')[oOperation.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[oOperation.success ? 'addClass' : 'removeClass']('text-success'); - $('#txTokenStatus').html(oOperation.success ? 'Success' : 'Failed' + (oOperation.failedReason ? (': ' + Ethplorer.getTxErrorReason(oOperation.failedReason)) : '')); - $('#operation-status').addClass(oOperation.success ? 'green' : 'red'); - } else if (oTx.blockNumber && txData.pending) { - $('#txTokenStatus').removeClass('text-danger text-success'); - $('#txTokenStatus').html('Processing'); - } else { - $('#txTokenStatus').removeClass('text-danger text-success'); - $('#txTokenStatus').html('Pending'); - } - }else{ - titleAdd += 'Operation'; - $('.token-operation-type').text('Operation'); - if(oTx.receipt && oTx.receipt.logs && oTx.receipt.logs.length){ - for(var i=0; i 0 && - txData.tx.success !== false - ) { - $('#token-operation-block').show(); - $('#token-operation-block .token-name:eq(0)').html('ETH'); - $('.token-operation-type').text('Transfer'); - txData.operation = { - from: txData.tx.from, - to: txData.tx.to, - valueEth: txData.tx.value, - success: txData.tx.success, - usdPrice: txData.tx.usdPrice - } - - var operationFields = ['operation', 'operation.from', 'operation.to']; - var value = Ethplorer.Utils.formatNum(txData.tx.value, true, 18, true, true) + '  ETH'; - if (txData.tx.success) { - // Custom price value - if(txData.tx.value && Ethplorer.ethPrice.rate) { - value += '
    $ ' + Ethplorer.Utils.formatNum(Ethplorer.ethPrice.rate * txData.tx.value, true, 2, true, true) + ''; - if (txData.tx.usdPrice) { - value += getHistDiffPriceString(txData.tx.usdPrice, Ethplorer.ethPrice.rate); - // Price of eth on transaction exceute - $('#historical-price').html(getHistUsdPriceString(txData.tx.usdPrice, txData.tx.value)); - } - } - $('#transfer-operation-value').html(value); - } else { - // if no history show with using fillValues - operationFields.push('operation.valueEth'); - } - - Ethplorer.fillValues('transfer', txData, operationFields); - Ethplorer.fillValues('transfer', txData, ['tx', 'tx.timestamp']); - - if(oTx.blockNumber && !txData.pending){ - $('#txTokenStatus')[txData.operation.success ? 'removeClass' : 'addClass']('text-danger'); - $('#txTokenStatus')[txData.operation.success ? 'addClass' : 'removeClass']('text-success'); - $('#txTokenStatus').html(txData.operation.success ? 'Success' : 'Failed'); - $('#operation-status').addClass(txData.operation.success ? 'green' : 'red'); - } else if (oTx.blockNumber && txData.pending) { - $('#operation-status').removeClass('text-danger text-success'); - $('#txTokenStatus').html('Processing'); - } else { - $('#operation-status').removeClass('text-danger text-success'); - $('#txTokenStatus').html('Pending'); - } - } - $('#tx-details-block').show(); - $('.tx-details-close').hide(); - } - - //document.title = 'Ethplorer'; - //document.title += (': ' + (titleAdd ? (titleAdd + ' -') : '')); - //document.title += (' hash ' + txHash); - - var idx = Ethplorer.Nav.get('opIdx'); - if(false !== idx){ - idx = parseInt(idx); - var el = $('[data-op-idx=' + idx + ']'); - if(el.length && ('undefined' !== typeof(el[0].operation))){ - $('.multiop .blue').addClass('selectable'); - $('.multiop .blue').removeClass('blue'); - el.addClass('blue'); - el.removeClass('selectable'); - Ethplorer.showOpDetails(oTx, el[0].operation); - setTimeout(function(){ - el[0].scrollIntoView({behavior: "instant", inline: "center"}) - }, 0) - } - }else if(multiop){ - Ethplorer.showOpDetails(oTx, txData.operations[0]); - } - - Ethplorer.Events.fire('ethp_showTxDetails_finish', txData); - Ethplorer.Utils.hideEmptyFields(); - Ethplorer.hideLoader(); - $('#disqus_thread').show(); - $('#txDetails').show(); - $("table").find("tr:visible:odd").addClass("odd"); - $("table").find("tr:visible:even").addClass("even"); - $("table").find("tr:visible:last").addClass("last"); - - Ethplorer.gaSendEvent('ethpPageView', 'viewTx', 'tx-ok'); - }, - getAddressDetails: function(address){ - // Check Address format first - address = address.toLowerCase(); - if(!Ethplorer.Utils.isAddress(address)){ - Ethplorer.error('Invalid address format'); - return; - } - Ethplorer.loadAddressData(address, Ethplorer.showAddressDetails); - }, - loadAddressData: function(address, data, callback){ - if('function' === typeof(data)){ - callback = data; - var data = {}; - } - data.data = address; - var page = Ethplorer.Nav.getString(); - if(page){ - data.page = page; - } - if(Ethplorer.debug){ - data.debugId = Ethplorer.debugId; - } - if(Ethplorer.showTx){ - data.showTx = Ethplorer.showTx; - } - $.getJSON(Ethplorer.service, data, function(_address){ - return function(data){ - if(data.debug){ - Ethplorer.requestDebug = data.debug; - } - if(data.ethPrice){ - Ethplorer.ethPrice = data.ethPrice; - } - callback(_address, data); - if(Ethplorer.data) Ethplorer.showFilter(Ethplorer.data); - } - }(address)); - }, - showAddressDetails: function(address, data){ - var srcAddress = address; - address = Ethplorer.Utils.toChecksumAddress(address); - Ethplorer.currentAddress = address; - Ethplorer.data = data; - var titleAdd = ''; - // Temporary hack - $('.address-type').text(data.isContract ? 'Contract' : 'Address'); - $('#ethplorer-path').show(); - data.address = address; - var aValues = ['address', 'balance']; - if(data.balanceIn){ - aValues.push('balanceIn'); - if('undefined' === typeof(data.hideBalanceOut)){ - aValues.push('balanceOut'); - } - } - Ethplorer.fillValues('address', data, aValues); - $('#address-token-balances, #address-token-details').hide(); - if(data.isContract && data.contract.isChainy){ - titleAdd = 'Chainy Information'; - Ethplorer.drawChainy(address, data); - $('#address-chainy-info').show(); - } - if(data.isContract){ - Ethplorer.fillValues('address', data, ['contract', 'contract.creator']); - } - var qrIcon = ''; - if(data.isContract && data.token){ - - qrIcon = ''; - $('#address-token-details').show(); - var oToken = Ethplorer.prepareToken(data.token); - // oToken.address = oToken.address; - // QUESTION: need explanation - var ttype = (address.toLowerCase() !== "0x55d34b686aa8c04921397c5807db9ecedba00a4c") ? 'Token ' : 'Contract '; - $('#ethplorer-path').html(qrIcon + ttype + oToken.name + '
    ' + Ethplorer.Utils.toChecksumAddress(oToken.address) + ''); - titleAdd = ttype + oToken.name + (oToken.symbol ? (' [' + oToken.symbol + ']') : '' ) + ' Information'; - // Read description from tx - if(data.contract && data.contract.code){ - var json = Ethplorer.Utils.parseJData(data.contract.code); - if(json && json.description){ - oToken.description = json.description; - } - } - // Read from config - if(Ethplorer.Config.tokens && ('undefined' !== typeof(Ethplorer.Config.tokens[oToken.address]))){ - if('undefined' !== typeof(Ethplorer.Config.tokens[oToken.address].description)){ - oToken.description = Ethplorer.Config.tokens[oToken.address].description; - } - } - // console.log(oToken); - var showAlert = true; // document.location.hash && (document.location.hash.indexOf('showAlert') > 0); - if(oToken.alert && showAlert){ - $('#ethplorer-alert').html(oToken.alert); - $('#ethplorer-alert').show(); - } - if(oToken.description){ - oToken.description = $('').text(oToken.description).html(); - oToken.description = oToken.description.replace(/http[s]?\:\/\/[^\s]*/g, '$&'); - oToken.description = oToken.description.replace(/~~~(.*)~~~\n?/g, '

    $1

    '); - oToken.description = oToken.description.replace(/\n/g, '
    '); - }else{ - oToken.description = ''; - } - - // Add website, social icons and other links - if(oToken.description && (oToken.website || oToken.facebook || oToken.twitter || oToken.reddit || oToken.telegram)){ - oToken.description = oToken.description + '
    '; - } - if(oToken.website){ - if(oToken.description){ - oToken.description = oToken.description + '
    '; - } - oToken.description = oToken.description + ' ' + oToken.website + ''; - } - if(oToken.facebook){ - oToken.description = oToken.description + '
    ' + oToken.facebook + ''; - } - if(oToken.twitter){ - oToken.description = oToken.description + '
    ' + oToken.twitter + ''; - } - if(oToken.reddit){ - oToken.description = oToken.description + '
    ' + oToken.reddit + ''; - } - if(oToken.telegram){ - oToken.description = oToken.description + '
    Join Channel'; - } - if(oToken.links){ - oToken.links = oToken.links.replace(/http[s]?\:\/\/[^\s]*/g, '$&'); - oToken.links = oToken.links.replace(/\n/g, '
    '); - oToken.description = oToken.description + '

    ' + oToken.links; - } - - if(oToken.image){ - $('#address-token-details .block-header').find('img').remove(); - $('#address-token-details .block-header').prepend(''); - } - $('.address-token-name').html(oToken.name); - if(Ethplorer.Config.updateLink){ - $('.address-token-name:eq(0)').append('Update') - } - - Ethplorer.drawHolders(srcAddress, data); - Ethplorer.drawIssuances(srcAddress, data); - - if(data.pager && data.pager.transfers){ - data.token.transfersCount = data.pager.transfers.total; - if(data.token.transfersCount > Ethplorer.maxListSize) Ethplorer.maxListSize = data.token.transfersCount; - } - if(data.pager && data.pager.issuances){ - data.token.issuancesCount = ''; - if(data.pager.issuances.total){ - data.token.issuancesCount = data.pager.issuances.total; - } - } - if(data.pager && data.pager.holders){ - data.token.holdersCount = data.pager.holders.total; - } - - if(data.contract && data.contract.txsCount && (data.contract.txsCount > data.token.txsCount)){ - data.token.txsCount = data.contract.txsCount; - } - if(data.token && data.token.txsCount){ - if(data.token.txsCount > Ethplorer.maxListSize) Ethplorer.maxListSize = data.token.txsCount; - } - - var fields = [ - 'token', 'token.name', 'token.price', 'token.description', 'token.owner', 'token.totalSupply', 'token.totalIn', 'token.totalOut', 'token.decimals', 'token.symbol', - 'token.txsCount', 'token.transfersCount', 'token.issuancesCount', 'token.holdersCount', 'token.createdAt', 'token.createdTx' - ]; - - $('#tab-issuances').show(); - $('#tab-holders').show(); - - Ethplorer.fillValues('address', data, fields); - - var totalSupply = oToken.totalSupply; - if(oToken.price && oToken.price.rate){ - var pf = parseFloat(totalSupply.replace(/\,/g,'').split(' ')[0]); - if(pf){ - pf = Ethplorer.Utils.round(pf * oToken.price.rate, 2); - totalSupply = totalSupply + '
    $ ' + Ethplorer.Utils.formatNum(pf, true, 2, true) + ''; - $('#address-token-totalSupply').html(totalSupply); - } - } - - if(oToken.estimatedDecimals){ - $('#address-token-decimals').append(' (estimated)'); - } - - Ethplorer.gaSendEvent('ethpPageView', 'viewToken', oToken.name ? oToken.name : 'N/A'); - - }else{ - // Fill prices - var totalPrice = 0; - var lastTotalPrice = 0; - if(Ethplorer.ethPrice && Ethplorer.ethPrice.rate && data.balance){ - totalPrice = Ethplorer.ethPrice.rate * data.balance; - if(Ethplorer.ethPrice.diff){ - var lastEthRate = Ethplorer.ethPrice.diff > -100 ? (Ethplorer.ethPrice.rate / (1 + Ethplorer.ethPrice.diff / 100)) : 0; - lastTotalPrice += lastEthRate * data.balance; - } - } - if(data.balances && data.balances.length){ - for(var k=0; k 0) && oToken.price && oToken.price.rate){ - data.balances[k].price = oToken.price.rate; - data.balances[k].balanceUSD = oToken.price.rate * qFloat; - var lastRate = oToken.price.diff > -100 ? (oToken.price.rate / (1 + oToken.price.diff / 100)) : 0; - lastTotalPrice += qFloat * lastRate; - totalPrice += data.balances[k].balanceUSD; - } - } - // Sort - var balances = data.balances.sort(function(a,b){ - if(a.price && !b.price) return -1; - if(b.price && !a.price) return 1; - if(a.balanceUSD < b.balanceUSD) - return 1; - if (a.balanceUSD > b.balanceUSD) - return -1; - return 0; - }); - // Show - $('#address-token-balances table').empty(); - for(var k=0; k'); - var qty = balance.qty; - if(!parseFloat(qty.toString()) && !(balance.totalIn || balance.totalOut)){ - // No balance and no movement - skip - continue; - } - var value = Ethplorer.Utils.formatNum(qty, true, oToken.decimals, true, true) + ' ' + oToken.symbol; - if(balances[k].price){ - var rate = oToken.price; - var price = balances[k].balanceUSD; - value += ('
    $ ' + Ethplorer.Utils.formatNum(price, true, 2, true, true) + ' '); - if(rate.diff){ - var cls = getDiffClass(rate.diff); - var hint = 'Updated at ' + Ethplorer.Utils.ts2date(rate.ts, true); - if(rate.diff > 0){ - rate.diff = '+' + rate.diff; - } - value = value + ' (' + Ethplorer.Utils.round(rate.diff, 2) + '%)' - } - value = value + '
    '; - - } - // @temporary off - if(false && (balance.totalIn || balance.totalOut)){ - value += '
    '; - var totalIn = Ethplorer.Utils.toBig(balance.totalIn); - var totalOut = Ethplorer.Utils.toBig(balance.totalOut); - if(Ethplorer.Utils.isSafari()){ - totalIn = parseFloat(totalIn.toString()) / Math.pow(10, oToken.decimals); - totalOut = parseFloat(totalOut.toString()) / Math.pow(10, oToken.decimals); - }else{ - totalIn = totalIn.div(Math.pow(10, oToken.decimals)); - totalOut = totalOut.div(Math.pow(10, oToken.decimals)); - } - value += ('
    Total In: ' + Ethplorer.Utils.formatNum(totalIn, true, oToken.decimals, true) + '
    '); - value += ('Total Out: ' + Ethplorer.Utils.formatNum(totalOut, true, oToken.decimals, true) + '
    '); - } - row.append('' + Ethplorer.Utils.getEthplorerLink(balance.contract, oToken.name, false) + ''); - row.append('' + value + ''); - row.find('td:eq(1)').addClass('text-right'); - $('#address-token-balances table').append(row); - } - } - - var totalDiff = Ethplorer.Utils.round(Ethplorer.Utils.pdiff(totalPrice, lastTotalPrice), 2); - if(totalPrice){ - var value = '~ $ ' + Ethplorer.Utils.formatNum(totalPrice, true, 2, true, true); - if(totalDiff){ - var cls = getDiffClass(totalDiff); - if(totalDiff > 0){ - totalDiff = '+' + totalDiff; - } - value = value + ' (' + Ethplorer.Utils.round(totalDiff, 2) + '%)'; - } - $('#address-balances-total').html('' + value + ''); - }else{ - $('#address-balances-total').html(' '); - } - Ethplorer.gaSendEvent('ethpPageView', 'viewAddress'); - } - - if(!data.isContract || !data.token){ - $('#addr-balance').addClass('blue'); - $('#addr-balance').addClass('even'); - $('#addr-balance').addClass('address-balance'); - $('.nav-tabs').hide(); - $('.filter-box').addClass('out-of-tabs'); - if(!$('#address-token-balances table tr').length){ - var row = $(''); - var cell = $(''); - cell.html('No token balances found'); - row.append(cell); - $('#address-token-balances table').append(row); - $('#address-token-balances table').show(); - if(!totalPrice) $('#address-balances-total').remove(); - } - $('#address-token-balances').show(); - }else{ - $('.filter-box').addClass('in-tabs'); - } - - if(!data.contract || !data.contract.isChainy){ - Ethplorer.drawTransfers(srcAddress, data); - } - - /*if(data.token){ - }else{ - document.title = 'Ethplorer'; - document.title += (': ' + (titleAdd ? (titleAdd + ' -') : '')); - document.title += ((data.isContract ? ' Ethereum contract ' : ' Ethereum address ') + Ethplorer.currentAddress); - }*/ - - Ethplorer.Events.fire('ethp_showAddressDetails_finish', data); - - $('.local-time-offset').text(Ethplorer.Utils.getTZOffset()); - Ethplorer.Utils.hideEmptyFields(); - Ethplorer.hideLoader(); - if(!data.isContract || (data.contract && data.contract.isChainy)) $('#ethplorer-path').html(qrIcon + "Address: " + address); - $('#disqus_thread').show(); - $('#addressDetails').show(); - - $("table").find("tr:visible:odd").addClass("odd"); - $("table").find("tr:visible:even").addClass("even"); - $("table").find("tr:visible:last").addClass("last"); - - // Just for fun - if('0xf3Db5Fa2C66B7aF3Eb0C0b782510816cbe4813b8' === address){ - $('#tab-holders span').text('Hodlers'); - $('#address-token-holders h3').text('Token Everex Hodlers'); - } - - Ethplorer.showAddressWidget(data); - Ethplorer.showFilter(data); - }, - showFilter: function(data){ - var activeTab = Ethplorer.getActiveTab(); - if(activeTab && data.pager && data.pager[activeTab]){ - if(activeTab != 'transfers'){ - $('#showTxChecks').hide(); - }else{ - $('#showTxChecks').show(); - } - if(data.pager[activeTab].records > 100000 || Ethplorer.maxListSize > 100000){ - $('#filter_list').hide(); - }else{ - if(Ethplorer.showTx && data.token){ - $('.filter-box').prepend(''); - } - $('#filter_list').show(); - } - } - }, - showAddressWidget: function(data){ - //console.log('testWidget = ' + testWidget); - var oToken = Ethplorer.prepareToken(data.token); - var address = Ethplorer.currentAddress; - if(('undefined' !== typeof(ethplorerWidget)) && (true || !Ethplorer.isProd)){ - if(data.token || (data.isContract && data.contract.isChainy)){ - if(data.isContract && data.contract.isChainy) oToken.name = 'Chainy'; - var widgetTitle = (oToken && oToken.name) ? ($('