diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..128c6ac20 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +.git +.vscode +cmake-build-debug \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..440838e30 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,18 @@ +--- +name: Bug report +about: Marketmaker 1.0 bug report + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Please answer following questions and attach requested info - it'll help to solve issue faster** +- What OS do you use? +- What marketmaker version do you run? +- Attach your coins.json config. +- Provide your enable script with response. +- Provide other curl scripts (with responses) which were executed prior to error. +- Attach full marketmaker console logs (start collecting right after marketmaker execution). +- ***Make sure that you don't send your passphrase, userpass and privkeys. Your funds might be stolen if you reveal this info publicly!*** +- Provide info for all nodes involved (e.g. if error occurs during atomic swap you should provide info for both Bob and Alice). diff --git a/.gitignore b/.gitignore index 3ae3a23ab..1355ce65a 100755 --- a/.gitignore +++ b/.gitignore @@ -263,4 +263,12 @@ Release/* build_win64_release/* DB/* +.env.client +.env.seed +etomic_build/client/DB +etomic_build/client/stats.log +etomic_build/client/unparsed.txt +etomic_build/seed/DB +etomic_build/seed/stats.log +etomic_build/seed/unparsed.txt iguana/exchanges/manychains diff --git a/.travis.yml b/.travis.yml index 5730c4869..581c49ba1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,6 @@ matrix: include: - os: linux compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-7 env: OS_NAME=Linux MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" - os: osx compiler: clang @@ -17,14 +11,39 @@ matrix: osx_image: xcode9.2 before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y && sudo apt-get update && sudo apt-get install -y g++-7; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then chmod +x travis_cmake_linux.sh && ./travis_cmake_linux.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then chmod +x travis_cmake_mac.sh && ./travis_cmake_mac.sh; fi - git submodule update --init --recursive script: + - export VERSION=`echo "$(git tag -l --points-at HEAD)"` + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export THREAD_COUNT=`echo "$(nproc --all)"`; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export THREAD_COUNT=`echo "$(sysctl -n hw.physicalcpu)"`; fi - mkdir build && cd build - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cmake -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7 ..; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cmake ..; fi - - cmake --build . --target marketmaker-mainnet + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cmake -DMM_VERSION="$VERSION" -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7 ..; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cmake -DMM_VERSION="$VERSION" ..; fi + - echo "cmake --build . --target marketmaker-mainnet -j $THREAD_COUNT" + - cmake --build . --target marketmaker-mainnet -j $THREAD_COUNT + - cmake --build . --target marketmaker-testnet -j $THREAD_COUNT cache: - directories: - - $HOME/.hunter \ No newline at end of file + apt: true + directories: + - $HOME/.hunter + +before_deploy: + - export TAG=`echo "$(git rev-parse --short HEAD)"` + - mkdir deploy + - strip iguana/exchanges/marketmaker-mainnet + - strip iguana/exchanges/marketmaker-testnet + - tar -cvzf deploy/marketmaker-"$TRAVIS_OS_NAME"-"$TAG".tar.gz -C iguana/exchanges marketmaker-mainnet marketmaker-testnet +deploy: + provider: releases + api_key: + secure: "JDwFBGO4WLra9bXr2dsovet8y/ymC0Y+LJNr5/qlUIDt97zVytGbIlUc8BuI2VZFcnAvrtfOGdCs9m/PcLzZd4bMxXSsuaU0AJk/Vj9KzrIIGPJ4uS39KpO1USUpPW+5e0Bisf30JN3N2NypwMbMu42TKjVqaXSbVQfh79Iu6PdnyfiFbbTEfMeiRRrD72c00rwAw7kmndf7Sv9MiMN8WTFe0cQz5eH8GU/BSbnDorSrtClU4r7McR98zXaig/8XVcT543tcqdYW95QO7OqOjAid3XzzA/bPUTjC/nF/AyTJDco26nts0bCrCYeZRXIWdEInFLIeRHhHD7sW7dILRT/I7WlaLWnRtwo8e1L+U1k1yZ84dQMpgBznttdwH3vSj0crwCbFuMaRMMbPeW0H8C1VitLy1mlapw3RDI9yKlcw4V6WjPbz0YKhAoZgT/M/SaGr4ZkoWNCPoV5+Gub78p24Y8Y9BptJgj5t9KAcmDwbJ9wPt006ObWnbXvapo+6N5Dk2zuyQe9seoupzy4CAiNdluzAAVWsV/SjnN2aapjXoxaAaLQC6T8C1l1BpYri9LSKrjerr4QLVl/nw2yovAKNEobLLBVpSwfg4R72fu1BMS65gVsOqtFfs+R47CY+1D1Slev+UmKNMdE51+aXM+1XeC6wDUS5d13mW1NLhOE=" + file_glob: true + file: "deploy/*" + on: + tags: true + skip_cleanup: true diff --git a/Dockerfile.clientnode b/Dockerfile.clientnode new file mode 100644 index 000000000..96d9177df --- /dev/null +++ b/Dockerfile.clientnode @@ -0,0 +1,9 @@ +FROM ubuntu:17.10 +USER root +RUN apt-get update && apt-get install -y rinetd curl libcurl3-gnutls +RUN echo "0.0.0.0 10271 10.100.0.1 10271" >> /etc/rinetd.conf +RUN echo "0.0.0.0 8923 10.100.0.1 8923" >> /etc/rinetd.conf +RUN useradd -u 111 jenkins +USER jenkins +WORKDIR /usr/mm/etomic_build/client +CMD /usr/sbin/rinetd && rm -rf DB && ./client \ No newline at end of file diff --git a/Dockerfile.seednode b/Dockerfile.seednode new file mode 100644 index 000000000..d431296b6 --- /dev/null +++ b/Dockerfile.seednode @@ -0,0 +1,9 @@ +FROM ubuntu:17.10 +USER root +RUN apt-get update && apt-get install -y rinetd curl libcurl3-gnutls +RUN echo "0.0.0.0 10271 10.100.0.1 10271" >> /etc/rinetd.conf +RUN echo "0.0.0.0 8923 10.100.0.1 8923" >> /etc/rinetd.conf +RUN useradd -u 111 jenkins +USER jenkins +WORKDIR /usr/mm/etomic_build/seed +CMD /usr/sbin/rinetd && rm -rf DB && ./run diff --git a/Jenkinsfile b/Jenkinsfile index f7bb536b0..ef2e76a87 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,11 +1,12 @@ pipeline { - agent { - docker { - image 'artempikulin/cmake-ubuntu' - } - - } + agent any stages { + stage('Prepare') { + steps { + sh '''cp -r /root/.env.client .env.client +cp -r /root/.env.seed .env.seed''' + } + } stage('Build') { steps { sh '''git submodule update --init --recursive @@ -13,7 +14,27 @@ rm -rf build mkdir build cd build cmake .. -cmake --build . --target marketmaker-testnet''' +cmake --build . --target marketmaker-testnet -j 4 +cd ../ +docker-compose build''' + } + } + stage('Trade BEER/ETH') { + steps { + sh '''docker-compose up -d +./start_BEER_OTHER_trade.sh ETH +timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f clientnode) +timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f seednode) +docker-compose down''' + } + } + stage('Trade ETH/BEER') { + steps { + sh '''docker-compose up -d +./start_BEER_OTHER_trade_inverted.sh ETH +timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f clientnode) +timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f seednode) +docker-compose down''' } } } diff --git a/appveyor.yml b/appveyor.yml index de2123bc5..3c82ea80a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,30 @@ version: 1.0.{build} -branches: - only: - - etomic build_script: -- cmd: marketmaker_build_etomic.cmd \ No newline at end of file +- cmd: marketmaker_build_etomic.cmd +cache: + - C:\.hunter + - marketmaker_depends + +after_build: + - '7z a mm-win.zip + .\build_win64_release\iguana\exchanges\Release\marketmaker-mainnet.exe + .\marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll + .\marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT\\msvcp140.dll" + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT\\vcruntime140.dll"' + +artifacts: + - path: mm-win.zip + name: marketmaker-mainnet + +deploy: + release: v$(appveyor_build_version) + provider: GitHub + auth_token: + secure: iabzoz73JgtOIyE/Nmz4a4XefmK+7pIeup+1Hunj4hGKrdfesFN+176DMApgfu8t + artifact: marketmaker-mainnet + draft: false + prerelease: false + on: + branch: master + appveyor_repo_tag: false \ No newline at end of file diff --git a/cpp-ethereum b/cpp-ethereum index 633c62c08..e804e95d9 160000 --- a/cpp-ethereum +++ b/cpp-ethereum @@ -1 +1 @@ -Subproject commit 633c62c08bc73c7c3935c948a8d6c656a3659976 +Subproject commit e804e95d9a71e87fc5e3e69a2888448f23bc724f diff --git a/crypto777/cJSON.c b/crypto777/cJSON.c index d62b71683..e0665e378 100755 --- a/crypto777/cJSON.c +++ b/crypto777/cJSON.c @@ -902,10 +902,10 @@ char *get_cJSON_fieldname(cJSON *obj) { if ( obj != 0 ) { - if ( obj->child != 0 && obj->child->string != 0 ) - return(obj->child->string); - else if ( obj->string != 0 ) + if ( obj->string != 0 ) return(obj->string); + if ( obj->child != 0 && obj->child->string != 0 ) + return(obj->child->string); } return((char *)""); } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..52da982c7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +version: '2' +services: + seednode: + build: + context: ./ + dockerfile: Dockerfile.seednode + volumes: + - ~/.zcash-params:/home/jenkins/.zcash-params + - ~/.komodo:/home/jenkins/.komodo + - .:/usr/mm + env_file: + - .env.seed + tty: true + networks: + default: + ipv4_address: 10.100.0.2 + + clientnode: + build: + context: ./ + dockerfile: Dockerfile.clientnode + volumes: + - ~/.zcash-params:/home/jenkins/.zcash-params + - ~/.komodo:/home/jenkins/.komodo + - .:/usr/mm + links: + - seednode + tty: true + env_file: + - .env.client + networks: + default: + ipv4_address: 10.100.0.3 + +networks: + default: + driver: bridge + ipam: + config: + - subnet: 10.100.0.0/16 + gateway: 10.100.0.1 \ No newline at end of file diff --git a/etomic_build/client b/etomic_build/client deleted file mode 100755 index fb4f0c935..000000000 --- a/etomic_build/client +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -source passphrase -source coins -./stop -iguana/exchanges/marketmaker "{\"netid\":9999,\"seednode\":\"5.9.253.204\",\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" & diff --git a/etomic_build/client/buy_BEER_OTHER b/etomic_build/client/buy_BEER_OTHER new file mode 100755 index 000000000..1b4fb5ff6 --- /dev/null +++ b/etomic_build/client/buy_BEER_OTHER @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"$1\",\"rel\":\"BEER\",\"price\":1}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"BEER\",\"rel\":\"$1\",\"relvolume\":0.1,\"price\":1}" diff --git a/etomic_build/client/client b/etomic_build/client/client new file mode 100755 index 000000000..22f5c462e --- /dev/null +++ b/etomic_build/client/client @@ -0,0 +1,4 @@ +#!/bin/bash +source passphrase +source ../coins +../../build/iguana/exchanges/marketmaker-testnet "{\"netid\":9999,\"seednode\":\"10.100.0.2\",\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" diff --git a/etomic_build/client/enable b/etomic_build/client/enable new file mode 100755 index 000000000..0bda2f3ce --- /dev/null +++ b/etomic_build/client/enable @@ -0,0 +1,7 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"NODEC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JST\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BEER\"}" diff --git a/etomic_build/client/myipaddr b/etomic_build/client/myipaddr new file mode 100644 index 000000000..f1649949c --- /dev/null +++ b/etomic_build/client/myipaddr @@ -0,0 +1 @@ +10.100.0.3 diff --git a/etomic_build/client/passphrase b/etomic_build/client/passphrase new file mode 100644 index 000000000..d54ee899d --- /dev/null +++ b/etomic_build/client/passphrase @@ -0,0 +1 @@ +export passphrase="$PASSPHRASE" diff --git a/etomic_build/client/setpassphrase b/etomic_build/client/setpassphrase new file mode 100755 index 000000000..81cc0b28f --- /dev/null +++ b/etomic_build/client/setpassphrase @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +source passphrase +curl --url "http://127.0.0.1:7783" --data "{\"netid\":9999,\"seednode\":\"10.100.0.2\",\"userpass\":\"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f\",\"method\":\"passphrase\",\"passphrase\":\"$passphrase\",\"gui\":\"nogui\"}" diff --git a/etomic_build/client/userpass b/etomic_build/client/userpass new file mode 100644 index 000000000..19fc21189 --- /dev/null +++ b/etomic_build/client/userpass @@ -0,0 +1,2 @@ +#export userpass="" +export userpass="$USERPASS" diff --git a/etomic_build/coins b/etomic_build/coins index 988b79784..4afe84fea 100755 --- a/etomic_build/coins +++ b/etomic_build/coins @@ -1,3 +1,3 @@ -export coins="[{\"coin\":\"OOT\",\"asset\":\"OOT\",\"rpcport\":12467}, {\"coin\":\"ETH\",\"name\":\"ethereum\",\"etomic\":\"0x0000000000000000000000000000000000000000\",\"rpcport\":80}, {\"coin\":\"EOS\",\"name\":\"EOS\",\"etomic\":\"0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0\",\"rpcport\":80}, {\"coin\":\"ZOI\",\"name\":\"zoin\",\"rpcport\":8255,\"pubtype\":80,\"p2shtype\":7,\"wiftype\":208,\"txfee\":1000}, {\"coin\": \"PIZZA\",\"asset\": \"PIZZA\",\"rpcport\": 11116},{\"coin\": \"BEER\",\"asset\": \"BEER\",\"rpcport\": 8923}, {\"coin\":\"GRS\",\"name\":\"groestlcoin\",\"rpcport\":1441,\"pubtype\":36,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":11998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":100000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":10000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" +export coins="[{\"coin\":\"OOT\",\"asset\":\"OOT\",\"rpcport\":12467}, {\"coin\":\"ETH\",\"name\":\"ethereum\",\"etomic\":\"0x0000000000000000000000000000000000000000\",\"rpcport\":80}, {\"coin\":\"EOS\",\"name\":\"EOS\",\"etomic\":\"0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0\",\"rpcport\":80},{\"coin\":\"JST\", \"name\":\"JST\",\"etomic\":\"0xc0eb7AeD740E1796992A08962c15661bDEB58003\",\"rpcport\":80},{\"coin\":\"NODEC\",\"name\":\"NODEC\",\"etomic\":\"0x05beb0a9ead354283041a6d35f3b833450fb5680\",\"rpcport\":80,\"decimals\":18},{\"coin\":\"ZOI\",\"name\":\"zoin\",\"rpcport\":8255,\"pubtype\":80,\"p2shtype\":7,\"wiftype\":208,\"txfee\":1000}, {\"coin\": \"PIZZA\",\"asset\": \"PIZZA\",\"rpcport\": 11116},{\"coin\": \"BEER\",\"asset\": \"BEER\",\"rpcport\": 8923}, {\"coin\":\"GRS\",\"name\":\"groestlcoin\",\"rpcport\":1441,\"pubtype\":36,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":11998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":100000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":10000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" #, {\"coin\":\"AUD\",\"asset\":\"AUD\",\"rpcport\":8045}, {\"coin\":\"BGN\",\"asset\":\"BGN\",\"rpcport\":9110}, {\"coin\":\"CAD\",\"asset\":\"CAD\",\"rpcport\":8720}, {\"coin\":\"CHF\",\"asset\":\"CHF\",\"rpcport\":15312}, {\"coin\":\"CNY\",\"asset\":\"CNY\",\"rpcport\":10384}, {\"coin\":\"CZK\",\"asset\":\"CZK\",\"rpcport\":9482}, {\"coin\":\"DKK\",\"asset\":\"DKK\",\"rpcport\":13830}, {\"coin\":\"EUR\",\"asset\":\"EUR\",\"rpcport\":8065}, {\"coin\":\"GBP\",\"asset\":\"GBP\",\"rpcport\":11505}, {\"coin\":\"HKD\",\"asset\":\"HKD\",\"rpcport\":15409}, {\"coin\":\"HRK\",\"asset\":\"HRK\",\"rpcport\":12617}, {\"coin\":\"HUF\",\"asset\":\"HUF\",\"rpcport\":13699}, {\"coin\":\"IDR\",\"asset\":\"IDR\",\"rpcport\":14459}, {\"coin\":\"ILS\",\"asset\":\"ILS\",\"rpcport\":14638}, {\"coin\":\"INR\",\"asset\":\"INR\",\"rpcport\":10536}, {\"coin\":\"JPY\",\"asset\":\"JPY\",\"rpcport\":13145}, {\"coin\":\"KRW\",\"asset\":\"KRW\",\"rpcport\":14020}, {\"coin\":\"MXN\",\"asset\":\"MXN\",\"rpcport\":13970}, {\"coin\":\"MYR\",\"asset\":\"MYR\",\"rpcport\":10688}, {\"coin\":\"NOK\",\"asset\":\"NOK\",\"rpcport\":11588}, {\"coin\":\"NZD\",\"asset\":\"NZD\",\"rpcport\":10915}, {\"coin\":\"PHP\",\"asset\":\"PHP\",\"rpcport\":11181}, {\"coin\":\"PLN\",\"asset\":\"PLN\",\"rpcport\":13493}, {\"coin\":\"BRL\",\"asset\":\"BRL\",\"rpcport\":9914}, {\"coin\":\"RON\",\"asset\":\"RON\",\"rpcport\":8675}, {\"coin\":\"RUB\",\"asset\":\"RUB\",\"rpcport\":8199}, {\"coin\":\"SEK\",\"asset\":\"SEK\",\"rpcport\":11447}, {\"coin\":\"SGD\",\"asset\":\"SGD\",\"rpcport\":14475}, {\"coin\":\"THB\",\"asset\":\"THB\",\"rpcport\":11847}, {\"coin\":\"TRY\",\"asset\":\"TRY\",\"rpcport\":13924}, {\"coin\":\"USD\",\"asset\":\"USD\",\"rpcport\":13967}, {\"coin\":\"ZAR\",\"asset\":\"ZAR\",\"rpcport\":15160}]" #{\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, diff --git a/etomic_build/enable b/etomic_build/enable index 0bcf62166..f43d63ff7 100755 --- a/etomic_build/enable +++ b/etomic_build/enable @@ -1,5 +1,4 @@ #!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}" -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"KMD\"}" curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}" diff --git a/etomic_build/passphrase b/etomic_build/passphrase deleted file mode 100644 index eb00095d6..000000000 --- a/etomic_build/passphrase +++ /dev/null @@ -1 +0,0 @@ -export passphrase="" diff --git a/etomic_build/run b/etomic_build/run deleted file mode 100755 index b757bb993..000000000 --- a/etomic_build/run +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -source passphrase -source coins -./stop - $1 iguana/exchanges/marketmaker "{\"netid\":9999,\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" & diff --git a/etomic_build/seed/enable b/etomic_build/seed/enable new file mode 100755 index 000000000..0bda2f3ce --- /dev/null +++ b/etomic_build/seed/enable @@ -0,0 +1,7 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"NODEC\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JST\"}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BEER\"}" diff --git a/etomic_build/seed/myipaddr b/etomic_build/seed/myipaddr new file mode 100644 index 000000000..da7788dc2 --- /dev/null +++ b/etomic_build/seed/myipaddr @@ -0,0 +1 @@ +10.100.0.2 diff --git a/etomic_build/seed/passphrase b/etomic_build/seed/passphrase new file mode 100644 index 000000000..d54ee899d --- /dev/null +++ b/etomic_build/seed/passphrase @@ -0,0 +1 @@ +export passphrase="$PASSPHRASE" diff --git a/etomic_build/seed/run b/etomic_build/seed/run new file mode 100755 index 000000000..96ceba6ca --- /dev/null +++ b/etomic_build/seed/run @@ -0,0 +1,4 @@ +#!/bin/bash +source passphrase +source ../coins +../../build/iguana/exchanges/marketmaker-testnet "{\"netid\":9999,\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" diff --git a/etomic_build/seed/sell_BEER_OTHER b/etomic_build/seed/sell_BEER_OTHER new file mode 100755 index 000000000..6ec45e1b9 --- /dev/null +++ b/etomic_build/seed/sell_BEER_OTHER @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"BEER\",\"rel\":\"$1\",\"price\":0.9}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"BEER\",\"rel\":\"$1\",\"basevolume\":0.1,\"price\":0.9}" diff --git a/etomic_build/seed/setpassphrase b/etomic_build/seed/setpassphrase new file mode 100755 index 000000000..b3df81427 --- /dev/null +++ b/etomic_build/seed/setpassphrase @@ -0,0 +1,4 @@ +#!/bin/bash +source userpass +source passphrase +curl --url "http://127.0.0.1:7783" --data "{\"netid\":9999,\"seednode\":\"5.9.253.204\",\"userpass\":\"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f\",\"method\":\"passphrase\",\"passphrase\":\"$passphrase\",\"gui\":\"nogui\"}" diff --git a/etomic_build/seed/userpass b/etomic_build/seed/userpass new file mode 100644 index 000000000..19fc21189 --- /dev/null +++ b/etomic_build/seed/userpass @@ -0,0 +1,2 @@ +#export userpass="" +export userpass="$USERPASS" diff --git a/etomic_build/userpass b/etomic_build/userpass index d097e0445..19fc21189 100644 --- a/etomic_build/userpass +++ b/etomic_build/userpass @@ -1,2 +1,2 @@ #export userpass="" -export userpass="c3d8c2a364b7d18c1f9d7321d017b92e9f9c791e4f5c741214fefdea8a071256" +export userpass="$USERPASS" diff --git a/iguana/coins/sec_7776 b/iguana/coins/sec_7776 new file mode 100755 index 000000000..1edbb8c17 --- /dev/null +++ b/iguana/coins/sec_7776 @@ -0,0 +1,2 @@ +curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SEC.conf\",\"path\":\"${HOME#"/"}/.komodo/SEC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SEC\",\"name\":\"SEC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"8f27938c\",\"p2p\":11539,\"rpc\":11540,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"185.148.145.43\"}" + diff --git a/iguana/dpow/dpow_network.c b/iguana/dpow/dpow_network.c index 5343f33c6..a2b2bb01d 100755 --- a/iguana/dpow/dpow_network.c +++ b/iguana/dpow/dpow_network.c @@ -1308,8 +1308,8 @@ int32_t dpow_addnotary(struct supernet_info *myinfo,struct dpow_info *dp,char *i char str[512]; uint32_t ipbits,*ptr; int32_t i,iter,n,retval = -1; if ( myinfo->IAMNOTARY == 0 ) return(-1); - if ( strcmp(ipaddr,"88.99.251.101") == 0 || strcmp(ipaddr,"82.202.193.100") == 0 ) - return(-1); + //if ( strcmp(ipaddr,"88.99.251.101") == 0 || strcmp(ipaddr,"82.202.193.100") == 0 ) + // return(-1); portable_mutex_lock(&myinfo->notarymutex); if ( myinfo->dpowsock >= 0 )//&& myinfo->dexsock >= 0 ) { diff --git a/iguana/dpow/dpow_tx.c b/iguana/dpow/dpow_tx.c index a1b10d9df..040d9e873 100755 --- a/iguana/dpow/dpow_tx.c +++ b/iguana/dpow/dpow_tx.c @@ -329,7 +329,7 @@ bits256 dpow_notarytx(struct supernet_info *myinfo,char *signedtx,int32_t *numsi memcpy(&serialized[len],sig,siglen); len += siglen; numsigs++; - } else printf("%s -> %s src_or_dest.%d Missing sig from k.%d\n",bp->srccoin->symbol,bp->destcoin->symbol,src_or_dest,k); + } //else printf("%s -> %s src_or_dest.%d Missing sig from k.%d\n",bp->srccoin->symbol,bp->destcoin->symbol,src_or_dest,k); } else serialized[len++] = 0; len += iguana_rwnum(1,&serialized[len],sizeof(sequenceid),&sequenceid); //printf("height.%d mod.%d VINI.%d <- i.%d j.%d\n",height,height % numnotaries,m,i,j); diff --git a/iguana/exchanges/CMakeLists.txt b/iguana/exchanges/CMakeLists.txt index 793aeb5a4..011e4cd37 100644 --- a/iguana/exchanges/CMakeLists.txt +++ b/iguana/exchanges/CMakeLists.txt @@ -31,4 +31,9 @@ target_link_libraries(marketmaker-mainnet ${MM_LIBS} etomiclib-mainnet) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_link_libraries(marketmaker-mainnet -static-libgcc -static-libstdc++) target_link_libraries(marketmaker-testnet -static-libgcc -static-libstdc++) -endif() \ No newline at end of file +endif() +if(NOT DEFINED MM_VERSION) + SET(MM_VERSION UNKNOWN) +endif() +target_compile_definitions(marketmaker-mainnet PRIVATE -DMM_VERSION="${MM_VERSION}") +target_compile_definitions(marketmaker-testnet PRIVATE -DMM_VERSION="${MM_VERSION}") \ No newline at end of file diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index 5176b8f47..ce948fa95 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -251,10 +251,14 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif) } #ifndef NOTETOMIC else if (coin->etomic[0] != 0) { - //balance = LP_etomic_get_balance(coin, coin->smartaddr); + int error = 0; + if (coin->inactive == 0) { + balance = LP_etomic_get_balance(coin, coin->smartaddr, &error); + } else { + balance = 0; + } jaddnum(item,"height",-1); - //jaddnum(item,"balance",dstr(balance)); - jaddnum(item,"balance",0); + jaddnum(item,"balance",dstr(balance)); } #endif else @@ -374,7 +378,7 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata) } void *curl_easy_init(); -uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath) +uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath,uint8_t decimals) { static void *ctx; char *name2; uint16_t origport = port; @@ -437,6 +441,7 @@ uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asse } coin->curl_handle = curl_easy_init(); portable_mutex_init(&coin->curl_mutex); + coin->decimals = decimals; return(port); } @@ -480,7 +485,7 @@ struct iguana_info *LP_coinfind(char *symbol) else if ( strcmp(symbol,"KMD") == 0 ) name = "komodo"; else return(0); - port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0); + port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0,0); if ( port == 0 ) isinactive = 1; else isinactive = 0; @@ -522,7 +527,9 @@ struct iguana_info *LP_coincreate(cJSON *item) } else if ( (name= jstr(item,"name")) == 0 ) name = symbol; - if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,juint(item,"wiftaddr"),juint(item,"taddr"),LP_busport(port),jstr(item,"confpath")) < 0 ) + + uint8_t decimals = juint(item,"decimals"); + if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,juint(item,"wiftaddr"),juint(item,"taddr"),LP_busport(port),jstr(item,"confpath"),decimals) < 0 ) { coin = LP_coinadd(&cdata); coin->inactive = (uint32_t)time(NULL); diff --git a/iguana/exchanges/LP_commands.c b/iguana/exchanges/LP_commands.c index 302db7006..1c77bc4f7 100644 --- a/iguana/exchanges/LP_commands.c +++ b/iguana/exchanges/LP_commands.c @@ -120,6 +120,7 @@ cancel(uuid)\n\ buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\ sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\ withdraw(coin, outputs[], broadcast=0)\n\ +eth_withdraw(coin, to, amount, gas, gas_price, broadcast=0)\n\ txblast(coin, utxotxid, utxovout, utxovalue, txfee, passphrase, outputs[], broadcast=0)\n\ sendrawtransaction(coin, signedtx)\n\ swapstatus(pending=0, fast=0)\n\ @@ -151,6 +152,7 @@ getprice(base, rel)\n\ //getmessages(firsti=0, num=100)\n\ //deletemessages(firsti=0, num=100)\n\ secretaddresses(prefix='secretaddress', passphrase, num=10, pubtype=60, taddr=0)\n\ +gen64addrs(passphrase, taddr=0, pubtype=60)\n\ electrum(coin, ipaddr, port)\n\ snapshot(coin, height)\n\ snapshot_balance(coin, height, addresses[])\n\ @@ -177,7 +179,13 @@ mpnet(onoff)\n\ sleep(seconds=60)\n\ listtransactions(coin, address, count=10, skip=0)\n\ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ +version\n\ \"}")); + if ( strcmp(method,"version") == 0 ) { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result",MM_VERSION); + return(jprint(retjson,1)); + } if ( (base= jstr(argjson,"base")) == 0 ) base = ""; @@ -233,9 +241,14 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ { if ( (ptr= LP_coinsearch("KMD")) != 0 ) { - if ( jint(argjson,"weeks") <= 0 || jdouble(argjson,"amount") < 10. ) - return(clonestr("{\"error\":\"instantdex_deposit needs to have weeks and amount\"}")); - else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1)); + if ( jint(argjson,"weeks") <= 0 ) { + return(clonestr("{\"error\":\"instantdex_deposit weeks param must be greater than zero\"}")); + } + if ( jdouble(argjson,"amount") < 10. ) { + return(clonestr("{\"error\":\"instantdex_deposit amount param must be equal or greater than 10\"}")); + } + + return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1)); } return(clonestr("{\"error\":\"cant find KMD\"}")); } @@ -403,11 +416,6 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ jaddbits256(retjson,"privkey",privkey); bitcoin_priv2wif(coin,wiftaddr,wifstr,privkey,wiftype); jaddstr(retjson,"wif",wifstr); -#ifndef NOTETOMIC - char ethaddr[50]; - LP_etomic_pubkeystr_to_addr(pubsecp, ethaddr); - jaddstr(retjson,"ethaddr",ethaddr); -#endif return(jprint(retjson,1)); } else return(clonestr("{\"error\":\"need to have passphrase\"}")); } @@ -419,6 +427,13 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ { return(LP_ticker(jstr(argjson,"base"),jstr(argjson,"rel"))); } + else if ( strcmp(method,"gen64addrs") == 0 ) + { + uint8_t taddr,pubtype; + pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype"); + taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr"); + return(LP_gen64addrs(ctx,jstr(argjson,"passphrase"),taddr,pubtype)); + } else if ( strcmp(method,"secretaddresses") == 0 ) { uint8_t taddr,pubtype; @@ -463,6 +478,12 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ } else if ( strcmp(method,"inuse") == 0 ) return(jprint(LP_inuse_json(),1)); +#ifndef NOTETOMIC + else if ( strcmp(method,"eth_gas_price") == 0 ) + { + return LP_eth_gas_price(); + } +#endif else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 ) return(retstr); if ( base[0] != 0 && rel[0] != 0 ) @@ -591,12 +612,35 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\ jaddstr(retjson,"coin",coin); return(jprint(retjson,1)); } +#ifndef NOTETOMIC + if (strcmp(coin, "ETOMIC") == 0 && LP_RTsmartbalance(ptr) < 20 * SATOSHIDEN) { + if (get_etomic_from_faucet(ptr->smartaddr) != 1) { + return(clonestr("{\"error\":\"Could not get ETOMIC from faucet!\"}")); + } + } + + if (ptr->etomic[0] != 0) { + if (isValidAddress(ptr->etomic) == 0) { + return(clonestr("{\"error\":\"'etomic' field is not valid address!\"}")); + } + + struct iguana_info *etomic_coin = LP_coinsearch("ETOMIC"); + if (etomic_coin->inactive != 0) { + return(clonestr("{\"error\":\"Enable ETOMIC first to use ETH/ERC20!\"}")); + } + + if (ptr->decimals == 0 && strcmp(coin, "ETH") != 0) { + ptr->decimals = getErc20DecimalsZeroOnError(ptr->etomic); + if (ptr->decimals == 0) { + return(clonestr("{\"error\":\"Could not get token decimals or token has zero decimals which is not supported!\"}")); + } + } + } +#endif if ( LP_conflicts_find(ptr) == 0 ) { cJSON *array; ptr->inactive = 0; - if ( ptr->smartaddr[0] != 0 ) - LP_unspents_load(coin,ptr->smartaddr); LP_unspents_load(coin,ptr->smartaddr); if ( strcmp(ptr->symbol,"KMD") == 0 ) LP_importaddress("KMD",BOTS_BONDADDRESS); diff --git a/iguana/exchanges/LP_etomic.c b/iguana/exchanges/LP_etomic.c index 532f8f4d5..2964ea03d 100644 --- a/iguana/exchanges/LP_etomic.c +++ b/iguana/exchanges/LP_etomic.c @@ -22,6 +22,9 @@ // Created by artem on 24.01.18. // #include "LP_etomic.h" +#define ALICE_PAYMENT_SENT 1 +#define BOB_DEPOSIT_SENT 1 +#define BOB_PAYMENT_SENT 1 int32_t LP_etomic_wait_for_confirmation(char *txId) { @@ -38,13 +41,16 @@ void LP_etomic_pubkeystr_to_addr(char *pubkey, char *output) char *LP_etomicalice_send_fee(struct basilisk_swap *swap) { char amount[100], secretKey[70], dexaddr[50]; - satoshisToWei(amount, swap->myfee.I.amount); + satoshisToWei(amount, LP_DEXFEE(swap->I.alicerealsat)); + swap->myfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat); uint8arrayToHex(secretKey, swap->persistent_privkey.bytes, 32); LP_etomic_pubkeystr_to_addr(INSTANTDEX_PUBKEY, dexaddr); if (strcmp(swap->I.alicestr,"ETH") == 0 ) { - return(sendEth(dexaddr, amount, secretKey, 1)); + return(sendEth(dexaddr, amount, secretKey, 1, 0, 0, 1)); } else { - return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1)); + struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr); + + return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1, 0, 0, 1, alicecoin->decimals)); } } @@ -55,7 +61,7 @@ uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap) return(0); } EthTxData data = getEthTxData(swap->otherfee.I.ethTxid); - if (strcmp(data.from, swap->I.etomicdest) != 0) { + if (compareAddresses(data.from, swap->I.etomicdest) == 0) { printf("Alice fee tx %s was sent from wrong address %s\n", swap->otherfee.I.ethTxid, data.from); return(0); } @@ -63,31 +69,33 @@ uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap) char dexaddr[50]; LP_etomic_pubkeystr_to_addr(INSTANTDEX_PUBKEY, dexaddr); if ( strcmp(swap->I.alicestr,"ETH") == 0 ) { - if (strcmp(data.to, dexaddr) != 0) { + if (compareAddresses(data.to, dexaddr) == 0) { printf("Alice fee %s was sent to wrong address %s\n", swap->otherfee.I.ethTxid, data.to); return(0); } uint64_t txValue = weiToSatoshi(data.valueHex); - if (txValue != swap->otherfee.I.amount) { - printf("Alice fee %s amount %" PRIu64 " is not equal to expected %" PRIu64 "\n", swap->otherfee.I.ethTxid, txValue, swap->otherfee.I.amount); + if (txValue != LP_DEXFEE(swap->I.alicerealsat)) { + printf("Alice fee %s amount %" PRIu64 " is not equal to expected %" PRId64 "\n", swap->otherfee.I.ethTxid, txValue, LP_DEXFEE(swap->I.alicerealsat)); return(0); } return(1); } else { - if (strcmp(data.to, swap->I.alicetomic) != 0) { + struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr); + + if (compareAddresses(data.to, swap->I.alicetomic) == 0) { printf("Alice ERC20 fee %s token address %s is not equal to expected %s\n", swap->otherfee.I.ethTxid, data.to, swap->I.alicetomic); return(0); } char weiAmount[70]; - satoshisToWei(weiAmount, swap->otherfee.I.amount); - return(verifyAliceErc20FeeData(swap->I.alicetomic, dexaddr, weiAmount, data.input)); + satoshisToWei(weiAmount, LP_DEXFEE(swap->I.alicerealsat)); + return(verifyAliceErc20FeeData(swap->I.alicetomic, dexaddr, weiAmount, data.input, alicecoin->decimals)); } } char *LP_etomicalice_send_payment(struct basilisk_swap *swap) { AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20; BasicTxData txData; - + swap->alicepayment.I.eth_amount = swap->I.alicerealsat; // set input and txData fields from the swap data structure memset(&txData,0,sizeof(txData)); if ( strcmp(swap->I.alicestr,"ETH") == 0 ) @@ -100,28 +108,31 @@ char *LP_etomicalice_send_payment(struct basilisk_swap *swap) strcpy(txData.from, swap->I.etomicdest); strcpy(txData.to, ETOMIC_ALICECONTRACT); - satoshisToWei(txData.amount, swap->I.alicesatoshis); + satoshisToWei(txData.amount, swap->I.alicerealsat); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); return(aliceSendsEthPayment(input,txData)); } else { + struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr); + memset(&input20,0,sizeof(input20)); strcpy(input20.bobAddress, swap->I.etomicsrc); uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32); strcpy(input20.tokenAddress, swap->I.alicetomic); - satoshisToWei(input20.amount, swap->I.alicesatoshis); + satoshisToWei(input20.amount, swap->I.alicerealsat); + input20.decimals = alicecoin->decimals; strcpy(txData.from, swap->I.etomicdest); strcpy(txData.to, ETOMIC_ALICECONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); - uint64_t allowance = getErc20Allowance(swap->I.etomicdest, ETOMIC_ALICECONTRACT, swap->I.alicetomic); - if (allowance < swap->I.alicesatoshis) { + uint64_t allowance = getErc20Allowance(swap->I.etomicdest, ETOMIC_ALICECONTRACT, swap->I.alicetomic, alicecoin->decimals); + if (allowance < swap->I.alicerealsat) { printf("Alice token allowance is too low, setting new allowance\n"); ApproveErc20Input approveErc20Input; strcpy(approveErc20Input.tokenAddress, swap->I.alicetomic); @@ -149,20 +160,19 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId) return(0); } EthTxData data = getEthTxData(txId); - if (strcmp(data.to, ETOMIC_ALICECONTRACT) != 0) { + if (compareAddresses(data.to, ETOMIC_ALICECONTRACT) == 0) { printf("Alice payment %s was sent to wrong address %s\n", txId, data.to); return(0); } - if (strcmp(data.from, swap->I.etomicdest) != 0) { + if (compareAddresses(data.from, swap->I.etomicdest) == 0) { printf("Alice payment %s was done from wrong address %s\n", txId, data.from); return(0); } AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20; - if ( strcmp(swap->I.alicestr,"ETH") == 0 ) { uint64_t paymentAmount = weiToSatoshi(data.valueHex); - if (paymentAmount != swap->I.alicesatoshis) { - printf("Alice payment amount %" PRIu64 " does not match expected %" PRIu64 "\n", paymentAmount, swap->I.alicesatoshis); + if (paymentAmount != swap->I.alicerealsat) { + printf("Alice payment amount %" PRIu64 " does not match expected %" PRIu64 "\n", paymentAmount, swap->I.alicerealsat); return(0); } memset(&input,0,sizeof(input)); @@ -173,13 +183,16 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId) return(verifyAliceEthPaymentData(input, data.input)); } else { + struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr); + memset(&input20,0,sizeof(input20)); strcpy(input20.bobAddress, swap->I.etomicsrc); uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32); strcpy(input20.tokenAddress, swap->I.alicetomic); - satoshisToWei(input20.amount, swap->I.alicesatoshis); + satoshisToWei(input20.amount, swap->I.alicerealsat); + input20.decimals = alicecoin->decimals; return(verifyAliceErc20PaymentData(input20, data.input)); } @@ -187,11 +200,11 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId) char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->alicePaymentEthTx) < 0) { - printf("Alice ETH payment %s is not found, can't reclaim\n", swap->alicePaymentEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]) < 0) { + printf("Alice ETH payment %s is not found, can't reclaim\n", swap->eth_tx_ids[BASILISK_ALICEPAYMENT]); return NULL; } - EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]); if (strcmp(receipt.status, "0x1") != 0) { printf("Alice payment receipt status failed, can't reclaim\n"); return NULL; @@ -201,13 +214,18 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap) memset(&txData,0,sizeof(txData)); memset(&input,0,sizeof(input)); - struct iguana_info *ecoin; + struct iguana_info *ecoin, *alice_coin; bits256 privkey; ecoin = LP_coinfind("ETOMIC"); + alice_coin = LP_coinfind(swap->dest); privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); uint8arrayToHex(input.dealId, swap->txids[BASILISK_ALICEPAYMENT].bytes, 32); - satoshisToWei(input.amount, swap->destamount); + if (alicePaymentStatus(input.dealId + 2) != ALICE_PAYMENT_SENT) { + printf("Alice payment smart contract status check failed, can't spend\n"); + return NULL; + } + satoshisToWei(input.amount, swap->alicerealsat); if (swap->alicetomic[0] != 0) { strcpy(input.tokenAddress, swap->alicetomic); @@ -223,6 +241,8 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap) } uint8arrayToHex(input.bobSecret, invertedSecret.bytes, 32); + input.decimals = alice_coin->decimals; + strcpy(txData.from, swap->etomicdest); strcpy(txData.to, ETOMIC_ALICECONTRACT); strcpy(txData.amount, "0"); @@ -232,11 +252,11 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap) char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->alicePaymentEthTx) < 0) { - printf("Alice ETH payment %s is not found, can't spend\n", swap->alicePaymentEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]) < 0) { + printf("Alice ETH payment %s is not found, can't spend\n", swap->eth_tx_ids[BASILISK_ALICEPAYMENT]); return NULL; } - EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]); if (strcmp(receipt.status, "0x1") != 0) { printf("Alice payment receipt status failed, can't spend\n"); return NULL; @@ -253,7 +273,12 @@ char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap) privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); uint8arrayToHex(input.dealId, swap->txids[BASILISK_ALICEPAYMENT].bytes, 32); - satoshisToWei(input.amount, swap->destamount); + if (alicePaymentStatus(input.dealId + 2) != ALICE_PAYMENT_SENT) { + printf("Alice payment smart contract status check failed, can't spend\n"); + return NULL; + } + + satoshisToWei(input.amount, swap->alicerealsat); if (swap->alicetomic[0] != 0) { strcpy(input.tokenAddress, swap->alicetomic); @@ -268,6 +293,8 @@ char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap) } uint8arrayToHex(input.aliceSecret, invertedSecret.bytes, 32); uint8arrayToHex(input.bobHash, swap->secretBn, 20); + struct iguana_info *alice_coin = LP_coinfind(swap->dest); + input.decimals = alice_coin->decimals; strcpy(txData.from, swap->etomicsrc); strcpy(txData.to, ETOMIC_ALICECONTRACT); @@ -292,24 +319,27 @@ char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap) strcpy(txData.from, swap->I.etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); - satoshisToWei(txData.amount, swap->bobdeposit.I.amount); + satoshisToWei(txData.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat)); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); return bobSendsEthDeposit(input, txData); } else { + struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr); + uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32); strcpy(input20.aliceAddress, swap->I.etomicdest); uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); - satoshisToWei(input20.amount, swap->bobdeposit.I.amount); + satoshisToWei(input20.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat)); strcpy(input20.tokenAddress, swap->I.bobtomic); input20.lockTime = swap->bobdeposit.I.locktime; + input20.decimals = bobcoin->decimals; strcpy(txData.from, swap->I.etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); - uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic); - if (allowance < swap->bobdeposit.I.amount) { + uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic, bobcoin->decimals); + if (allowance < LP_DEPOSITSATOSHIS(swap->I.bobrealsat)) { printf("Bob token allowance is too low, setting new allowance\n"); ApproveErc20Input approveErc20Input; strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic); @@ -337,11 +367,11 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId) return(0); } EthTxData data = getEthTxData(txId); - if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) { + if (compareAddresses(data.to, ETOMIC_BOBCONTRACT) == 0) { printf("Bob deposit txid %s was sent to wrong address %s\n", txId, data.to); return(0); } - if (strcmp(data.from, swap->I.etomicsrc) != 0) { + if (compareAddresses(data.from, swap->I.etomicsrc) == 0) { printf("Bob deposit txid %s was sent from wrong address %s\n", txId, data.from); return(0); } @@ -351,8 +381,8 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId) memset(&input20,0,sizeof(input20)); if ( strcmp(swap->I.bobstr,"ETH") == 0 ) { uint64_t depositAmount = weiToSatoshi(data.valueHex); - if (depositAmount != swap->bobdeposit.I.amount) { - printf("Bob deposit %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, depositAmount, swap->bobdeposit.I.amount); + if (depositAmount != LP_DEPOSITSATOSHIS(swap->I.bobrealsat)) { + printf("Bob deposit %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, depositAmount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat)); return(0); } uint8arrayToHex(input.depositId, swap->bobdeposit.I.actualtxid.bytes, 32); @@ -362,12 +392,15 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId) return verifyBobEthDepositData(input, data.input); } else { + struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr); + uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32); strcpy(input20.aliceAddress, swap->I.etomicdest); uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20); - satoshisToWei(input20.amount, swap->bobdeposit.I.amount); + satoshisToWei(input20.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat)); strcpy(input20.tokenAddress, swap->I.bobtomic); input20.lockTime = swap->bobdeposit.I.locktime; + input20.decimals = bobcoin->decimals; return verifyBobErc20DepositData(input20, data.input); } @@ -375,8 +408,8 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId) char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->bobDepositEthTx) < 0) { - printf("Bob deposit %s is not found, can't refund\n", swap->bobDepositEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]) < 0) { + printf("Bob deposit %s is not found, can't refund\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]); return NULL; } BobRefundsDepositInput input; @@ -384,17 +417,23 @@ char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap) memset(&txData,0,sizeof(txData)); memset(&input,0,sizeof(input)); - struct iguana_info *ecoin; + struct iguana_info *ecoin, *bobcoin; bits256 privkey; ecoin = LP_coinfind("ETOMIC"); + bobcoin = LP_coinfind(swap->src); privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); - EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]); if (strcmp(receipt.status, "0x1") != 0) { - printf("Bob deposit %s receipt status failed, can't refund\n", swap->bobDepositEthTx); + printf("Bob deposit %s receipt status failed, can't refund\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]); return NULL; } uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32); + if (bobDepositStatus(input.depositId + 2) != BOB_DEPOSIT_SENT) { + printf("Bob deposit smart contract status check failed, can't claim\n"); + return NULL; + } + strcpy(input.aliceAddress, swap->etomicdest); bits256 invertedSecret; @@ -409,7 +448,8 @@ char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap) } else { strcpy(input.tokenAddress, "0x0000000000000000000000000000000000000000"); } - satoshisToWei(input.amount, swap->values[BASILISK_BOBDEPOSIT]); + satoshisToWei(input.amount, LP_DEPOSITSATOSHIS(swap->bobrealsat)); + input.decimals = bobcoin->decimals; strcpy(txData.from, swap->etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); @@ -435,24 +475,27 @@ char *LP_etomicbob_sends_payment(struct basilisk_swap *swap) strcpy(txData.from, swap->I.etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); - satoshisToWei(txData.amount, swap->bobpayment.I.amount); + satoshisToWei(txData.amount, swap->I.bobrealsat); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); return bobSendsEthPayment(input, txData); } else { + struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr); + uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32); strcpy(input20.aliceAddress, swap->I.etomicdest); uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); - satoshisToWei(input20.amount, swap->bobpayment.I.amount); + satoshisToWei(input20.amount, swap->I.bobrealsat); strcpy(input20.tokenAddress, swap->I.bobtomic); input20.lockTime = swap->bobpayment.I.locktime; + input20.decimals = bobcoin->decimals; strcpy(txData.from, swap->I.etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); strcpy(txData.amount, "0"); uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32); - uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic); - if (allowance < swap->bobpayment.I.amount) { + uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic, bobcoin->decimals); + if (allowance < swap->I.bobrealsat) { printf("Bob token allowance is too low, setting new allowance\n"); ApproveErc20Input approveErc20Input; strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic); @@ -480,21 +523,20 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId) return 0; } EthTxData data = getEthTxData(txId); - if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) { + if (compareAddresses(data.to, ETOMIC_BOBCONTRACT) == 0) { printf("Bob payment %s was sent to wrong address %s\n", txId, data.to); } - if (strcmp(data.from, swap->I.etomicsrc) != 0) { + if (compareAddresses(data.from, swap->I.etomicsrc) == 0) { printf("Bob payment %s was sent from wrong address %s\n", txId, data.from); } BobSendsEthPaymentInput input; BobSendsErc20PaymentInput input20; memset(&input,0,sizeof(input)); memset(&input20,0,sizeof(input20)); - if ( strcmp(swap->I.bobstr,"ETH") == 0 ) { uint64_t paymentAmount = weiToSatoshi(data.valueHex); - if (paymentAmount != swap->bobpayment.I.amount) { - printf("Bob payment %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, paymentAmount, swap->bobpayment.I.amount); + if (paymentAmount != swap->I.bobrealsat) { + printf("Bob payment %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, paymentAmount, swap->I.bobrealsat); return(0); } uint8arrayToHex(input.paymentId, swap->bobpayment.I.actualtxid.bytes, 32); @@ -504,12 +546,15 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId) return verifyBobEthPaymentData(input, data.input); } else { + struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr); + uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32); strcpy(input20.aliceAddress, swap->I.etomicdest); uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20); - satoshisToWei(input20.amount, swap->bobpayment.I.amount); + satoshisToWei(input20.amount, swap->I.bobrealsat); strcpy(input20.tokenAddress, swap->I.bobtomic); input20.lockTime = swap->bobpayment.I.locktime; + input20.decimals = bobcoin->decimals; return verifyBobErc20PaymentData(input20, data.input); } @@ -517,8 +562,8 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId) char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->bobPaymentEthTx) < 0) { - printf("Bob payment %s is not found, can't reclaim\n", swap->bobPaymentEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBPAYMENT]) < 0) { + printf("Bob payment %s is not found, can't reclaim\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]); return NULL; } BobReclaimsBobPaymentInput input; @@ -526,17 +571,22 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap) memset(&txData,0,sizeof(txData)); memset(&input,0,sizeof(input)); - struct iguana_info *ecoin; + struct iguana_info *ecoin, *bobcoin; bits256 privkey; ecoin = LP_coinfind("ETOMIC"); + bobcoin = LP_coinfind(swap->src); privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); - EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBPAYMENT]); if (strcmp(receipt.status, "0x1") != 0) { printf("Bob payment receipt status failed, can't reclaim\n"); return NULL; } uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32); + if (bobPaymentStatus(input.paymentId + 2) != BOB_PAYMENT_SENT) { + printf("Bob payment smart contract status check failed, can't spend\n"); + return NULL; + } strcpy(input.aliceAddress, swap->etomicdest); uint8arrayToHex(input.aliceHash, swap->secretAm, 20); @@ -545,7 +595,8 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap) } else { strcpy(input.tokenAddress, "0x0000000000000000000000000000000000000000"); } - satoshisToWei(input.amount, swap->values[BASILISK_BOBPAYMENT]); + satoshisToWei(input.amount, swap->bobrealsat); + input.decimals = bobcoin->decimals; strcpy(txData.from, swap->etomicsrc); strcpy(txData.to, ETOMIC_BOBCONTRACT); @@ -556,8 +607,8 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap) char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->bobPaymentEthTx) < 0) { - printf("Bob payment %s is not found, can't spend\n", swap->bobPaymentEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBPAYMENT]) < 0) { + printf("Bob payment %s is not found, can't spend\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]); return NULL; } AliceSpendsBobPaymentInput input; @@ -565,18 +616,23 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap) memset(&txData,0,sizeof(txData)); memset(&input,0,sizeof(input)); - EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBPAYMENT]); if (strcmp(receipt.status, "0x1") != 0) { - printf("Bob payment %s receipt status failed, can't spend\n", swap->bobPaymentEthTx); + printf("Bob payment %s receipt status failed, can't spend\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]); return NULL; } - struct iguana_info *ecoin; + struct iguana_info *ecoin, *bobcoin; bits256 privkey; ecoin = LP_coinfind("ETOMIC"); + bobcoin = LP_coinfind(swap->src); privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32); - satoshisToWei(input.amount, swap->values[BASILISK_BOBPAYMENT]); + if (bobPaymentStatus(input.paymentId + 2) != BOB_PAYMENT_SENT) { + printf("Bob payment smart contract status check failed, can't spend\n"); + return NULL; + } + satoshisToWei(input.amount, swap->bobrealsat); if (swap->bobtomic[0] != 0) { strcpy(input.tokenAddress, swap->bobtomic); @@ -591,6 +647,7 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap) invertedSecret.bytes[i] = swap->privAm.bytes[31 - i]; } uint8arrayToHex(input.aliceSecret, invertedSecret.bytes, 32); + input.decimals = bobcoin->decimals; strcpy(txData.from, swap->etomicdest); strcpy(txData.to, ETOMIC_BOBCONTRACT); @@ -601,8 +658,8 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap) char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap) { - if (waitForConfirmation(swap->bobDepositEthTx) < 0) { - printf("Bob deposit %s is not found, can't claim\n", swap->bobDepositEthTx); + if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]) < 0) { + printf("Bob deposit %s is not found, can't claim\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]); return NULL; } AliceClaimsBobDepositInput input; @@ -610,19 +667,25 @@ char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap) memset(&txData,0,sizeof(txData)); memset(&input,0,sizeof(input)); - EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx); + EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]); if (strcmp(receipt.status, "0x1") != 0) { printf("Bob deposit receipt status failed, can't claim\n"); return NULL; } - struct iguana_info *ecoin; + struct iguana_info *ecoin, *bobcoin; bits256 privkey; ecoin = LP_coinfind("ETOMIC"); + bobcoin = LP_coinfind(swap->src); privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr); uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32); - satoshisToWei(input.amount, swap->values[BASILISK_BOBDEPOSIT]); + if (bobDepositStatus(input.depositId + 2) != BOB_DEPOSIT_SENT) { + printf("Bob deposit smart contract status check failed, can't claim\n"); + return NULL; + } + + satoshisToWei(input.amount, LP_DEPOSITSATOSHIS(swap->bobrealsat)); if (swap->bobtomic[0] != 0) { strcpy(input.tokenAddress, swap->bobtomic); @@ -632,6 +695,7 @@ char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap) strcpy(input.bobAddress, swap->etomicsrc); uint8arrayToHex(input.bobHash, swap->secretBn, 20); + input.decimals = bobcoin->decimals; strcpy(txData.from, swap->etomicdest); strcpy(txData.to, ETOMIC_BOBCONTRACT); @@ -702,13 +766,13 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64]) uint8_t LP_etomic_is_empty_tx_id(char *txId) { - if (strcmp(txId, EMPTY_ETH_TX_ID) == 0) { + if (txId[0] == 0 || strcmp(txId, EMPTY_ETH_TX_ID) == 0) { return 1; } return 0; } -uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr) +uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr, int *error) { if (coin->etomic[0] == 0) { printf("Trying to get etomic balance for non-etomic coin %s!", coin->symbol); @@ -716,8 +780,8 @@ uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr) } if (strcmp(coin->symbol, "ETH") == 0) { - return getEthBalance(coinaddr); + return getEthBalance(coinaddr, error); } else { - return getErc20BalanceSatoshi(coinaddr, coin->etomic); + return getErc20BalanceSatoshi(coinaddr, coin->etomic, coin->decimals, error); } } diff --git a/iguana/exchanges/LP_etomic.h b/iguana/exchanges/LP_etomic.h index af5de5f63..8a744cb3d 100644 --- a/iguana/exchanges/LP_etomic.h +++ b/iguana/exchanges/LP_etomic.h @@ -49,7 +49,7 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64]); uint8_t LP_etomic_is_empty_tx_id(char *txId); -uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr); +uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr, int *error); void LP_etomic_pubkeystr_to_addr(char *pubkey, char *output); diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index f95b98c61..dbb46e4f1 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -206,7 +206,7 @@ struct basilisk_rawtxinfo { char destaddr[64],ethTxid[75]; bits256 txid,signedtxid,actualtxid; - int64_t amount,change,inputsum; + int64_t amount,change,inputsum,eth_amount; int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys; uint32_t locktime,crcs[2]; uint8_t addrtype,pubkey33[33],rmd160[20]; @@ -241,7 +241,7 @@ struct basilisk_swapinfo bits256 myhash,otherhash,orderhash; uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration; int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms; - int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee; + int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee,alicerealsat,bobrealsat; bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn; uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2]; @@ -256,29 +256,31 @@ struct basilisk_swapinfo uint8_t userdata_bobrefund[256],userdata_bobrefundlen; }; -#define BASILISK_ALICESPEND 0 -#define BASILISK_BOBSPEND 1 -#define BASILISK_BOBPAYMENT 2 +#define BASILISK_MYFEE 0 +#define BASILISK_OTHERFEE 1 +#define BASILISK_BOBDEPOSIT 2 #define BASILISK_ALICEPAYMENT 3 -#define BASILISK_BOBDEPOSIT 4 -#define BASILISK_OTHERFEE 5 -#define BASILISK_MYFEE 6 +#define BASILISK_BOBPAYMENT 4 +#define BASILISK_ALICESPEND 5 +#define BASILISK_BOBSPEND 6 #define BASILISK_BOBREFUND 7 #define BASILISK_BOBRECLAIM 8 #define BASILISK_ALICERECLAIM 9 #define BASILISK_ALICECLAIM 10 //0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0 -static char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" }; +static char *txnames[] = { "myfee", "otherfee", "bobdeposit", "alicepayment", "bobpayment", "alicespend", "bobspend", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" }; struct LP_swap_remember { bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)]; - uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid; + uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid,alicerealsat,bobrealsat; int64_t values[sizeof(txnames)/sizeof(*txnames)]; uint32_t finishtime,tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate; int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33]; - char uuidstr[65],Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)],bobDepositEthTx[75],bobPaymentEthTx[75],alicePaymentEthTx[75]; + char uuidstr[65],Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)]; + char eth_tx_ids[sizeof(txnames)/sizeof(*txnames)][75]; + int64_t eth_values[sizeof(txnames)/sizeof(*txnames)]; }; struct LP_outpoint @@ -312,7 +314,7 @@ struct iguana_info double price_kmd,force,perc,goal,goalperc,relvolume,rate; void *electrum; void *ctx; uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB,fillsatoshis; - uint8_t pubkey33[33],zcash; + uint8_t pubkey33[33],zcash,decimals; int32_t privkeydepth,bobfillheight; void *curl_handle; portable_mutex_t curl_mutex; bits256 cachedtxid,notarizationtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen; diff --git a/iguana/exchanges/LP_mmjson.c b/iguana/exchanges/LP_mmjson.c index 0dc67da56..591f46025 100644 --- a/iguana/exchanges/LP_mmjson.c +++ b/iguana/exchanges/LP_mmjson.c @@ -259,7 +259,11 @@ int32_t MMJSON_decodeitem(cJSON *lineobj,uint8_t *linebuf,int32_t i,int32_t len, arbstr[j++] = c; } arbstr[j] = 0; - jaddstr(lineobj,fieldstr,arbstr); + if (strcmp(fieldstr, "txChain") == 0) { + cJSON_AddItemToObject(lineobj, fieldstr, cJSON_Parse(arbstr)); + } else { + jaddstr(lineobj, fieldstr, arbstr); + } break; default: if ( valind < MMJSON_BOUNDARY ) diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index a4fa473b4..7e8b66f4d 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -30,6 +30,9 @@ // there is an issue about waiting for notarization for a swap that never starts (expiration ok) #include +#ifndef MM_VERSION +#define MM_VERSION "UNKNOWN" +#endif long LP_cjson_allocated,LP_cjson_total,LP_cjson_count; @@ -117,7 +120,7 @@ struct LP_globals { //struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2]; bits256 LP_mypub25519,LP_privkey,LP_mypriv25519,LP_passhash; - uint64_t LP_skipstatus[10000]; + uint64_t LP_skipstatus[10000], LP_required_etomic_balance; uint16_t netid; uint8_t LP_myrmd160[20],LP_pubsecp[33]; uint32_t LP_sessionid,counter,mpnet; @@ -1126,6 +1129,7 @@ void LP_swapsloop(void *ctx) if ( (sp->finished= LP_swapwait(0,sp->requestid,sp->quoteid,-1,0)) != 0 ) { } + sleep(3); } } if ( nonz == 0 ) @@ -1136,7 +1140,7 @@ void LP_swapsloop(void *ctx) LP_alice_eligible((uint32_t)time(NULL)); sleep(6); } - } + } else sleep(10); LP_gtc_iteration(ctx,LP_myipaddr,LP_mypubsock); } } @@ -1222,7 +1226,7 @@ void queue_loop(void *ctx) } if ( (json= cJSON_Parse((char *)ptr->msg)) != 0 ) { - if ( 1 && ptr->msglen < sizeof(linebuf) ) + if ( ptr->msglen < sizeof(linebuf) ) { if ( (k= MMJSON_encode(linebuf,(char *)ptr->msg)) > 0 ) { @@ -1421,8 +1425,7 @@ extern int32_t bitcoind_RPC_inittime; void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson) { - char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx(); - sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request)); + char *myipaddr=0; long filesize,n; int32_t valid,timeout; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx(); bitcoind_RPC_inittime = 1; if ( LP_MAXPRICEINFOS > 256 ) { @@ -1430,7 +1433,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu exit(-1); } LP_showwif = juint(argjson,"wif"); - printf("showwif.%d %s %u\n",LP_showwif,version,calc_crc32(0,version,(int32_t)strlen(version))); + printf("showwif.%d version: %s %u\n",LP_showwif,MM_VERSION,calc_crc32(0,MM_VERSION,(int32_t)strlen(MM_VERSION))); if ( passphrase == 0 || passphrase[0] == 0 ) { printf("jeezy says we cant use the nullstring as passphrase and I agree\n"); @@ -1505,10 +1508,10 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu myipaddr = clonestr("127.0.0.1"); #ifndef _WIN32 #ifndef FROM_JS - if ( system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 ) + char ipfname[64]; + strcpy(ipfname,"myipaddr"); + if ( access( ipfname, F_OK ) != -1 || system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 ) { - char ipfname[64]; - strcpy(ipfname,"myipaddr"); if ( (myipaddr= OS_filestr(&filesize,ipfname)) != 0 && myipaddr[0] != 0 ) { n = strlen(myipaddr); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index 2362f9e90..fc48bbf3e 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -198,12 +198,12 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 ) return(-10); } - if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis ) + if ( strcmp(destcoin, "ETOMIC") != 0 && autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis ) { printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee)); return(-11); } - if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis ) + if ( strcmp(srccoin, "ETOMIC") != 0 && butxo != 0 && srcvalue < qp->txfee+qp->satoshis ) { printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee)); return(-33); @@ -221,7 +221,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str printf("error -14: txfee %.8f < %.8f or desttxfee %.8f < %.8f\n",dstr(qp->txfee),dstr(LP_REQUIRED_TXFEE*txfee),dstr(qp->desttxfee),dstr(LP_REQUIRED_TXFEE*desttxfee)); return(-14); } - if ( butxo != 0 ) + if ( butxo != 0 && strcmp(srccoin, "ETOMIC") != 0) { if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT ) { @@ -421,14 +421,22 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb memset(butxo,0,sizeof(*butxo)); if ( iambob != 0 ) { - targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee) + 3*txfee; + if (strcmp(coin->symbol, "ETOMIC") == 0) { + targetval = 100000000 + 3*txfee; + } else { + targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee) + 3*txfee; + } targetval2 = (targetval / 8) * 9 + 3*txfee; fee = txfee; ratio = LP_MINVOL; } else { - targetval = relvolume*SATOSHIDEN + 3*desttxfee; + if (strcmp(coin->symbol, "ETOMIC") == 0) { + targetval = 100000000 + 3*desttxfee; + } else { + targetval = relvolume*SATOSHIDEN + 3*desttxfee; + } targetval2 = (targetval / 777) + 3*desttxfee; fee = desttxfee; ratio = LP_MINCLIENTVOL; @@ -1023,7 +1031,7 @@ double LP_trades_pricevalidate(struct LP_quoteinfo *qp,struct iguana_info *coin, printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,qprice); return(-3); } - if ( qprice < (price - 0.00000001) * 0.998 ) + if ( qprice < (price - 0.00000001) * 0.998) { printf(" quote price %.8f (%llu/%llu %.8f) too low vs %.8f for %s/%s price %.8f %.8f\n",qprice,(long long)qp->destsatoshis,(long long)(qp->satoshis-qp->txfee),(double)qp->destsatoshis/(qp->satoshis-qp->txfee),price,qp->srccoin,qp->destcoin,price,(price - 0.00000001) * 0.998); return(-77); @@ -1130,7 +1138,11 @@ printf("bob %s received REQUEST.(%s) mpnet.%d fill.%d gtc.%d\n",bits256_str(str, qp->vout = butxo->payment.vout; qp->txid2 = butxo->deposit.txid; qp->vout2 = butxo->deposit.vout; - qp->satoshis = butxo->swap_satoshis;// + qp->txfee; + if (coin->etomic[0] == 0) { + qp->satoshis = butxo->swap_satoshis;// + qp->txfee; + } else { + qp->satoshis = LP_basesatoshis(dstr(qp->destsatoshis), price, qp->txfee, qp->desttxfee); + } qp->quotetime = (uint32_t)time(NULL); break; } @@ -1771,13 +1783,13 @@ char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,cha autxo->swap_satoshis = destsatoshis; //printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis)); } - else if ( autxo->swap_satoshis - desttxfee < destsatoshis ) + else if ( autxo->swap_satoshis - desttxfee < destsatoshis && relcoin->etomic[0] == 0) { autxo->swap_satoshis -= desttxfee; destsatoshis = autxo->swap_satoshis; printf("second path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis)); } - if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT ) + if ( relcoin->etomic[0] == 0 && (destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT )) { printf("destsatoshis %.8f vs utxo %.8f this would have triggered an quote error -13\n",dstr(destsatoshis),dstr(autxo->payment.value)); return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is a bit larger than what you want to trade\"}")); diff --git a/iguana/exchanges/LP_portfolio.c b/iguana/exchanges/LP_portfolio.c index dea9bce00..bdfb9e2a9 100644 --- a/iguana/exchanges/LP_portfolio.c +++ b/iguana/exchanges/LP_portfolio.c @@ -95,14 +95,18 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr) cJSON *array,*item; bits256 zero; int32_t i,n; uint64_t valuesum,satoshisum,value; valuesum = satoshisum = 0; memset(zero.bytes,0,sizeof(zero)); -/* #ifndef NOTETOMIC struct iguana_info *coin = LP_coinfind(symbol); - if (coin->etomic[0] != 0) { - valuesum = LP_etomic_get_balance(coin, coinaddr); + if (coin->etomic[0] != 0 && coin->inactive == 0) { + int error = 0; + uint64_t etomic_balance = LP_etomic_get_balance(coin, coinaddr, &error); + if (error == 0) { + valuesum = etomic_balance; + } else { + valuesum = *valuep; + } } else #endif -*/ if ( (array= LP_listunspent(symbol,coinaddr,zero,zero)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) diff --git a/iguana/exchanges/LP_privkey.c b/iguana/exchanges/LP_privkey.c index 95fd9b60e..716bfc30b 100644 --- a/iguana/exchanges/LP_privkey.c +++ b/iguana/exchanges/LP_privkey.c @@ -202,6 +202,66 @@ char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8 return(jprint(retjson,1)); } +uint32_t komodo_segid32(char *coinaddr) +{ + bits256 addrhash; + vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr)); + return(addrhash.uints[0]); +} + +char *LP_gen64addrs(void *ctx,char *passphrase,uint8_t taddr,uint8_t pubtype) +{ + int32_t i,segid,n=64; uint8_t tmptype,pubkey33[33],rmd160[20]; char str[65],str2[65],buf[8192],wifstr[64],coinaddr[64],coinaddrs[64][64],wifstrs[64][64]; uint64_t mask = 0; bits256 checkprivkey,privkey,pubkey; cJSON *retjson,*addrs,*array; + if ( passphrase == 0 || passphrase[0] == 0 ) + passphrase = "password"; + memset(coinaddrs,0,sizeof(coinaddrs)); + memset(wifstrs,0,sizeof(wifstrs)); + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); + bitcoin_priv2pub(ctx,"KMD",pubkey33,coinaddr,privkey,taddr,pubtype); + //sprintf(output,"\"addresses\":["); + for (i=0; bitweight(mask)<64; i++) + { + sprintf(buf,"%s %03d",passphrase,i); + conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)buf,(int32_t)strlen(buf)); + bitcoin_priv2pub(ctx,"KMD",pubkey33,coinaddr,privkey,taddr,pubtype); + bitcoin_priv2wif("KMD",0,wifstr,privkey,188); + bitcoin_wif2priv("KMD",0,&tmptype,&checkprivkey,wifstr); + bitcoin_addr2rmd160("KMD",taddr,&tmptype,rmd160,coinaddr); + if ( bits256_cmp(checkprivkey,privkey) != 0 ) + { + printf("WIF.(%s) error -> %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey)); + free_json(retjson); + return(clonestr("{\"error\":\"couldnt validate wifstr\"}")); + } + else if ( tmptype != pubtype ) + { + printf("checktype.%d != pubtype.%d\n",tmptype,pubtype); + free_json(retjson); + return(clonestr("{\"error\":\"couldnt validate pubtype\"}")); + } + segid = komodo_segid32(coinaddr) & 0x3f; + if ( (mask & (1LL << segid)) == 0 ) + { + mask |= (1LL << segid); + strcpy(coinaddrs[segid],coinaddr); + strcpy(wifstrs[segid],wifstr); + printf("./komodo-cli -ac_name=POSTEST64 importprivkey %s "" %s\n",wifstr,bitweight(mask)<64?"false":"true"); + } + //sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,isymbol,passphrase) > 0 ) { wifstr = passphrase; @@ -339,7 +400,7 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan #ifndef NOTETOMIC if ( coin->etomic[0] != 0 ) { - uint8_t check64[64],checktype,checkrmd160[20],rmd160[20]; char checkaddr[64],checkaddr2[64]; + uint8_t check64[64],checktype,checkrmd160[20]; char checkaddr[64],checkaddr2[64]; if ( LP_etomic_priv2pub(check64,privkey) == 0 ) { if ( memcmp(check64,coin->pubkey33+1,32) == 0 ) @@ -374,8 +435,8 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan coin->counter++; memcpy(G.LP_pubsecp,coin->pubkey33,33); bitcoin_priv2wif(coin->symbol,coin->wiftaddr,tmpstr,privkey,coin->wiftype); - bitcoin_addr2rmd160(coin->symbol,coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr); - LP_privkeyadd(privkey,G.LP_myrmd160); + bitcoin_addr2rmd160(coin->symbol,coin->taddr,&tmptype,rmd160,coin->smartaddr); + LP_privkeyadd(privkey,rmd160); G.LP_privkey = privkey; if ( G.counter++ == 0 ) { @@ -443,7 +504,7 @@ void verus_utxos(struct iguana_info *coin,char *coinaddr) char *verusblocks() { - bits256 hash,txid; uint8_t script[44]; double value,avestakedsize,stakedval,RTu3sum,powsum,supply,possum,histo[1280],myhisto[1280]; int32_t num10,num17,num20,num16,num23000,numpow,numpos,num,locked,height,i,m,n,z,numstaked,posflag,npos,npow; char hashstr[64],firstaddr[64],stakingaddr[64],*addr0,*lastaddr,*hexstr; cJSON *blockjson,*txobj,*vouts,*vout,*vout1,*sobj,*addresses,*txs; + bits256 hash,txid; uint8_t script[44]; double value,avestakedsize,stakedval,RTu3sum,powsum,supply,possum,histo[1280],myhisto[1280]; int32_t num10,num17,num20,num16,num23000,numpow,numpos,num,locked,height,i,m,n,z,gotblock,numstaked,posflag,npos,npow; char hashstr[64],firstaddr[64],stakingaddr[64],*addr0,*lastaddr,*hexstr; cJSON *blockjson,*txobj,*vouts,*vout,*vout1,*sobj,*addresses,*txs; struct iguana_info *coin = LP_coinfind("VRSC"); if ( coin == 0 ) return(clonestr("{\"error\":\"VRSC not active\"}")); @@ -472,6 +533,7 @@ char *verusblocks() value = 0; posflag = 0; locked = 0; + gotblock = 0; lastaddr = addr0 = ""; memset(script,0,sizeof(script)); memset(firstaddr,0,sizeof(firstaddr)); @@ -486,6 +548,13 @@ char *verusblocks() value = jdouble(vout,"value"); supply += value; hexstr = 0; + if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 ) + { + if ( strcmp(hexstr,"2102ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92ac") == 0 || strcmp(hexstr,"2102aef0f54a967031f4c63b36d12741fbb9ca39713baedfff7f8c0d0d8ee14ee0ebac") == 0 || strcmp(hexstr,"76a914cc39e9e699f86b03a5cf1d7f2a0b411cf652641788ac") == 0 || strcmp(hexstr,"76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac") == 0 ) + { + gotblock = 1; + } + } if ( m == 2 && (vout1= jitem(vouts,1)) != 0 ) { // 6a2001039bbc0bb17576a9149a3af738444dd86b55c86752247aec2e7deb842688ac @@ -505,7 +574,7 @@ char *verusblocks() locked = ((int32_t)script[6] << 16) + ((int32_t)script[5] << 8) + script[4]; addr0 = firstaddr; } else printf("unexpected vout1.(%s) (%s).%d %.8f\n",jprint(vout1,0),hexstr!=0?hexstr:"",(int32_t)strlen(hexstr),jdouble(vout1,"value")); - } else printf("coinbase without opret (%s)\n",jprint(vouts,0)); + } //else printf("coinbase without opret (%s)\n",jprint(vouts,0)); } } free_json(txobj); @@ -569,7 +638,7 @@ char *verusblocks() numpow++; if ( num < 100 && strcmp(coinaddr,addr0) == 0 ) printf("ht.%-5d lock.%-7d PoW coinbase.(%s) %.8f\n",height,locked,addr0,value); - if ( strcmp(coinaddr,addr0) == 0 ) + if ( strcmp(coinaddr,addr0) == 0 || gotblock != 0 ) powsum += value, npow++; } histo[locked/1000] += value; @@ -645,6 +714,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase) int32_t LP_passphrase_init(char *passphrase,char *gui,uint16_t netid,char *seednode) { static void *ctx; struct iguana_info *coin,*tmp; int32_t counter; + uint8_t pubkey33[100]; if ( ctx == 0 ) ctx = bitcoin_ctx(); if ( G.LP_pendingswaps != 0 ) @@ -679,8 +749,11 @@ int32_t LP_passphrase_init(char *passphrase,char *gui,uint16_t netid,char *seedn memset(&G,0,sizeof(G)); G.netid = netid; safecopy(G.seednode,seednode,sizeof(G.seednode)); + vcalc_sha256(0,G.LP_passhash.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); LP_privkey_updates(ctx,LP_mypubsock,passphrase); + bitcoin_pubkey33(ctx, pubkey33, G.LP_privkey); + calc_rmd160_sha256(G.LP_myrmd160, pubkey33, 33); init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20); G.LP_sessionid = (uint32_t)time(NULL); safecopy(G.gui,gui,sizeof(G.gui)); diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index deaacf1c9..dd694d9ab 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -13,10 +13,33 @@ * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ +#include "LP_include.h" +#include "../../includes/cJSON.h" // // LP_remember.c // marketmaker // +char *coin_name_by_tx_index(struct LP_swap_remember *rswap, int32_t tx_index) +{ + switch (tx_index) { + case BASILISK_MYFEE: + case BASILISK_OTHERFEE: + case BASILISK_ALICEPAYMENT: + case BASILISK_ALICERECLAIM: + case BASILISK_BOBSPEND: + return rswap->dest; + case BASILISK_BOBDEPOSIT: + case BASILISK_BOBPAYMENT: + case BASILISK_BOBRECLAIM: + case BASILISK_BOBREFUND: + case BASILISK_ALICESPEND: + case BASILISK_ALICECLAIM: + return rswap->src; + default: + return 0; + } +} + void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen) { int32_t i; char scriptstr[513]; @@ -70,6 +93,13 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,",\"bobtomic\":\"%s\"",swap->I.bobtomic); if ( swap->I.etomicsrc[0] != 0 ) fprintf(fp,",\"etomicsrc\":\"%s\"",swap->I.etomicsrc); +#ifndef NOTETOMIC + if (swap->myfee.I.ethTxid[0] != 0) { + fprintf(fp,",\"aliceFeeEthTx\":\"%s\"", swap->myfee.I.ethTxid); + } + if (swap->otherfee.I.ethTxid[0] != 0) { + fprintf(fp,",\"aliceFeeEthTx\":\"%s\"", swap->otherfee.I.ethTxid); + } if (swap->bobdeposit.I.ethTxid[0] != 0) { fprintf(fp,",\"bobDepositEthTx\":\"%s\"", swap->bobdeposit.I.ethTxid); } @@ -80,6 +110,9 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx fprintf(fp,",\"alicePaymentEthTx\":\"%s\"", swap->alicepayment.I.ethTxid); } + fprintf(fp,",\"aliceRealSat\":\"%" PRId64 "\"", swap->I.alicerealsat); + fprintf(fp,",\"bobRealSat\":\"%" PRId64 "\"", swap->I.bobrealsat); +#endif fprintf(fp,",\"alicecoin\":\"%s\"",swap->I.alicestr); if ( swap->I.alicetomic[0] != 0 ) fprintf(fp,",\"alicetomic\":\"%s\"",swap->I.alicetomic); @@ -250,6 +283,22 @@ void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx { if ( (reqjson= cJSON_Parse(fstr)) != 0 ) { +#ifndef NOTETOMIC + if (strcmp(rawtx->symbol,"ETOMIC") == 0) { + jdelete(reqjson,"txid"); + jdelete(reqjson,"amount"); + jaddstr(reqjson,"txid", rawtx->I.ethTxid); + jaddnum(reqjson,"amount", dstr(rawtx->I.eth_amount)); + jdelete(reqjson, "coin"); + if (rawtx == &swap->myfee || rawtx == &swap->otherfee || rawtx == &swap->alicepayment || rawtx == &swap->bobspend || rawtx == &swap->alicereclaim) { + jaddstr(reqjson,"coin", swap->I.alicestr); + } + + if (rawtx == &swap->bobdeposit || rawtx == &swap->bobrefund || rawtx == &swap->aliceclaim || rawtx == &swap->bobpayment || rawtx == &swap->bobreclaim || rawtx == &swap->alicespend) { + jaddstr(reqjson,"coin", swap->I.bobstr); + } + } +#endif if ( jobj(reqjson,"method") != 0 ) jdelete(reqjson,"method"); jaddstr(reqjson,"method","update"); @@ -429,9 +478,9 @@ int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind) case BASILISK_OTHERFEE: return(!iambob); break; case BASILISK_BOBSPEND: case BASILISK_ALICEPAYMENT: - case BASILISK_ALICERECLAIM: - case BASILISK_ALICECLAIM: return(0); + case BASILISK_ALICERECLAIM: return(0); break; + case BASILISK_ALICECLAIM: case BASILISK_BOBDEPOSIT: case BASILISK_ALICESPEND: case BASILISK_BOBPAYMENT: @@ -656,13 +705,31 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) jaddnum(item,"alicetxfee",dstr(rswap->Atxfee)); jadd64bits(item,"aliceid",rswap->aliceid); array = cJSON_CreateArray(); + cJSON *tx_chain = cJSON_CreateArray(); for (i=0; isentflags[i] != 0 ) - jaddistr(array,txnames[i]); + if ( rswap->sentflags[i] != 0 ) { + jaddistr(array, txnames[i]); + cJSON *tx = cJSON_CreateObject(); + jaddstr(tx, "stage", txnames[i]); + jaddstr(tx, "coin", coin_name_by_tx_index(rswap, i)); +#ifndef NOTETOMIC + if (LP_etomic_is_empty_tx_id(rswap->eth_tx_ids[i]) == 0) { + jaddstr(tx, "txid", rswap->eth_tx_ids[i]); + jaddnum(tx, "amount", dstr(rswap->eth_values[i])); + } else { +#endif + jaddbits256(tx, "txid", rswap->txids[i]); + jaddnum(tx, "amount", dstr(rswap->values[i])); +#ifndef NOTETOMIC + } +#endif + jaddi(tx_chain, tx); + } if ( rswap->txbytes[i] != 0 ) free(rswap->txbytes[i]), rswap->txbytes[i] = 0; } + jadd(item, "txChain", tx_chain); jadd(item,"sentflags",array); array = cJSON_CreateArray(); for (i=0; ipaymentspent); jaddbits256(item,"Apaymentspent",rswap->Apaymentspent); jaddbits256(item,"depositspent",rswap->depositspent); + jaddbits256(item,"alicedexfee",rswap->iambob == 0 ? rswap->txids[BASILISK_MYFEE] : rswap->txids[BASILISK_OTHERFEE]); return(item); } @@ -901,16 +969,32 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag) strcpy(rswap->etomicdest,jstr(txobj,"etomicdest")); } + rswap->bobrealsat = jint(txobj, "bobRealSat"); + rswap->alicerealsat = jint(txobj, "aliceRealSat"); + + if (jstr(txobj,"aliceFeeEthTx") != 0) { + if (rswap->iambob == 0) { + strcpy(rswap->eth_tx_ids[BASILISK_MYFEE], jstr(txobj, "aliceFeeEthTx")); + rswap->eth_values[BASILISK_MYFEE] = LP_DEXFEE(rswap->alicerealsat); + } else { + strcpy(rswap->eth_tx_ids[BASILISK_OTHERFEE], jstr(txobj, "aliceFeeEthTx")); + rswap->eth_values[BASILISK_OTHERFEE] = LP_DEXFEE(rswap->alicerealsat); + } + } + if (jstr(txobj,"bobDepositEthTx") != 0) { - strcpy(rswap->bobDepositEthTx, jstr(txobj,"bobDepositEthTx")); + strcpy(rswap->eth_tx_ids[BASILISK_BOBDEPOSIT], jstr(txobj,"bobDepositEthTx")); + rswap->eth_values[BASILISK_BOBDEPOSIT] = LP_DEPOSITSATOSHIS(rswap->bobrealsat); } if (jstr(txobj,"bobPaymentEthTx") != 0) { - strcpy(rswap->bobPaymentEthTx, jstr(txobj,"bobPaymentEthTx")); + strcpy(rswap->eth_tx_ids[BASILISK_BOBPAYMENT], jstr(txobj,"bobPaymentEthTx")); + rswap->eth_values[BASILISK_BOBPAYMENT] = rswap->bobrealsat; } if (jstr(txobj,"alicePaymentEthTx") != 0) { - strcpy(rswap->alicePaymentEthTx, jstr(txobj,"alicePaymentEthTx")); + strcpy(rswap->eth_tx_ids[BASILISK_ALICEPAYMENT], jstr(txobj,"alicePaymentEthTx")); + rswap->eth_values[BASILISK_ALICEPAYMENT] = rswap->alicerealsat; } if (jstr(txobj,"bobtomic") != 0) { @@ -1275,6 +1359,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, { char *aliceSpendEthTxId = LP_etomicalice_spends_bob_payment(&rswap); if (aliceSpendEthTxId != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_ALICESPEND], aliceSpendEthTxId); + rswap.eth_values[BASILISK_ALICESPEND] = rswap.bobrealsat; free(aliceSpendEthTxId); } else { printf("Alice spend ETH tx send failed!\n"); @@ -1324,6 +1410,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, { char *aliceClaimsEthTxId = LP_etomicalice_claims_bob_deposit(&rswap); if (aliceClaimsEthTxId != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_ALICECLAIM], aliceClaimsEthTxId); + rswap.eth_values[BASILISK_ALICECLAIM] = LP_DEPOSITSATOSHIS(rswap.bobrealsat); free(aliceClaimsEthTxId); } else { printf("Alice Bob deposit claim ETH tx failed!\n"); @@ -1356,7 +1444,13 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, if ( rswap.alicetomic[0] != 0 ) { char *aliceReclaimEthTx = LP_etomicalice_reclaims_payment(&rswap); - free(aliceReclaimEthTx); + if (aliceReclaimEthTx != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_ALICERECLAIM], aliceReclaimEthTx); + rswap.eth_values[BASILISK_ALICERECLAIM] = rswap.alicerealsat; + free(aliceReclaimEthTx); + } else { + printf("Alice could not reclaim ETH/ERC20 payment!\n"); + } } #endif } @@ -1400,6 +1494,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, { char *bobSpendEthTx = LP_etomicbob_spends_alice_payment(&rswap); if (bobSpendEthTx != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_BOBSPEND], bobSpendEthTx); + rswap.eth_values[BASILISK_BOBSPEND] = rswap.alicerealsat; free(bobSpendEthTx); } else { printf("Bob spends Alice payment ETH tx send failed!\n"); @@ -1437,6 +1533,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, { char *bobReclaimEthTx = LP_etomicbob_reclaims_payment(&rswap); if (bobReclaimEthTx != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_BOBRECLAIM], bobReclaimEthTx); + rswap.eth_values[BASILISK_BOBRECLAIM] = rswap.bobrealsat; free(bobReclaimEthTx); } else { printf("Bob reclaims payment ETH tx send failed!\n"); @@ -1490,6 +1588,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals, { char *bobRefundsEthTx = LP_etomicbob_refunds_deposit(&rswap); if (bobRefundsEthTx != NULL) { + strcpy(rswap.eth_tx_ids[BASILISK_BOBREFUND], bobRefundsEthTx); + rswap.eth_values[BASILISK_BOBREFUND] = LP_DEPOSITSATOSHIS(rswap.bobrealsat); free(bobRefundsEthTx); } else { printf("Bob refunds deposit ETH tx send failed!\n"); diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 615942e0a..e5a3d3e12 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -137,6 +137,12 @@ int32_t LP_getheight(int32_t *notarizedp,struct iguana_info *coin) uint64_t LP_RTsmartbalance(struct iguana_info *coin) { +#ifndef NOTETOMIC + if (coin->etomic[0] != 0) { + int error = 0; + return LP_etomic_get_balance(coin, coin->smartaddr, &error); + } +#endif cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value; bits256 zero; valuesum = 0; memset(zero.bytes,0,sizeof(zero)); @@ -401,6 +407,8 @@ int32_t LP_address_isvalid(char *symbol,char *address) int32_t isvalid = 0; cJSON *retjson; if ( symbol == 0 || symbol[0] == 0 ) return(0); + if ( strcmp(symbol,"BCH") == 0 && (address[0] == '1' || address[0] == '3') ) + return(-1); if ( (retjson= LP_validateaddress(symbol,address)) != 0 ) { if ( jobj(retjson,"isvalid") != 0 && is_cJSON_True(jobj(retjson,"isvalid")) != 0 ) diff --git a/iguana/exchanges/LP_signatures.c b/iguana/exchanges/LP_signatures.c index 40228f796..00318551b 100644 --- a/iguana/exchanges/LP_signatures.c +++ b/iguana/exchanges/LP_signatures.c @@ -128,25 +128,29 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) safecopy(qp->gui,LP_gui,sizeof(qp->gui)); safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); safecopy(qp->uuidstr,jstr(argjson,"uuid"),sizeof(qp->uuidstr)); +#ifndef NOTETOMIC if ( LP_etomicsymbol(activesymbol,etomic,qp->srccoin) != 0 ) { - if ( (etomicstr= jstr(argjson,"bobtomic")) == 0 || strcmp(etomicstr,etomic) != 0 ) + if ( (etomicstr= jstr(argjson,"bobtomic")) == 0 || compareAddresses(etomicstr,etomic) == 0 ) { printf("etomic src mismatch (%s) vs (%s)\n",etomicstr!=0?etomicstr:"",etomic); return(-1); } } +#endif safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); safecopy(qp->etomicsrc,jstr(argjson,"etomicsrc"),sizeof(qp->etomicsrc)); safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); +#ifndef NOTETOMIC if ( LP_etomicsymbol(activesymbol,etomic,qp->destcoin) != 0 ) { - if ( (etomicstr= jstr(argjson,"alicetomic")) == 0 || strcmp(etomicstr,etomic) != 0 ) + if ( (etomicstr= jstr(argjson,"alicetomic")) == 0 || compareAddresses(etomicstr,etomic) == 0 ) { printf("etomic dest mismatch (%s) vs (%s)\n",etomicstr!=0?etomicstr:"",etomic); return(-1); } } +#endif safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); safecopy(qp->etomicdest,jstr(argjson,"etomicdest"),sizeof(qp->etomicdest)); qp->aliceid = j64bits(argjson,"aliceid"); @@ -454,6 +458,17 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re jaddstr(reqjson,"pubsecp",pubsecpstr); if ( (kmd= LP_coinfind("KMD")) != 0 && (ap= LP_address(kmd,kmd->smartaddr)) != 0 && ap->instantdex_credits != 0 ) jaddnum(reqjson,"credits",dstr(ap->instantdex_credits)); +#ifndef NOTETOMIC + if (basecoin->etomic[0] != 0) { + int error = 0; + uint64_t etomic_coin_balance = LP_etomic_get_balance(basecoin, basecoin->smartaddr, &error); + jaddstr(reqjson,"utxocoin","ETH_OR_ERC20"); + jaddnum(reqjson,"bal",dstr(etomic_coin_balance)); + jaddnum(reqjson,"min",dstr(etomic_coin_balance)); + jaddnum(reqjson,"max",dstr(etomic_coin_balance)); + jaddnum(reqjson,"n",1); + } else +#endif if ( (numutxos= LP_address_minmax(1,&median,&minsize,&maxsize,basecoin,basecoin->smartaddr)) != 0 ) { //printf("send %s numutxos.%d median %.8f min %.8f max %.8f\n",base,numutxos,dstr(median),dstr(minsize),dstr(maxsize)); diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index 71162b67d..8c71e1586 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -1277,7 +1277,21 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port) jaddnum(retjson,"restart",kickval); } } +#ifndef NOTETOMIC + if (strcmp(coin->symbol, "ETOMIC") == 0) { + cJSON *balance = cJSON_CreateObject(); + electrum_address_getbalance(coin->symbol, ep, &balance, coin->smartaddr); + int64_t confirmed = get_cJSON_int(balance, "confirmed"); + int64_t unconfirmed = get_cJSON_int(balance, "unconfirmed"); + if ((confirmed + unconfirmed) < 20 * SATOSHIDEN && get_etomic_from_faucet(coin->smartaddr) != 1) { + coin->inactive = (uint32_t)time(NULL); + coin->electrum = ep->prev; + cJSON_Delete(balance); + return(cJSON_Parse("{\"error\":\"Could not get ETOMIC from faucet!\"}")); + } + cJSON_Delete(balance); + } +#endif //printf("(%s)\n",jprint(retjson,0)); return(retjson); } - diff --git a/iguana/exchanges/LP_swap.c b/iguana/exchanges/LP_swap.c index 74316972b..746f9e1cd 100644 --- a/iguana/exchanges/LP_swap.c +++ b/iguana/exchanges/LP_swap.c @@ -854,7 +854,17 @@ void LP_bobloop(void *_swap) expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; bobwaittimeout = LP_calc_waittimeout(bobstr); alicewaittimeout = LP_calc_waittimeout(alicestr); - if ( swap != 0 ) +#ifndef NOTETOMIC + if (swap->I.bobtomic[0] != 0 || swap->I.alicetomic[0] != 0) { + int error = 0; + uint64_t eth_balance = getEthBalance(swap->I.etomicsrc, &error); + if (eth_balance < 500000) { + err = -5000, printf("Bob ETH balance too low, aborting swap!\n"); + } + } +#endif + + if ( swap != 0 && err == 0) { if ( LP_waitsend("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) err = -2000, printf("error waitsend pubkeys\n"); @@ -866,7 +876,6 @@ void LP_bobloop(void *_swap) err = -2003, printf("error bobscripts deposit\n"); else { - uint8_t error = 0; swap->bobrefund.utxovout = 0; swap->bobrefund.utxotxid = swap->bobdeposit.I.signedtxid; basilisk_bobdeposit_refund(swap,swap->I.putduration); @@ -876,33 +885,32 @@ void LP_bobloop(void *_swap) LP_unavailableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash); if ( LP_waitfor(swap->N.pair,swap,bobwaittimeout,LP_verify_otherfee) < 0 ) { - error = 1; err = -2004, printf("error waiting for alicefee\n"); } - if ( error == 0 ) + if ( err == 0 ) { if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 ) { - error = 1; err = -2005, printf("error sending bobdeposit\n"); } } - LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash); - m = swap->I.bobconfirms; - while ( (n= LP_numconfirms(bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,1)) < m ) - { - LP_swap_critical = (uint32_t)time(NULL); + if (err == 0) { LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash); - char str[65];printf("%d wait for bobdeposit %s numconfs.%d %s %s\n",n,swap->bobdeposit.I.destaddr,m,bobstr,bits256_str(str,swap->bobdeposit.I.signedtxid)); - sleep(10); - } - printf("wait for alicepayment\n"); - if ( error == 0 && LP_waitfor(swap->N.pair,swap,bobwaittimeout + alicewaittimeout,LP_verify_alicepayment) < 0 ) - { - error = 1; - err = -2006, printf("error waiting for alicepayment\n"); + m = swap->I.bobconfirms; + while ((n = LP_numconfirms(bobstr, swap->bobdeposit.I.destaddr, swap->bobdeposit.I.signedtxid, 0, 1)) < m) { + LP_swap_critical = (uint32_t) time(NULL); + LP_unavailableset(swap->bobpayment.utxotxid, swap->bobpayment.utxovout, (uint32_t) time(NULL) + 60, swap->I.otherhash); + char str[65]; + printf("%d wait for bobdeposit %s numconfs.%d %s %s\n", n, swap->bobdeposit.I.destaddr, m, bobstr, bits256_str(str, swap->bobdeposit.I.signedtxid)); + sleep(10); + } + + printf("wait for alicepayment\n"); + if (LP_waitfor(swap->N.pair, swap, bobwaittimeout + alicewaittimeout, LP_verify_alicepayment) < 0) { + err = -2006, printf("error waiting for alicepayment\n"); + } } - if (error == 0) + if (err == 0) { LP_swap_critical = (uint32_t)time(NULL); if ( basilisk_bobscripts_set(swap,0,1) < 0 ) @@ -958,7 +966,18 @@ void LP_aliceloop(void *_swap) expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT; bobwaittimeout = LP_calc_waittimeout(bobstr); alicewaittimeout = LP_calc_waittimeout(alicestr); - if ( swap != 0 ) + +#ifndef NOTETOMIC + if (swap->I.bobtomic[0] != 0 || swap->I.alicetomic[0] != 0) { + int error = 0; + uint64_t eth_balance = getEthBalance(swap->I.etomicdest, &error); + if (eth_balance < 500000) { + err = -5001, printf("Alice ETH balance too low, aborting swap!\n"); + } + } +#endif + + if ( swap != 0 && err == 0) { printf("start swap iamalice pair.%d\n",swap->N.pair); if ( LP_sendwait("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 ) @@ -1191,6 +1210,16 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 free(swap); return(0); } +#ifndef NOTETOMIC + if (strcmp(alicestr, "ETOMIC") == 0) { + swap->I.alicerealsat = swap->I.alicesatoshis; + swap->I.alicesatoshis = 100000000; + } + if (strcmp(bobstr, "ETOMIC") == 0) { + swap->I.bobrealsat = swap->I.bobsatoshis; + swap->I.bobsatoshis = 100000000; + } +#endif if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE ) swap->I.bobinsurance = LP_MIN_TXFEE; if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE ) @@ -1311,6 +1340,20 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256 swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout; swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2; swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout; +#ifndef NOTETOMIC + if (strcmp(alicestr, "ETOMIC") == 0) { + swap->alicepayment.I.eth_amount = swap->I.alicerealsat; + if (swap->I.iambob == 1) { + swap->otherfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat); + } else { + swap->myfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat); + } + } + if (strcmp(bobstr, "ETOMIC") == 0) { + swap->bobpayment.I.eth_amount = swap->I.bobrealsat; + swap->bobdeposit.I.eth_amount = LP_DEPOSITSATOSHIS(swap->I.bobrealsat); + } +#endif LP_mark_spent(bobstr,qp->txid,qp->vout); LP_mark_spent(bobstr,qp->txid2,qp->vout2); LP_mark_spent(alicestr,qp->desttxid,qp->destvout); diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index f7352fe36..32d1cab01 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -1117,13 +1117,13 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_ preselected[numpre++] = up; else { - printf("couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout); + //printf("couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout); sleep(1); value = LP_txvalue(0,coin->symbol,utxotxid,utxovout); LP_address_utxoadd(0,(uint32_t)time(NULL),"withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1); if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 ) preselected[numpre++] = up; - else printf("second couldnt add address_utxo after not finding\n"); + else printf("second couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout); //return(0); } } @@ -2087,31 +2087,112 @@ char *LP_movecoinbases(char *symbol) #ifndef NOTETOMIC +char *LP_eth_tx_fee(struct iguana_info *coin, char *dest_addr, char *amount, int64_t gas, int64_t gas_price) +{ + bits256 privkey; + cJSON *retjson = cJSON_CreateObject(); + int64_t actual_gas_price = 0, actual_gas = 0; + char privkey_str[70]; + + if (gas_price > 0) { + actual_gas_price = gas_price; + } else { + actual_gas_price = getGasPriceFromStation(0); + if (actual_gas_price == 0) { + return (clonestr("{\"error\":\"Couldn't get gas price from station!\"}")); + } + } + cJSON_AddNumberToObject(retjson, "gas_price", actual_gas_price); + + if (gas > 0) { + actual_gas = gas; + } else if (strcmp(coin->symbol, "ETH") == 0) { + actual_gas = 21000; + } else { + privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr); + uint8arrayToHex(privkey_str, privkey.bytes, 32); + actual_gas = estimate_erc20_gas(coin->etomic, dest_addr, amount, privkey_str, coin->decimals); + if (actual_gas == 0) { + return (clonestr("{\"error\":\"Couldn't estimate erc20 transfer gas usage!\"}")); + } + } + cJSON_AddNumberToObject(retjson, "gas", actual_gas); + + double_t eth_fee = (actual_gas_price * actual_gas) / 1000000000.0; + cJSON_AddNumberToObject(retjson, "eth_fee", eth_fee); + return(jprint(retjson,1)); +} + char *LP_eth_withdraw(struct iguana_info *coin,cJSON *argjson) { cJSON *retjson = cJSON_CreateObject(); + cJSON *gas_json = cJSON_GetObjectItem(argjson, "gas"); + cJSON *gas_price_json = cJSON_GetObjectItem(argjson, "gas_price"); char *dest_addr, *tx_id, privkey_str[70], amount_str[100]; - int64_t amount; + int64_t amount = 0, gas = 0, gas_price = 0, broadcast = 0; bits256 privkey; dest_addr = jstr(argjson, "to"); + if (dest_addr == NULL) { + return(clonestr("{\"error\":\"param 'to' is required!\"}")); + } + + if (isValidAddress(dest_addr) == 0) { + return(clonestr("{\"error\":\"'to' address is not valid!\"}")); + } + amount = jdouble(argjson, "amount") * 100000000; - privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr); - uint8arrayToHex(privkey_str, privkey.bytes, 32); + if (amount == 0) { + return(clonestr("{\"error\":\"'amount' is not set or equal to zero!\"}")); + } + if (gas_json != NULL && is_cJSON_Number(gas_json)) { + gas = gas_json->valueint; + if (gas < 21000) { + return (clonestr("{\"error\":\"'gas' can't be lower than 21000!\"}")); + } + } + if (gas_price_json != NULL && is_cJSON_Number(gas_price_json)) { + gas_price = gas_price_json->valueint; + if (gas_price < 1) { + return (clonestr("{\"error\":\"'gas_price' can't be lower than 1!\"}")); + } + } + + broadcast = jint(argjson, "broadcast"); satoshisToWei(amount_str, amount); - if (strcmp(coin->symbol, "ETH") == 0) { - tx_id = sendEth(dest_addr, amount_str, privkey_str, 0); + if (broadcast == 1) { + privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr); + uint8arrayToHex(privkey_str, privkey.bytes, 32); + if (strcmp(coin->symbol, "ETH") == 0) { + tx_id = sendEth(dest_addr, amount_str, privkey_str, 0, gas, gas_price, 0); + } else { + tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0, gas, gas_price, 0, coin->decimals); + } + if (tx_id != NULL) { + jaddstr(retjson, "tx_id", tx_id); + free(tx_id); + } else { + jaddstr(retjson, "error", "Error sending transaction"); + } + return (jprint(retjson, 1)); } else { - tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0); + return LP_eth_tx_fee(coin, dest_addr, amount_str, gas, gas_price); } - jaddstr(retjson, "tx_id", tx_id); - return(jprint(retjson,1)); } +char *LP_eth_gas_price() +{ + cJSON *retjson = cJSON_CreateObject(); + uint64_t gas_price = getGasPriceFromStation(0); + if (gas_price > 0) { + cJSON_AddNumberToObject(retjson, "gas_price", gas_price); + } else { + cJSON_AddStringToObject(retjson, "error", "Could not get gas price from station!"); + } + return(jprint(retjson,1)); +} #endif - - int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr) { struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj; diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index f00db34c0..b81ec3449 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -699,7 +699,8 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr //printf("address balance call LP_listunspent %s electrum.%p etomic.%d\n",coin->symbol,coin->electrum,coin->etomic[0]); #ifndef NOTETOMIC if (coin->etomic[0] != 0) { - balance = LP_etomic_get_balance(coin, coinaddr); + int error = 0; + balance = LP_etomic_get_balance(coin, coinaddr, &error); } else #endif if ( coin->electrum == 0 ) @@ -787,7 +788,14 @@ cJSON *LP_balances(char *coinaddr) } else { - if ( (balance= LP_RTsmartbalance(coin)) != 0 ) +#ifndef NOTETOMIC + if (coin->etomic[0] == 0 || coin->inactive == 0) { +#endif + balance = LP_RTsmartbalance(coin); +#ifndef NOTETOMIC + } +#endif + if ( balance != 0 ) { item = cJSON_CreateObject(); jaddstr(item,"coin",coin->symbol); @@ -1185,7 +1193,7 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol return(-1); } destaddr[0] = destaddr2[0] = 0; - if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 ) + if ( coin != 0 && (strcmp(coin->symbol, "ETOMIC") == 0 || (coin->inactive != 0 && IAMLP != 0))) bypass = 1; if ( bypass != 0 ) val = satoshis; @@ -1209,16 +1217,27 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol strcpy(destaddr,destaddr2); if ( coin != 0 ) { - if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) - return(0); + char txid_str[100], txid2_str[100]; + bits256_str(txid_str, txid); + bits256_str(txid2_str, txid2); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) { + printf("Could not find tx out: %s %d\n", txid_str, vout); + return (0); + } else free_json(txobj); - if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) - return(0); + if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) { + printf("Could not find tx out: %s %d\n", txid_str, vout2); + return (0); + } else free_json(txobj); - if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 ) - return(0); - if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 ) - return(0); + if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 ) { + printf("Txid numconfirms is less or equal to zero: %s %d\n", txid_str, vout); + return (0); + } + if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 ) { + printf("Txid numconfirms is less or equal to zero: %s %d\n", txid2_str, vout2); + return (0); + } } return(1); } diff --git a/iguana/exchanges/auto_chipsbtc b/iguana/exchanges/auto_chipsbtc index 35b9319e4..40e61d94b 100755 --- a/iguana/exchanges/auto_chipsbtc +++ b/iguana/exchanges/auto_chipsbtc @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.00006,\"maxprice\":0.0002,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" +curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.00002,\"maxprice\":0.0002,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/auto_chipskmd b/iguana/exchanges/auto_chipskmd index 5a5794c86..fd2c7d6ca 100755 --- a/iguana/exchanges/auto_chipskmd +++ b/iguana/exchanges/auto_chipskmd @@ -1,2 +1,2 @@ source userpass -curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.15,\"maxprice\":0.4,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" +curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.05,\"maxprice\":0.4,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}" diff --git a/iguana/exchanges/coins b/iguana/exchanges/coins index fc1e8e778..c380a7756 100644 --- a/iguana/exchanges/coins +++ b/iguana/exchanges/coins @@ -1,2 +1,2 @@ -export coins="[{\"coin\":\"PAT\",\"name\":\"pat\",\"etomic\":\"0xBB1fA4FdEB3459733bF67EbC6f893003fA976a82\",\"rpcport\":80},{\"coin\":\"PRLPAY\",\"asset\":\"PRLPAY\",\"rpcport\":9679}, {\"coin\":\"MLM\",\"name\":\"mktcoin\",\"rpcport\":9276,\"pubtype\":110,\"p2shtype\":115,\"wiftype\":238,\"txfee\":10000}, {\"coin\":\"CRDS\",\"name\":\"credits\",\"rpcport\":31050,\"pubtype\":28,\"p2shtype\":10,\"wiftype\":140,\"txfee\":10000}, {\"coin\":\"UCASH\",\"name\":\"ucash\",\"etomic\":\"0x92e52a1a235d9a103d970901066ce910aacefd37\",\"rpcport\":80}, {\"coin\":\"RVT\",\"name\":\"rivetz\",\"etomic\":\"0x3d1ba9be9f66b8ee101911bc36d3fb562eac2244\",\"rpcport\":80}, {\"coin\":\"DCN\",\"name\":\"dentacoin\",\"etomic\":\"0x08d32b0da63e2C3bcF8019c9c5d849d7a9d791e6\",\"rpcport\":80}, {\"coin\":\"ATB\",\"name\":\"atbcoin\",\"confpath\":\"${HOME#}/.ATBCoinWallet/atbcoin.conf\",\"rpcport\":8332,\"pubtype\":23,\"p2shtype\":83,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"SRN\",\"name\":\"sirin-labs-token\",\"etomic\":\"0x68d57c9a1c35f63e2c83ee8e49a64e9d70528d25\",\"rpcport\":80},{\"coin\":\"ELF\",\"name\":\"aelf\",\"etomic\":\"0xbf2179859fc6D5BEE9Bf9158632Dc51678a4100e\",\"rpcport\":80}, {\"coin\":\"HXX\",\"name\":\"hexxcoin\",\"rpcport\":29200,\"pubtype\":40,\"p2shtype\":10,\"wiftype\":210,\"txfee\":100000}, {\"coin\":\"XSN\",\"name\":\"xsn\",\"confpath\":\"${HOME#}/.xsncore/xsn.conf\",\"rpcport\":51473,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"DROP\",\"name\":\"dropil\",\"etomic\":\"0x4672bad527107471cb5067a887f4656d585a8a31\",\"rpcport\":80}, {\"coin\":\"GPN\",\"name\":\"gpncoin\",\"etomic\":\"0xE2b407160AAd5540eAc0e80338b9a5085C60F25B\",\"rpcport\":80}, {\"coin\":\"SANC\",\"name\":\"sancoj\",\"etomic\":\"0x03ec7bb59be036870ef696a2abf124f496d6735a\",\"rpcport\":80},{\"coin\":\"LRC\",\"name\":\"loopring\",\"etomic\":\"0xEF68e7C694F40c8202821eDF525dE3782458639f\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"IOST\",\"name\":\"iostoken\",\"etomic\":\"0xfa1a856cfa3409cfa145fa4e20eb270df3eb21ab\",\"rpcport\":80}, {\"coin\":\"WTC\",\"name\":\"waltonchain\",\"etomic\":\"0xb7cb1c96db6b22b0d3d9536e0108d062bd488f74\",\"rpcport\":80}, {\"coin\":\"XOV\",\"name\":\"xovbank\",\"etomic\":\"0x153eD9CC1b792979d2Bde0BBF45CC2A7e436a5F9\",\"rpcport\":80}, {\"coin\":\"FSN\",\"name\":\"fusion\",\"etomic\":\"0xd0352a019e9ab9d757776f532377aaebd36fd541\",\"rpcport\":80}, {\"coin\":\"AION\",\"name\":\"aion\",\"etomic\":\"0x4CEdA7906a5Ed2179785Cd3A40A69ee8bc99C466\",\"rpcport\":80}, {\"coin\":\"NAS\",\"name\":\"nebulas-token\",\"etomic\":\"0x5d65d971895edc438f465c17db6992698a52318d\",\"rpcport\":80}, {\"coin\":\"RHOC\",\"name\":\"rchain\",\"etomic\":\"0x168296bb09e24a88805cb9c33356536b980d3fc5\",\"rpcport\":80}, {\"coin\":\"BTM\",\"name\":\"bytom\",\"etomic\":\"0xcB97e65F07DA24D46BcDD078EBebd7C6E6E3d750\",\"rpcport\":80}, {\"coin\":\"AE\",\"name\":\"aeternity\",\"etomic\":\"0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d\",\"rpcport\":80}, {\"coin\":\"ZIL\",\"name\":\"zilliqa\",\"etomic\":\"0x05f4a42e251f2d52b8ed15e9fedaacfcef1fad27\",\"rpcport\":80}, {\"coin\":\"FLLW\",\"name\":\"followcoin\",\"etomic\":\"0x0200412995f1bafef0d3f97c4e28ac2515ec1ece\",\"rpcport\":80}, {\"coin\":\"HYD\",\"name\":\"hydra\",\"etomic\":\"0xD233495C48EB0143661fFC8458EAfc21b633f97f\",\"rpcport\":80}, {\"coin\":\"VRSC\",\"asset\":\"VRSC\",\"rpcport\":27486}, {\"coin\":\"CHAIN\",\"asset\":\"CHAIN\",\"rpcport\":15587},{\"coin\":\"POWR\",\"name\":\"power-ledger\",\"etomic\":\"0x595832f8fc6bf59c85c527fec3740a1b7a361269\",\"rpcport\":80},{\"coin\":\"TUSD\",\"name\":\"trueusd\",\"etomic\":\"0x8dd5fbce2f6a956c3022ba3663759011dd51e73e\",\"rpcport\":80}, {\"coin\":\"VEN\",\"name\":\"vechain\",\"etomic\":\"0xd850942ef8811f2a866692a623011bde52a462c1\",\"rpcport\":80}, {\"coin\":\"DSEC\",\"asset\":\"DSEC\",\"rpcport\":11557},{\"coin\":\"LOOM\",\"name\":\"loom-network\",\"etomic\":\"0xa4e8c3ec456107ea67d3075bf9e3df3a75823db0\",\"rpcport\":80}, {\"coin\":\"ANN\",\"name\":\"agentnotneeded\",\"etomic\":\"0xe0e73E8fc3a0fA161695be1D75E1Bc3E558957c4\",\"rpcport\":80},{\"coin\":\"PRL\",\"name\":\"oyster\",\"etomic\":\"0x1844b21593262668b7248d0f57a220caaba46ab9\",\"rpcport\":80}, {\"coin\":\"MGO\",\"name\":\"mobilego\",\"etomic\":\"0x40395044Ac3c0C57051906dA938B54BD6557F212\",\"rpcport\":80},{\"coin\":\"DRGN\",\"name\":\"dragonchain\",\"etomic\":\"0x419c4db4b9e25d6db2ad9691ccb832c8d9fda05e\",\"rpcport\":80}, {\"coin\":\"GLD\",\"name\":\"goldcoin\",\"rpcport\":9332,\"pubtype\":32,\"p2shtype\":5,\"wiftype\":160,\"txfee\":100000}, {\"coin\":\"BTK\",\"name\":\"bitcointoken\",\"etomic\":\"0xdb8646F5b487B5Dd979FAC618350e85018F557d4\",\"rpcport\":80},{\"coin\":\"DGPT\",\"name\":\"digipulse\",\"etomic\":\"0xf6cFe53d6FEbaEEA051f400ff5fc14F0cBBDacA1\",\"rpcport\":80}, {\"coin\":\"OCT\",\"name\":\"octus\",\"etomic\":\"0x7e9d365C0C97Fe5FcAdcc1B513Af974b768C5867\",\"rpcport\":80},{\"coin\":\"STWY\",\"name\":\"storweeytoken\",\"etomic\":\"0x8a8c71f032362fca2994f75d854f911ec381ac5a\",\"rpcport\":80}, {\"coin\":\"SPK\",\"name\":\"Sparks\",\"rpcport\":8892,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"PCL\",\"name\":\"peculium\",\"etomic\":\"0x3618516f45cd3c913f81f9987af41077932bc40d\",\"rpcport\":80}, {\"coin\":\"RLTY\",\"name\":\"smartrealty\",\"etomic\":\"0xbe99b09709fc753b09bcf557a992f6605d5997b0\",\"rpcport\":80},{\"coin\":\"CIX\",\"name\":\"cryptonetix\",\"etomic\":\"0x1175a66a5c3343Bbf06AA818BB482DdEc30858E0\",\"rpcport\":80}, {\"coin\":\"GLXT\",\"asset\":\"GLXT\",\"rpcport\":15723}, {\"coin\":\"PYRO\",\"name\":\"pyro\",\"confpath\":\"${HOME#}/.pyrocore/pyro.conf\",\"rpcport\":9696,\"pubtype\":55,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\": \"BNTN\",\"asset\": \"BNTN\",\"rpcport\": 14358},{\"coin\":\"ORE\",\"name\":\"galactrum\",\"rpcport\":6269,\"pubtype\":38,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"ELD\",\"name\":\"maker\",\"etomic\":\"0xaaf7d4cd097317d68174215395eb02c2cca81e31\",\"rpcport\":80}, {\"coin\":\"CENNZ\",\"name\":\"centrality\",\"etomic\":\"0x1122b6a0e00dce0563082b6e2953f3a943855c1f\",\"rpcport\":80}, {\"coin\":\"PGN\",\"name\":\"pigeon\",\"rpcport\":8756,\"pubtype\":55,\"p2shtype\":122,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XCG\",\"name\":\"Xchange\",\"confpath\":\"${HOME#}/.Xchangecore/Xchange.conf\",\"rpcport\":9386,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"AXE\",\"name\":\"axe\",\"confpath\":\"${HOME#}/.axecore/axe.conf\",\"rpcport\":9337,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"PEW\",\"name\":\"brofist\",\"rpcport\":12454,\"pubtype\":55,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000,\"confpath\":\"${HOME#}/.brofistcore/brofist.conf\"}, {\"coin\":\"BCBC\",\"name\":\"bitcoin@cbc\",\"confpath\":\"${HOME#}/.bitcoin@cbc/bitcoin.conf\",\"rpcport\":8340,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"GRLC\",\"name\":\"garlicoin\",\"rpcport\":42068,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"EQL\",\"asset\":\"EQL\",\"rpcport\":10306}, {\"coin\":\"OCC\",\"name\":\"originalcryptocoin\",\"etomic\":\"0x0235fe624e044a05eed7a43e16e3083bc8a4287a\",\"rpcport\":80}, {\"coin\":\"DIN\",\"name\":\"dinero\",\"rpcport\":9998,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":204,\"txfee\":10000,\"confpath\":\"${HOME#}/.dinerocore/dinero.conf\"}, {\"coin\":\"BUCK\",\"name\":\"buck\",\"rpcport\":5739,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LYS\",\"name\":\"lightyears\",\"etomic\":\"0xdd41fbd1ae95c5d9b198174a28e04be6b3d1aa27\",\"rpcport\":80}, {\"coin\":\"RAP\",\"name\":\"rapture\",\"rpcport\":14776,\"pubtype\":60,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000,\"confpath\":\"${HOME#}/.rapturecore/rapture.conf\"}, {\"coin\":\"RADIUS\",\"name\":\"radius\",\"rpcport\":4089,\"pubtype\":60,\"p2shtype\":16,\"wiftype\":15,\"txfee\":10000,\"confpath\":\"${HOME#}/.radiuscore/radius.conf\"},{\"coin\":\"BTCL\",\"name\":\"btclite\",\"etomic\":\"0x5acd19b9c91e596b1f062f18e3d02da7ed8d1e50\",\"rpcport\":80}, {\"coin\":\"SEQ\",\"name\":\"sequence\",\"rpcport\":16663,\"isPoS\":1,\"pubtype\":63,\"p2shtype\":64,\"wiftype\":170,\"txfee\":10000}, {\"coin\":\"DYN\",\"name\":\"dynamic\",\"rpcport\":33350,\"pubtype\":30,\"p2shtype\":10,\"wiftype\":140,\"txfee\":10000}, {\"coin\":\"SBTC\",\"name\":\"SuperBitcoin\",\"rpcport\":28282,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000,\"confpath\":\"${HOME#}/.sbtc/sbtc.conf\"}, {\"coin\":\"FJC\",\"name\":\"fujicoin\",\"rpcport\":3776,\"pubtype\":36,\"p2shtype\":16,\"wiftype\":164,\"txfee\":100000}, {\"coin\":\"AIR\",\"name\":\"airtoken\",\"etomic\":\"0x27dce1ec4d3f72c3e457cc50354f1f975ddef488\",\"rpcport\":80}, {\"coin\":\"VRT\",\"name\":\"virtus\",\"confpath\":\"${HOME#}/.virtuscore/virtus.conf\",\"rpcport\":13880,\"pubtype\":70,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"DRT\",\"name\":\"domraider\",\"etomic\":\"0x9af4f26941677c706cfecf6d3379ff01bb85d5ab\",\"rpcport\":80}, {\"coin\":\"BITS\",\"name\":\"bitstar\",\"rpcport\":15715,\"isPoS\":1,\"pubtype\":25,\"p2shtype\":8,\"wiftype\":153,\"txfee\":10000}, {\"coin\":\"FTC\",\"name\":\"feathercoin\",\"rpcport\":9337,\"pubtype\":14,\"p2shtype\":5,\"wiftype\":142,\"txfee\":1000000}, {\"coin\":\"PXT\",\"name\":\"populous-xbrl-token\",\"etomic\":\"0xc14830e53aa344e8c14603a91229a0b925b0b262\",\"rpcport\":80}, {\"coin\":\"USDT\",\"name\":\"tether\",\"etomic\":\"0xdac17f958d2ee523a2206206994597c13d831ec7\",\"rpcport\":80}, {\"coin\":\"ELI\",\"name\":\"elicoin\",\"rpcport\":9332,\"pubtype\":33,\"p2shtype\":102,\"wiftype\":205,\"txfee\":10000}, {\"coin\":\"SCRIV\",\"name\":\"scriv\",\"confpath\":\"${HOME#}/.scrivcore/scriv.conf\",\"rpcport\":7998,\"pubtype\":125,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"ELP\",\"name\":\"ellerium\",\"rpcport\":61020,\"pubtype\":23,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"ROI\",\"name\":\"ROIcoin\",\"rpcport\":3376,\"pubtype\":60,\"p2shtype\":122,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XCOIN\",\"name\":\"xcoin\",\"rpcport\":22717,\"pubtype\":137,\"p2shtype\":15,\"wiftype\":75,\"txfee\":100000}, {\"coin\":\"BBT\",\"name\":\"bitboost\",\"etomic\":\"0x1500205f50bf3fd976466d0662905c9ff254fc9c\",\"rpcport\":80}, {\"coin\":\"TRX\",\"name\":\"tron\",\"etomic\":\"0xf230b790e05390fc8295f4d3f60332c93bed42e2\",\"rpcport\":80}, {\"coin\":\"OMG\",\"name\":\"omisego\",\"etomic\":\"0xd26114cd6EE289AccF82350c8d8487fedB8A0C07\",\"rpcport\":80}, {\"coin\":\"ICX\",\"name\":\"icon\",\"etomic\":\"0xb5a5f22694352c15b00323844ad545abb2b11028\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"BNB\",\"name\":\"binance-coin\",\"etomic\":\"0xB8c77482e45F1F44dE1745F52C74426C631bDD52\",\"rpcport\":80}, {\"coin\":\"DGD\",\"name\":\"digixdao\",\"etomic\":\"0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A\",\"rpcport\":80,\"decimals\":9}, {\"coin\":\"PPT\",\"name\":\"populous\",\"etomic\":\"0xd4fa1460F537bb9085d22C7bcCB5DD450Ef28e3a\",\"rpcport\":80}, {\"coin\":\"MKR\",\"name\":\"maker\",\"etomic\":\"0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2\",\"rpcport\":80}, {\"coin\":\"SNT\",\"name\":\"status\",\"etomic\":\"0x744d70FDBE2Ba4CF95131626614a1763DF805B9E\",\"rpcport\":80}, {\"coin\":\"REP\",\"name\":\"augur\",\"etomic\":\"0xE94327D07Fc17907b4DB788E5aDf2ed424adDff6\",\"rpcport\":80}, {\"coin\":\"ZRX\",\"name\":\"0x\",\"etomic\":\"0xE41d2489571d322189246DaFA5ebDe1F4699F498\",\"rpcport\":80}, {\"coin\":\"BAT\",\"name\":\"basic-attention-token\",\"etomic\":\"0x0D8775F648430679A709E98d2b0Cb6250d2887EF\",\"rpcport\":80}, {\"coin\":\"ETHOS\",\"name\":\"ethos\",\"etomic\":\"0x5Af2Be193a6ABCa9c8817001F45744777Db30756\",\"rpcport\":80}, {\"coin\":\"QASH\",\"name\":\"qash\",\"etomic\":\"0x618E75Ac90b12c6049Ba3b27f5d5F8651b0037F6\",\"rpcport\":80}, {\"coin\":\"FUN\",\"name\":\"funfair\",\"etomic\":\"0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b\",\"rpcport\":80}, {\"coin\":\"KNC\",\"name\":\"kyber-network\",\"etomic\":\"0xdd974D5C2e2928deA5F71b9825b8b646686BD200\",\"rpcport\":80}, {\"coin\":\"SALT\",\"name\":\"salt\",\"etomic\":\"0x4156D3342D5c385a87D264F90653733592000581\",\"rpcport\":80}, {\"coin\":\"BNT\",\"name\":\"bancor\",\"etomic\":\"0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C\",\"rpcport\":80}, {\"coin\":\"ICN\",\"name\":\"iconomi\",\"etomic\":\"0x888666CA69E0f178DED6D75b5726Cee99A87D698\",\"rpcport\":80}, {\"coin\":\"PAY\",\"name\":\"tenx\",\"etomic\":\"0xB97048628DB6B661D4C2aA833e95Dbe1A905B280\",\"rpcport\":80}, {\"coin\":\"REQ\",\"name\":\"request-network\",\"etomic\":\"0x8f8221aFbB33998d8584A2B05749bA73c37a938a\",\"rpcport\":80}, {\"coin\":\"STORJ\",\"name\":\"storj\",\"etomic\":\"0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC\",\"rpcport\":80}, {\"coin\":\"GNO\",\"name\":\"gnosis-gno\",\"etomic\":\"0x6810e776880C02933D47DB1b9fc05908e5386b96\",\"rpcport\":80}, {\"coin\":\"RLC\",\"name\":\"rlc\",\"etomic\":\"0x607F4C5BB672230e8672085532f7e901544a7375\",\"rpcport\":80}, {\"coin\":\"ENJ\",\"name\":\"enjin-coin\",\"etomic\":\"0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c\",\"rpcport\":80}, {\"coin\":\"QSP\",\"name\":\"quantstamp\",\"etomic\":\"0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d\",\"rpcport\":80}, {\"coin\":\"RDN\",\"name\":\"raiden-network-token\",\"etomic\":\"0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6\",\"rpcport\":80}, {\"coin\":\"CVC\",\"name\":\"civic\",\"etomic\":\"0x41e5560054824eA6B0732E656E3Ad64E20e94E45\",\"rpcport\":80}, {\"coin\":\"SAN\",\"name\":\"santiment\",\"etomic\":\"0x7C5A0CE9267ED19B22F8cae653F198e3E8daf098\",\"rpcport\":80}, {\"coin\":\"ANT\",\"name\":\"aragon\",\"etomic\":\"0x960b236A07cf122663c4303350609A66A7B288C0\",\"rpcport\":80}, {\"coin\":\"MANA\",\"name\":\"decentraland\",\"etomic\":\"0x0F5D2fB29fb7d3CFeE444a200298f468908cC942\",\"rpcport\":80}, {\"coin\":\"MCO\",\"name\":\"monaco\",\"etomic\":\"0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d\",\"rpcport\":80}, {\"coin\":\"MTL\",\"name\":\"metal\",\"etomic\":\"0xF433089366899D83a9f26A773D59ec7eCF30355e\",\"rpcport\":80}, {\"coin\":\"EDG\",\"name\":\"edgeless\",\"etomic\":\"0x08711D3B02C8758F2FB3ab4e80228418a7F8e39c\",\"rpcport\":80}, {\"coin\":\"MLN\",\"name\":\"melon\",\"etomic\":\"0xBEB9eF514a379B997e0798FDcC901Ee474B6D9A1\",\"rpcport\":80}, {\"coin\":\"AMB\",\"name\":\"amber\",\"etomic\":\"0x4DC3643DbC642b72C158E7F3d2ff232df61cb6CE\",\"rpcport\":80}, {\"coin\":\"WINGS\",\"name\":\"wings\",\"etomic\":\"0x667088b212ce3d06a1b553a7221E1fD19000d9aF\",\"rpcport\":80}, {\"coin\":\"RCN\",\"name\":\"ripio-credit-network\",\"etomic\":\"0xF970b8E36e23F7fC3FD752EeA86f8Be8D83375A6\",\"rpcport\":80}, {\"coin\":\"SNGLS\",\"name\":\"singulardtv\",\"etomic\":\"0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009\",\"rpcport\":80}, {\"coin\":\"TAAS\",\"name\":\"taas\",\"etomic\":\"0xE7775A6e9Bcf904eb39DA2b68c5efb4F9360e08C\",\"rpcport\":80}, {\"coin\":\"DNT\",\"name\":\"district0x\",\"etomic\":\"0x0AbdAce70D3790235af448C88547603b945604ea\",\"rpcport\":80}, {\"coin\":\"CFI\",\"name\":\"cofound-it\",\"etomic\":\"0x12FEF5e57bF45873Cd9B62E9DBd7BFb99e32D73e\",\"rpcport\":80}, {\"coin\":\"LUN\",\"name\":\"lunyr\",\"etomic\":\"0xfa05A73FfE78ef8f1a739473e462c54bae6567D9\",\"rpcport\":80}, {\"coin\":\"ADT\",\"name\":\"adtoken\",\"etomic\":\"0xD0D6D6C5Fe4a677D343cC433536BB717bAe167dD\",\"rpcport\":80}, {\"coin\":\"AST\",\"name\":\"airswap\",\"etomic\":\"0x27054b13b1B798B345b591a4d22e6562d47eA75a\",\"rpcport\":80}, {\"coin\":\"CDT\",\"name\":\"blox\",\"etomic\":\"0x177d39AC676ED1C67A2b268AD7F1E58826E5B0af\",\"rpcport\":80}, {\"coin\":\"TKN\",\"name\":\"tokencard\",\"etomic\":\"0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a\",\"rpcport\":80}, {\"coin\":\"HMQ\",\"name\":\"humaniq\",\"etomic\":\"0xcbCC0F036ED4788F63FC0fEE32873d6A7487b908\",\"rpcport\":80}, {\"coin\":\"NMR\",\"name\":\"numeraire\",\"etomic\":\"0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671\",\"rpcport\":80}, {\"coin\":\"NET\",\"name\":\"nimiq\",\"etomic\":\"0xcfb98637bcae43C13323EAa1731cED2B716962fD\",\"rpcport\":80}, {\"coin\":\"TRST\",\"name\":\"trust\",\"etomic\":\"0xCb94be6f13A1182E4A4B6140cb7bf2025d28e41B\",\"rpcport\":80}, {\"coin\":\"GUP\",\"name\":\"guppy\",\"etomic\":\"0xf7B098298f7C69Fc14610bf71d5e02c60792894C\",\"rpcport\":80}, {\"coin\":\"1ST\",\"name\":\"firstblood\",\"etomic\":\"0xAf30D2a7E90d7DC361c8C4585e9BB7D2F6f15bc7\",\"rpcport\":80}, {\"coin\":\"TIME\",\"name\":\"chronobank\",\"etomic\":\"0x6531f133e6DeeBe7F2dcE5A0441aA7ef330B4e53\",\"rpcport\":80}, {\"coin\":\"SWT\",\"name\":\"swarm-city\",\"etomic\":\"0xB9e7F8568e08d5659f5D29C4997173d84CdF2607\",\"rpcport\":80}, {\"coin\":\"ROL\",\"name\":\"dice\",\"etomic\":\"0x2e071D2966Aa7D8dECB1005885bA1977D6038A65\",\"rpcport\":80}, {\"coin\":\"XAUR\",\"name\":\"xaurum\",\"etomic\":\"0x4DF812F6064def1e5e029f1ca858777CC98D2D81\",\"rpcport\":80}, {\"coin\":\"PLU\",\"name\":\"pluton\",\"etomic\":\"0xD8912C10681D8B21Fd3742244f44658dBA12264E\",\"rpcport\":80}, {\"coin\":\"HGT\",\"name\":\"hellogold\",\"etomic\":\"0xba2184520A1cC49a6159c57e61E1844E085615B6\",\"rpcport\":80}, {\"coin\":\"VSL\",\"name\":\"vslice\",\"etomic\":\"0x5c543e7AE0A1104f78406C340E9C64FD9fCE5170\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"IND\",\"name\":\"indorse-token\",\"etomic\":\"0xf8e386EDa857484f5a12e4B5DAa9984E06E73705\",\"rpcport\":80}, {\"coin\":\"FYN\",\"name\":\"fundyourselfnow\",\"etomic\":\"0x88FCFBc22C6d3dBaa25aF478C578978339BDe77a\",\"rpcport\":80},{\"coin\":\"SMART\",\"name\":\"smartcash\",\"rpcport\":9679,\"pubtype\":63,\"p2shtype\":18,\"wiftype\":191,\"txfee\":200000}, {\"coin\":\"BTCP\",\"name\":\"btcprivate\",\"rpcport\":7932,\"taddr\":19,\"pubtype\":37,\"p2shtype\":175,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DNR\",\"isPoS\":1,\"active\":1,\"name\":\"denarius\",\"rpcport\":32339,\"pubtype\":30,\"p2shtype\":90,\"wiftype\":158,\"txfee\":10000}, {\"coin\":\"RVN\",\"name\":\"raven\",\"rpcport\":8766,\"pubtype\":60,\"p2shtype\":122,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"VIVO\",\"name\":\"vivo\",\"confpath\":\"${HOME#}/.vivocore/vivo.conf\",\"rpcport\":9998,\"pubtype\":70,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"KNG\",\"name\":\"kings\",\"rpcport\":44888,\"pubtype\":75,\"p2shtype\":125,\"wiftype\":203,\"txfee\":10000}, {\"coin\":\"UFO\",\"name\":\"ufocoin\",\"confpath\":\"${HOME#}/.ufo/ufocoin.conf\",\"rpcport\":9888,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":155,\"txfee\":100000}, {\"coin\":\"ETH\",\"name\":\"ethereum\",\"etomic\":\"0x0000000000000000000000000000000000000000\",\"rpcport\":80}, {\"coin\":\"EOS\",\"name\":\"EOS\",\"etomic\":\"0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0\",\"rpcport\":80}, {\"coin\":\"KREDS\",\"name\":\"kreds\",\"rpcport\":3850,\"pubtype\":45,\"p2shtype\":5,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"SNG\",\"name\":\"snowgem\",\"rpcport\":16112,\"taddr\":28,\"pubtype\":40,\"p2shtype\":45,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"ZEL\",\"name\":\"zelcash\",\"rpcport\":16124,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"HTML\",\"name\":\"htmlcoin\",\"rpcport\":4889,\"pubtype\":41,\"p2shtype\":100,\"wiftype\":169,\"txfee\":400000}, {\"coin\":\"MNX\",\"name\":\"Minexcoin\",\"rpcport\":17786,\"pubtype\":75,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LTZ\",\"name\":\"litecoinz\",\"rpcport\":29332,\"taddr\":10,\"pubtype\":179,\"p2shtype\":184,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"BAY\",\"name\":\"bitbay\",\"isPoS\":1,\"rpcport\":19915,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, {\"coin\":\"OOT\",\"asset\":\"OOT\",\"rpcport\":12467}, {\"coin\":\"ZOI\",\"name\":\"zoin\",\"rpcport\":8255,\"pubtype\":80,\"p2shtype\":7,\"wiftype\":208,\"txfee\":1000}, {\"coin\": \"PIZZA\",\"asset\": \"PIZZA\",\"rpcport\": 11116},{\"coin\": \"BEER\",\"asset\": \"BEER\",\"rpcport\": 8923}, {\"coin\":\"GRS\",\"name\":\"groestlcoin\",\"rpcport\":1441,\"pubtype\":36,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":11998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":100000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":10000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" +export coins="[{\"coin\":\"SEC\",\"asset\":\"SEC\",\"rpcport\":11540},{\"coin\":\"PAT\",\"name\":\"pat\",\"etomic\":\"0xBB1fA4FdEB3459733bF67EbC6f893003fA976a82\",\"rpcport\":80},{\"coin\":\"PRLPAY\",\"asset\":\"PRLPAY\",\"rpcport\":9679}, {\"coin\":\"MLM\",\"name\":\"mktcoin\",\"rpcport\":9276,\"pubtype\":110,\"p2shtype\":115,\"wiftype\":238,\"txfee\":10000}, {\"coin\":\"CRDS\",\"name\":\"credits\",\"rpcport\":31050,\"pubtype\":28,\"p2shtype\":10,\"wiftype\":140,\"txfee\":10000}, {\"coin\":\"UCASH\",\"name\":\"ucash\",\"etomic\":\"0x92e52a1a235d9a103d970901066ce910aacefd37\",\"rpcport\":80}, {\"coin\":\"RVT\",\"name\":\"rivetz\",\"etomic\":\"0x3d1ba9be9f66b8ee101911bc36d3fb562eac2244\",\"rpcport\":80}, {\"coin\":\"DCN\",\"name\":\"dentacoin\",\"etomic\":\"0x08d32b0da63e2C3bcF8019c9c5d849d7a9d791e6\",\"rpcport\":80}, {\"coin\":\"ATB\",\"name\":\"atbcoin\",\"confpath\":\"${HOME#}/.ATBCoinWallet/atbcoin.conf\",\"rpcport\":8332,\"pubtype\":23,\"p2shtype\":83,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"SRN\",\"name\":\"sirin-labs-token\",\"etomic\":\"0x68d57c9a1c35f63e2c83ee8e49a64e9d70528d25\",\"rpcport\":80},{\"coin\":\"ELF\",\"name\":\"aelf\",\"etomic\":\"0xbf2179859fc6D5BEE9Bf9158632Dc51678a4100e\",\"rpcport\":80}, {\"coin\":\"HXX\",\"name\":\"hexxcoin\",\"rpcport\":29200,\"pubtype\":40,\"p2shtype\":10,\"wiftype\":210,\"txfee\":100000}, {\"coin\":\"XSN\",\"name\":\"xsn\",\"confpath\":\"${HOME#}/.xsncore/xsn.conf\",\"rpcport\":51473,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"DROP\",\"name\":\"dropil\",\"etomic\":\"0x4672bad527107471cb5067a887f4656d585a8a31\",\"rpcport\":80}, {\"coin\":\"GPN\",\"name\":\"gpncoin\",\"etomic\":\"0xE2b407160AAd5540eAc0e80338b9a5085C60F25B\",\"rpcport\":80}, {\"coin\":\"SANC\",\"name\":\"sancoj\",\"etomic\":\"0x03ec7bb59be036870ef696a2abf124f496d6735a\",\"rpcport\":80},{\"coin\":\"LRC\",\"name\":\"loopring\",\"etomic\":\"0xEF68e7C694F40c8202821eDF525dE3782458639f\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"IOST\",\"name\":\"iostoken\",\"etomic\":\"0xfa1a856cfa3409cfa145fa4e20eb270df3eb21ab\",\"rpcport\":80}, {\"coin\":\"WTC\",\"name\":\"waltonchain\",\"etomic\":\"0xb7cb1c96db6b22b0d3d9536e0108d062bd488f74\",\"rpcport\":80}, {\"coin\":\"XOV\",\"name\":\"xovbank\",\"etomic\":\"0x153eD9CC1b792979d2Bde0BBF45CC2A7e436a5F9\",\"rpcport\":80}, {\"coin\":\"FSN\",\"name\":\"fusion\",\"etomic\":\"0xd0352a019e9ab9d757776f532377aaebd36fd541\",\"rpcport\":80}, {\"coin\":\"AION\",\"name\":\"aion\",\"etomic\":\"0x4CEdA7906a5Ed2179785Cd3A40A69ee8bc99C466\",\"rpcport\":80}, {\"coin\":\"NAS\",\"name\":\"nebulas-token\",\"etomic\":\"0x5d65d971895edc438f465c17db6992698a52318d\",\"rpcport\":80}, {\"coin\":\"RHOC\",\"name\":\"rchain\",\"etomic\":\"0x168296bb09e24a88805cb9c33356536b980d3fc5\",\"rpcport\":80}, {\"coin\":\"BTM\",\"name\":\"bytom\",\"etomic\":\"0xcB97e65F07DA24D46BcDD078EBebd7C6E6E3d750\",\"rpcport\":80}, {\"coin\":\"AE\",\"name\":\"aeternity\",\"etomic\":\"0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d\",\"rpcport\":80}, {\"coin\":\"ZIL\",\"name\":\"zilliqa\",\"etomic\":\"0x05f4a42e251f2d52b8ed15e9fedaacfcef1fad27\",\"rpcport\":80}, {\"coin\":\"FLLW\",\"name\":\"followcoin\",\"etomic\":\"0x0200412995f1bafef0d3f97c4e28ac2515ec1ece\",\"rpcport\":80}, {\"coin\":\"HYD\",\"name\":\"hydra\",\"etomic\":\"0xD233495C48EB0143661fFC8458EAfc21b633f97f\",\"rpcport\":80}, {\"coin\":\"VRSC\",\"asset\":\"VRSC\",\"rpcport\":27486}, {\"coin\":\"CHAIN\",\"asset\":\"CHAIN\",\"rpcport\":15587},{\"coin\":\"POWR\",\"name\":\"power-ledger\",\"etomic\":\"0x595832f8fc6bf59c85c527fec3740a1b7a361269\",\"rpcport\":80},{\"coin\":\"TUSD\",\"name\":\"trueusd\",\"etomic\":\"0x8dd5fbce2f6a956c3022ba3663759011dd51e73e\",\"rpcport\":80}, {\"coin\":\"VEN\",\"name\":\"vechain\",\"etomic\":\"0xd850942ef8811f2a866692a623011bde52a462c1\",\"rpcport\":80}, {\"coin\":\"DSEC\",\"asset\":\"DSEC\",\"rpcport\":11557},{\"coin\":\"LOOM\",\"name\":\"loom-network\",\"etomic\":\"0xa4e8c3ec456107ea67d3075bf9e3df3a75823db0\",\"rpcport\":80}, {\"coin\":\"ANN\",\"name\":\"agentnotneeded\",\"etomic\":\"0xe0e73E8fc3a0fA161695be1D75E1Bc3E558957c4\",\"rpcport\":80},{\"coin\":\"PRL\",\"name\":\"oyster\",\"etomic\":\"0x1844b21593262668b7248d0f57a220caaba46ab9\",\"rpcport\":80}, {\"coin\":\"MGO\",\"name\":\"mobilego\",\"etomic\":\"0x40395044Ac3c0C57051906dA938B54BD6557F212\",\"rpcport\":80},{\"coin\":\"DRGN\",\"name\":\"dragonchain\",\"etomic\":\"0x419c4db4b9e25d6db2ad9691ccb832c8d9fda05e\",\"rpcport\":80}, {\"coin\":\"GLD\",\"name\":\"goldcoin\",\"rpcport\":9332,\"pubtype\":32,\"p2shtype\":5,\"wiftype\":160,\"txfee\":100000}, {\"coin\":\"BTK\",\"name\":\"bitcointoken\",\"etomic\":\"0xdb8646F5b487B5Dd979FAC618350e85018F557d4\",\"rpcport\":80},{\"coin\":\"DGPT\",\"name\":\"digipulse\",\"etomic\":\"0xf6cFe53d6FEbaEEA051f400ff5fc14F0cBBDacA1\",\"rpcport\":80}, {\"coin\":\"OCT\",\"name\":\"octus\",\"etomic\":\"0x7e9d365C0C97Fe5FcAdcc1B513Af974b768C5867\",\"rpcport\":80},{\"coin\":\"STWY\",\"name\":\"storweeytoken\",\"etomic\":\"0x8a8c71f032362fca2994f75d854f911ec381ac5a\",\"rpcport\":80}, {\"coin\":\"SPK\",\"name\":\"Sparks\",\"rpcport\":8892,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"PCL\",\"name\":\"peculium\",\"etomic\":\"0x3618516f45cd3c913f81f9987af41077932bc40d\",\"rpcport\":80}, {\"coin\":\"RLTY\",\"name\":\"smartrealty\",\"etomic\":\"0xbe99b09709fc753b09bcf557a992f6605d5997b0\",\"rpcport\":80},{\"coin\":\"CIX\",\"name\":\"cryptonetix\",\"etomic\":\"0x1175a66a5c3343Bbf06AA818BB482DdEc30858E0\",\"rpcport\":80}, {\"coin\":\"GLXT\",\"asset\":\"GLXT\",\"rpcport\":15723}, {\"coin\":\"PYRO\",\"name\":\"pyro\",\"confpath\":\"${HOME#}/.pyrocore/pyro.conf\",\"rpcport\":9696,\"pubtype\":55,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\": \"BNTN\",\"asset\": \"BNTN\",\"rpcport\": 14358},{\"coin\":\"ORE\",\"name\":\"galactrum\",\"rpcport\":6269,\"pubtype\":38,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"ELD\",\"name\":\"maker\",\"etomic\":\"0xaaf7d4cd097317d68174215395eb02c2cca81e31\",\"rpcport\":80}, {\"coin\":\"CENNZ\",\"name\":\"centrality\",\"etomic\":\"0x1122b6a0e00dce0563082b6e2953f3a943855c1f\",\"rpcport\":80}, {\"coin\":\"PGN\",\"name\":\"pigeon\",\"rpcport\":8756,\"pubtype\":55,\"p2shtype\":122,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XCG\",\"name\":\"Xchange\",\"confpath\":\"${HOME#}/.Xchangecore/Xchange.conf\",\"rpcport\":9386,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"AXE\",\"name\":\"axe\",\"confpath\":\"${HOME#}/.axecore/axe.conf\",\"rpcport\":9337,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"PEW\",\"name\":\"brofist\",\"rpcport\":12454,\"pubtype\":55,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000,\"confpath\":\"${HOME#}/.brofistcore/brofist.conf\"}, {\"coin\":\"BCBC\",\"name\":\"bitcoin@cbc\",\"confpath\":\"${HOME#}/.bitcoin@cbc/bitcoin.conf\",\"rpcport\":8340,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"GRLC\",\"name\":\"garlicoin\",\"rpcport\":42068,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"EQL\",\"asset\":\"EQL\",\"rpcport\":10306}, {\"coin\":\"OCC\",\"name\":\"originalcryptocoin\",\"etomic\":\"0x0235fe624e044a05eed7a43e16e3083bc8a4287a\",\"rpcport\":80}, {\"coin\":\"DIN\",\"name\":\"dinero\",\"rpcport\":9998,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":204,\"txfee\":10000,\"confpath\":\"${HOME#}/.dinerocore/dinero.conf\"}, {\"coin\":\"BUCK\",\"name\":\"buck\",\"rpcport\":5739,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LYS\",\"name\":\"lightyears\",\"etomic\":\"0xdd41fbd1ae95c5d9b198174a28e04be6b3d1aa27\",\"rpcport\":80}, {\"coin\":\"RAP\",\"name\":\"rapture\",\"rpcport\":14776,\"pubtype\":60,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000,\"confpath\":\"${HOME#}/.rapturecore/rapture.conf\"}, {\"coin\":\"RADIUS\",\"name\":\"radius\",\"rpcport\":4089,\"pubtype\":60,\"p2shtype\":16,\"wiftype\":15,\"txfee\":10000,\"confpath\":\"${HOME#}/.radiuscore/radius.conf\"},{\"coin\":\"BTCL\",\"name\":\"btclite\",\"etomic\":\"0x5acd19b9c91e596b1f062f18e3d02da7ed8d1e50\",\"rpcport\":80}, {\"coin\":\"SEQ\",\"name\":\"sequence\",\"rpcport\":16663,\"isPoS\":1,\"pubtype\":63,\"p2shtype\":64,\"wiftype\":170,\"txfee\":10000}, {\"coin\":\"DYN\",\"name\":\"dynamic\",\"rpcport\":33350,\"pubtype\":30,\"p2shtype\":10,\"wiftype\":140,\"txfee\":10000}, {\"coin\":\"SBTC\",\"name\":\"SuperBitcoin\",\"rpcport\":28282,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000,\"confpath\":\"${HOME#}/.sbtc/sbtc.conf\"}, {\"coin\":\"FJC\",\"name\":\"fujicoin\",\"rpcport\":3776,\"pubtype\":36,\"p2shtype\":16,\"wiftype\":164,\"txfee\":100000}, {\"coin\":\"AIR\",\"name\":\"airtoken\",\"etomic\":\"0x27dce1ec4d3f72c3e457cc50354f1f975ddef488\",\"rpcport\":80}, {\"coin\":\"VRT\",\"name\":\"virtus\",\"confpath\":\"${HOME#}/.virtuscore/virtus.conf\",\"rpcport\":13880,\"pubtype\":70,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"DRT\",\"name\":\"domraider\",\"etomic\":\"0x9af4f26941677c706cfecf6d3379ff01bb85d5ab\",\"rpcport\":80}, {\"coin\":\"BITS\",\"name\":\"bitstar\",\"rpcport\":15715,\"isPoS\":1,\"pubtype\":25,\"p2shtype\":8,\"wiftype\":153,\"txfee\":10000}, {\"coin\":\"FTC\",\"name\":\"feathercoin\",\"rpcport\":9337,\"pubtype\":14,\"p2shtype\":5,\"wiftype\":142,\"txfee\":1000000}, {\"coin\":\"PXT\",\"name\":\"populous-xbrl-token\",\"etomic\":\"0xc14830e53aa344e8c14603a91229a0b925b0b262\",\"rpcport\":80}, {\"coin\":\"USDT\",\"name\":\"tether\",\"etomic\":\"0xdac17f958d2ee523a2206206994597c13d831ec7\",\"rpcport\":80}, {\"coin\":\"ELI\",\"name\":\"elicoin\",\"rpcport\":9332,\"pubtype\":33,\"p2shtype\":102,\"wiftype\":205,\"txfee\":10000}, {\"coin\":\"SCRIV\",\"name\":\"scriv\",\"confpath\":\"${HOME#}/.scrivcore/scriv.conf\",\"rpcport\":7998,\"pubtype\":125,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"ELP\",\"name\":\"ellerium\",\"rpcport\":61020,\"pubtype\":23,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"ROI\",\"name\":\"ROIcoin\",\"rpcport\":3376,\"pubtype\":60,\"p2shtype\":122,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XCOIN\",\"name\":\"xcoin\",\"rpcport\":22717,\"pubtype\":137,\"p2shtype\":15,\"wiftype\":75,\"txfee\":100000}, {\"coin\":\"BBT\",\"name\":\"bitboost\",\"etomic\":\"0x1500205f50bf3fd976466d0662905c9ff254fc9c\",\"rpcport\":80}, {\"coin\":\"TRX\",\"name\":\"tron\",\"etomic\":\"0xf230b790e05390fc8295f4d3f60332c93bed42e2\",\"rpcport\":80}, {\"coin\":\"OMG\",\"name\":\"omisego\",\"etomic\":\"0xd26114cd6EE289AccF82350c8d8487fedB8A0C07\",\"rpcport\":80}, {\"coin\":\"ICX\",\"name\":\"icon\",\"etomic\":\"0xb5a5f22694352c15b00323844ad545abb2b11028\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"BNB\",\"name\":\"binance-coin\",\"etomic\":\"0xB8c77482e45F1F44dE1745F52C74426C631bDD52\",\"rpcport\":80}, {\"coin\":\"DGD\",\"name\":\"digixdao\",\"etomic\":\"0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A\",\"rpcport\":80,\"decimals\":9}, {\"coin\":\"PPT\",\"name\":\"populous\",\"etomic\":\"0xd4fa1460F537bb9085d22C7bcCB5DD450Ef28e3a\",\"rpcport\":80}, {\"coin\":\"MKR\",\"name\":\"maker\",\"etomic\":\"0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2\",\"rpcport\":80}, {\"coin\":\"SNT\",\"name\":\"status\",\"etomic\":\"0x744d70FDBE2Ba4CF95131626614a1763DF805B9E\",\"rpcport\":80}, {\"coin\":\"REP\",\"name\":\"augur\",\"etomic\":\"0xE94327D07Fc17907b4DB788E5aDf2ed424adDff6\",\"rpcport\":80}, {\"coin\":\"ZRX\",\"name\":\"0x\",\"etomic\":\"0xE41d2489571d322189246DaFA5ebDe1F4699F498\",\"rpcport\":80}, {\"coin\":\"BAT\",\"name\":\"basic-attention-token\",\"etomic\":\"0x0D8775F648430679A709E98d2b0Cb6250d2887EF\",\"rpcport\":80}, {\"coin\":\"ETHOS\",\"name\":\"ethos\",\"etomic\":\"0x5Af2Be193a6ABCa9c8817001F45744777Db30756\",\"rpcport\":80}, {\"coin\":\"QASH\",\"name\":\"qash\",\"etomic\":\"0x618E75Ac90b12c6049Ba3b27f5d5F8651b0037F6\",\"rpcport\":80}, {\"coin\":\"FUN\",\"name\":\"funfair\",\"etomic\":\"0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b\",\"rpcport\":80}, {\"coin\":\"KNC\",\"name\":\"kyber-network\",\"etomic\":\"0xdd974D5C2e2928deA5F71b9825b8b646686BD200\",\"rpcport\":80}, {\"coin\":\"SALT\",\"name\":\"salt\",\"etomic\":\"0x4156D3342D5c385a87D264F90653733592000581\",\"rpcport\":80}, {\"coin\":\"BNT\",\"name\":\"bancor\",\"etomic\":\"0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C\",\"rpcport\":80}, {\"coin\":\"ICN\",\"name\":\"iconomi\",\"etomic\":\"0x888666CA69E0f178DED6D75b5726Cee99A87D698\",\"rpcport\":80}, {\"coin\":\"PAY\",\"name\":\"tenx\",\"etomic\":\"0xB97048628DB6B661D4C2aA833e95Dbe1A905B280\",\"rpcport\":80}, {\"coin\":\"REQ\",\"name\":\"request-network\",\"etomic\":\"0x8f8221aFbB33998d8584A2B05749bA73c37a938a\",\"rpcport\":80}, {\"coin\":\"STORJ\",\"name\":\"storj\",\"etomic\":\"0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC\",\"rpcport\":80}, {\"coin\":\"GNO\",\"name\":\"gnosis-gno\",\"etomic\":\"0x6810e776880C02933D47DB1b9fc05908e5386b96\",\"rpcport\":80}, {\"coin\":\"RLC\",\"name\":\"rlc\",\"etomic\":\"0x607F4C5BB672230e8672085532f7e901544a7375\",\"rpcport\":80}, {\"coin\":\"ENJ\",\"name\":\"enjin-coin\",\"etomic\":\"0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c\",\"rpcport\":80}, {\"coin\":\"QSP\",\"name\":\"quantstamp\",\"etomic\":\"0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d\",\"rpcport\":80}, {\"coin\":\"RDN\",\"name\":\"raiden-network-token\",\"etomic\":\"0x255Aa6DF07540Cb5d3d297f0D0D4D84cb52bc8e6\",\"rpcport\":80}, {\"coin\":\"CVC\",\"name\":\"civic\",\"etomic\":\"0x41e5560054824eA6B0732E656E3Ad64E20e94E45\",\"rpcport\":80}, {\"coin\":\"SAN\",\"name\":\"santiment\",\"etomic\":\"0x7C5A0CE9267ED19B22F8cae653F198e3E8daf098\",\"rpcport\":80}, {\"coin\":\"ANT\",\"name\":\"aragon\",\"etomic\":\"0x960b236A07cf122663c4303350609A66A7B288C0\",\"rpcport\":80}, {\"coin\":\"MANA\",\"name\":\"decentraland\",\"etomic\":\"0x0F5D2fB29fb7d3CFeE444a200298f468908cC942\",\"rpcport\":80}, {\"coin\":\"MCO\",\"name\":\"monaco\",\"etomic\":\"0xB63B606Ac810a52cCa15e44bB630fd42D8d1d83d\",\"rpcport\":80}, {\"coin\":\"MTL\",\"name\":\"metal\",\"etomic\":\"0xF433089366899D83a9f26A773D59ec7eCF30355e\",\"rpcport\":80}, {\"coin\":\"EDG\",\"name\":\"edgeless\",\"etomic\":\"0x08711D3B02C8758F2FB3ab4e80228418a7F8e39c\",\"rpcport\":80}, {\"coin\":\"MLN\",\"name\":\"melon\",\"etomic\":\"0xBEB9eF514a379B997e0798FDcC901Ee474B6D9A1\",\"rpcport\":80}, {\"coin\":\"AMB\",\"name\":\"amber\",\"etomic\":\"0x4DC3643DbC642b72C158E7F3d2ff232df61cb6CE\",\"rpcport\":80}, {\"coin\":\"WINGS\",\"name\":\"wings\",\"etomic\":\"0x667088b212ce3d06a1b553a7221E1fD19000d9aF\",\"rpcport\":80}, {\"coin\":\"RCN\",\"name\":\"ripio-credit-network\",\"etomic\":\"0xF970b8E36e23F7fC3FD752EeA86f8Be8D83375A6\",\"rpcport\":80}, {\"coin\":\"SNGLS\",\"name\":\"singulardtv\",\"etomic\":\"0xaeC2E87E0A235266D9C5ADc9DEb4b2E29b54D009\",\"rpcport\":80}, {\"coin\":\"TAAS\",\"name\":\"taas\",\"etomic\":\"0xE7775A6e9Bcf904eb39DA2b68c5efb4F9360e08C\",\"rpcport\":80}, {\"coin\":\"DNT\",\"name\":\"district0x\",\"etomic\":\"0x0AbdAce70D3790235af448C88547603b945604ea\",\"rpcport\":80}, {\"coin\":\"CFI\",\"name\":\"cofound-it\",\"etomic\":\"0x12FEF5e57bF45873Cd9B62E9DBd7BFb99e32D73e\",\"rpcport\":80}, {\"coin\":\"LUN\",\"name\":\"lunyr\",\"etomic\":\"0xfa05A73FfE78ef8f1a739473e462c54bae6567D9\",\"rpcport\":80}, {\"coin\":\"ADT\",\"name\":\"adtoken\",\"etomic\":\"0xD0D6D6C5Fe4a677D343cC433536BB717bAe167dD\",\"rpcport\":80}, {\"coin\":\"AST\",\"name\":\"airswap\",\"etomic\":\"0x27054b13b1B798B345b591a4d22e6562d47eA75a\",\"rpcport\":80}, {\"coin\":\"CDT\",\"name\":\"blox\",\"etomic\":\"0x177d39AC676ED1C67A2b268AD7F1E58826E5B0af\",\"rpcport\":80}, {\"coin\":\"TKN\",\"name\":\"tokencard\",\"etomic\":\"0xaAAf91D9b90dF800Df4F55c205fd6989c977E73a\",\"rpcport\":80}, {\"coin\":\"HMQ\",\"name\":\"humaniq\",\"etomic\":\"0xcbCC0F036ED4788F63FC0fEE32873d6A7487b908\",\"rpcport\":80}, {\"coin\":\"NMR\",\"name\":\"numeraire\",\"etomic\":\"0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671\",\"rpcport\":80}, {\"coin\":\"NET\",\"name\":\"nimiq\",\"etomic\":\"0xcfb98637bcae43C13323EAa1731cED2B716962fD\",\"rpcport\":80}, {\"coin\":\"TRST\",\"name\":\"trust\",\"etomic\":\"0xCb94be6f13A1182E4A4B6140cb7bf2025d28e41B\",\"rpcport\":80}, {\"coin\":\"GUP\",\"name\":\"guppy\",\"etomic\":\"0xf7B098298f7C69Fc14610bf71d5e02c60792894C\",\"rpcport\":80}, {\"coin\":\"1ST\",\"name\":\"firstblood\",\"etomic\":\"0xAf30D2a7E90d7DC361c8C4585e9BB7D2F6f15bc7\",\"rpcport\":80}, {\"coin\":\"TIME\",\"name\":\"chronobank\",\"etomic\":\"0x6531f133e6DeeBe7F2dcE5A0441aA7ef330B4e53\",\"rpcport\":80}, {\"coin\":\"SWT\",\"name\":\"swarm-city\",\"etomic\":\"0xB9e7F8568e08d5659f5D29C4997173d84CdF2607\",\"rpcport\":80}, {\"coin\":\"ROL\",\"name\":\"dice\",\"etomic\":\"0x2e071D2966Aa7D8dECB1005885bA1977D6038A65\",\"rpcport\":80}, {\"coin\":\"XAUR\",\"name\":\"xaurum\",\"etomic\":\"0x4DF812F6064def1e5e029f1ca858777CC98D2D81\",\"rpcport\":80}, {\"coin\":\"PLU\",\"name\":\"pluton\",\"etomic\":\"0xD8912C10681D8B21Fd3742244f44658dBA12264E\",\"rpcport\":80}, {\"coin\":\"HGT\",\"name\":\"hellogold\",\"etomic\":\"0xba2184520A1cC49a6159c57e61E1844E085615B6\",\"rpcport\":80}, {\"coin\":\"VSL\",\"name\":\"vslice\",\"etomic\":\"0x5c543e7AE0A1104f78406C340E9C64FD9fCE5170\",\"rpcport\":80,\"decimals\":18}, {\"coin\":\"IND\",\"name\":\"indorse-token\",\"etomic\":\"0xf8e386EDa857484f5a12e4B5DAa9984E06E73705\",\"rpcport\":80}, {\"coin\":\"FYN\",\"name\":\"fundyourselfnow\",\"etomic\":\"0x88FCFBc22C6d3dBaa25aF478C578978339BDe77a\",\"rpcport\":80},{\"coin\":\"SMART\",\"name\":\"smartcash\",\"rpcport\":9679,\"pubtype\":63,\"p2shtype\":18,\"wiftype\":191,\"txfee\":200000}, {\"coin\":\"BTCP\",\"name\":\"btcprivate\",\"rpcport\":7932,\"taddr\":19,\"pubtype\":37,\"p2shtype\":175,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DNR\",\"isPoS\":1,\"active\":1,\"name\":\"denarius\",\"rpcport\":32339,\"pubtype\":30,\"p2shtype\":90,\"wiftype\":158,\"txfee\":10000}, {\"coin\":\"RVN\",\"name\":\"raven\",\"rpcport\":8766,\"pubtype\":60,\"p2shtype\":122,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"VIVO\",\"name\":\"vivo\",\"confpath\":\"${HOME#}/.vivocore/vivo.conf\",\"rpcport\":9998,\"pubtype\":70,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"KNG\",\"name\":\"kings\",\"rpcport\":44888,\"pubtype\":75,\"p2shtype\":125,\"wiftype\":203,\"txfee\":10000}, {\"coin\":\"UFO\",\"name\":\"ufocoin\",\"confpath\":\"${HOME#}/.ufo/ufocoin.conf\",\"rpcport\":9888,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":155,\"txfee\":100000}, {\"coin\":\"ETH\",\"name\":\"ethereum\",\"etomic\":\"0x0000000000000000000000000000000000000000\",\"rpcport\":80}, {\"coin\":\"EOS\",\"name\":\"EOS\",\"etomic\":\"0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0\",\"rpcport\":80}, {\"coin\":\"KREDS\",\"name\":\"kreds\",\"rpcport\":3850,\"pubtype\":45,\"p2shtype\":5,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"SNG\",\"name\":\"snowgem\",\"rpcport\":16112,\"taddr\":28,\"pubtype\":40,\"p2shtype\":45,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"ZEL\",\"name\":\"zelcash\",\"rpcport\":16124,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"PIVX\",\"name\":\"pivx\",\"rpcport\":51473,\"pubtype\":30,\"p2shtype\":13,\"wiftype\":212,\"txfee\":10000}, {\"coin\":\"HTML\",\"name\":\"htmlcoin\",\"rpcport\":4889,\"pubtype\":41,\"p2shtype\":100,\"wiftype\":169,\"txfee\":400000}, {\"coin\":\"MNX\",\"name\":\"Minexcoin\",\"rpcport\":17786,\"pubtype\":75,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LTZ\",\"name\":\"litecoinz\",\"rpcport\":29332,\"taddr\":10,\"pubtype\":179,\"p2shtype\":184,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"BAY\",\"name\":\"bitbay\",\"isPoS\":1,\"rpcport\":19915,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":10000}, {\"coin\":\"OOT\",\"asset\":\"OOT\",\"rpcport\":12467}, {\"coin\":\"ZOI\",\"name\":\"zoin\",\"rpcport\":8255,\"pubtype\":80,\"p2shtype\":7,\"wiftype\":208,\"txfee\":1000}, {\"coin\": \"PIZZA\",\"asset\": \"PIZZA\",\"rpcport\": 11116},{\"coin\": \"BEER\",\"asset\": \"BEER\",\"rpcport\": 8923}, {\"coin\":\"GRS\",\"name\":\"groestlcoin\",\"rpcport\":1441,\"pubtype\":36,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"XMCC\",\"name\":\"monoeci\",\"confpath\":\"${HOME#}/.monoeciCore/monoeci.conf\",\"rpcport\":24156,\"pubtype\":50,\"p2shtype\":73,\"wiftype\":77,\"txfee\":10000}, {\"coin\":\"BTCH\",\"asset\":\"BTCH\",\"rpcport\":8800},{\"coin\":\"ETOMIC\",\"asset\":\"ETOMIC\",\"rpcport\":10271},{\"coin\":\"AXO\",\"asset\":\"AXO\",\"rpcport\":12927},{\"coin\":\"CRC\",\"name\":\"crowdcoin\",\"confpath\":\"${HOME#}/.crowdcoincore/crowdcoin.conf\",\"rpcport\":11998,\"pubtype\":28,\"p2shtype\":88,\"wiftype\":0,\"txfee\":10000}, {\"coin\":\"VOT\",\"name\":\"votecoin\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"INN\",\"name\":\"innova\",\"confpath\":\"${HOME#}/.innovacore/innova.conf\",\"rpcport\":8818,\"pubtype\":102,\"p2shtype\":20,\"wiftype\":195,\"txfee\":10000}, {\"coin\":\"MOON\",\"name\":\"mooncoin\",\"rpcport\":44663,\"pubtype\":3,\"p2shtype\":22,\"wiftype\":131,\"txfee\":100000}, {\"coin\":\"CRW\",\"name\":\"crown\",\"rpcport\":9341,\"pubtype\":0,\"p2shtype\":28,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"EFL\",\"name\":\"egulden\",\"confpath\":\"${HOME#}/.egulden/coin.conf\",\"rpcport\":21015,\"pubtype\":48,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"GBX\",\"name\":\"gobyte\",\"confpath\":\"${HOME#}/.gobytecore/gobyte.conf\",\"rpcport\":12454,\"pubtype\":38,\"p2shtype\":10,\"wiftype\":198,\"txfee\":10000}, {\"coin\":\"BCO\",\"name\":\"bridgecoin\",\"rpcport\":6332,\"pubtype\":27,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BLK\",\"name\":\"blackcoin\",\"confpath\":\"${HOME#}/.lore/blackcoin.conf\",\"isPoS\":1,\"rpcport\":15715,\"pubtype\":25,\"p2shtype\":85,\"wiftype\":153,\"txfee\":100000}, {\"coin\":\"BTG\",\"name\":\"bitcoingold\",\"rpcport\":8332,\"pubtype\":38,\"p2shtype\":23,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BCH\",\"name\":\"bch\",\"rpcport\":33333,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"ABY\",\"name\":\"applebyte\",\"rpcport\":8607,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":100000}, {\"coin\":\"STAK\",\"name\":\"straks\",\"rpcport\":7574,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"XZC\",\"name\":\"zcoin\",\"rpcport\":8888,\"pubtype\":82,\"p2shtype\":7,\"wiftype\":210,\"txfee\":10000}, {\"coin\":\"QTUM\",\"name\":\"qtum\",\"rpcport\":3889,\"pubtype\":58,\"p2shtype\":50,\"wiftype\":128,\"txfee\":400000}, {\"coin\":\"PURA\",\"name\":\"pura\",\"rpcport\":55555,\"pubtype\":55,\"p2shtype\":16,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"DSR\",\"name\":\"desire\",\"confpath\":\"${HOME#}/.desirecore/desire.conf\",\"rpcport\":9918,\"pubtype\":30,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"MNZ\",\"asset\":\"MNZ\",\"rpcport\":14337},{\"coin\":\"BTCZ\",\"name\":\"bitcoinz\",\"rpcport\":1979,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"MAGA\",\"name\":\"magacoin\",\"rpcport\":5332,\"pubtype\":23,\"p2shtype\":50,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"BSD\",\"name\":\"bitsend\",\"rpcport\":8800,\"pubtype\":102,\"p2shtype\":5,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"IOP\",\"name\":\"IoP\",\"rpcport\":8337,\"pubtype\":117,\"p2shtype\":174,\"wiftype\":49,\"txfee\":10000}, {\"coin\":\"BLOCK\",\"name\":\"blocknetdx\",\"rpcport\":41414,\"pubtype\":26,\"p2shtype\":28,\"wiftype\":154,\"txfee\":10000}, {\"coin\":\"CHIPS\", \"name\": \"chips\", \"rpcport\":57776,\"pubtype\":60, \"p2shtype\":85, \"wiftype\":188, \"txfee\":10000}, {\"coin\":\"888\",\"name\":\"octocoin\",\"rpcport\":22888,\"pubtype\":18,\"p2shtype\":5,\"wiftype\":176,\"txfee\":2000000}, {\"coin\":\"ARG\",\"name\":\"argentum\",\"rpcport\":13581,\"pubtype\":23,\"p2shtype\":5,\"wiftype\":151,\"txfee\":50000}, {\"coin\":\"GLT\",\"name\":\"globaltoken\",\"rpcport\":9320,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":166,\"txfee\":10000}, {\"coin\":\"ZER\",\"name\":\"zero\",\"rpcport\":23801,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"HODLC\",\"name\":\"hodlcoin\",\"rpcport\":11989,\"pubtype\":40,\"p2shtype\":5,\"wiftype\":168,\"txfee\":5000}, {\"coin\":\"UIS\",\"name\":\"unitus\",\"rpcport\":50604,\"pubtype\":68,\"p2shtype\":10,\"wiftype\":132,\"txfee\":2000000}, {\"coin\":\"HUC\",\"name\":\"huntercoin\",\"rpcport\":8399,\"pubtype\":40,\"p2shtype\":13,\"wiftype\":168,\"txfee\":100000}, {\"coin\":\"BDL\",\"name\":\"bitdeal\",\"rpcport\":9332,\"pubtype\":38,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"ARC\",\"name\":\"arcticcoin\",\"confpath\":\"${HOME#}/.arcticcore/arcticcoin.conf\",\"rpcport\":7208,\"pubtype\":23,\"p2shtype\":8,\"wiftype\":176,\"txfee\":10000}, {\"coin\":\"ZCL\",\"name\":\"zclassic\",\"rpcport\":8023,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000}, {\"coin\":\"VIA\",\"name\":\"viacoin\",\"rpcport\":5222,\"pubtype\":71,\"p2shtype\":33,\"wiftype\":199,\"txfee\":100000}, {\"coin\":\"ERC\",\"name\":\"europecoin\",\"rpcport\":11989,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":168,\"txfee\":10000},{\"coin\":\"FAIR\",\"name\":\"faircoin\",\"confpath\":\"${HOME#}/.faircoin2/faircoin.conf\",\"rpcport\":40405,\"pubtype\":95,\"p2shtype\":36,\"wiftype\":223,\"txfee\":1000000}, {\"coin\":\"FLO\",\"name\":\"florincoin\",\"rpcport\":7313,\"pubtype\":35,\"p2shtype\":8,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"SXC\",\"name\":\"sexcoin\",\"rpcport\":9561,\"pubtype\":62,\"p2shtype\":5,\"wiftype\":190,\"txfee\":100000}, {\"coin\":\"CREA\",\"name\":\"creativecoin\",\"rpcport\":17711,\"pubtype\":28,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000}, {\"coin\":\"TRC\",\"name\":\"terracoin\",\"confpath\":\"${HOME#}/.terracoincore/terracoin.conf\",\"rpcport\":13332,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"BTA\",\"name\":\"bata\",\"rpcport\":5493,\"pubtype\":25,\"p2shtype\":5,\"wiftype\":188,\"txfee\":100000}, {\"coin\":\"SMC\",\"name\":\"smartcoin\",\"rpcport\":58583,\"pubtype\":63,\"p2shtype\":5,\"wiftype\":191,\"txfee\":1000000}, {\"coin\":\"NMC\",\"name\":\"namecoin\",\"rpcport\":8336,\"pubtype\":52,\"p2shtype\":13,\"wiftype\":180,\"txfee\":100000}, {\"coin\":\"NAV\",\"name\":\"navcoin\",\"isPoS\":1,\"confpath\":\"${HOME#}/.navcoin4/navcoin.conf\",\"rpcport\":44444,\"pubtype\":53,\"p2shtype\":85,\"wiftype\":150,\"txfee\":10000}, {\"coin\":\"EMC2\",\"name\":\"einsteinium\",\"rpcport\":41879,\"pubtype\":33,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"SYS\",\"name\":\"syscoin\",\"rpcport\":8370,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"I0C\",\"name\":\"i0coin\",\"rpcport\":7332,\"pubtype\":105,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"DASH\",\"confpath\":\"${HOME#}/.dashcore/dash.conf\",\"name\":\"dashcore\",\"rpcport\":9998,\"pubtype\":76,\"p2shtype\":16,\"wiftype\":204,\"txfee\":10000}, {\"coin\":\"STRAT\", \"name\": \"stratis\", \"active\":0, \"rpcport\":16174,\"pubtype\":63, \"p2shtype\":125, \"wiftype\":191, \"txfee\":10000}, {\"confpath\":\"${HOME#}/.muecore/mue.conf\",\"coin\":\"MUE\",\"name\":\"muecore\",\"rpcport\":29683,\"pubtype\":16,\"p2shtype\":76,\"wiftype\":126,\"txfee\":10000}, {\"coin\":\"MONA\",\"name\":\"monacoin\",\"rpcport\":9402,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":176,\"txfee\":100000},{\"coin\":\"XMY\",\"name\":\"myriadcoin\",\"rpcport\":10889,\"pubtype\":50,\"p2shtype\":9,\"wiftype\":178,\"txfee\":5000}, {\"coin\":\"MAC\",\"name\":\"machinecoin\",\"rpcport\":40332,\"pubtype\":50,\"p2shtype\":5,\"wiftype\":178,\"txfee\":100000}, {\"coin\":\"BTX\",\"name\":\"bitcore\",\"rpcport\":8556,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":50000}, {\"coin\":\"XRE\",\"name\":\"revolvercoin\",\"rpcport\":8775,\"pubtype\":0,\"p2shtype\":5,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"LBC\",\"name\":\"lbrycrd\",\"rpcport\":9245,\"pubtype\":85,\"p2shtype\":122,\"wiftype\":28,\"txfee\":10000}, {\"coin\":\"SIB\",\"name\":\"sibcoin\",\"rpcport\":1944,\"pubtype\":63,\"p2shtype\":40,\"wiftype\":128,\"txfee\":10000}, {\"coin\":\"VTC\", \"name\":\"vertcoin\", \"rpcport\":5888, \"pubtype\":71, \"p2shtype\":5, \"wiftype\":128, \"txfee\":100000 }, {\"coin\":\"REVS\",\"active\":0, \"asset\":\"REVS\",\"rpcport\":10196}, {\"coin\":\"JUMBLR\",\"active\":0, \"asset\":\"JUMBLR\",\"rpcport\":15106}, {\"coin\":\"DOGE\",\"name\":\"dogecoin\",\"rpcport\":22555,\"pubtype\":30,\"p2shtype\":22,\"wiftype\":158,\"txfee\":100000000}, {\"coin\":\"HUSH\",\"name\":\"hush\",\"rpcport\":8822,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":1000 }, {\"active\":0,\"coin\":\"ZEC\",\"name\":\"zcash\",\"rpcport\":8232,\"taddr\":28,\"pubtype\":184,\"p2shtype\":189,\"wiftype\":128,\"txfee\":10000 }, {\"coin\":\"DGB\",\"name\":\"digibyte\",\"rpcport\":14022,\"pubtype\":30,\"p2shtype\":5,\"wiftype\":128,\"txfee\":100000}, {\"coin\":\"ZET\", \"name\":\"zetacoin\", \"pubtype\":80, \"p2shtype\":9,\"rpcport\":8332, \"wiftype\":224, \"txfee\":10000}, {\"coin\":\"GAME\", \"rpcport\":40001, \"name\":\"gamecredits\", \"pubtype\":38, \"p2shtype\":5, \"wiftype\":166, \"txfee\":100000}, {\"coin\":\"LTC\", \"name\":\"litecoin\", \"rpcport\":9332, \"pubtype\":48, \"p2shtype\":5, \"wiftype\":176, \"txfee\":100000 }, {\"coin\":\"SUPERNET\",\"asset\":\"SUPERNET\",\"rpcport\":11341}, {\"coin\":\"WLC\",\"asset\":\"WLC\",\"rpcport\":12167}, {\"coin\":\"PANGEA\",\"asset\":\"PANGEA\",\"rpcport\":14068}, {\"coin\":\"DEX\",\"asset\":\"DEX\",\"rpcport\":11890}, {\"coin\":\"BET\",\"asset\":\"BET\",\"rpcport\":14250}, {\"coin\":\"CRYPTO\",\"asset\":\"CRYPTO\",\"rpcport\":8516}, {\"coin\":\"HODL\",\"asset\":\"HODL\",\"rpcport\":14431}, {\"coin\":\"MSHARK\",\"asset\":\"MSHARK\",\"rpcport\":8846}, {\"coin\":\"BOTS\",\"asset\":\"BOTS\",\"rpcport\":11964}, {\"coin\":\"MGW\",\"asset\":\"MGW\",\"rpcport\":12386}, {\"coin\":\"COQUI\",\"asset\":\"COQUI\",\"rpcport\":14276}, {\"coin\":\"KV\",\"asset\":\"KV\",\"rpcport\":8299}, {\"coin\":\"CEAL\",\"asset\":\"CEAL\",\"rpcport\":11116}, {\"coin\":\"MESH\",\"asset\":\"MESH\",\"rpcport\":9455}]" #{\"coin\":\"CMM\",\"name\":\"commercium\",\"rpcport\":9657,\"pubtype\":28,\"p2shtype\":50,\"wiftype\":140,\"txfee\":10000}, diff --git a/iguana/exchanges/etomicswap/etomiccurl.c b/iguana/exchanges/etomicswap/etomiccurl.c index e7f1296ee..a547111e0 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.c +++ b/iguana/exchanges/etomicswap/etomiccurl.c @@ -1,7 +1,6 @@ #include "etomiccurl.h" #include -static char *ethRpcUrl = ETOMIC_URL; pthread_mutex_t sendTxMutex = PTHREAD_MUTEX_INITIALIZER; struct string { @@ -36,16 +35,15 @@ size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) cJSON *parseEthRpcResponse(char *requestResult) { - printf("Trying to parse ETH RPC response: %s\n", requestResult); cJSON *json = cJSON_Parse(requestResult); if (json == NULL) { - printf("ETH RPC response parse failed!\n"); + printf("ETH RPC response parse failed: %s!\n", requestResult); return NULL; } cJSON *tmp = cJSON_GetObjectItem(json, "result"); cJSON *error = cJSON_GetObjectItem(json, "error"); cJSON *result = NULL; - if (!is_cJSON_Null(tmp)) { + if (tmp != NULL && !is_cJSON_Null(tmp)) { result = cJSON_Duplicate(tmp, 1); } else if (error != NULL && !is_cJSON_Null(error)) { char *errorString = cJSON_PrintUnformatted(error); @@ -56,7 +54,7 @@ cJSON *parseEthRpcResponse(char *requestResult) return result; } -char* sendRequest(char* request) +char* sendRequest(char *request, char *url) { CURL *curl; CURLcode res; @@ -72,13 +70,15 @@ char* sendRequest(char* request) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); - curl_easy_setopt(curl, CURLOPT_URL, ethRpcUrl); + curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + curl_easy_cleanup(curl); + return NULL; } /* always cleanup */ @@ -98,7 +98,7 @@ cJSON *sendRpcRequest(char *method, cJSON *params) cJSON_AddItemToObject(request, "params", cJSON_Duplicate(params, 1)); cJSON_AddNumberToObject(request, "id", 1); string = cJSON_PrintUnformatted(request); - char* requestResult = sendRequest(string); + char* requestResult = sendRequest(string, ETOMIC_URL); free(string); cJSON_Delete(request); cJSON *result = parseEthRpcResponse(requestResult); @@ -151,8 +151,8 @@ char* sendRawTx(char* rawTx) int64_t getNonce(char* address) { - // we should lock this mutex and unlock it only when transaction was already sent. - // make sure that sendRawTx is called after getting a nonce! + // we should lock this mutex and unlock it only when transaction was already sent or failed. + // make sure that sendRawTx or unlock_send_tx_mutex is called after getting a nonce! if (pthread_mutex_lock(&sendTxMutex) != 0) { printf("Nonce mutex lock failed\n"); }; @@ -186,7 +186,7 @@ char* getEthBalanceRequest(char* address) return balance; } -char* ethCall(char* to, const char* data) +char *ethCall(char *to, const char *data) { cJSON *params = cJSON_CreateArray(); cJSON *txObject = cJSON_CreateObject(); @@ -196,7 +196,7 @@ char* ethCall(char* to, const char* data) cJSON_AddItemToArray(params, cJSON_CreateString("latest")); cJSON *resultJson = sendRpcRequest("eth_call", params); cJSON_Delete(params); - char* result = NULL; + char *result = NULL; if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) { result = (char *) malloc(strlen(resultJson->valuestring) + 1); strcpy(result, resultJson->valuestring); @@ -205,6 +205,26 @@ char* ethCall(char* to, const char* data) return result; } +uint64_t estimateGas(char *from, char *to, const char *data) +{ + cJSON *params = cJSON_CreateArray(); + cJSON *txObject = cJSON_CreateObject(); + cJSON_AddStringToObject(txObject, "from", from); + cJSON_AddStringToObject(txObject, "to", to); + cJSON_AddStringToObject(txObject, "data", data); + cJSON_AddItemToArray(params, txObject); + cJSON_AddItemToArray(params, cJSON_CreateString("latest")); + cJSON *resultJson = sendRpcRequest("eth_estimateGas", params); + cJSON_Delete(params); + uint64_t result = 0; + if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) { + result = (uint64_t)strtoul(resultJson->valuestring, NULL, 0); + result = (result / 100) * 120; // add 20% because real gas usage might differ from estimate + } + cJSON_Delete(resultJson); + return result; +} + EthTxReceipt getEthTxReceipt(char *txId) { EthTxReceipt result; @@ -265,7 +285,7 @@ EthTxData getEthTxData(char *txId) return result; } -uint64_t getGasPriceFromStation() +uint64_t getGasPriceFromStation(uint8_t defaultOnErr) { CURL *curl; CURLcode res; @@ -283,6 +303,12 @@ uint64_t getGasPriceFromStation() curl_easy_setopt(curl, CURLOPT_URL, "https://ethgasstation.info/json/ethgasAPI.json"); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); + uint64_t result; + if (defaultOnErr == 1) { + result = DEFAULT_GAS_PRICE; + } else { + result = 0; + } /* Check for errors */ if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); @@ -292,9 +318,9 @@ uint64_t getGasPriceFromStation() /* always cleanup */ curl_easy_cleanup(curl); cJSON *resultJson = cJSON_Parse(s.ptr); - uint64_t result = DEFAULT_GAS_PRICE; free(s.ptr); if (resultJson == NULL) { + printf("Could not parse gas station response!\n"); return result; } @@ -342,3 +368,40 @@ int32_t waitForConfirmation(char *txId) return((int32_t)receipt.confirmations); } + +void unlock_send_tx_mutex() +{ + pthread_mutex_unlock(&sendTxMutex); +} + +uint8_t get_etomic_from_faucet(char *etomic_addr) +{ + char* string; + cJSON *request = cJSON_CreateObject(); + cJSON_AddStringToObject(request, "etomicAddress", etomic_addr); + string = cJSON_PrintUnformatted(request); + char* requestResult = sendRequest(string, FAUCET_URL); + free(string); + cJSON_Delete(request); + + if (requestResult == NULL) { + return 0; + } + + cJSON *json = cJSON_Parse(requestResult); + if (json == NULL) { + printf("ETOMIC faucet response parse failed!\n"); + return 0; + } + cJSON *error = cJSON_GetObjectItem(json, "error"); + uint8_t result = 0; + if (error != NULL && !is_cJSON_Null(error)) { + char *errorString = cJSON_PrintUnformatted(error); + printf("Got ETOMIC faucet error: %s\n", errorString); + free(errorString); + } else { + result = 1; + } + cJSON_Delete(json); + return result; +} diff --git a/iguana/exchanges/etomicswap/etomiccurl.h b/iguana/exchanges/etomicswap/etomiccurl.h index c0433bc75..2b765b150 100644 --- a/iguana/exchanges/etomicswap/etomiccurl.h +++ b/iguana/exchanges/etomicswap/etomiccurl.h @@ -16,9 +16,11 @@ extern "C"{ #define DEFAULT_GAS_PRICE 100 #else #define ETOMIC_URL "http://195.201.0.6:8555" -#define DEFAULT_GAS_PRICE 4 +#define DEFAULT_GAS_PRICE 10 #endif +#define FAUCET_URL "http://195.201.116.176:8000/getEtomic" + typedef struct { uint64_t blockNumber; @@ -39,13 +41,16 @@ typedef struct char* sendRawTx(char* rawTx); char* sendRawTxWaitConfirm(char* rawTx); char* ethCall(char* to, const char* data); +uint64_t estimateGas(char *from, char *to, const char *data); int64_t getNonce(char* address); char* getEthBalanceRequest(char* address); EthTxReceipt getEthTxReceipt(char *txId); EthTxData getEthTxData(char *txId); uint64_t getEthBlockNumber(); -uint64_t getGasPriceFromStation(); +uint64_t getGasPriceFromStation(uint8_t defaultOnErr); int32_t waitForConfirmation(char *txId); +void unlock_send_tx_mutex(); +uint8_t get_etomic_from_faucet(char *etomic_addr); #ifdef __cplusplus } diff --git a/iguana/exchanges/etomicswap/etomiclib.cpp b/iguana/exchanges/etomicswap/etomiclib.cpp index 204848477..f80ba22f4 100644 --- a/iguana/exchanges/etomicswap/etomiclib.cpp +++ b/iguana/exchanges/etomicswap/etomiclib.cpp @@ -4,6 +4,7 @@ #include "etomiclib.h" #include "etomiccurl.h" #include +#include #include #include #include @@ -27,18 +28,18 @@ TransactionSkeleton txDataToSkeleton(BasicTxData txData) tx.to = jsToAddress(txData.to); tx.value = jsToU256(txData.amount); tx.gas = 200000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + tx.gasPrice = getGasPriceFromStation(1) * boost::multiprecision::pow(u256(10), 9); tx.nonce = getNonce(txData.from); return tx; } char *signTx(TransactionSkeleton& tx, char* secret) { - Secret& secretKey = *(new Secret(secret)); - auto baseTx = new TransactionBase(tx, secretKey); - RLPStream& rlpStream = *(new RLPStream()); - baseTx->streamRLP(rlpStream); - std::stringstream& ss = *(new std::stringstream); + Secret secretKey(secret); + TransactionBase baseTx(tx, secretKey); + RLPStream rlpStream; + baseTx.streamRLP(rlpStream); + std::stringstream ss; ss << rlpStream.out(); return stringStreamToChar(ss); } @@ -50,7 +51,7 @@ char *approveErc20(ApproveErc20Input input) tx.to = jsToAddress(input.tokenAddress); tx.value = 0; tx.gas = 300000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); + tx.gasPrice = getGasPriceFromStation(1) * boost::multiprecision::pow(u256(10), 9); tx.nonce = getNonce(input.owner); std::stringstream ss; ss << "0x095ea7b3" @@ -101,7 +102,12 @@ uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data) std::stringstream aliceSendsErc20PaymentData(AliceSendsErc20PaymentInput input) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } u256 amount = jsToU256(input.amount); if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); @@ -148,12 +154,20 @@ char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxDat std::stringstream ss; u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); + if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } } + ss << "0x8b9a167a" << toHex(jsToBytes(input.dealId)) << toHex(toBigEndian(amount)) @@ -179,12 +193,20 @@ char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData std::stringstream ss; u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); + if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } } + ss << "0x392ec66b" << toHex(jsToBytes(input.dealId)) << toHex(toBigEndian(amount)) @@ -241,7 +263,13 @@ uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data) std::stringstream bobSendsErc20DepositData(BobSendsErc20DepositInput input) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + u256 amount = jsToU256(input.amount); u256 lockTime = input.lockTime; if (decimals < 18) { @@ -289,7 +317,13 @@ char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData) u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -316,7 +350,13 @@ char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -374,9 +414,15 @@ uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data) std::stringstream bobSendsErc20PaymentData(BobSendsErc20PaymentInput input) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); u256 amount = jsToU256(input.amount); u256 lockTime = input.lockTime; + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -422,7 +468,13 @@ char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -450,7 +502,13 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData u256 amount = jsToU256(input.amount); dev::Address tokenAddress = jsToAddress(input.tokenAddress); if (tokenAddress != ZeroAddress) { - uint8_t decimals = getErc20Decimals(input.tokenAddress); + uint8_t decimals; + if (input.decimals > 0) { + decimals = input.decimals; + } else { + decimals = getErc20Decimals(input.tokenAddress); + } + if (decimals < 18) { amount /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -472,54 +530,69 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData char* privKey2Addr(char* privKey) { - Secret& secretKey = *(new Secret(privKey)); - std::stringstream& ss = *(new std::stringstream); + Secret secretKey(privKey); + std::stringstream ss; ss << "0x" << toAddress(secretKey); return stringStreamToChar(ss); }; char* pubKey2Addr(char* pubKey) { - Public& publicKey = *(new Public(pubKey)); - std::stringstream& ss = *(new std::stringstream); + Public publicKey(pubKey); + std::stringstream ss; ss << "0x" << toAddress(publicKey); return stringStreamToChar(ss); }; -char* getPubKeyFromPriv(char* privKey) +char* getPubKeyFromPriv(char *privKey) { - Public publicKey = toPublic(*(new Secret(privKey))); - std::stringstream& ss = *(new std::stringstream); + Public publicKey = toPublic(Secret(privKey)); + std::stringstream ss; ss << "0x" << publicKey; return stringStreamToChar(ss); } -uint64_t getEthBalance(char* address) +uint64_t getEthBalance(char *address, int *error) { char* hexBalance = getEthBalanceRequest(address); - // convert wei to satoshi - u256 balance = jsToU256(hexBalance) / boost::multiprecision::pow(u256(10), 10); - free(hexBalance); - return static_cast(balance); + if (hexBalance != NULL) { + // convert wei to satoshi + u256 balance = jsToU256(hexBalance) / boost::multiprecision::pow(u256(10), 10); + free(hexBalance); + return static_cast(balance); + } else { + *error = 1; + return 0; + } } -uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress) +uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress, uint8_t setDecimals, int *error) { std::stringstream ss; ss << "0x70a08231" << "000000000000000000000000" << toHex(jsToAddress(address)); - std::stringstream& resultStream = *(new std::stringstream); char* hexBalance = ethCall(tokenAddress, ss.str().c_str()); // convert wei to satoshi - uint8_t decimals = getErc20Decimals(tokenAddress); - u256 balance = jsToU256(hexBalance); - if (decimals < 18) { - balance *= boost::multiprecision::pow(u256(10), 18 - decimals); + uint8_t decimals; + if (hexBalance != NULL) { + if (setDecimals > 0) { + decimals = setDecimals; + } else { + decimals = getErc20Decimals(tokenAddress); + } + + u256 balance = jsToU256(hexBalance); + if (decimals < 18) { + balance *= boost::multiprecision::pow(u256(10), 18 - decimals); + } + balance /= boost::multiprecision::pow(u256(10), 10); + free(hexBalance); + return static_cast(balance); + } else { + *error = 1; + return 0; } - balance /= boost::multiprecision::pow(u256(10), 10); - free(hexBalance); - return static_cast(balance); } char *getErc20BalanceHexWei(char *address, char *tokenAddress) @@ -532,7 +605,7 @@ char *getErc20BalanceHexWei(char *address, char *tokenAddress) return hexBalance; } -uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress) +uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress, uint8_t set_decimals) { std::stringstream ss; ss << "0xdd62ed3e" @@ -541,7 +614,12 @@ uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress) << "000000000000000000000000" << toHex(jsToAddress(spender)); char* hexAllowance = ethCall(tokenAddress, ss.str().c_str()); - uint8_t decimals = getErc20Decimals(tokenAddress); + uint8_t decimals; + if (set_decimals > 0) { + decimals = set_decimals; + } else { + decimals = getErc20Decimals(tokenAddress); + } u256 allowance = jsToU256(hexAllowance); if (decimals < 18) { allowance *= boost::multiprecision::pow(u256(10), 18 - decimals); @@ -560,6 +638,18 @@ uint8_t getErc20Decimals(char *tokenAddress) return decimals; } +uint8_t getErc20DecimalsZeroOnError(char *tokenAddress) +{ + char* hexDecimals = ethCall(tokenAddress, "0x313ce567"); + if (hexDecimals != NULL) { + auto decimals = (uint8_t) strtol(hexDecimals, NULL, 0); + free(hexDecimals); + return decimals; + } else { + return 0; + } +} + void uint8arrayToHex(char *dest, uint8_t *input, int len) { strcpy(dest, "0x"); @@ -582,17 +672,30 @@ uint64_t weiToSatoshi(char *wei) return static_cast(satoshi); } -char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm) +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice, uint8_t defaultGasOnErr) { TransactionSkeleton tx; char *from = privKey2Addr(privKey), *result; tx.from = jsToAddress(from); tx.to = jsToAddress(to); tx.value = jsToU256(amount); - tx.gas = 21000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); tx.nonce = getNonce(from); free(from); + if (gas > 0) { + tx.gas = gas; + } else { + tx.gas = 21000; + } + if (gasPrice > 0) { + tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9); + } else { + tx.gasPrice = getGasPriceFromStation(defaultGasOnErr) * boost::multiprecision::pow(u256(10), 9); + if (tx.gasPrice == 0 && !defaultGasOnErr) { + printf("Could not get gas price from station!\n"); + unlock_send_tx_mutex(); + return NULL; + } + } char *rawTx = signTx(tx, privKey); if (waitConfirm == 0) { @@ -604,10 +707,15 @@ char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm) return result; } -std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amount) +std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amount, uint8_t setDecimals) { u256 amountWei = jsToU256(amount); - uint8_t decimals = getErc20Decimals(tokenAddress); + uint8_t decimals; + if (setDecimals > 0) { + decimals = setDecimals; + } else { + decimals = getErc20Decimals(tokenAddress); + } if (decimals < 18) { amountWei /= boost::multiprecision::pow(u256(10), 18 - decimals); } @@ -620,19 +728,64 @@ std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amoun return ss; } -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm) +uint64_t estimate_erc20_gas( + char *tokenAddress, + char *to, + char *amount, + char *privKey, + uint8_t decimals +) +{ + std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals); + char *from = privKey2Addr(privKey); + uint64_t result = estimateGas(from, tokenAddress, ss.str().c_str()); + free(from); + return result; +} + +char *sendErc20( + char *tokenAddress, + char *to, + char *amount, + char *privKey, + uint8_t waitConfirm, + int64_t gas, + int64_t gasPrice, + uint8_t defaultGasOnErr, + uint8_t decimals +) { TransactionSkeleton tx; char *from = privKey2Addr(privKey), *result; + std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals); + tx.from = jsToAddress(from); tx.to = jsToAddress(tokenAddress); tx.value = 0; - tx.gas = 60000; - tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9); tx.nonce = getNonce(from); + + if (gas > 0) { + tx.gas = gas; + } else { + uint64_t gasEstimation = estimateGas(from, tokenAddress, ss.str().c_str()); + if (gasEstimation > 0) { + tx.gas = gasEstimation; + } else { + tx.gas = 150000; + } + } free(from); + if (gasPrice > 0) { + tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9); + } else { + tx.gasPrice = getGasPriceFromStation(defaultGasOnErr) * boost::multiprecision::pow(u256(10), 9); + if (tx.gasPrice == 0 && !defaultGasOnErr) { + printf("Could not get gas price from station!\n"); + unlock_send_tx_mutex(); + return NULL; + } + } - std::stringstream ss = getErc20TransferData(tokenAddress, to, amount); tx.data = jsToBytes(ss.str()); char *rawTx = signTx(tx, privKey); @@ -645,12 +798,61 @@ char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8 return result; } -uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data) +uint8_t verifyAliceErc20FeeData(char *tokenAddress, char *to, char *amount, char *data, uint8_t decimals) { - std::stringstream ss = getErc20TransferData(tokenAddress, to, amount); + std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals); if (strcmp(ss.str().c_str(), data) != 0) { printf("Alice ERC20 fee data %s is not equal to expected %s\n", data, ss.str().c_str()); return 0; } return 1; } + +uint8_t alicePaymentStatus(char *paymentId) +{ + char buffer[100]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, "0x81cd872a"); + strcat(buffer, paymentId); + char *hexStatus = ethCall(ETOMIC_ALICECONTRACT, buffer); + auto status = (uint8_t) strtol(hexStatus + 66, NULL, 0); + free(hexStatus); + return status; +} + +uint8_t bobDepositStatus(char *depositId) +{ + char buffer[100]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, "0x3d4dff7b"); + strcat(buffer, depositId); + char *hexStatus = ethCall(ETOMIC_BOBCONTRACT, buffer); + auto status = (uint8_t) strtol(hexStatus + 130, NULL, 0); + free(hexStatus); + return status; +} + +uint8_t bobPaymentStatus(char *paymentId) +{ + char buffer[100]; + memset(buffer, 0, sizeof(buffer)); + strcpy(buffer, "0x0716326d"); + strcat(buffer, paymentId); + char *hexStatus = ethCall(ETOMIC_BOBCONTRACT, buffer); + auto status = (uint8_t) strtol(hexStatus + 130, NULL, 0); + free(hexStatus); + return status; +} + +uint8_t compareAddresses(char *address1, char *address2) +{ + auto addr_bytes_1 = jsToAddress(address1); + auto addr_bytes_2 = jsToAddress(address2); + return static_cast(addr_bytes_1 == addr_bytes_2); +} + +uint8_t isValidAddress(char *address) +{ + std::regex r("^(0x|0X)?[a-fA-F0-9]{40}$"); + return static_cast(std::regex_match(address, r)); +} diff --git a/iguana/exchanges/etomicswap/etomiclib.h b/iguana/exchanges/etomicswap/etomiclib.h index c7b846ddb..6075124a5 100644 --- a/iguana/exchanges/etomicswap/etomiclib.h +++ b/iguana/exchanges/etomicswap/etomiclib.h @@ -38,6 +38,7 @@ typedef struct { char bobAddress[65]; char aliceHash[65]; char bobHash[65]; + uint8_t decimals; } AliceSendsErc20PaymentInput; typedef struct { @@ -47,6 +48,7 @@ typedef struct { char bobAddress[65]; char aliceHash[65]; char bobSecret[70]; + uint8_t decimals; } AliceReclaimsAlicePaymentInput; typedef struct { @@ -56,6 +58,7 @@ typedef struct { char aliceAddress[65]; char aliceSecret[70]; char bobHash[65]; + uint8_t decimals; } BobSpendsAlicePaymentInput; typedef struct { @@ -72,6 +75,7 @@ typedef struct { char aliceAddress[65]; char bobHash[65]; uint64_t lockTime; + uint8_t decimals; } BobSendsErc20DepositInput; typedef struct { @@ -80,6 +84,7 @@ typedef struct { char tokenAddress[65]; char aliceAddress[65]; char bobSecret[70]; + uint8_t decimals; } BobRefundsDepositInput; typedef struct { @@ -88,6 +93,7 @@ typedef struct { char tokenAddress[65]; char bobAddress[65]; char bobHash[65]; + uint8_t decimals; } AliceClaimsBobDepositInput; typedef struct { @@ -104,6 +110,7 @@ typedef struct { char aliceAddress[65]; char aliceHash[65]; uint64_t lockTime; + uint8_t decimals; } BobSendsErc20PaymentInput; typedef struct { @@ -112,6 +119,7 @@ typedef struct { char tokenAddress[65]; char aliceAddress[65]; char aliceHash[65]; + uint8_t decimals; } BobReclaimsBobPaymentInput; typedef struct { @@ -120,6 +128,7 @@ typedef struct { char tokenAddress[65]; char aliceSecret[70]; char bobAddress[65]; + uint8_t decimals; } AliceSpendsBobPaymentInput; typedef struct { @@ -164,24 +173,50 @@ char* pubKey2Addr(char* pubKey); char* getPubKeyFromPriv(char* privKey); // returns satoshis, not wei! -uint64_t getEthBalance(char* address); -uint64_t getErc20BalanceSatoshi(char* address, char tokenAddress[65]); +uint64_t getEthBalance(char* address, int *error); +uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress, uint8_t setDecimals, int *error); char *getErc20BalanceHexWei(char* address, char tokenAddress[65]); uint8_t getErc20Decimals(char *tokenAddress); // returns satoshis, not wei! -uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress); +uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress, uint8_t set_decimals); void uint8arrayToHex(char *dest, uint8_t *input, int len); void satoshisToWei(char *dest, uint64_t input); uint64_t weiToSatoshi(char *wei); -char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm); -char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm); +char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice, uint8_t defaultGasOnErr); +char *sendErc20( + char *tokenAddress, + char *to, + char *amount, + char *privKey, + uint8_t waitConfirm, + int64_t gas, + int64_t gasPrice, + uint8_t defaultGasOnErr, + uint8_t decimals +); + +uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data, uint8_t decimals); + +uint8_t alicePaymentStatus(char *paymentId); +uint8_t bobDepositStatus(char *depositId); +uint8_t bobPaymentStatus(char *paymentId); + +uint64_t estimate_erc20_gas( + char *tokenAddress, + char *to, + char *amount, + char *privKey, + uint8_t decimals +); + +uint8_t compareAddresses(char *address1, char *address2); +uint8_t isValidAddress(char *address); +uint8_t getErc20DecimalsZeroOnError(char *tokenAddress); -uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data); -// Your prototype or Definition #ifdef __cplusplus } #endif diff --git a/iguana/exchanges/gen64addrs b/iguana/exchanges/gen64addrs new file mode 100755 index 000000000..d907807dd --- /dev/null +++ b/iguana/exchanges/gen64addrs @@ -0,0 +1,3 @@ +#!/bin/bash +source userpass +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"gen64addrs\",\"passphrase\":\"default\"}" diff --git a/iguana/exchanges/mm.c b/iguana/exchanges/mm.c index 5e17513d3..304ca6aa9 100644 --- a/iguana/exchanges/mm.c +++ b/iguana/exchanges/mm.c @@ -164,6 +164,7 @@ int main(int argc, const char * argv[]) { char dirname[512]; double incr; cJSON *retjson; OS_init(); + printf("BarterDEX Marketmaker %s \n",MM_VERSION); if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 ) { bits256 privkey,checkkey; uint8_t tmptype; char kmdwif[64],str[65],str2[65],*retstr; diff --git a/iguana/exchanges/mm2.md b/iguana/exchanges/mm2.md new file mode 100644 index 000000000..b88dfb815 --- /dev/null +++ b/iguana/exchanges/mm2.md @@ -0,0 +1,102 @@ +# Market Maker 2 + +This document will help us track the information related to the MarketMaker Rust rewrite. + +## Rewrite goals + +Rewrites and ports +[are costly](http://nibblestew.blogspot.com/2017/04/why-dont-you-just-rewrite-it-in-x.html). +We tend to think that porting is simple, and on some level this intuition is true +because we can skip some high-level design decisions and focus on translating the existing logic, +but it still takes a lot of time +and though we don't need to make some of the new design decisions, +we might spend no less effort to reverse-engineer and understand the old ones. + +So why the rewrite then? + +Carol, in her talk about rewrites, offers some possible reasons: + +"*If* you have some code in C or another language, and need to change it, or it’s slow, or it crashes a +lot, or no one understands it anymore, THEN maybe a rewrite in Rust would be a good fit. +I would also posit that more people are *able* to write production Rust than production C, so if your +team *is* willing to learn Rust, it might actually expand the number of +maintainers." - https://github.com/carols10cents/rust-out-your-c-talk, https://www.youtube.com/watch?v=SKGVItFlK3w. + +And we have some of these: + +* We *need to change* the MarketMaker: +A more approachable and reliable API. +Ability to embed the MarketMaker in the GUI applications. +Ways to more easily deploy it at home by running it from small computers like on a spare mobile phone or on a Raspberry Pi 3. +Ability to process multiple API calls in parallel. +A faster version of the `swapstatus` API call. + +* The MarketMaker *crashes a lot*, +to quote hyperDEX: "The biggest issue with the MM right now, is bobs crash or does not have the orders in users orderbook, or when users try to do a order it doesnt work or goes unmatched or other random stuff" +and lukechilds: "We've frequently experienced crashes while querying all swaps with swapstatus". +We want it to be stable and reliable instead. + +## Purely functional core + +One of our goals is to make the MarketMaker 2 more +[stable and reliable](https://softwareengineering.stackexchange.com/questions/158054/stability-vs-reliability). +We want it to crash less often. +If there was a failure, we want to simplify and preferably automate recovery. +And we want to reduce the time between a failure and a fix. + +We'll make a big step towards these goals if the core of the MarketMaker is purely functional. +That is, if we can untangle the *state* of the MarketMaker from the code operating on that state. + +The benefits we want to reap from this are: +* Transparency. Some bugs are hard to fix because we don't have enough information about them. We might be lucky to have been running the program in a debugger or finding the necessary bits it verbose logs, but more often than not this is not the case: we know that a failure has happened, but have no idea where and on what input. Separating the state from the code allows the state to be easily shared with a developer, which means much faster roundtrips between discovering a failure and fixing it. +* Replayability. Having a separate state allows us to easily replay any operation. If a failure occured in the middle of a transaction, it should be possible to try a new version of the code without manually repeating all the steps that were necessary to initiate the transaction. And the updated code will run exactly on the failing transaction, not on some other transaction initiated at a later time, which means that users will benefit from less friction and developers will have a better chance to fix the hard-to-reproduce bugs. +* Testability. Stateless code is much easier to test and according to Kent Beck is often a natural result of a Test-Driven development process. +* Portability. Separating the state from the code allows us to more easily use the stateless parts from the sandboxed environments, such as when running under the Web Assembly (WASM). We only need to port the state-managing layer, fully reusing the stateless code. +* Hot reloading. When the code is separated from state, it's trivial to reload it, both with the shared libraries in CPU-native environments (dlopen) and with WASM in GUI environments. This might positively affect the development cycle, reducing the round-trip time from a failure to a fix. +* Concurrency. MarketMaker can currently only perform a single API operation at the time. The more stateless code we have the easier it should be to introduce the parallel execution of API requests in the future. + +Implementation might consist of two layers. +A layer that is ported to the host environment (native, JS, Java, Objective-C, cross-compiled Raspberry Pi 3, etc) and implements the TCP/IP communication, state management, hot reloading, all things that won't fit into the WASM sandbox. +And a layer that implements the core logic in a stateless manner and which is compiled into a native shared library or, in the future, to WASM. + +Parts of the state might be marked as sensitive. +This will give the users an option to share only the information that can be freely shared, +without a risk of loosing money that is. +Even without the sensitive information a state snapshot might provide the developer with enough data to quickly triage and/or fix the failure, therefore improving the roundtrip time before a failure and a fix. +Plus users will more easily share their problems when it's quick, automatic and doesn't pose a monetary risk. + +The feasibility of this approach is yet to be evaluated, but we can move gradually towards it +by separating the code into the stateful and stateless layers while working on the basic Rust port. + +During the initial Rust port we're going to +a) Mark the ported functions as purely functional or stateful, allowing us to more easily focus on the state management code in the future. +b) Where possible, take a low-hanging fruit and try to refactor the functions towards being stateless. +c) Probably mark as stateful the `sleep`ing functions, because `sleep` can be seen as changing the global state (moving the time forwards) and might negatively affect Transparency (we have no idea what's going on while a function is sleeping), Testability (sleeping tests might kill the TDD development cycle), Portability (sleeps are not compatible with WASM), Hot reloading and Concurrency (let's say we want to load new version of the code, but the old version is still sleeping somewhere). + +## Gradual rewrite + +Above in the [Rewrite goals](#rewrite-goals) section we have identified some of the goals that we pursue with this rewrite. +These goals constitute the Value (in the Lean Production terms) that we are going to create. + +For a project to suceed it is usually important to make shorter the path the Value takes to the users. +(Inventory is waste. If we have created the Value but the users can't get their hands on it, we're wasting that Value). + +Hence we're going to start with a gradual rewrite. Keeping the version under rewrite immediately avaliable to the users willing to experiment with it. + +Let's list the good things that should come out of the gradual rewrite: +* Transparency. With the second version of the MarketMaker being immediately available we can always check the Value we're getting. Is it more stable? Does it have new functions? Or did we hit the wall? What's going on with the code and how can we help? Gradual rewrite is critical for transparency because the change is available in small increments. We can more easily see what function has changed or what new functionality was added when we aren't being uprooted from the familiar context. +* Risk reduction. It comes with transparency, as we can now more easily measure the progress, identify the roadblocks as they occur, see certain problems when they occur and not months after. Plus a gradual rewrite will by default follow the outline of the original project. We have a working system and we're improving it piece by piece, having the original design to fall back to. This makes it less likely for the rewrite to suffer from far-reaching redesign flaws (cf. [Second-system effect](https://en.wikipedia.org/wiki/Second-system_effect)) and creative blocks (cf. [Pantsing](https://www.wikiwrimo.org/wiki/Pantsing)). +* Feedback. Incorporating user feedback is critical for most projects out there, allowing us to iteratively improve the functionality in the right direction (cf. [Fail faster](https://www.youtube.com/watch?v=rDjrOaoHz9s), [PDIA](https://www.youtube.com/watch?v=ZKdjBbiGjao)). The more early we get the feedback, the more time we have to react, and at a lesser cost. +* Motivation. Feedback is not only important to guide us, but also to show us that our work is meaningful and changes lives to the better. It is the cornerstone of Agile (["Build projects around motivated individuals"](https://www.agilealliance.org/agile101/12-principles-behind-the-agile-manifesto/)) and affects our performance on all levels, down to the physical health. + +The plan so far is to by default use the C functions as the atomic units of rewrite. +Rust FFI allows us to swap any C function with a similar Rust function. +Porting on this level we +* reuse the function-level modularity of the C language; +* preserve the code meta-data (Git history will show a nice diff between the C and Rust functions, we'll be able to easily investigate the evolution of the code back to its roots); +* avoid the complexity and slow-downs associated with adding RPC/networking layers or drawing new lines of abstraction; +* have a good indicator of the porting progress (how many functions were ported, how many remains). + +Focusing on the function call chains that are a common part of a failure/crash or touch on the new functionality +will allow us to leverage the [Pareto principle](https://en.wikipedia.org/wiki/Pareto_principle), +advancing on 80% of desired Value (stability, functionality) with 20% of initial effort. \ No newline at end of file diff --git a/iguana/exchanges/mshark b/iguana/exchanges/mshark index 0d6260aad..fa3ae0a64 100755 --- a/iguana/exchanges/mshark +++ b/iguana/exchanges/mshark @@ -1,4 +1,4 @@ #!/bin/bash source userpass # this will only work for watchonly addresses that have been rescanned and with active coins -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":100}, {\"coin\":\"komodo\",\"balance\":100000}, {\"coin\":\"chips\",\"balance\":100000}],\"divisor\":1400000}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":25}],\"divisor\":1400000}" diff --git a/iguana/exchanges/prices/autoprice b/iguana/exchanges/prices/autoprice index d58c337e7..8092b2bb2 100755 --- a/iguana/exchanges/prices/autoprice +++ b/iguana/exchanges/prices/autoprice @@ -35,15 +35,15 @@ source trackbtc #source revs #source trackbtc -sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"komodo\",\"balance\":120000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":100}" +sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":25}" curl --url "http://127.0.0.1:7783" --data "{\"base\":\"MSHARK\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"margin\":$margin,\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[$sharkholdings],\"divisor\":1400000}" -curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":570}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":612529}" +curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":540}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}" curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"HODL\",\"rel\":\"KMD\",\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}" -dexholdings="{\"coin\":\"blocknet\",\"balance\":2500000}" +dexholdings="{\"coin\":\"blocknet\",\"balance\":2000000}" curl --url "http://127.0.0.1:7783" --data "{\"base\":\"DEX\",\"rel\":\"KMD\",\"margin\":$margin,\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf\",\"holdings\":[$dexholdings],\"divisor\":1000000}" curl --url "http://127.0.0.1:7783" --data "{\"base\":\"BOTS\",\"rel\":\"KMD\",\"margin\":$margin,\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P\",\"holdings\":[$dexholdings],\"divisor\":3333333}" diff --git a/iguana/exchanges/supernet b/iguana/exchanges/supernet index f7b09a20b..e7e11b43f 100755 --- a/iguana/exchanges/supernet +++ b/iguana/exchanges/supernet @@ -15,5 +15,5 @@ echo supernet curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\"}" echo supernet -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":570}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2350000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":612529}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":540}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2350000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}" diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index 425bc41ed..db3808263 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -535,7 +535,7 @@ STRING_ARG(iguana,addnotary,ipaddr) } char NOTARY_CURRENCIES[][65] = { - "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "VOTE2018", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL" "ZILLA" + "REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "VOTE2018", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC" }; // "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", diff --git a/iguana/m_notary b/iguana/m_notary index 9eff95e6b..c23e6f7d1 100755 --- a/iguana/m_notary +++ b/iguana/m_notary @@ -2,4 +2,4 @@ pkill -15 iguana rm -f ../agents/iguana *.o git pull -./m_notary_run $1 +./m_notary_run "$1" "$2" diff --git a/iguana/m_notary_run b/iguana/m_notary_run index fd2b90ab9..770e30e6f 100755 --- a/iguana/m_notary_run +++ b/iguana/m_notary_run @@ -8,7 +8,8 @@ clang -g -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../b clang -g -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a -lnanomsg -lcurl -lssl -lcrypto -lpthread -lz -lm -stdbuf -oL $1 ../agents/iguana notary & #> iguana.log 2> error.log & +iguana_arg=${2:-notary} +stdbuf -oL $1 ../agents/iguana $iguana_arg & #> iguana.log 2> error.log & myip=`curl -s4 checkip.amazonaws.com` source pubkey.txt @@ -25,6 +26,8 @@ curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"ad curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"138.121.203.210\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"139.99.149.41\"}" curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"209.58.169.65\"}" +curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"5.189.232.34\"}" + #tests/addnotarys_7776 coins/btc_7776 @@ -66,6 +69,7 @@ coins/eql_7776 coins/zilla_7776 coins/vrsc_7776 coins/rfox_7776 +coins/sec_7776 #curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}" diff --git a/iguana/m_splitfund b/iguana/m_splitfund index 58b80a3b7..9ac1cc6ca 100755 --- a/iguana/m_splitfund +++ b/iguana/m_splitfund @@ -36,3 +36,5 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DSEC\",\"agent\":\"iguana curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GLXT\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"EQL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}" curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZILLA\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RFOX\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}" +curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEC\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}" diff --git a/marketmaker_build_depends.cmd b/marketmaker_build_depends.cmd index a09e0ea04..6a294d20c 100644 --- a/marketmaker_build_depends.cmd +++ b/marketmaker_build_depends.cmd @@ -36,54 +36,66 @@ exit rem MSBuild /help echo. echo Decker will automatically download and build all needed *.dll and *.lib for you ;) -timeout /t 5 /nobreak mkdir marketmaker_depends mkdir x64\Release rem --- pthreads --- :compile_pthreads +if not exist marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib ( cd marketmaker_depends git clone https://github.com/DeckerSU/pthread-win32 cd pthread-win32 MSBuild pthread.2015.sln /t:Rebuild /p:Configuration=Release /p:Platform=Win32 MSBuild pthread.2015.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64 cd ../.. +) copy marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib OSlibs\win\x64\pthread_lib.lib rem --- nanomsg --- :compile_nanomsg - -cd marketmaker_depends -git clone https://github.com/nanomsg/nanomsg -cd nanomsg -mkdir build_msvc_2015_win32 -mkdir build_msvc_2015_win64 -cd build_msvc_2015_win64 -cmake -G "Visual Studio 14 2015 Win64" .. -cmake --build . --config Release --target nanomsg -cd ../../.. +if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.lib ( + if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.exp ( + if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll ( + cd marketmaker_depends + git clone https://github.com/nanomsg/nanomsg + cd nanomsg + mkdir build_msvc_2015_win32 + mkdir build_msvc_2015_win64 + cd build_msvc_2015_win64 + cmake -G "Visual Studio 14 2015 Win64" .. + cmake --build . --config Release --target nanomsg + cd ../../.. + ) + ) +) copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.lib OSlibs\win\x64\release\nanomsg.lib copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.exp OSlibs\win\x64\release\nanomsg.exp copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll x64\Release\nanomsg.dll rem --- curl --- :compile_curl -cd marketmaker_depends -git clone https://github.com/curl/curl -cd curl -mkdir build_msvc_2015_win32 -mkdir build_msvc_2015_win64 -cd build_msvc_2015_win64 -cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_USE_WINSSL:BOOL=ON .. -cmake --build . --config Release --target libcurl +if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib ( + if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.exp ( + if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll ( + cd marketmaker_depends + git clone https://github.com/curl/curl + cd curl + mkdir build_msvc_2015_win32 + mkdir build_msvc_2015_win64 + cd build_msvc_2015_win64 + cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_USE_WINSSL:BOOL=ON .. + cmake --build . --config Release --target libcurl -rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB=ON -DCURL_DISABLE_LDAP=ON -DCURL_STATIC_CRT=ON -rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB:BOOL=ON -DCURL_STATIC_CRT:BOOL=ON -DHTTP_ONLY:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=RELEASE .. -rem cmake --build . --config Release -rem cmake --build . --config Release --target libcurl + rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB=ON -DCURL_DISABLE_LDAP=ON -DCURL_STATIC_CRT=ON + rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB:BOOL=ON -DCURL_STATIC_CRT:BOOL=ON -DHTTP_ONLY:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=RELEASE .. + rem cmake --build . --config Release + rem cmake --build . --config Release --target libcurl -cd ../../.. + cd ../../.. + ) + ) +) copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib OSlibs\win\x64\release\libcurl.lib copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.exp OSlibs\win\x64\release\libcurl.exp copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll x64\Release\libcurl.dll \ No newline at end of file diff --git a/marketmaker_build_etomic.cmd b/marketmaker_build_etomic.cmd index ed76db72c..2b8f9a02d 100644 --- a/marketmaker_build_etomic.cmd +++ b/marketmaker_build_etomic.cmd @@ -7,16 +7,13 @@ copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib copy marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread.lib echo [#2] Prepare build etomic needed things ... -git submodule init git submodule update --init --recursive cd cpp-ethereum -rem git submodule init -rem git submodule update --init -call scripts\install_deps.bat +call scripts\install_deps.bat cd .. mkdir build_win64_release cd build_win64_release -cmake .. -G "Visual Studio 14 2015 Win64" +cmake .. -G "Visual Studio 14 2015 Win64" -DMM_VERSION="%APPVEYOR_BUILD_VERSION%" rem Steps before build: rem diff --git a/start_BEER_OTHER_trade.sh b/start_BEER_OTHER_trade.sh new file mode 100755 index 000000000..a81500397 --- /dev/null +++ b/start_BEER_OTHER_trade.sh @@ -0,0 +1,8 @@ +#!/bin/bash +docker-compose exec -T clientnode ./enable +sleep 3 +docker-compose exec -T seednode ./enable +sleep 3 +docker-compose exec -T seednode ./sell_BEER_OTHER $1 +sleep 3 +docker-compose exec -T clientnode ./buy_BEER_OTHER $1 \ No newline at end of file diff --git a/start_BEER_OTHER_trade_inverted.sh b/start_BEER_OTHER_trade_inverted.sh new file mode 100755 index 000000000..1b0f9d4be --- /dev/null +++ b/start_BEER_OTHER_trade_inverted.sh @@ -0,0 +1,8 @@ +#!/bin/bash +docker-compose exec -T clientnode ./enable +sleep 3 +docker-compose exec -T seednode ./enable +sleep 3 +docker-compose exec -T clientnode ./buy_BEER_OTHER $1 +sleep 3 +docker-compose exec -T seednode ./sell_BEER_OTHER $1 \ No newline at end of file diff --git a/travis_cmake_linux.sh b/travis_cmake_linux.sh new file mode 100644 index 000000000..f11b08e4d --- /dev/null +++ b/travis_cmake_linux.sh @@ -0,0 +1,5 @@ +#!/bin/bash +sudo rm -rf /usr/local/cmake-3.9.2 && sudo rm -rf /usr/local/cmake +wget https://cmake.org/files/v3.12/cmake-3.12.0-rc2-Linux-x86_64.sh +chmod +x cmake-3.12.0-rc2-Linux-x86_64.sh +sudo ./cmake-3.12.0-rc2-Linux-x86_64.sh --skip-license --exclude-subdir --prefix=/usr/local \ No newline at end of file diff --git a/travis_cmake_mac.sh b/travis_cmake_mac.sh new file mode 100644 index 000000000..f2fbadca0 --- /dev/null +++ b/travis_cmake_mac.sh @@ -0,0 +1,6 @@ +#!/bin/bash +brew uninstall cmake --force +wget https://cmake.org/files/v3.12/cmake-3.12.0-rc2-Darwin-x86_64.tar.gz +tar -xzf cmake-3.12.0-rc2-Darwin-x86_64.tar.gz +cp -r cmake-3.12.0-rc2-Darwin-x86_64/CMake.app/Contents/bin/* /usr/local/bin/ +cp -r cmake-3.12.0-rc2-Darwin-x86_64/CMake.app/Contents/share/* /usr/local/share/ \ No newline at end of file