From 8a124c64d26831501cab0a1ec1423a10d308d9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Ciemi=C4=99ga?= Date: Wed, 5 Oct 2016 22:18:01 +0200 Subject: [PATCH] Proper gradle support (#254) * Refactored to gradle structure * Excluded /build from modules * Excluded /build from modules * Fixed libs folder * Urls in README fixed --- .gitignore | 8 + .idea/compiler.xml | 22 + .idea/copyright/profiles_settings.xml | 3 + .idea/gradle.xml | 19 + .idea/misc.xml | 62 ++ .idea/modules.xml | 10 + .idea/runConfigurations.xml | 12 + .idea/vcs.xml | 6 + DataModule/.classpath | 9 - DataModule/.gitignore | 22 - DataModule/.project | 33 - .../org.eclipse.core.resources.prefs | 2 - .../.settings/org.eclipse.jdt.core.prefs | 4 - DataModule/proguard-project.txt | 20 - DataModule/project.properties | 15 - DataModuleTester/.classpath | 9 - DataModuleTester/.gitignore | 22 - DataModuleTester/.project | 33 - .../.settings/org.eclipse.jdt.core.prefs | 4 - DataModuleTester/DataModuleTester.apk | Bin 190579 -> 0 bytes DataModuleTester/libs/gson-2.2.4.jar | Bin 190418 -> 0 bytes DataModuleTester/proguard-project.txt | 20 - DataModuleTester/project.properties | 15 - README.md | 46 +- build.gradle | 15 + dataModule/.gitignore | 1 + dataModule/build.gradle | 18 + .../bundles/debug/AndroidManifest.xml | 11 + .../bundles/debug/res/values/values.xml | 7 + .../src/main}/AndroidManifest.xml | 20 +- .../coinguardian/config/MarketsConfig.java | 238 ++--- .../coinguardian/config/Settings.java | 14 +- .../coinguardian/model/CheckerInfo.java | 50 +- .../coinguardian/model/CurrencyPairInfo.java | 72 +- .../model/CurrencyPairsListWithDate.java | 20 +- .../coinguardian/model/CurrencySubunit.java | 36 +- .../model/CurrencySubunitsMap.java | 28 +- .../coinguardian/model/CurrencySymbol.java | 32 +- .../mobnetic/coinguardian/model/Futures.java | 52 +- .../coinguardian/model/FuturesMarket.java | 44 +- .../mobnetic/coinguardian/model/Market.java | 196 ++-- .../mobnetic/coinguardian/model/Ticker.java | 50 +- .../model/currency/CurrenciesSubunits.java | 50 +- .../coinguardian/model/currency/Currency.java | 340 +++---- .../model/currency/CurrencySymbols.java | 110 +-- .../model/currency/VirtualCurrency.java | 686 ++++++------- .../coinguardian/model/market/AllCoin.java | 148 +-- .../coinguardian/model/market/Anxpro.java | 232 ++--- .../coinguardian/model/market/Basebit.java | 132 +-- .../coinguardian/model/market/Bit2c.java | 90 +- .../coinguardian/model/market/BitBay.java | 104 +- .../coinguardian/model/market/BitCore.java | 80 +- .../coinguardian/model/market/BitKonan.java | 104 +- .../model/market/BitMarket24PL.java | 116 +-- .../model/market/BitMarketPL.java | 94 +- .../coinguardian/model/market/BitMaszyna.java | 94 +- .../coinguardian/model/market/BitTrex.java | 114 +-- .../coinguardian/model/market/BitX.java | 112 +-- .../model/market/BitcoinAverage.java | 118 +-- .../model/market/BitcoinCentralNet.java | 88 +- .../model/market/BitcoinCoId.java | 142 +-- .../model/market/BitcoinToYou.java | 90 +- .../model/market/BitcoinVenezuela.java | 126 +-- .../coinguardian/model/market/Bitcurex.java | 106 +- .../coinguardian/model/market/BitexLa.java | 88 +- .../coinguardian/model/market/Bitfinex.java | 110 +-- .../coinguardian/model/market/BitoEX.java | 86 +- .../coinguardian/model/market/Bitorado.java | 132 +-- .../coinguardian/model/market/Bitso.java | 88 +- .../coinguardian/model/market/Bitstamp.java | 90 +- .../coinguardian/model/market/BitxCom.java | 134 +-- .../coinguardian/model/market/Bleutrade.java | 144 +-- .../coinguardian/model/market/Btc38.java | 146 +-- .../coinguardian/model/market/BtcBox.java | 88 +- .../coinguardian/model/market/BtcMarkets.java | 100 +- .../coinguardian/model/market/BtcXIndia.java | 90 +- .../coinguardian/model/market/Btcchina.java | 100 +- .../coinguardian/model/market/Btce.java | 238 ++--- .../coinguardian/model/market/Btcturk.java | 92 +- .../coinguardian/model/market/Bter.java | 128 +-- .../coinguardian/model/market/Buttercoin.java | 82 +- .../coinguardian/model/market/CCex.java | 130 +-- .../coinguardian/model/market/Campbx.java | 82 +- .../coinguardian/model/market/CexIO.java | 214 ++-- .../coinguardian/model/market/CleverCoin.java | 88 +- .../coinguardian/model/market/CoinDesk.java | 108 +-- .../coinguardian/model/market/CoinJar.java | 112 +-- .../model/market/CoinMarketIO.java | 168 ++-- .../coinguardian/model/market/CoinMateIO.java | 100 +- .../coinguardian/model/market/CoinSecure.java | 98 +- .../coinguardian/model/market/CoinSwap.java | 114 +-- .../model/market/CoinTraderNet.java | 98 +- .../coinguardian/model/market/CoinTree.java | 82 +- .../coinguardian/model/market/Coinapult.java | 102 +- .../coinguardian/model/market/Coinbase.java | 136 +-- .../coinguardian/model/market/Coinse.java | 222 ++--- .../coinguardian/model/market/Comkort.java | 140 +-- .../model/market/CryptoAltex.java | 114 +-- .../coinguardian/model/market/CryptoRush.java | 138 +-- .../model/market/CryptoTrade.java | 182 ++-- .../coinguardian/model/market/Cryptoine.java | 144 +-- .../coinguardian/model/market/Cryptonit.java | 140 +-- .../coinguardian/model/market/Cryptopia.java | 140 +-- .../coinguardian/model/market/Cryptsy.java | 476 ++++----- .../coinguardian/model/market/Dashcurex.java | 106 +- .../model/market/DolarBlueNet.java | 80 +- .../coinguardian/model/market/FoscEx.java | 100 +- .../coinguardian/model/market/FoxBit.java | 88 +- .../coinguardian/model/market/Fxbtc.java | 98 +- .../coinguardian/model/market/FybSE.java | 82 +- .../coinguardian/model/market/FybSG.java | 82 +- .../coinguardian/model/market/Gemini.java | 134 +-- .../coinguardian/model/market/HitBtc.java | 126 +-- .../coinguardian/model/market/Huobi.java | 118 +-- .../coinguardian/model/market/Igot.java | 120 +-- .../coinguardian/model/market/ItBit.java | 112 +-- .../coinguardian/model/market/Justcoin.java | 144 +-- .../coinguardian/model/market/Koinim.java | 102 +- .../coinguardian/model/market/Korbit.java | 90 +- .../coinguardian/model/market/Kraken.java | 192 ++-- .../coinguardian/model/market/LakeBTC.java | 114 +-- .../coinguardian/model/market/Livecoin.java | 142 +-- .../model/market/LocalBitcoins.java | 118 +-- .../coinguardian/model/market/McxNOW.java | 202 ++-- .../coinguardian/model/market/Mercado.java | 104 +- .../coinguardian/model/market/Mexbt.java | 90 +- .../coinguardian/model/market/MintPal.java | 124 +-- .../coinguardian/model/market/Mtgox.java | 136 +-- .../model/market/OKCoinFutures.java | 134 +-- .../coinguardian/model/market/Okcoin.java | 110 +-- .../coinguardian/model/market/Paymium.java | 116 +-- .../coinguardian/model/market/Poloniex.java | 122 +-- .../coinguardian/model/market/Prelude.java | 198 ++-- .../coinguardian/model/market/QuadrigaCX.java | 90 +- .../coinguardian/model/market/Quoine.java | 136 +-- .../coinguardian/model/market/Ripio.java | 84 +- .../model/market/SevenNineSix.java | 108 +-- .../coinguardian/model/market/ShapeShift.java | 138 +-- .../coinguardian/model/market/ShareXcoin.java | 116 +-- .../coinguardian/model/market/SwissCex.java | 140 +-- .../coinguardian/model/market/TheRock.java | 148 +-- .../coinguardian/model/market/Unisend.java | 84 +- .../coinguardian/model/market/Unknown.java | 68 +- .../coinguardian/model/market/Uphold.java | 142 +-- .../model/market/VaultOfSatoshi.java | 158 +-- .../coinguardian/model/market/Vaultoro.java | 72 +- .../coinguardian/model/market/Vircurex.java | 918 +++++++++--------- .../coinguardian/model/market/Virtex.java | 122 +-- .../coinguardian/model/market/Winkdex.java | 84 +- .../coinguardian/model/market/YoBit.java | 148 +-- .../coinguardian/model/market/Zaydo.java | 90 +- .../model/market/example/MarketExample.java | 98 +- .../util/CurrencyPairsMapHelper.java | 156 +-- .../coinguardian/util/CurrencyUtils.java | 46 +- .../coinguardian/util/FormatUtilsBase.java | 194 ++-- .../coinguardian/util/MarketsConfigUtils.java | 80 +- .../coinguardian/util/ParseUtils.java | 22 +- .../mobnetic/coinguardian/util/TimeUtils.java | 38 +- .../coinguardian/util/XmlParserUtils.java | 70 +- .../src/main}/res/values/market_cautions.xml | 18 +- dataModuleTester/.gitignore | 1 + dataModuleTester/build.gradle | 25 + .../libs/volley.jar | Bin .../src/main}/AndroidManifest.xml | 56 +- .../tester/MainActivity.java | 594 ++++++------ .../dialog/DynamicCurrencyPairsDialog.java | 254 ++--- .../tester/util/CheckErrorsUtils.java | 172 ++-- .../tester/util/HttpsHelper.java | 102 +- .../tester/util/MarketCurrencyPairsStore.java | 74 +- .../volley/CheckerErrorParsedError.java | 38 +- .../volley/CheckerVolleyMainRequest.java | 144 +-- .../volley/CheckerVolleyNextRequest.java | 38 +- ...DynamicCurrencyPairsVolleyMainRequest.java | 140 +-- ...DynamicCurrencyPairsVolleyNextRequest.java | 38 +- .../tester/volley/UnknownVolleyError.java | 24 +- .../generic/GenericCheckerVolleyRequest.java | 32 +- .../volley/generic/GzipVolleyRequest.java | 332 ++++--- .../volley/generic/ResponseErrorListener.java | 36 +- .../volley/generic/ResponseListener.java | 32 +- .../res/drawable-hdpi/ic_action_info.png | Bin .../main}/res/drawable-hdpi/ic_launcher.png | Bin .../res/drawable-mdpi/ic_action_info.png | Bin .../main}/res/drawable-mdpi/ic_launcher.png | Bin .../res/drawable-xhdpi/ic_action_info.png | Bin .../main}/res/drawable-xhdpi/ic_launcher.png | Bin .../res/drawable-xxhdpi/ic_action_info.png | Bin .../main}/res/drawable-xxhdpi/ic_launcher.png | Bin .../res/drawable-xxxhdpi/ic_launcher.png | Bin .../layout/dynamic_currency_pairs_dialog.xml | 64 +- .../src/main}/res/layout/main_activity.xml | 198 ++-- .../src/main}/res/values-v11/styles.xml | 20 +- .../src/main}/res/values-v14/styles.xml | 20 +- .../src/main}/res/values/check_errors.xml | 22 +- .../src/main}/res/values/strings.xml | 0 .../src/main}/res/values/styles.xml | 34 +- gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 +++ gradlew.bat | 90 ++ settings.gradle | 2 + 200 files changed, 9954 insertions(+), 9686 deletions(-) create mode 100644 .gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml delete mode 100644 DataModule/.classpath delete mode 100644 DataModule/.gitignore delete mode 100644 DataModule/.project delete mode 100644 DataModule/.settings/org.eclipse.core.resources.prefs delete mode 100644 DataModule/.settings/org.eclipse.jdt.core.prefs delete mode 100644 DataModule/proguard-project.txt delete mode 100644 DataModule/project.properties delete mode 100644 DataModuleTester/.classpath delete mode 100644 DataModuleTester/.gitignore delete mode 100644 DataModuleTester/.project delete mode 100644 DataModuleTester/.settings/org.eclipse.jdt.core.prefs delete mode 100644 DataModuleTester/DataModuleTester.apk delete mode 100644 DataModuleTester/libs/gson-2.2.4.jar delete mode 100644 DataModuleTester/proguard-project.txt delete mode 100644 DataModuleTester/project.properties create mode 100644 build.gradle create mode 100644 dataModule/.gitignore create mode 100644 dataModule/build.gradle create mode 100644 dataModule/build/intermediates/bundles/debug/AndroidManifest.xml create mode 100644 dataModule/build/intermediates/bundles/debug/res/values/values.xml rename {DataModule => dataModule/src/main}/AndroidManifest.xml (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/config/MarketsConfig.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/config/Settings.java (93%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CheckerInfo.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CurrencyPairInfo.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java (94%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CurrencySubunit.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/CurrencySymbol.java (95%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/Futures.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/FuturesMarket.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/Market.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/Ticker.java (94%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/currency/Currency.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/AllCoin.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Anxpro.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Basebit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bit2c.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitBay.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitCore.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitKonan.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitMarket24PL.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitMarketPL.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitMaszyna.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitTrex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitX.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitcoinAverage.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitcoinCoId.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitcoinToYou.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bitcurex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitexLa.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bitfinex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitoEX.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bitorado.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bitso.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bitstamp.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BitxCom.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bleutrade.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Btc38.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BtcBox.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BtcMarkets.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/BtcXIndia.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Btcchina.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Btce.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Btcturk.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Bter.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Buttercoin.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CCex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Campbx.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CexIO.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CleverCoin.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinDesk.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinJar.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinMarketIO.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinMateIO.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinSecure.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinSwap.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinTraderNet.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CoinTree.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Coinapult.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Coinbase.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Coinse.java (98%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Comkort.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CryptoAltex.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CryptoRush.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/CryptoTrade.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Cryptoine.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Cryptonit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Cryptopia.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Cryptsy.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Dashcurex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/DolarBlueNet.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/FoscEx.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/FoxBit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Fxbtc.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/FybSE.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/FybSG.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Gemini.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/HitBtc.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Huobi.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Igot.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/ItBit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Justcoin.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Koinim.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Korbit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Kraken.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/LakeBTC.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Livecoin.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/LocalBitcoins.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/McxNOW.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Mercado.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Mexbt.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/MintPal.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Mtgox.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/OKCoinFutures.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Okcoin.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Paymium.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Poloniex.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Prelude.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/QuadrigaCX.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Quoine.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Ripio.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/SevenNineSix.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/ShapeShift.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/ShareXcoin.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/SwissCex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/TheRock.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Unisend.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Unknown.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Uphold.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/VaultOfSatoshi.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Vaultoro.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Vircurex.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Virtex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Winkdex.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/YoBit.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/Zaydo.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/model/market/example/MarketExample.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/CurrencyUtils.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/FormatUtilsBase.java (97%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/MarketsConfigUtils.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/ParseUtils.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/TimeUtils.java (96%) rename {DataModule/src => dataModule/src/main/java}/com/mobnetic/coinguardian/util/XmlParserUtils.java (96%) rename {DataModule => dataModule/src/main}/res/values/market_cautions.xml (98%) create mode 100644 dataModuleTester/.gitignore create mode 100644 dataModuleTester/build.gradle rename {DataModuleTester => dataModuleTester}/libs/volley.jar (100%) rename {DataModuleTester => dataModuleTester/src/main}/AndroidManifest.xml (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java (96%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java (95%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java (96%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java (96%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java (97%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java (91%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java (96%) rename {DataModuleTester/src => dataModuleTester/src/main/java}/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-hdpi/ic_action_info.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-hdpi/ic_launcher.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-mdpi/ic_action_info.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-mdpi/ic_launcher.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-xhdpi/ic_action_info.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-xhdpi/ic_launcher.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-xxhdpi/ic_action_info.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-xxhdpi/ic_launcher.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/drawable-xxxhdpi/ic_launcher.png (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/layout/dynamic_currency_pairs_dialog.xml (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/layout/main_activity.xml (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/values-v11/styles.xml (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/values-v14/styles.xml (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/values/check_errors.xml (97%) rename {DataModuleTester => dataModuleTester/src/main}/res/values/strings.xml (100%) rename {DataModuleTester => dataModuleTester/src/main}/res/values/styles.xml (97%) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c6cbe562 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..96cc43ef --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 00000000..e7bedf33 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..d494f36d --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..7158618b --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..ec4e9391 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 00000000..7f68460d --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DataModule/.classpath b/DataModule/.classpath deleted file mode 100644 index 26bdfa6e..00000000 --- a/DataModule/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/DataModule/.gitignore b/DataModule/.gitignore deleted file mode 100644 index c52f1d41..00000000 --- a/DataModule/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# built application files -*.apk -*.ap_ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ - -# Local configuration file (sdk path, etc) -local.properties - -# Eclipse project files -#.classpath -#.project -#project.properties -/.apt_generated diff --git a/DataModule/.project b/DataModule/.project deleted file mode 100644 index ff152ee8..00000000 --- a/DataModule/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - DataModule - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/DataModule/.settings/org.eclipse.core.resources.prefs b/DataModule/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 86f31b52..00000000 --- a/DataModule/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java=UTF-8 diff --git a/DataModule/.settings/org.eclipse.jdt.core.prefs b/DataModule/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 48ab4c6b..00000000 --- a/DataModule/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/DataModule/proguard-project.txt b/DataModule/proguard-project.txt deleted file mode 100644 index b60ae7ea..00000000 --- a/DataModule/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/DataModule/project.properties b/DataModule/project.properties deleted file mode 100644 index dd07128d..00000000 --- a/DataModule/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-18 -android.library=true diff --git a/DataModuleTester/.classpath b/DataModuleTester/.classpath deleted file mode 100644 index 26bdfa6e..00000000 --- a/DataModuleTester/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/DataModuleTester/.gitignore b/DataModuleTester/.gitignore deleted file mode 100644 index 0371fa2c..00000000 --- a/DataModuleTester/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# built application files -#*.apk -*.ap_ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ - -# Local configuration file (sdk path, etc) -local.properties - -# Eclipse project files -#.classpath -#.project -#project.properties -/.apt_generated diff --git a/DataModuleTester/.project b/DataModuleTester/.project deleted file mode 100644 index ed0c3046..00000000 --- a/DataModuleTester/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - DataModuleTester - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/DataModuleTester/.settings/org.eclipse.jdt.core.prefs b/DataModuleTester/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 48ab4c6b..00000000 --- a/DataModuleTester/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/DataModuleTester/DataModuleTester.apk b/DataModuleTester/DataModuleTester.apk deleted file mode 100644 index 6942987a97d37cc72630bded7bd7f984f6e5f14f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190579 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.z0K^9juuQ)v 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

ZQp#4*lqI+u)cb)^pU4`IqliK^9r;s13r6BJD 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%0D>R|V>()~s8o_i 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¨6zYEG=XDI(&H=Ex*vqMd{!KUB;$1soH%*Nw9?H6d%OSvkpF@0!L^lMCi z=9&Rg;2rIbq8HTs;l0dFG=HK_f1}pvY+9!x-|ytf_j_u-n{C=%Uu?$r(ar3xKFqf* zt4?jaP5y({E4v5$T)eaJ1Fl;EycE~CiiMtm^h@OkqLrca7EuO>p|aIbhGT9qwo6fl zz%Axwn0|{WLq|>-PP}F0GJLEn!v&wB3}Lkl5JP3Bp$yCOl%Y3I8P=+0SZd4GA4%OZ z(%n*ctC?si_@a`B-z~-Rd8V3Ad@p{vZhRu-tGAf-3BKw}P`91mQJW{<*Qohkm6Px5 z4hc}V%J*$*zQI@JDTaJMm?z&$vhuwzPreVS`R=i0>!iJS3zwfIqgI-Ob2E*X z`Q+9Typdm~YwPdBY=Pa`E)jiyeM>Ee9pr-Ij(YnWcLo9!TK)rg|lS(E~WbB`gykT zy1p>=R#8R;%DCE4#<{nem+_jcGB(_5KK?h~D(0m5+tJ&SPx>{{^h*VOma6nwYt!Em zhqzO2W$!=e*JZMGSzp!Z9sR~>*WDWFlfyb(wtlOi%UYE#yP*xAZWv33^3>^>YMv80 zW68O<9ga|%dA?1}^I%S%@BI{c9^*FV z`7t%mvmnnyhCDx&C(mQu+IWuXzkI9EkNze|%$G~qdH;=?_ss@gfa$-@^B$?aT%0up z-Y`zCq3d7Sx2%q$I!_|+e^>Jk{wmK<^G@&By-nO5e7PjT%*aB7H?r`iP_|H`->Bz!Jnw?bZT@7N0QtyI~ocx_%gzT+hPmdI6?HPE#;c3;Ln;J?7-BY*KAr%CZM zJJQ*K-};DBVsJYr@QRPzRA6vBH}IT~v=&0BOetT+|Ca?;v)m4n%j;~qziCA z>ODxmf*dPvbUqDK4g65+qgUQ0>gfomr?YKB#}aWrzKy-VKF8+Z8kTGgPa&)%$6*VG z|3^_fhn!6km9y-M#7abQ{#+cEjN&?Saacmcm7x||4i?MGutg?VEH%Rx=U{PlP=Qj5 z_OLrod)TkGhx63-;O1wrp9S2>ygj%`k-gUe?IFh61I%sd-m`)jxk8yC`|M}AQyK%VQ!`7WE`TJQN z`typni#BzUZhxDEltC$fbQ6%8Rq_o`vvaNGrzOZ{w(f^b)O5-KAdo0m?&^PERe-quc zmBbxpn4XR8eYyy)6j#`uqVIU4oMI(%)T7?>D<$+|ha!y@5laeBBQAt0lJjsO>Qo-67(-2IAT( zWv^$BzJtXj@*gR`2J#DW`M2ugVr!L??#RAl+$Zgn#hum|5@kY3ch9v?3K9*!mFhV$ z_cPtOcVUZly%X*bcLsbP@_en-t$Z&h-_>`p{ah{I-} z>9OX^|FtIhU!=?b_eUt-_eLn6XiJeh%*UFQcL=_4r9t*Usqr+x(N{FadYxRRa8dc= zO1=D1LB`4{&x3rgxRB3uaDS)Q1+vlkYe}z*t;699;Poz-`ve!hbXwuKj#M}qRh-1< z3R1nN3#slwr)xQtSC&&P4qSEGNG3ak{8Hm8B~l-|b^H;RpWOk@(+oTz4I+2_5Pd3v zcaXCe(mf{^j>Qlb>bo!SI{5mySjx`BnX;CLE?1*z9{vn52hJxFYZJK6H`X z6nZY~zo5nam7fiJU9{)FtL^zZXwN@@_WZ+~_N?5Q-JY-G?fD11J^wJLJs)%D@a_4! z5!&+)MrhAJ9HBi69y8%i!DFt6@@+B=<6%k-uvF@q31R-(<-5Eq9u&txM#tJGC`TlQWVsuH*az zPeV#y_ipeUq;Ff$HB7#zCDv_RhBZvS4yKmt)|~x;7wtvwOZ-JKeF+F{Cr)05vAQzUsb#n?rwmK-lwql%4EGz#(3htS@xv&?$54hs z3AK;QKUEpdQp@mQP8rV2Q-(_oWq8<7hHLLK@5k5Q_4(dfxJ}LHV>$V}H%~qvGvsp@ z&1WHh>*=Yxn0^xG(+y)fdnMFKy1)AqNpJfx(Ds+k0xI!ul*`9>ZL=fONrNoGEa9)% zYe8mz#d$i6_~Tqm>*GSM^?|##T+hQ1fml&XWsMwx7|}G@0b`65_(ic&;bi(iPBPh9 zLd!Lk*3(PMV%@s@oV(e3lEd9M_7ino9yO-eNst4&`*d3F7BqY!haaADH`fC<%&Q}w zAJe!h`OC+F_tbj{?-sO$xkTkYLmT+|-J%V&EBgJ$E5LmNeH-al1kVDDxBm*y(kOPi zqxTkaL#orZ!Sj1+#`}L!ZvpQO-r)b8Z43$g0q+N9ZZ6^WI^GS;+zN!-OWEhWF4p!a z8AsN=lBB3-zI^;;8Z>Y4yp6d4e;piGsKfoifXhB3#`L$42KNeDEDqW6u0kO@JbpL3 zLoeZ3Y-eYX-moY9wK?Zo_p1KtO#PwshVdV~o1IbekrzOkcpgTW)Z&O;DKF8z1N1ES zlki8~LETNN9^KuSFW=4dZcif{?4`Q9(_iK8K5}!>DBau0zrCC38TrUfMc#7uZX}io z*CFujNUs-jE^Oi@NjzQ7=<~&(@!SeJ%FY`G|3(=fL`5WjRI|+48yV?6fFSGZ%=-%T!OmD(R z9Mr#}>P^^b8Ry)?c!N)3c^X3{wB?>u<$Aj!6-uk3Gi9H&OlPl@asR<5KkdPtymDHr zPTjtPy4RqFI1yrar&zOBf&DK!do|ck)uk{?E}`-{9YY|0T~J-#u(!rL8D?8{?IyrD zIo{R_Kc7@8m4WO(p<)ZP+^b!!ifs2O@5}J-@F_|BclwmGB=~pvl!FBR-QF&r&F#V) zMZA4JTZckTgFf50=q)B?C@I+v%FOHrbElKtKJt>wBeOJT%VlyQPqS2FY0|VEJZ&dW z+r`tSX+r8eO`iIoNS&oA(s%39FECC2fby?Rf2*@hF3L*(fWp$J`Ec@lxOhHj`e#WZ zeV&s+krS4_$ctN-mjYd03QhA;^>2}v5*?4a^By+G^pTgKKRrfz<>PIFONsrx`|jcV z4*Fe$_Pe{Ff1d)QS)t^SG`_R<9>I6kd@8Cz2RCo3)n4iu?eOZueMw4=zcT#o4Ln>@XOI~|}o!Gr&8$cjHt{XWH zx$Y9ib$>2+?wsv{=PEfom!2yF{A5}mp;C?K{#31d#xWa%ok(spoAnB7;9ne0>qGHVs?US72*6ctp(yPNW zdbl_}F51p?zq}`TkISaXi9nMR8BNky@+&A!v{8g|3x}Z5iIhg(IvuC6@i02>%SN1B zo^X{)zd1m^89=`ibLjVdm3}|`O!T{9JC`xYYi=X`_PCAo+wU>b?@b;3puLd~barTO zq%McPc23`&+u3|aPuICX*SVCgc;na>*{k?$=P2g9a<@vCxj>gnpvzp9E;jyp$Nuet z7eqKOVC8*oyWj=c<;l&j=pV1==^qOr&kJ?^gVv|oKNjlxhaRK#k9X8^%!hK!gmNrY z%OT{__qMaMEk05zVZE}ox0x=n_U0q!L-~BWK%%yrsWWUSNVh;=Gx^SC;B(VUlq+$s82{^_T-B!If977% z=Pxvj|7WV@y+~KyIzxFEo0M0`0_Q>a85mx{@%IbvIWX$uj>1Yeo^PtIWYWNLywymm zP+;C=!#$6vyO!P_bDV_clSz@?=P0G_Q9R`f(m*hV(!g9ocOHJOjraH5%k=e(?SBtz8Cd`65vb7S$ z<{jNCDK@N=Dyrcx+Tcg`GF>+xSz>52Be%)!Qe&H3;6b^Q*=HN*R&t+%Y|5fr7tpPX z&mg@-P>#gEz+UV(Fo z+0N{_M41Au!*&HX7lZi~ZY}|{lh02|i8fd9fca`}hOr}Wy-&SQ)O#D$djr&aR}L?! zx=)O!Yjv`9ovCas>TceBLS`GOu2zmXMvJ;?xi7bkFNeBXp4G+~wR6k5R4r=@l(iAc zx;#gw=)Ok!E$d%a{#$1}$ zXmo)}qgJ3%Gtj6zr#)P9pWwAOeyXuW@V;-~$L;{}Ndb?>`~K=S^1f85k@xNSTyr6x zbbhIrd#;KadB7be?WzZ8+>_O=3MKP)b-zlpPM}#BXx5X{t{zd_)vZPPdEdVK*m>Je zM~hvbdtNB={`!4l%#A?aml(#}0zNjrbsy8oPWXG>oB3(X61qaMnXc{i<6W0jk71=7 z-#VXN^`}p8jKtZqpWeTWBjI2KN5VPmhK0Aqc<$RF=+bEz&&zj+HrDm2+L*Zi_V^ua zJs-!a)Z)ABQV=8+MVS8VV5SoF{hmcT#5!{jZ+%nOhO>E4>kc-y>D$U0Xe(=2Td5Fj zh4E?}EsWeq(0%z1(Powb-Iqa|S!0+N(Dyobus!=DsqMUzY=J_0%*T3r@wwjZI|a7#)0qe z_~*?doV>huL7I3+L+(mN5=x!SJ3CD>e&4HM#7d~%$2@r?A1$uo$BZXbdUgXnyMdlb zgY1ZKaEF7My#7*EPJC_$lexX+-qBuVj^hZ3Azp;-G~ubGl4GkZDcEAU*`~EvA36Q7 zduc=tG&*Cy9vmeQdwD{7+KlOhNusE8C z`ey#M`et^mzL~vR#=9{D{odapc<`w}zf(=;Js+y=@eTu@l#{ZA?! zM@wF3gOfPDM>e>K3&(+tH8>6okieS-{9f+1``KFDQOX}55%VFj9-UYmb9;i?dbDQe ztmd+{KH|+ zS2o-)`auuWV-NI$%{gm5o9@rQ2Pt^ZSMC>ey{<^VFZb2^*?C>uYZL7rPlB?YSKN2= z$!EE>J-49g9-LmvNL3!t?daiZ{{eMJ&nNBoXm+IT$0eG57Cmpk=yv`6x%~JnpxRl7 z$&YVQ=@tdLMS*T-7~4;!oAr#Tv&S?&tGqn?!qRnBK=< z&i6VR@MU3J4{EKs>OhKPdmD+$g|1Ge$o`T8UlLs4>gDSihFy+dYw~Qx1578+Cw+mY zfi2B@a)U&ql>bG08JAeSWFxr zZU&^sXmVM@1EMVsKwXZ4ws>C7{HNssQ4a&3X>D!k17dFctE@KrN>-b#AF&MzdaQnc z)onICE&_U7q?1kg9w?0S+YICUMLNoC%QMaosSAV4Rw#)g#9_t=ncHF17sW`N$IJBut za@y1(wM|{3Yg4s`HWeJEP5tZvv-Jjj8^SiFZ)2aoP5GqrJo(le{`5fZczGGLt;@2; z%V?hQ@w#u#fo7NGjF-|*F^1e##LmMpS`>i$V(QM;nl<^Ctu<@%uhVUmXYGnn zp55)x%dS%yT|v#tDr9FRy-uS*Gd_ zwF}W>1NAF27t8SYi!VoV1MxJMx3E-QB=j3XKB=}C(IUNKIMjLRHUpT;k0;(hQ^n`A z>u$wpYsh0gv(zx>b;7miy+hs*UvLxt<@%H}lcXMtc$hMk53eAfM?veB$c^+~SvvEx z$-r*ylF|&v(uaDqxpgyM>X&q#pIgie6C5^Oejlp;WNB+M?D;aY&jdDoQ$@&cf{tG_KrPGGp&l+}xbll}|IZ~B+iFAwsqtilsqS-XG4TjQ10q6y=V&9Wz} z{ya_+HO@E$OP5>d^@DpTte^WS+MOde0tPtx?#F#ifn(Gd<0uo-1)X&E`;I+6NmaI| zFa1cpI1bEKS2l#mn)5GA=RfM$Vti{X%Y1A6@|tAN8}QwAwlXH&b@*gP@XIGpVysOk22#y9+Nvrd+Kwl2vKARz|owPV@l#Yg7ls}(-fr>lpHW&^D)cEd< z`Mq7QMGQbq-Yf)nhZjnlgzscOiy0j4aE_4fY)7tLb8{nqb-Z#kR^*9vv{Od53=yMu zUg+jUw@?zJ`wGEGt{dXKyzYvHJiSBQKKw^}#iMCIA&bPiHDnX86j7x)`ZcbJ~Nn~y48SNjnVB)@b%Npc_;{e9f zb}oYjy%p0DN1k;YbYGfQH4GwoUw9hRd|k|1x&HCCjgSm<-6bXM6q}DZ^^gtUPB|Y; ze2q}OY=OUQIRja(`Uc3p9Jk+*Z+pls9jz7yRyUKZ6eR^fmv+|)w{))Oty_2U-CJV1 zXd73vSJ3*oI0RmrqgN?j*@9!m<5#YB=0-h~wwE<6}1R{1tAli~d#y)2x&oKE1?!O(k{DKgCpu;Vsj zB^gJRG*NAL%%!_l-J7N1&IEgZh+#TbI}^uM#sC!22?Xp9t@D#HHXk9q&36KiB;y{A zya(uH1VLJY4J^Z_stN9AmYm0~v8*bun)~tx!UiDK1V7v!Hh{(V^Y@*=aBr5_I}@E- z6AeDeKjM!vOhqMqBZ{}f0jdTdM)Km03Gdd2mwB{3AD>@<>F)s-qWQ)3Y znM_T`dQWkvDCk}K8T(%*_Y?E|NlcN@%Ii@k>T$lf`RaTANa78MWou{=VweIIUlg^! z91EZzwCy_x0?hZW#kRY%F2z^{LaFosO&>x&j|E_Vx!30{T7;U~$$ng!scs#H-4OX( zc|1x`535LSVfp6_NBvBCvD0_ci1-QrW+%5>K^fkxz6Aj{+AL`qiMBOtaUEMmL?KAP zXFYgMaO}bJ>6WSg-~P2<$q*MD)xnZ{Jk?r%JS!6iX8rS& zDy6r2m}cF!9Nkb#-k7F{Ir;k+J+*xVE>pfis$&(~;{$R5<9JuyPqcxqC3K0-%W0zK z|Jsy1$0JlGk=;vb+bbxnBHLA$PZ1i#HfZf0!dD6|Q>k+F4LzeJe{Fm~onB5K9-*kU zJ91TaWoI5#=hAzHZM-BNxSpNZR2VR5)S9pA{5}cbnNcfKmPom^*@F`c&t+Cy9>3S> ze#&((HX0$fLk@qqV7KydL*FydfMKbY&XbF?os+#ijTNk#J9ZQ_-%N;B4?v&;3dA=B*AKK8=+v@8iAM8wZE4RpG=DO(6uXJ7N z&kkB1aRtHulEK3_oye1D3}jT`6rLb++WohwM%pq#v4 z7j!5GP9ocQ!6;BdtDmLYl3Og-g)jgt(_>FbLa}h-gIvj%?)H?~OF5q-OQE^tZ=u?1 zH?a@i3bqgcN0h#KC)AOCUdnebq(Uw}kPS?JUl_$)D`zIYqd2?EUcb^~^>)lU#wBO; z4;rMlk37 z0KXTfZxRod0x=(0&se_y?0Bc9H6k06&dX-&e8KH0PsitJZvJT(P4^+GQJzHD zXgd*~5~_hpC9I2OurTg)raAC@3uWIfu~=U7ybIz>TIjhcIV0SlQ&@ zj1riK;-EotsvxaiwM>%)aFC5EC^M*S71Nc|$l|xj6eP$~js*wokW3Y19%Ritcu!Q@(K4;^|z99IZIWn4pX z|4r zHmQaLCCafZL0SZR%l-hFse%}TXt^AtgEDQVYQSC7X%7un)~v_rNq?1CN8y0Yf4>2q zQ3A(M=MP|XG0+gKcoOpt-iWLi_ysK&NqY!eB$sO$!-LLzC(j}YPUR4ji3Hq}W0?%% z8ONN50Kydm*}zn7r=Gy>7*#=&L1Vzg)u1xwp>qh3raTJ_mSbAxTS@}!i_AQ#BBVtY z?IB+8{cn?8NV$0L32;!0JWCCPMFs7lC$i%z=%a^ZkV{^y69pJvj60@H<;XUq24+!5 zYk_X`eyE4TTp`CY0(l6b3W5v5V;+)&0_nIaAOTI~SYp9k|Iij=F%K03J$n7NFz3O6 zfGm?mu;LZW24v=pOcN$35UVOkJ!r*l69tTI3iD2&*KZcn71D?^)5HM^XhZqQE z@jaoYy?#S_HqL2dTWm)iK|Cwj9S|1bZTyfxrn_!1;PB^|HV~iSjH+ z-*Uuvp1s+oF+6z8nn06wu!bp23~&&>DhLP6wXw|%33xa824PgqHS|6dUM-Vev8GRz z0i2cqV;k;V1Y@&`;lXDXQ3ZMRGO!LkgS)nS6FBV&04;!HL3p-P`rsIxLu%lM=y%D4 z%v_l!Hed}4m~1f2hEx4kwt7v8u^gCWZxmz%Pl?O^%kqhAU48f+iPfsh#+N<9#PM9r z&zf!2$z){`bX4sh;MJ8 z(iW@LBhJ>CNye_6Dst&*Jo)d^ovtd8z4s`Kxy^?JX`+~ypbw7aRC)Hvv za7|gS$bXAn?#BGAri~AcOp%c8r&e4FLh6)VxFa<5&(0%iXqsailx^hTj=t!SitxvY zz9NJ^`P`fRZ~BvJW8(C$ulAX2ldroW?c!Di!AcZ8&!pYg0o0%GxV+^(zYDb6Xiq6n zfoIFc5ux~hv5HL@FtJkG0}$PduM6MFK#~2oKImP>nHQ1j)~{{wN(3(W3l1M?e&bsk za9=jRIN-Hvg5A*G zf%2Z%ZoiGwJ~=!D6Z2x$sSc`d&L%winUtHU^X(LcR}3b!^YYqcD-}22GN;NWH_SaA zZ<;FaD18Nwc$%Cx@2HaX+aA8CX09h0^o1;m^?Ov+@h^hh9>L=`K?TZNOm)oxTgF?I z9Qn=hI}e->_F}0g3@NN1$m91Nm8@-dsV9C-a!+EJxnZmyOeJ!LsuPWSwG;PM(@IqC z0J98S^6VHz7n0^jD=*Ux%xks}((OJ82N&YzFG z>m3|jn`#Fx8wMl9IXOA=Gv_8XrrwJNBe#`Z2?r5f$bGKE7o0+YpG=Kao_Dv|o_D$R z*zN?&jH|kE3--}-^gX{_BM0v{Ud}Y0d8}JnRqumL0!of)?-gb*zkTh4AL#BKlhXzz zbc*h{j?t(d&eV;yv3v#L`s;9v=er74#$1p8R6QD8Z+v_L!0z9J9{!cD&y&2{jfA~> zc2_B%Xe*zmoCfCt_SbD&1D>v*@M8k%thqYg#w4L#-PTn<4J03o*X6@+{LEXHBmHZ% zdQj-S29`Vk)w!>V4Q_7(+D8eTW;uN2(-kG30#XgEv5$c;t6w>@-Ai6A#B-lPWL84D z0?`AuRL2cz9YfODH%tw0H4dt0l#myGsHX>4JoWto9Z-R<-Q_|NFaB0sJuu;USlp5O zOT-g}EL0~CPI^BKsRo~z?9J-qZFy-qVsI$N1jIWtR%*=`Vls#|b1s*?#NkrF0%=b# zdOW}Gu7GJzz`KIPf=j{0n}X7v&aV+(K}?RWmR7UG(!ALG0H%=F7w$-u_)RwS#24@b zmZg(RM&cgHwG86R%Da*hWz)@O{U&NnXr=S6Yrf8o(xbA*R$MD*mKo7H%a(tu0)MJ3 z5M3_*6Zm?4v+k~y97V_w{`{$2|FC+jJua}TfG&X2=t_J{-k~S41n;@+56EP+t-kWx zO&Mv2>{+@eocDbuIR5rtMs)wAawF1LTXLoiTrsK)CjR%!^rAp+v)f!M>&c zb3?zaTIilt_38yVZR@(xA>L8n@K&!e%lz?dP|@#2&@HLAL3-E@zr;&W)lG2MsS9#c z{hUl_a?5>Fj^>?)YMI<6$|Qg0V;#N7HT9GxsoLBac;GfqkKAiqBQY-?(H>F^NmreW zC=vN@xpdxw``d6KCJ7uUTv4_)wn(;+tO^$&$|7pQ7F-NpI)n4hL%sOmvAUY3v+&85 z6eK-;3kW4XdS>u+hOyX&yTR7$SrfmK-(}RUW-2-Q7E>$hpPKYp;QLu|oRgsnT-?z$ z$z6K?QNia7xZRn4c>GG-c*9e*-gkffo5y?4j&3V>);lfA+iZ6&JB474BA6UU-Bmxm zsQ%w$-lc(@?||BWkAIJ~d{p+i|9f=o#lkF;xW)K7HfS5>Oo+>12DP!vF#>d15Kpa` zYQZ_|ap|PCh$t1djX4u9Xb5chV_#o`b$%`p9MW;|lOEEoxw)nd6}zUP8)SG2_PKF$ zCG9!K4`p770`y*K`f< zP#Hi?h`4t^*AW@eDZz5B+WMJgE7EoU#c0`tDCuH?PP4P^zY)?H`rmV)o*|@yu zG2^$@ZE)8NdfbU~-g)aB%i~)@ zaMdI6i@c0SIR4lo)FxQYad3yU{CCszM^n~iL%HOY1H*HnYEv)!EP+vRl)m99Yl7aK znK)yG!@FpP*--eNJGu8IGYKvBalb&!@rQWNFgp3t?M zL&!BtS8@5*go}r-Ojdz1*W6F5? z$e=kvM??!hwn-I@qV8NpQe85d&QPFUbChwS-l01hweY<$75AW|xbt>*9`&f5 z!P}XzaoX9#<7e>5z5#^bPu6v~=_?Z0@|FS5Xy3K?D_I`*D_QyZuAh(HmsM5tZl3*) zDUEzPL;hD@)P5DR9T*1d1ctnz59mOpHxRd#B!JuJ!1?j~sr0k)>3Xy9zo%%Ahpy>+ zV)dPFzbj?^OXhA#%5#$ok>#P)(AwB07~_$E#r%e&z(kqr^1a8*J3668s2+hW{KPH6 zIef)`f+9}_`M#K5X3SVkhOUXZ$6_0AE=PJ8!44P~k)E1?Ju-zC z!v9;Md0eaKpWuj}$OCGibq(>>N4AO}>f=LI})f<;@ z_eYkEPcw)|mcui5Yzgm2mY?m4fsytbQJ%|8#5?bx|Hw>Zr!Wb0?_(XlFFc!j-~Q&G zDSVfbm9}E?yoF0z)JDOG$U7g4F&dF)zQs7HxRMW}*6qKIztaRBy20nTF+P z-74EX(+RzTWe8yW6Fg6{AKcoPI`S_02IU5XE1cP}4@Shk+$m!3_9_l~Iq(hrcE|L( zwV?d!=wg2!u9^CuO84Pxg?hXaUk{ZNc0c#0{K*pn9o1GM2Ru+@q)|wFjywuJoNpzM zCzwtLzU>nQ>fO(0+PyD0ac_F`DXwQ$ZR%G){$63qQ@dd8>d>2Q7N=wTqfTrYnup8O2ld}Z3>4r{!ybkukomGKjqt}gLk3J`hQ z3w}h@*j7n)}T_ii8MbN$PEqX8VEJf)sGNppQv zuOjeyRNwLZ?}pdJFY@24Nuq{i?A;RDQlD^^epB99MVBzW;Fg6i&$t7t%?cgaeqk}g3r!j&;NMY~<+HPtQ1TJ~A=x%e?D^_9WAZ%z@^af{ zpbGAoZA_78>QHb3>4}%2-j5a$?=VWCiG%CW{&Am@84r(k65q1Rw0kh8KPO+PuMpkwXfF*oi-kc*4s2jeml zPSO~yc8JMzn;h?2$LUQ zg*CSa(b-z(KBe<6)aSyO3!sdzT1|JSn5=+1L;KG-QHwu;vtXkQyxn}jEHo6M9z`-W z_!1}xF~93+#d%tmTKkPLZ{}3ZeNE)qC>-s)-vaOhs+chOW?S9cq6y;HH&x8E5)uS9dGO6G^ zN+Q$j53D(Z@Q``1T)8wP4Swo;JY`{m*eY-aExBSrJ>SmzS3_TOY(7A9cqWlOc|8%R z1@7&>CA)4Z7}T#7^`5CG*9|fZ*87nn+gurUdJ3 z9{aQMP+1$Tk5rcz*jH0H0Jo$Py_d}#$4Kn;Da|Me%PzjW{i~@fit~+|vGt7yinQe%mk@g42N>gpm|K81u_C~%6>J`!@ndqywz97wWK4`~zUxYdUEx#nw zABLy37sbCs%r`!TG!_ZIE+$UZKe@)+^*=osY#+XSw7b4I%>}L%8EqeW8Y|VO0@by} ziN5Z}S8pAa7s~@>wAVf_zHfRo7OTD%&F$X+jAzwfz;?p+d7(wvDs3ZQx_I1b|3k2# z9}aMj t$Ygk&7;xX-`3Qe9 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

y)d@^y=s9`#39r;>ehppwbYq0U{|$2}4K7 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

-X*@Tz0V@JE<{JVc!OO7(MCcH*%up!yjaDX0y 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 M$1P8rF<>(NAA9kPA^-pY diff --git a/DataModuleTester/proguard-project.txt b/DataModuleTester/proguard-project.txt deleted file mode 100644 index f2fe1559..00000000 --- a/DataModuleTester/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/DataModuleTester/project.properties b/DataModuleTester/project.properties deleted file mode 100644 index 56f8b7b9..00000000 --- a/DataModuleTester/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-18 -android.library.reference.1=../DataModule diff --git a/README.md b/README.md index 9bec5e93..a692934f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ __Bitcoin Checker__ is a FREE app to track the most recent prices of your favour ###Hello Bitcoin Checker users! As you know, the number of virtual currencies is increasing very fast. Currency pairs set on existing exchanges change almost every day and there is also a need to add newer and newer exchanges over time. -_We proudly announce_ that [DataModule](https://github.com/mobnetic/BitcoinChecker/tree/master/DataModule) (containing exchanges and currency pairs) for Bitcoin Checker app is now _OPEN_ for our users to make this application _even better_! This means that _anyone_ can now: +_We proudly announce_ that [DataModule](dataModule) (containing exchanges and currency pairs) for Bitcoin Checker app is now _OPEN_ for our users to make this application _even better_! This means that _anyone_ can now: * Add support for a new exchange * Update currency pairs on their favourite exchange @@ -19,16 +19,16 @@ https://play.google.com/store/apps/details?id=com.mobnetic.coinguardian #Introduction To start working, you should fork this repo. It basically contains two projects: -* [DataModule](https://github.com/mobnetic/BitcoinChecker/tree/master/DataModule): Library project that stores information about exchanges and currencies used in Bitcoin Checker. This is the project that you will work with. -* [DataModuleTester](https://github.com/mobnetic/BitcoinChecker/tree/master/DataModuleTester): Simple project that provides minimal interface in order to launch and test your changes - to see if they will work :) +* [DataModule](dataModule): Library project that stores information about exchanges and currencies used in Bitcoin Checker. This is the project that you will work with. +* [DataModuleTester](dataModuleTester): Simple project that provides minimal interface in order to launch and test your changes - to see if they will work :) -The whole tutorial described below refers to the [DataModule](https://github.com/mobnetic/BitcoinChecker/tree/master/DataModule) project because only this project is meant to be edited by users. After making your changes, please create a pull request to the original repo. +The whole tutorial described below refers to the [DataModule](dataModule) project because only this project is meant to be edited by users. After making your changes, please create a pull request to the original repo. #Updating currency pairs on existing exchange: *__Note if particular exchange supports dynamic currency pairs syncing mechanism there is NO need to add pairs manually here.__ * -To update currency pairs on your favourite exchange, you have to find the corresponding exchange class file in the [com.mobnetic.coinguardian.model.market](https://github.com/mobnetic/BitcoinChecker/tree/master/DataModule/src/com/mobnetic/coinguardian/model/market) package. +To update currency pairs on your favourite exchange, you have to find the corresponding exchange class file in the [com.mobnetic.coinguardian.model.market](dataModule/src/main/java/com/mobnetic/coinguardian/model/market) package. In every exchange file there is a `CURRENCY_PAIRS` HashMap that contains a base currency (as a key) and a list of counter currencies. Every combination of base and counter currency represents one currency pair. ```java CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ // Base currency @@ -38,10 +38,10 @@ CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ // Base currency Currency.EUR // Counter currency }); ``` -This example from [BTC-e](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Btce.java) represents 4 pairs: `LTC/BTC`, `LTC/USD`, `LTC/RUR` and `LTC/EUR`. +This example from [BTC-e](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btce.java) represents 4 pairs: `LTC/BTC`, `LTC/USD`, `LTC/RUR` and `LTC/EUR`. ###Adding new pair on Cryptsy? -This is generally enough, but while adding a new currency pair on [Cryptsy](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Cryptsy.java) you also need to provide a special pair ID. Please include it in a map called `CURRENCY_PAIRS_IDS`, as shown here: +This is generally enough, but while adding a new currency pair on [Cryptsy](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Cryptsy.java) you also need to provide a special pair ID. Please include it in a map called `CURRENCY_PAIRS_IDS`, as shown here: ```java [...] CURRENCY_PAIRS_IDS.put("DOGE_BTC", 132); @@ -55,8 +55,8 @@ The simplest way to find the pair ID is to click or hover on that particular pai Try to keep alphabetical order of base currencies (or even with counter currencies) but sometimes it's also good to mirror the order from the exchange site. While adding new pairs, you should use currency names from these two classes: -- [Currency](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/currency/Currency.java) - where you can find fiat currencies -- [VirtualCurrency](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java) - where all of the crypto/virtual currencies are stored +- [Currency](dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/Currency.java) - where you can find fiat currencies +- [VirtualCurrency](dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java) - where all of the crypto/virtual currencies are stored ###Some currencies are missing? You want to add some currency pairs but one currency (or both) is missing in Currency or VirtualCurrency class? @@ -65,12 +65,12 @@ Just add them to the Currency or VirtualCurrency class. Please put all fiat/norm #Adding new exchange: ###Example: -Please see the example of a class that represents a single exchange here - [MarketExample](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/example/MarketExample.java) +Please see the example of a class that represents a single exchange here - [MarketExample](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/example/MarketExample.java) ##1. New exchange configuration: To add support for a new exchange, you have to provide some constants describing that particular exchange: * `NAME` - name of the exchange that will be displayed in the app. -* `TTS_NAME` - name of the exchange that will be used in spoken announements. Sometimes it's just fine to put `NAME` here (see [Kraken](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Kraken.java)), but sometimes it's better to provide a more spoken friendly version (like on [McxNOW](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/McxNOW.java) - "MCX now"). +* `TTS_NAME` - name of the exchange that will be used in spoken announements. Sometimes it's just fine to put `NAME` here (see [Kraken](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Kraken.java)), but sometimes it's better to provide a more spoken friendly version (like on [McxNOW](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/McxNOW.java) - "MCX now"). * `URL` - this field stores the Url for the Ticker API. Most often it contains two parameters, but sometimes it has one (%1$s and %2$s). These parameters are replaced with currency names or the selected currency pair. Providing a URL is described in the next section. * `CURRENCY_PAIRS` - map of all currencies supported by this exchange - described later. @@ -81,7 +81,7 @@ public MarketExample() { } ``` ##2. Providing currency pairs: -If given exchanges provides a mechanism to fetch currency pairs dynamically, there is no need to specify them manually then. Please see [this section](https://github.com/mobnetic/BitcoinChecker/blob/master/README.md#6-fetching-currency-pairs-directly-from-exchange). +If given exchanges provides a mechanism to fetch currency pairs dynamically, there is no need to specify them manually then. Please see [this section](#6-fetching-currency-pairs-directly-from-exchange). Otherwise you have to specify which currency pairs are supported by your new exchange. Description for this is done above, in the [Updating currency pairs on existing exchange](https://github.com/mobnetic/BitcoinCheckerDataModule#updating-currency-pairs-on-existing-exchange) section. @@ -125,7 +125,7 @@ public String getUrl(int requestId, CheckerInfo checkerInfo) { ``` ###3a. Providing other parameters in URL (advanced): -Sometimes there is a need to include some kind of pair ID instead of just currency names. Please see [Cryptsy](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Cryptsy.java) as an example. There is a separate `CURRENCY_PAIRS_IDS` map that holds pair ids: +Sometimes there is a need to include some kind of pair ID instead of just currency names. Please see [Cryptsy](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Cryptsy.java) as an example. There is a separate `CURRENCY_PAIRS_IDS` map that holds pair ids: ```java [...] CURRENCY_PAIRS_IDS.put("DMD_BTC", 72); @@ -151,7 +151,7 @@ public String getUrl(int requestId, CheckerInfo checkerInfo) { ``` ##4. Parsing API response: -While parsing the response from the exchange you have to fill the fieds of [Ticker](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/Ticker.java) object. +While parsing the response from the exchange you have to fill the fieds of [Ticker](dataModule/src/main/java/com/mobnetic/coinguardian/model/Ticker.java) object. If the API response is just in plain JSON object, you can parse it in the parseTickerFromJsonObject method: ```java @Override @@ -167,7 +167,7 @@ protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, T ``` __IMPORTANT:__ The ticker.last field is mandatory; the rest of the fields are optional. -__NOTE:__ Parsing the `timestamp` field (in millis) is not required. If omitted, Bitcoin Checker will fill it with `now` date. If you want to parse this information, please note that some exchanges provide time in different formats (like seconds or nanos) so you have to multiply or divide it to get the time in millis format. You can use `TimeUtils.NANOS_IN_MILLIS` or `TimeUtils.MILLIS_IN_SECOND` constants from [TimeUtils](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/util/TimeUtils.java) for that. +__NOTE:__ Parsing the `timestamp` field (in millis) is not required. If omitted, Bitcoin Checker will fill it with `now` date. If you want to parse this information, please note that some exchanges provide time in different formats (like seconds or nanos) so you have to multiply or divide it to get the time in millis format. You can use `TimeUtils.NANOS_IN_MILLIS` or `TimeUtils.MILLIS_IN_SECOND` constants from [TimeUtils](dataModule/src/main/java/com/mobnetic/coinguardian/util/TimeUtils.java) for that. ###4a. Parsing non JSONObject responses (advanced): Sometimes responses are more complicated than plain JSON, then you should use the `parseTicker` method. The default implementation try to parse received response as a `JSONObject`, but you can parse also other formats by overriding this method: @@ -178,12 +178,12 @@ protected void parseTicker(int requestId, String responseString, Ticker ticker, ``` Here you can find examples of usage: -* [Huobi](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Huobi.java): "almost" JSON object response, there is a need to trim some characters at the begining and at the end of the response -* [MintPal](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/MintPal.java): JSON array response (instead of JSON object) -* [McxNOW](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/McxNOW.java): XML based response +* [Huobi](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Huobi.java): "almost" JSON object response, there is a need to trim some characters at the begining and at the end of the response +* [MintPal](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/MintPal.java): JSON array response (instead of JSON object) +* [McxNOW](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/McxNOW.java): XML based response ##5. Parsing error (not required): -Sometimes an exchange is down but with some error message in their API (See [Crypto-Trade](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/CryptoTrade.java) as an example). You can also handle this situation and display an error message directly from the exchange to the user. There are two methods related with it and they are designed in a similar way to parsing a normal response: +Sometimes an exchange is down but with some error message in their API (See [Crypto-Trade](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CryptoTrade.java) as an example). You can also handle this situation and display an error message directly from the exchange to the user. There are two methods related with it and they are designed in a similar way to parsing a normal response: ```java protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo); @@ -195,7 +195,7 @@ protected String parseError(int requestId, String responseString, CheckerInfo ch ##6. Fetching currency pairs directly from exchange: If there is any API (or other way) to obtain currency pairs directly from exchange (without need to update them manually) you should implement currency pairs fetching functionality instead of providing a static set of currency pairs. -See example on [Basebit](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Basebit.java). +See example on [Basebit](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Basebit.java). Because there are no static currency pairs defined - you should pass a `null` as a last argument in the constructor and do NOT initialize `CURRENCY_PAIRS` at all. You need to provide the url to fetch currency pairs instead: ```java private final static String URL_CURRENCY_PAIRS = "http://pubapi.cryptsy.com/api.php?method=marketdatav2"; @@ -217,9 +217,9 @@ protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonOb or protected void parseCurrencyPairs(int requestId, String responseString, List pairs) ``` -While parsing currency pairs you need to create [CurrencyPairInfo](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairInfo.java) and add it to `List pairs`. The last argument `pairId` is a unique pair id used on some exchanges. You can just pass `null` if there is no such thing on given exchange. +While parsing currency pairs you need to create [CurrencyPairInfo](dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairInfo.java) and add it to `List pairs`. The last argument `pairId` is a unique pair id used on some exchanges. You can just pass `null` if there is no such thing on given exchange. -You can also use multiple requests to fetch currency pairs from exchange - it is described in section [Multiple requests while fetching currency pairs](https://github.com/mobnetic/BitcoinChecker/blob/master/README.md#multiple-requests-while-fetching-currency-pairs). +You can also use multiple requests to fetch currency pairs from exchange - it is described in section [Multiple requests while fetching currency pairs](#multiple-requests-while-fetching-currency-pairs). ##7. Enabling exchange: To enable a newly created exchange, you should add the corresponding line at the bottom of `MarketsConfig` file: @@ -234,7 +234,7 @@ static { ##Multiple requests per exchange: Some exchanges do not provide a nice ticker api with the all important information (bid, ask, vol, high, low, last), so there is a need to perform a few requests (for example 2) to acquire as much information as possible. These requests will be performed in a sequense and a new price notification will appear when all of these requests are finished. -See the [Poloniex](https://github.com/mobnetic/BitcoinChecker/blob/master/DataModule/src/com/mobnetic/coinguardian/model/market/Poloniex.java) exchange as a good example. In order to perform 2 requests you have to override `getNumOfRequests` method: +See the [Poloniex](dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Poloniex.java) exchange as a good example. In order to perform 2 requests you have to override `getNumOfRequests` method: ```java @Override public int getNumOfRequests(CheckerInfo checkerRecord) { diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..305dc055 --- /dev/null +++ b/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.2.0' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/dataModule/.gitignore b/dataModule/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/dataModule/.gitignore @@ -0,0 +1 @@ +/build diff --git a/dataModule/build.gradle b/dataModule/build.gradle new file mode 100644 index 00000000..34cf2fcc --- /dev/null +++ b/dataModule/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 23 + buildToolsVersion "24.0.3" + + defaultConfig { + minSdkVersion 9 + targetSdkVersion 18 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} diff --git a/dataModule/build/intermediates/bundles/debug/AndroidManifest.xml b/dataModule/build/intermediates/bundles/debug/AndroidManifest.xml new file mode 100644 index 00000000..d07c499d --- /dev/null +++ b/dataModule/build/intermediates/bundles/debug/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/dataModule/build/intermediates/bundles/debug/res/values/values.xml b/dataModule/build/intermediates/bundles/debug/res/values/values.xml new file mode 100644 index 00000000..ee13075b --- /dev/null +++ b/dataModule/build/intermediates/bundles/debug/res/values/values.xml @@ -0,0 +1,7 @@ + + + This exchange has limit for 3000 requests per hour. Make sure you don\'t exceed the limit:) + Caution: Due to this exchange\'s specification checking price on it may consume a lot of mobile data (while on mobile network). Be sure that you understand the possible consequences. + Selected market was probably removed and does not exist. Please choose another one. + This exchange has limit for 100 requests per minute. Make sure you don\'t exceed the limit:) + \ No newline at end of file diff --git a/DataModule/AndroidManifest.xml b/dataModule/src/main/AndroidManifest.xml similarity index 96% rename from DataModule/AndroidManifest.xml rename to dataModule/src/main/AndroidManifest.xml index 1bc020b7..b0c8e0f3 100644 --- a/DataModule/AndroidManifest.xml +++ b/dataModule/src/main/AndroidManifest.xml @@ -1,10 +1,10 @@ - - - - - + + + + + diff --git a/DataModule/src/com/mobnetic/coinguardian/config/MarketsConfig.java b/dataModule/src/main/java/com/mobnetic/coinguardian/config/MarketsConfig.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/config/MarketsConfig.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/config/MarketsConfig.java index e6a06c90..dcb0911a 100644 --- a/DataModule/src/com/mobnetic/coinguardian/config/MarketsConfig.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/config/MarketsConfig.java @@ -1,119 +1,119 @@ -package com.mobnetic.coinguardian.config; - -import java.util.LinkedHashMap; - -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.market.*; - -public class MarketsConfig { - - public final static LinkedHashMap MARKETS = new LinkedHashMap(); - private final static void addMarket(Market market) { - MarketsConfig.MARKETS.put(market.key, market); - } - - static { - addMarket(new Bitstamp()); - addMarket(new Btcchina()); - addMarket(new Btce()); - addMarket(new Bitcurex()); - addMarket(new Mercado()); - addMarket(new Kraken()); - addMarket(new Bitfinex()); - addMarket(new Okcoin()); - addMarket(new Cryptsy()); - addMarket(new Coinbase()); - addMarket(new Vircurex()); - addMarket(new Fxbtc()); - addMarket(new Bter()); - addMarket(new Justcoin()); - addMarket(new Btcturk()); - addMarket(new Coinse()); - addMarket(new Campbx()); - addMarket(new BitcoinAverage()); - addMarket(new TheRock()); - addMarket(new CexIO()); - addMarket(new Virtex()); - addMarket(new Huobi()); - addMarket(new VaultOfSatoshi()); - addMarket(new CoinMarketIO()); - addMarket(new McxNOW()); - addMarket(new CryptoTrade()); - addMarket(new MintPal()); - addMarket(new CoinJar()); - addMarket(new Poloniex()); - addMarket(new Winkdex()); - addMarket(new Anxpro()); - addMarket(new BitX()); - addMarket(new CCex()); - addMarket(new BitMarketPL()); - addMarket(new Bitorado()); - addMarket(new CryptoRush()); - addMarket(new CoinDesk()); - addMarket(new Koinim()); - addMarket(new FybSE()); - addMarket(new FybSG()); - addMarket(new Prelude()); - addMarket(new BitKonan()); - addMarket(new BitTrex()); - addMarket(new Comkort()); - addMarket(new Bit2c()); - addMarket(new CryptoAltex()); - addMarket(new BtcMarkets()); - addMarket(new SwissCex()); - addMarket(new Bleutrade()); - addMarket(new ShareXcoin()); - addMarket(new Unisend()); - addMarket(new BitcoinVenezuela()); - addMarket(new Korbit()); - addMarket(new CoinTree()); - addMarket(new Cryptonit()); - addMarket(new LakeBTC()); - addMarket(new BitMaszyna()); - addMarket(new BitCore()); - addMarket(new Zaydo()); - addMarket(new AllCoin()); - addMarket(new Ripio()); - addMarket(new DolarBlueNet()); - addMarket(new Basebit()); - addMarket(new CoinSwap()); - addMarket(new Paymium()); - addMarket(new Bitso()); - addMarket(new Cryptoine()); - addMarket(new BitcoinToYou()); - addMarket(new BitexLa()); - addMarket(new ItBit()); - addMarket(new BitcoinCoId()); - addMarket(new HitBtc()); - addMarket(new CleverCoin()); - addMarket(new BitBay()); - addMarket(new FoxBit()); - addMarket(new QuadrigaCX()); - addMarket(new CoinMateIO()); - addMarket(new BitMarket24PL()); - addMarket(new Buttercoin()); - addMarket(new CoinTraderNet()); - addMarket(new LocalBitcoins()); - addMarket(new Cryptopia()); - addMarket(new Igot()); - addMarket(new SevenNineSix()); - addMarket(new Mexbt()); - addMarket(new Vaultoro()); - addMarket(new BitxCom()); - addMarket(new BtcBox()); - addMarket(new BtcXIndia()); - addMarket(new Uphold()); - addMarket(new YoBit()); - addMarket(new ShapeShift()); - addMarket(new BitoEX()); - addMarket(new OKCoinFutures()); -// addMarket(new FoscEx()); - addMarket(new CoinSecure()); - addMarket(new Dashcurex()); - addMarket(new Quoine()); - addMarket(new Livecoin()); - addMarket(new Gemini()); - addMarket(new Coinapult()); - addMarket(new Btc38()); - } -} +package com.mobnetic.coinguardian.config; + +import java.util.LinkedHashMap; + +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.market.*; + +public class MarketsConfig { + + public final static LinkedHashMap MARKETS = new LinkedHashMap(); + private final static void addMarket(Market market) { + MarketsConfig.MARKETS.put(market.key, market); + } + + static { + addMarket(new Bitstamp()); + addMarket(new Btcchina()); + addMarket(new Btce()); + addMarket(new Bitcurex()); + addMarket(new Mercado()); + addMarket(new Kraken()); + addMarket(new Bitfinex()); + addMarket(new Okcoin()); + addMarket(new Cryptsy()); + addMarket(new Coinbase()); + addMarket(new Vircurex()); + addMarket(new Fxbtc()); + addMarket(new Bter()); + addMarket(new Justcoin()); + addMarket(new Btcturk()); + addMarket(new Coinse()); + addMarket(new Campbx()); + addMarket(new BitcoinAverage()); + addMarket(new TheRock()); + addMarket(new CexIO()); + addMarket(new Virtex()); + addMarket(new Huobi()); + addMarket(new VaultOfSatoshi()); + addMarket(new CoinMarketIO()); + addMarket(new McxNOW()); + addMarket(new CryptoTrade()); + addMarket(new MintPal()); + addMarket(new CoinJar()); + addMarket(new Poloniex()); + addMarket(new Winkdex()); + addMarket(new Anxpro()); + addMarket(new BitX()); + addMarket(new CCex()); + addMarket(new BitMarketPL()); + addMarket(new Bitorado()); + addMarket(new CryptoRush()); + addMarket(new CoinDesk()); + addMarket(new Koinim()); + addMarket(new FybSE()); + addMarket(new FybSG()); + addMarket(new Prelude()); + addMarket(new BitKonan()); + addMarket(new BitTrex()); + addMarket(new Comkort()); + addMarket(new Bit2c()); + addMarket(new CryptoAltex()); + addMarket(new BtcMarkets()); + addMarket(new SwissCex()); + addMarket(new Bleutrade()); + addMarket(new ShareXcoin()); + addMarket(new Unisend()); + addMarket(new BitcoinVenezuela()); + addMarket(new Korbit()); + addMarket(new CoinTree()); + addMarket(new Cryptonit()); + addMarket(new LakeBTC()); + addMarket(new BitMaszyna()); + addMarket(new BitCore()); + addMarket(new Zaydo()); + addMarket(new AllCoin()); + addMarket(new Ripio()); + addMarket(new DolarBlueNet()); + addMarket(new Basebit()); + addMarket(new CoinSwap()); + addMarket(new Paymium()); + addMarket(new Bitso()); + addMarket(new Cryptoine()); + addMarket(new BitcoinToYou()); + addMarket(new BitexLa()); + addMarket(new ItBit()); + addMarket(new BitcoinCoId()); + addMarket(new HitBtc()); + addMarket(new CleverCoin()); + addMarket(new BitBay()); + addMarket(new FoxBit()); + addMarket(new QuadrigaCX()); + addMarket(new CoinMateIO()); + addMarket(new BitMarket24PL()); + addMarket(new Buttercoin()); + addMarket(new CoinTraderNet()); + addMarket(new LocalBitcoins()); + addMarket(new Cryptopia()); + addMarket(new Igot()); + addMarket(new SevenNineSix()); + addMarket(new Mexbt()); + addMarket(new Vaultoro()); + addMarket(new BitxCom()); + addMarket(new BtcBox()); + addMarket(new BtcXIndia()); + addMarket(new Uphold()); + addMarket(new YoBit()); + addMarket(new ShapeShift()); + addMarket(new BitoEX()); + addMarket(new OKCoinFutures()); +// addMarket(new FoscEx()); + addMarket(new CoinSecure()); + addMarket(new Dashcurex()); + addMarket(new Quoine()); + addMarket(new Livecoin()); + addMarket(new Gemini()); + addMarket(new Coinapult()); + addMarket(new Btc38()); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/config/Settings.java b/dataModule/src/main/java/com/mobnetic/coinguardian/config/Settings.java similarity index 93% rename from DataModule/src/com/mobnetic/coinguardian/config/Settings.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/config/Settings.java index 678ce8a2..cd52411b 100644 --- a/DataModule/src/com/mobnetic/coinguardian/config/Settings.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/config/Settings.java @@ -1,7 +1,7 @@ -package com.mobnetic.coinguardian.config; - -public class Settings { - - public static String userCountry; - -} +package com.mobnetic.coinguardian.config; + +public class Settings { + + public static String userCountry; + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CheckerInfo.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CheckerInfo.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/CheckerInfo.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CheckerInfo.java index 934fe8f4..ed335bc2 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CheckerInfo.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CheckerInfo.java @@ -1,25 +1,25 @@ -package com.mobnetic.coinguardian.model; - -import java.util.Locale; - -public class CheckerInfo extends CurrencyPairInfo { - - protected final int contractType; - - public CheckerInfo(String currencyBase, String currencyCounter, String currencyPairId, int contractType) { - super(currencyBase, currencyCounter, currencyPairId); - this.contractType = contractType; - } - - public String getCurrencyBaseLowerCase() { - return getCurrencyBase().toLowerCase(Locale.US); - } - - public String getCurrencyCounterLowerCase() { - return getCurrencyCounter().toLowerCase(Locale.US); - } - - public int getContractType() { - return contractType; - } -} +package com.mobnetic.coinguardian.model; + +import java.util.Locale; + +public class CheckerInfo extends CurrencyPairInfo { + + protected final int contractType; + + public CheckerInfo(String currencyBase, String currencyCounter, String currencyPairId, int contractType) { + super(currencyBase, currencyCounter, currencyPairId); + this.contractType = contractType; + } + + public String getCurrencyBaseLowerCase() { + return getCurrencyBase().toLowerCase(Locale.US); + } + + public String getCurrencyCounterLowerCase() { + return getCurrencyCounter().toLowerCase(Locale.US); + } + + public int getContractType() { + return contractType; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairInfo.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairInfo.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairInfo.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairInfo.java index 9255f3c3..dc3f689a 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairInfo.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairInfo.java @@ -1,36 +1,36 @@ -package com.mobnetic.coinguardian.model; - - -public class CurrencyPairInfo implements Comparable{ - - protected final String currencyBase; - protected final String currencyCounter; - protected final String currencyPairId; - - public CurrencyPairInfo(String currencyBase, String currencyCounter, String currencyPairId) { - this.currencyBase = currencyBase; - this.currencyCounter = currencyCounter; - this.currencyPairId = currencyPairId; - } - - public String getCurrencyBase() { - return currencyBase; - } - - public String getCurrencyCounter() { - return currencyCounter; - } - - public String getCurrencyPairId() { - return currencyPairId; - } - - @Override - public int compareTo(CurrencyPairInfo another) throws NullPointerException { - if(currencyBase==null || another.currencyBase==null || currencyCounter==null || another.currencyCounter==null) - throw new NullPointerException(); - - int compBase = currencyBase.compareToIgnoreCase(another.currencyBase); - return compBase!=0 ? compBase : currencyCounter.compareToIgnoreCase(another.currencyCounter); - } -} +package com.mobnetic.coinguardian.model; + + +public class CurrencyPairInfo implements Comparable{ + + protected final String currencyBase; + protected final String currencyCounter; + protected final String currencyPairId; + + public CurrencyPairInfo(String currencyBase, String currencyCounter, String currencyPairId) { + this.currencyBase = currencyBase; + this.currencyCounter = currencyCounter; + this.currencyPairId = currencyPairId; + } + + public String getCurrencyBase() { + return currencyBase; + } + + public String getCurrencyCounter() { + return currencyCounter; + } + + public String getCurrencyPairId() { + return currencyPairId; + } + + @Override + public int compareTo(CurrencyPairInfo another) throws NullPointerException { + if(currencyBase==null || another.currencyBase==null || currencyCounter==null || another.currencyCounter==null) + throw new NullPointerException(); + + int compBase = currencyBase.compareToIgnoreCase(another.currencyBase); + return compBase!=0 ? compBase : currencyCounter.compareToIgnoreCase(another.currencyCounter); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java similarity index 94% rename from DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java index 2d52bda5..0648b5b8 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencyPairsListWithDate.java @@ -1,10 +1,10 @@ -package com.mobnetic.coinguardian.model; - -import java.util.List; - -public class CurrencyPairsListWithDate { - - public long date; - public List pairs; - -} +package com.mobnetic.coinguardian.model; + +import java.util.List; + +public class CurrencyPairsListWithDate { + + public long date; + public List pairs; + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunit.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunit.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunit.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunit.java index a4778007..419fb109 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunit.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunit.java @@ -1,18 +1,18 @@ -package com.mobnetic.coinguardian.model; - -public class CurrencySubunit { - - public final String name; - public final long subunitToUnit; - public final boolean allowDecimal; - - public CurrencySubunit(String name, long subunitToUnit) { - this(name, subunitToUnit, true); - } - - public CurrencySubunit(String name, long subunitToUnit, boolean allowDecimal) { - this.name = name; - this.subunitToUnit = subunitToUnit; - this.allowDecimal = allowDecimal; - } -} +package com.mobnetic.coinguardian.model; + +public class CurrencySubunit { + + public final String name; + public final long subunitToUnit; + public final boolean allowDecimal; + + public CurrencySubunit(String name, long subunitToUnit) { + this(name, subunitToUnit, true); + } + + public CurrencySubunit(String name, long subunitToUnit, boolean allowDecimal) { + this.name = name; + this.subunitToUnit = subunitToUnit; + this.allowDecimal = allowDecimal; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java index 8b13736f..09ffc221 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySubunitsMap.java @@ -1,14 +1,14 @@ -package com.mobnetic.coinguardian.model; - -import java.util.LinkedHashMap; - -public class CurrencySubunitsMap extends LinkedHashMap { - - private static final long serialVersionUID = -7219011491064245859L; - - public CurrencySubunitsMap(CurrencySubunit... currencySubunits) { - for(CurrencySubunit currencySubunit : currencySubunits) - put(currencySubunit.subunitToUnit, currencySubunit); - } - -} +package com.mobnetic.coinguardian.model; + +import java.util.LinkedHashMap; + +public class CurrencySubunitsMap extends LinkedHashMap { + + private static final long serialVersionUID = -7219011491064245859L; + + public CurrencySubunitsMap(CurrencySubunit... currencySubunits) { + for(CurrencySubunit currencySubunit : currencySubunits) + put(currencySubunit.subunitToUnit, currencySubunit); + } + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySymbol.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySymbol.java similarity index 95% rename from DataModule/src/com/mobnetic/coinguardian/model/CurrencySymbol.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySymbol.java index 26faea40..7aa0c5e5 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/CurrencySymbol.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/CurrencySymbol.java @@ -1,16 +1,16 @@ -package com.mobnetic.coinguardian.model; - -public class CurrencySymbol { - - public final String symbol; - public final boolean symbolFirst; - - public CurrencySymbol(String symbol) { - this(symbol, false); - } - - public CurrencySymbol(String symbol, boolean symbolFirst) { - this.symbol = symbol; - this.symbolFirst = symbolFirst; - } -} +package com.mobnetic.coinguardian.model; + +public class CurrencySymbol { + + public final String symbol; + public final boolean symbolFirst; + + public CurrencySymbol(String symbol) { + this(symbol, false); + } + + public CurrencySymbol(String symbol, boolean symbolFirst) { + this.symbol = symbol; + this.symbolFirst = symbolFirst; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/Futures.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Futures.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/Futures.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/Futures.java index 9a7bcf4d..3d7d766c 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/Futures.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Futures.java @@ -1,26 +1,26 @@ -package com.mobnetic.coinguardian.model; - -public class Futures { - - public final static int CONTRACT_TYPE_WEEKLY = 0; - public final static int CONTRACT_TYPE_BIWEEKLY = 1; - public final static int CONTRACT_TYPE_MONTHLY = 2; - public final static int CONTRACT_TYPE_BIMONTHLY = 3; - public final static int CONTRACT_TYPE_QUARTERLY = 4; - - private final static String[] CONTRACT_TYPE_SHORT_NAMES = new String[] { - "1W", - "2W", - "1M", - "2M", - "3M" - }; - - public static String getContractTypeShortName(int contractType) { - if (contractType >=0 && contractType < CONTRACT_TYPE_SHORT_NAMES.length) { - return CONTRACT_TYPE_SHORT_NAMES[contractType]; - } - return null; - } - -} +package com.mobnetic.coinguardian.model; + +public class Futures { + + public final static int CONTRACT_TYPE_WEEKLY = 0; + public final static int CONTRACT_TYPE_BIWEEKLY = 1; + public final static int CONTRACT_TYPE_MONTHLY = 2; + public final static int CONTRACT_TYPE_BIMONTHLY = 3; + public final static int CONTRACT_TYPE_QUARTERLY = 4; + + private final static String[] CONTRACT_TYPE_SHORT_NAMES = new String[] { + "1W", + "2W", + "1M", + "2M", + "3M" + }; + + public static String getContractTypeShortName(int contractType) { + if (contractType >=0 && contractType < CONTRACT_TYPE_SHORT_NAMES.length) { + return CONTRACT_TYPE_SHORT_NAMES[contractType]; + } + return null; + } + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/FuturesMarket.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/FuturesMarket.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/FuturesMarket.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/FuturesMarket.java index 4ff1b575..7ffa3f83 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/FuturesMarket.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/FuturesMarket.java @@ -1,22 +1,22 @@ -package com.mobnetic.coinguardian.model; - -import java.util.HashMap; - -public abstract class FuturesMarket extends Market { - - public final int[] contractTypes; - - public FuturesMarket(String name, String ttsName, HashMap currencyPairs, int[] contractTypes) { - super(name, ttsName, currencyPairs); - this.contractTypes = contractTypes; - } - - @Override - public final String getUrl(int requestId, CheckerInfo checkerInfo) { - // TODO Auto-generated method stub - return getUrl(requestId, checkerInfo, checkerInfo.getContractType()); - } - - protected abstract String getUrl(int requestId, CheckerInfo checkerInfo, int contractType); - -} +package com.mobnetic.coinguardian.model; + +import java.util.HashMap; + +public abstract class FuturesMarket extends Market { + + public final int[] contractTypes; + + public FuturesMarket(String name, String ttsName, HashMap currencyPairs, int[] contractTypes) { + super(name, ttsName, currencyPairs); + this.contractTypes = contractTypes; + } + + @Override + public final String getUrl(int requestId, CheckerInfo checkerInfo) { + // TODO Auto-generated method stub + return getUrl(requestId, checkerInfo, checkerInfo.getContractType()); + } + + protected abstract String getUrl(int requestId, CheckerInfo checkerInfo, int contractType); + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/Market.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Market.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/Market.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/Market.java index 40a6fb2e..73ae21a8 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/Market.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Market.java @@ -1,98 +1,98 @@ -package com.mobnetic.coinguardian.model; - -import java.util.HashMap; -import java.util.List; - -import org.json.JSONObject; - -import android.text.TextUtils; - -import com.mobnetic.coinguardian.util.TimeUtils; - -public abstract class Market { - - public final String key; - public final String name; - public final String ttsName; - public HashMap currencyPairs; - - public Market(String name, String ttsName, HashMap currencyPairs) { - this.key = this.getClass().getSimpleName(); - this.name = name; - this.ttsName = ttsName; - this.currencyPairs = currencyPairs; - } - - public int getCautionResId() { - return 0; - } - - - // ==================== - // Parse Ticker - // ==================== - public int getNumOfRequests(CheckerInfo checkerInfo) { - return 1; - } - - public abstract String getUrl(int requestId, CheckerInfo checkerInfo); - - public final Ticker parseTickerMain(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - parseTicker(requestId, responseString, ticker, checkerInfo); - if(ticker.timestamp<=0) - ticker.timestamp = System.currentTimeMillis(); - else - ticker.timestamp = TimeUtils.parseTimeToMillis(ticker.timestamp); - - return ticker; - } - - protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - parseTickerFromJsonObject(requestId, new JSONObject(responseString), ticker, checkerInfo); - } - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - // do parsing - } - - // ==================== - // Parse Error - // ==================== - public final String parseErrorMain(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { - return parseError(requestId, responseString, checkerInfo); - } - - protected String parseError(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { - return parseErrorFromJsonObject(requestId, new JSONObject(responseString), checkerInfo); - } - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - throw new Exception(); - } - - // ==================== - // Parse currency pairs - // ==================== - public int getCurrencyPairsNumOfRequests() { - return 1; - } - - public String getCurrencyPairsUrl(int requestId) { - return null; - } - - public final void parseCurrencyPairsMain(int requestId, String responseString, List pairs) throws Exception { - parseCurrencyPairs(requestId, responseString, pairs); - - for(int i=pairs.size()-1; i>=0; --i) { - CurrencyPairInfo currencyPairInfo = pairs.get(i); - if(currencyPairInfo==null || TextUtils.isEmpty(currencyPairInfo.getCurrencyBase()) || TextUtils.isEmpty(currencyPairInfo.getCurrencyCounter())) - pairs.remove(i); - } - } - - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - parseCurrencyPairsFromJsonObject(requestId, new JSONObject(responseString), pairs); - } - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - // do parsing - } -} +package com.mobnetic.coinguardian.model; + +import java.util.HashMap; +import java.util.List; + +import org.json.JSONObject; + +import android.text.TextUtils; + +import com.mobnetic.coinguardian.util.TimeUtils; + +public abstract class Market { + + public final String key; + public final String name; + public final String ttsName; + public HashMap currencyPairs; + + public Market(String name, String ttsName, HashMap currencyPairs) { + this.key = this.getClass().getSimpleName(); + this.name = name; + this.ttsName = ttsName; + this.currencyPairs = currencyPairs; + } + + public int getCautionResId() { + return 0; + } + + + // ==================== + // Parse Ticker + // ==================== + public int getNumOfRequests(CheckerInfo checkerInfo) { + return 1; + } + + public abstract String getUrl(int requestId, CheckerInfo checkerInfo); + + public final Ticker parseTickerMain(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + parseTicker(requestId, responseString, ticker, checkerInfo); + if(ticker.timestamp<=0) + ticker.timestamp = System.currentTimeMillis(); + else + ticker.timestamp = TimeUtils.parseTimeToMillis(ticker.timestamp); + + return ticker; + } + + protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + parseTickerFromJsonObject(requestId, new JSONObject(responseString), ticker, checkerInfo); + } + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + // do parsing + } + + // ==================== + // Parse Error + // ==================== + public final String parseErrorMain(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { + return parseError(requestId, responseString, checkerInfo); + } + + protected String parseError(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { + return parseErrorFromJsonObject(requestId, new JSONObject(responseString), checkerInfo); + } + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + throw new Exception(); + } + + // ==================== + // Parse currency pairs + // ==================== + public int getCurrencyPairsNumOfRequests() { + return 1; + } + + public String getCurrencyPairsUrl(int requestId) { + return null; + } + + public final void parseCurrencyPairsMain(int requestId, String responseString, List pairs) throws Exception { + parseCurrencyPairs(requestId, responseString, pairs); + + for(int i=pairs.size()-1; i>=0; --i) { + CurrencyPairInfo currencyPairInfo = pairs.get(i); + if(currencyPairInfo==null || TextUtils.isEmpty(currencyPairInfo.getCurrencyBase()) || TextUtils.isEmpty(currencyPairInfo.getCurrencyCounter())) + pairs.remove(i); + } + } + + protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { + parseCurrencyPairsFromJsonObject(requestId, new JSONObject(responseString), pairs); + } + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + // do parsing + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/Ticker.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Ticker.java similarity index 94% rename from DataModule/src/com/mobnetic/coinguardian/model/Ticker.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/Ticker.java index 65c70224..b3a22fff 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/Ticker.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/Ticker.java @@ -1,25 +1,25 @@ -package com.mobnetic.coinguardian.model; - - -public class Ticker { - - public double bid; - public double ask; - public double vol; - public double high; - public double low; - public double last; - public long timestamp; - - public final static int NO_DATA = -1; - - public Ticker() { - bid = NO_DATA; - ask = NO_DATA; - vol = NO_DATA; - high = NO_DATA; - low = NO_DATA; - last = NO_DATA; - timestamp = NO_DATA; - } -} +package com.mobnetic.coinguardian.model; + + +public class Ticker { + + public double bid; + public double ask; + public double vol; + public double high; + public double low; + public double last; + public long timestamp; + + public final static int NO_DATA = -1; + + public Ticker() { + bid = NO_DATA; + ask = NO_DATA; + vol = NO_DATA; + high = NO_DATA; + low = NO_DATA; + last = NO_DATA; + timestamp = NO_DATA; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java index 95149d66..546b6dd7 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrenciesSubunits.java @@ -1,25 +1,25 @@ -package com.mobnetic.coinguardian.model.currency; - -import java.util.HashMap; - -import com.mobnetic.coinguardian.model.CurrencySubunit; -import com.mobnetic.coinguardian.model.CurrencySubunitsMap; - -public class CurrenciesSubunits { - - public final static HashMap CURRENCIES_SUBUNITS = new HashMap(); - static { - CURRENCIES_SUBUNITS.put(VirtualCurrency.BTC, new CurrencySubunitsMap( - new CurrencySubunit(VirtualCurrency.BTC, 1), - new CurrencySubunit(VirtualCurrency.mBTC, 1000), - new CurrencySubunit(VirtualCurrency.uBTC, 1000000), - new CurrencySubunit(VirtualCurrency.Satoshi, 100000000, false) - ) - ); - CURRENCIES_SUBUNITS.put(VirtualCurrency.LTC, new CurrencySubunitsMap( - new CurrencySubunit(VirtualCurrency.LTC, 1), - new CurrencySubunit(VirtualCurrency.mLTC, 1000) - ) - ); - } -} +package com.mobnetic.coinguardian.model.currency; + +import java.util.HashMap; + +import com.mobnetic.coinguardian.model.CurrencySubunit; +import com.mobnetic.coinguardian.model.CurrencySubunitsMap; + +public class CurrenciesSubunits { + + public final static HashMap CURRENCIES_SUBUNITS = new HashMap(); + static { + CURRENCIES_SUBUNITS.put(VirtualCurrency.BTC, new CurrencySubunitsMap( + new CurrencySubunit(VirtualCurrency.BTC, 1), + new CurrencySubunit(VirtualCurrency.mBTC, 1000), + new CurrencySubunit(VirtualCurrency.uBTC, 1000000), + new CurrencySubunit(VirtualCurrency.Satoshi, 100000000, false) + ) + ); + CURRENCIES_SUBUNITS.put(VirtualCurrency.LTC, new CurrencySubunitsMap( + new CurrencySubunit(VirtualCurrency.LTC, 1), + new CurrencySubunit(VirtualCurrency.mLTC, 1000) + ) + ); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/currency/Currency.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/Currency.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/currency/Currency.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/Currency.java index 8c449f2a..7e8642d7 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/currency/Currency.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/Currency.java @@ -1,170 +1,170 @@ -package com.mobnetic.coinguardian.model.currency; - - -public class Currency { - - public static final String AED = "AED"; - public static final String AFN = "AFN"; - public static final String ALL = "ALL"; - public static final String AMD = "AMD"; - public static final String ANG = "ANG"; - public static final String AOA = "AOA"; - public static final String ARS = "ARS"; - public static final String AUD = "AUD"; - public static final String AWG = "AWG"; - public static final String AZN = "AZN"; - public static final String BAM = "BAM"; - public static final String BBD = "BBD"; - public static final String BDT = "BDT"; - public static final String BGN = "BGN"; - public static final String BHD = "BHD"; - public static final String BIF = "BIF"; - public static final String BMD = "BMD"; - public static final String BND = "BND"; - public static final String BOB = "BOB"; - public static final String BRL = "BRL"; - public static final String BSD = "BSD"; - public static final String BTN = "BTN"; - public static final String BWP = "BWP"; - public static final String BYR = "BYR"; - public static final String BZD = "BZD"; - public static final String CAD = "CAD"; - public static final String CDF = "CDF"; - public static final String CHF = "CHF"; - public static final String CLP = "CLP"; - public static final String CNY = "CNY"; - public static final String COP = "COP"; - public static final String CRC = "CRC"; - public static final String CUP = "CUP"; - public static final String CVE = "CVE"; - public static final String CZK = "CZK"; - public static final String DJF = "DJF"; - public static final String DKK = "DKK"; - public static final String DOP = "DOP"; - public static final String DZD = "DZD"; - public static final String EEK = "EEK"; - public static final String EGP = "EGP"; - public static final String ERN = "ERN"; - public static final String ETB = "ETB"; - public static final String EUR = "EUR"; - public static final String FJD = "FJD"; - public static final String FKP = "FKP"; - public static final String GBP = "GBP"; - public static final String GEL = "GEL"; - public static final String GHS = "GHS"; - public static final String GIP = "GIP"; - public static final String GMD = "GMD"; - public static final String GNF = "GNF"; - public static final String GOLD = "GOLD"; - public static final String GTQ = "GTQ"; - public static final String GYD = "GYD"; - public static final String HKD = "HKD"; - public static final String HNL = "HNL"; - public static final String HRK = "HRK"; - public static final String HTG = "HTG"; - public static final String HUF = "HUF"; - public static final String IDR = "IDR"; - public static final String ILS = "ILS"; - public static final String INR = "INR"; - public static final String IQD = "IQD"; - public static final String IRR = "IRR"; - public static final String ISK = "ISK"; - public static final String JMD = "JMD"; - public static final String JOD = "JOD"; - public static final String JPY = "JPY"; - public static final String KES = "KES"; - public static final String KGS = "KGS"; - public static final String KHR = "KHR"; - public static final String KMF = "KMF"; - public static final String KPW = "KPW"; - public static final String KRW = "KRW"; - public static final String KWD = "KWD"; - public static final String KYD = "KYD"; - public static final String KZT = "KZT"; - public static final String LAK = "LAK"; - public static final String LBP = "LBP"; - public static final String LKR = "LKR"; - public static final String LRD = "LRD"; - public static final String LSL = "LSL"; - public static final String LTL = "LTL"; - public static final String LVL = "LVL"; - public static final String LYD = "LYD"; - public static final String MAD = "MAD"; - public static final String MDL = "MDL"; - public static final String MGA = "MGA"; - public static final String MKD = "MKD"; - public static final String MMK = "MMK"; - public static final String MNT = "MNT"; - public static final String MOP = "MOP"; - public static final String MRO = "MRO"; - public static final String MUR = "MUR"; - public static final String MVR = "MVR"; - public static final String MWK = "MWK"; - public static final String MXN = "MXN"; - public static final String MYR = "MYR"; - public static final String MZN = "MZN"; - public static final String NAD = "NAD"; - public static final String NGN = "NGN"; - public static final String NIO = "NIO"; - public static final String NIS = "NIS"; - public static final String NOK = "NOK"; - public static final String NPR = "NPR"; - public static final String NZD = "NZD"; - public static final String OMR = "OMR"; - public static final String PAB = "PAB"; - public static final String PEN = "PEN"; - public static final String PGK = "PGK"; - public static final String PHP = "PHP"; - public static final String PKR = "PKR"; - public static final String PLN = "PLN"; - public static final String PYG = "PYG"; - public static final String QAR = "QAR"; - public static final String RON = "RON"; - public static final String RSD = "RSD"; - public static final String RUB = "RUB"; - public static final String RUR = "RUR"; - public static final String RWF = "RWF"; - public static final String SAR = "SAR"; - public static final String SBD = "SBD"; - public static final String SCR = "SCR"; - public static final String SDG = "SDG"; - public static final String SEK = "SEK"; - public static final String SGD = "SGD"; - public static final String SHP = "SHP"; - public static final String SLL = "SLL"; - public static final String SOS = "SOS"; - public static final String SRD = "SRD"; - public static final String STD = "STD"; - public static final String SVC = "SVC"; - public static final String SYP = "SYP"; - public static final String SZL = "SZL"; - public static final String THB = "THB"; - public static final String TJS = "TJS"; - public static final String TMM = "TMM"; - public static final String TND = "TND"; - public static final String TOP = "TOP"; - public static final String TRY = "TRY"; - public static final String TTD = "TTD"; - public static final String TWD = "TWD"; - public static final String TZS = "TZS"; - public static final String UAH = "UAH"; - public static final String UGX = "UGX"; - public static final String USD = "USD"; - public static final String UYU = "UYU"; - public static final String UZS = "UZS"; - public static final String VEF = "VEF"; - public static final String VND = "VND"; - public static final String VUV = "VUV"; - public static final String WST = "WST"; - public static final String XAF = "XAF"; - public static final String XAG = "XAG"; - public static final String XAU = "XAU"; - public static final String XCD = "XCD"; - public static final String XOF = "XOF"; - public static final String XPF = "XPF"; - public static final String YER = "YER"; - public static final String ZAR = "ZAR"; - public static final String ZMK = "ZMK"; - public static final String ZWL = "ZWL"; - -} +package com.mobnetic.coinguardian.model.currency; + + +public class Currency { + + public static final String AED = "AED"; + public static final String AFN = "AFN"; + public static final String ALL = "ALL"; + public static final String AMD = "AMD"; + public static final String ANG = "ANG"; + public static final String AOA = "AOA"; + public static final String ARS = "ARS"; + public static final String AUD = "AUD"; + public static final String AWG = "AWG"; + public static final String AZN = "AZN"; + public static final String BAM = "BAM"; + public static final String BBD = "BBD"; + public static final String BDT = "BDT"; + public static final String BGN = "BGN"; + public static final String BHD = "BHD"; + public static final String BIF = "BIF"; + public static final String BMD = "BMD"; + public static final String BND = "BND"; + public static final String BOB = "BOB"; + public static final String BRL = "BRL"; + public static final String BSD = "BSD"; + public static final String BTN = "BTN"; + public static final String BWP = "BWP"; + public static final String BYR = "BYR"; + public static final String BZD = "BZD"; + public static final String CAD = "CAD"; + public static final String CDF = "CDF"; + public static final String CHF = "CHF"; + public static final String CLP = "CLP"; + public static final String CNY = "CNY"; + public static final String COP = "COP"; + public static final String CRC = "CRC"; + public static final String CUP = "CUP"; + public static final String CVE = "CVE"; + public static final String CZK = "CZK"; + public static final String DJF = "DJF"; + public static final String DKK = "DKK"; + public static final String DOP = "DOP"; + public static final String DZD = "DZD"; + public static final String EEK = "EEK"; + public static final String EGP = "EGP"; + public static final String ERN = "ERN"; + public static final String ETB = "ETB"; + public static final String EUR = "EUR"; + public static final String FJD = "FJD"; + public static final String FKP = "FKP"; + public static final String GBP = "GBP"; + public static final String GEL = "GEL"; + public static final String GHS = "GHS"; + public static final String GIP = "GIP"; + public static final String GMD = "GMD"; + public static final String GNF = "GNF"; + public static final String GOLD = "GOLD"; + public static final String GTQ = "GTQ"; + public static final String GYD = "GYD"; + public static final String HKD = "HKD"; + public static final String HNL = "HNL"; + public static final String HRK = "HRK"; + public static final String HTG = "HTG"; + public static final String HUF = "HUF"; + public static final String IDR = "IDR"; + public static final String ILS = "ILS"; + public static final String INR = "INR"; + public static final String IQD = "IQD"; + public static final String IRR = "IRR"; + public static final String ISK = "ISK"; + public static final String JMD = "JMD"; + public static final String JOD = "JOD"; + public static final String JPY = "JPY"; + public static final String KES = "KES"; + public static final String KGS = "KGS"; + public static final String KHR = "KHR"; + public static final String KMF = "KMF"; + public static final String KPW = "KPW"; + public static final String KRW = "KRW"; + public static final String KWD = "KWD"; + public static final String KYD = "KYD"; + public static final String KZT = "KZT"; + public static final String LAK = "LAK"; + public static final String LBP = "LBP"; + public static final String LKR = "LKR"; + public static final String LRD = "LRD"; + public static final String LSL = "LSL"; + public static final String LTL = "LTL"; + public static final String LVL = "LVL"; + public static final String LYD = "LYD"; + public static final String MAD = "MAD"; + public static final String MDL = "MDL"; + public static final String MGA = "MGA"; + public static final String MKD = "MKD"; + public static final String MMK = "MMK"; + public static final String MNT = "MNT"; + public static final String MOP = "MOP"; + public static final String MRO = "MRO"; + public static final String MUR = "MUR"; + public static final String MVR = "MVR"; + public static final String MWK = "MWK"; + public static final String MXN = "MXN"; + public static final String MYR = "MYR"; + public static final String MZN = "MZN"; + public static final String NAD = "NAD"; + public static final String NGN = "NGN"; + public static final String NIO = "NIO"; + public static final String NIS = "NIS"; + public static final String NOK = "NOK"; + public static final String NPR = "NPR"; + public static final String NZD = "NZD"; + public static final String OMR = "OMR"; + public static final String PAB = "PAB"; + public static final String PEN = "PEN"; + public static final String PGK = "PGK"; + public static final String PHP = "PHP"; + public static final String PKR = "PKR"; + public static final String PLN = "PLN"; + public static final String PYG = "PYG"; + public static final String QAR = "QAR"; + public static final String RON = "RON"; + public static final String RSD = "RSD"; + public static final String RUB = "RUB"; + public static final String RUR = "RUR"; + public static final String RWF = "RWF"; + public static final String SAR = "SAR"; + public static final String SBD = "SBD"; + public static final String SCR = "SCR"; + public static final String SDG = "SDG"; + public static final String SEK = "SEK"; + public static final String SGD = "SGD"; + public static final String SHP = "SHP"; + public static final String SLL = "SLL"; + public static final String SOS = "SOS"; + public static final String SRD = "SRD"; + public static final String STD = "STD"; + public static final String SVC = "SVC"; + public static final String SYP = "SYP"; + public static final String SZL = "SZL"; + public static final String THB = "THB"; + public static final String TJS = "TJS"; + public static final String TMM = "TMM"; + public static final String TND = "TND"; + public static final String TOP = "TOP"; + public static final String TRY = "TRY"; + public static final String TTD = "TTD"; + public static final String TWD = "TWD"; + public static final String TZS = "TZS"; + public static final String UAH = "UAH"; + public static final String UGX = "UGX"; + public static final String USD = "USD"; + public static final String UYU = "UYU"; + public static final String UZS = "UZS"; + public static final String VEF = "VEF"; + public static final String VND = "VND"; + public static final String VUV = "VUV"; + public static final String WST = "WST"; + public static final String XAF = "XAF"; + public static final String XAG = "XAG"; + public static final String XAU = "XAU"; + public static final String XCD = "XCD"; + public static final String XOF = "XOF"; + public static final String XPF = "XPF"; + public static final String YER = "YER"; + public static final String ZAR = "ZAR"; + public static final String ZMK = "ZMK"; + public static final String ZWL = "ZWL"; + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java index eb8af416..5b4375b1 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/CurrencySymbols.java @@ -1,55 +1,55 @@ -package com.mobnetic.coinguardian.model.currency; - -import java.util.HashMap; - -public class CurrencySymbols { - - public final static HashMap CURRENCY_SYMBOLS = new HashMap(); - static { - CURRENCY_SYMBOLS.put(Currency.USD, "$"); - CURRENCY_SYMBOLS.put(Currency.PLN, "zÅ‚"); - CURRENCY_SYMBOLS.put(Currency.CNY, "Â¥"); - CURRENCY_SYMBOLS.put(Currency.EUR, "€"); -// CURRENCY_SYMBOLS.put(CAD, "$"); - CURRENCY_SYMBOLS.put(Currency.GBP, "£"); - CURRENCY_SYMBOLS.put(Currency.CHF, "Fr"); - CURRENCY_SYMBOLS.put(Currency.RUB, "Ñ€."); - CURRENCY_SYMBOLS.put(Currency.RUR, "Ñ€."); - CURRENCY_SYMBOLS.put(Currency.AUD, "$"); - CURRENCY_SYMBOLS.put(Currency.SEK, "kr"); - CURRENCY_SYMBOLS.put(Currency.DKK, "kr"); - CURRENCY_SYMBOLS.put(Currency.HKD, "$"); - CURRENCY_SYMBOLS.put(Currency.SGD, "$"); - CURRENCY_SYMBOLS.put(Currency.THB, "฿"); - CURRENCY_SYMBOLS.put(Currency.NZD, "$"); - CURRENCY_SYMBOLS.put(Currency.JPY, "Â¥"); - CURRENCY_SYMBOLS.put(Currency.BRL, "R$"); - CURRENCY_SYMBOLS.put(Currency.KRW, "â‚©"); - - CURRENCY_SYMBOLS.put(Currency.AFN, "Ø‹"); - CURRENCY_SYMBOLS.put(Currency.ALL, "L"); - CURRENCY_SYMBOLS.put(Currency.DZD, "د.ج"); - CURRENCY_SYMBOLS.put(Currency.AOA, "Kz"); - CURRENCY_SYMBOLS.put(Currency.ARS, "$"); - CURRENCY_SYMBOLS.put(Currency.AMD, "Õ¤Ö€."); - CURRENCY_SYMBOLS.put(Currency.AWG, "Æ’"); - CURRENCY_SYMBOLS.put(Currency.AZN, "m"); - CURRENCY_SYMBOLS.put(Currency.BSD, "$"); - CURRENCY_SYMBOLS.put(Currency.BHD, "ب.د"); - CURRENCY_SYMBOLS.put(Currency.BDT, "৳"); - CURRENCY_SYMBOLS.put(Currency.BBD, "$"); - CURRENCY_SYMBOLS.put(Currency.BYR, "Br"); - CURRENCY_SYMBOLS.put(Currency.BZD, "$"); - CURRENCY_SYMBOLS.put(Currency.BMD, "$"); - CURRENCY_SYMBOLS.put(Currency.BTN, "Nu."); - CURRENCY_SYMBOLS.put(Currency.BOB, "Bs."); - CURRENCY_SYMBOLS.put(Currency.BAM, "КМ"); - CURRENCY_SYMBOLS.put(Currency.BWP, "P"); - CURRENCY_SYMBOLS.put(Currency.BND, "$"); - CURRENCY_SYMBOLS.put(Currency.BGN, "лв"); - CURRENCY_SYMBOLS.put(Currency.BIF, "Fr"); - CURRENCY_SYMBOLS.put(Currency.TRY, "TL"); - CURRENCY_SYMBOLS.put(Currency.ZAR, "R"); - CURRENCY_SYMBOLS.put(Currency.IDR, "Rp"); - } -} +package com.mobnetic.coinguardian.model.currency; + +import java.util.HashMap; + +public class CurrencySymbols { + + public final static HashMap CURRENCY_SYMBOLS = new HashMap(); + static { + CURRENCY_SYMBOLS.put(Currency.USD, "$"); + CURRENCY_SYMBOLS.put(Currency.PLN, "zÅ‚"); + CURRENCY_SYMBOLS.put(Currency.CNY, "Â¥"); + CURRENCY_SYMBOLS.put(Currency.EUR, "€"); +// CURRENCY_SYMBOLS.put(CAD, "$"); + CURRENCY_SYMBOLS.put(Currency.GBP, "£"); + CURRENCY_SYMBOLS.put(Currency.CHF, "Fr"); + CURRENCY_SYMBOLS.put(Currency.RUB, "Ñ€."); + CURRENCY_SYMBOLS.put(Currency.RUR, "Ñ€."); + CURRENCY_SYMBOLS.put(Currency.AUD, "$"); + CURRENCY_SYMBOLS.put(Currency.SEK, "kr"); + CURRENCY_SYMBOLS.put(Currency.DKK, "kr"); + CURRENCY_SYMBOLS.put(Currency.HKD, "$"); + CURRENCY_SYMBOLS.put(Currency.SGD, "$"); + CURRENCY_SYMBOLS.put(Currency.THB, "฿"); + CURRENCY_SYMBOLS.put(Currency.NZD, "$"); + CURRENCY_SYMBOLS.put(Currency.JPY, "Â¥"); + CURRENCY_SYMBOLS.put(Currency.BRL, "R$"); + CURRENCY_SYMBOLS.put(Currency.KRW, "â‚©"); + + CURRENCY_SYMBOLS.put(Currency.AFN, "Ø‹"); + CURRENCY_SYMBOLS.put(Currency.ALL, "L"); + CURRENCY_SYMBOLS.put(Currency.DZD, "د.ج"); + CURRENCY_SYMBOLS.put(Currency.AOA, "Kz"); + CURRENCY_SYMBOLS.put(Currency.ARS, "$"); + CURRENCY_SYMBOLS.put(Currency.AMD, "Õ¤Ö€."); + CURRENCY_SYMBOLS.put(Currency.AWG, "Æ’"); + CURRENCY_SYMBOLS.put(Currency.AZN, "m"); + CURRENCY_SYMBOLS.put(Currency.BSD, "$"); + CURRENCY_SYMBOLS.put(Currency.BHD, "ب.د"); + CURRENCY_SYMBOLS.put(Currency.BDT, "৳"); + CURRENCY_SYMBOLS.put(Currency.BBD, "$"); + CURRENCY_SYMBOLS.put(Currency.BYR, "Br"); + CURRENCY_SYMBOLS.put(Currency.BZD, "$"); + CURRENCY_SYMBOLS.put(Currency.BMD, "$"); + CURRENCY_SYMBOLS.put(Currency.BTN, "Nu."); + CURRENCY_SYMBOLS.put(Currency.BOB, "Bs."); + CURRENCY_SYMBOLS.put(Currency.BAM, "КМ"); + CURRENCY_SYMBOLS.put(Currency.BWP, "P"); + CURRENCY_SYMBOLS.put(Currency.BND, "$"); + CURRENCY_SYMBOLS.put(Currency.BGN, "лв"); + CURRENCY_SYMBOLS.put(Currency.BIF, "Fr"); + CURRENCY_SYMBOLS.put(Currency.TRY, "TL"); + CURRENCY_SYMBOLS.put(Currency.ZAR, "R"); + CURRENCY_SYMBOLS.put(Currency.IDR, "Rp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java index de09f7f9..998a2b12 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/currency/VirtualCurrency.java @@ -1,343 +1,343 @@ -package com.mobnetic.coinguardian.model.currency; - -public class VirtualCurrency { - - public static final String _10_5 = "10-5"; - public static final String _21 = "21"; - public static final String _42 = "42"; - public static final String _66 = "66"; - public static final String _888 = "888"; - public static final String ADT = "ADT"; - public static final String ALB = "ALB"; - public static final String ALF = "ALF"; - public static final String ALP = "ALP"; - public static final String ALT = "ALT"; - public static final String AMC = "AMC"; - public static final String ANC = "ANC"; - public static final String ANI = "ANI"; - public static final String ANT = "ANT"; - public static final String ARG = "ARG"; - public static final String ASC = "ASC"; - public static final String AUR = "AUR"; - public static final String BAT = "BAT"; - public static final String BC = "BC"; - public static final String BCC = "BCC"; - public static final String BCX = "BCX"; - public static final String BEE = "BEE"; - public static final String BEER = "BEER"; - public static final String BELA = "BELA"; - public static final String BELI = "BELI"; - public static final String BEN = "BEN"; - public static final String BET = "BET"; - public static final String BF1 = "BF1"; - public static final String BIL = "BIL"; - public static final String BLA = "BLA"; - public static final String BLC = "BLC"; - public static final String BQC = "BQC"; - public static final String BTB = "BTB"; - public static final String BTC = "BTC"; - public static final String mBTC = "mBTC"; - public static final String uBTC = "µBTC"; - public static final String Satoshi = "Satoshi"; - public static final String BTCS = "BTCS"; - public static final String BTE = "BTE"; - public static final String BTG = "BTG"; - public static final String BTP = "BTP"; - public static final String BTQ = "BTQ"; - public static final String BTR = "BTR"; - public static final String BUK = "BUK"; - public static final String BUR = "BUR"; - public static final String C2 = "C2"; - public static final String CACH = "CACH"; - public static final String CAGE = "CAGE"; - public static final String CAP = "CAP"; - public static final String CARB = "CARB"; - public static final String CASH = "CASH"; - public static final String CAT = "CAT"; - public static final String CDC = "CDC"; - public static final String CENT = "CENT"; - public static final String CGA = "CGA"; - public static final String CGB = "CGB"; - public static final String CIN = "CIN"; - public static final String CL = "CL"; - public static final String CLR = "CLR"; - public static final String CMC = "CMC"; - public static final String CNC = "CNC"; - public static final String CNOTE = "CNOTE"; - public static final String COIN = "COIN"; - public static final String COINO = "COINO"; - public static final String COL = "COL"; - public static final String COLA = "COLA"; - public static final String CON = "CON"; - public static final String CORG = "CORG"; - public static final String CPR = "CPR"; - public static final String CR = "CR"; - public static final String CRA = "CRA"; - public static final String CRC = "CRC"; - public static final String CRD = "CRD"; - public static final String CREA = "CREA"; - public static final String CRN = "CRN"; - public static final String CRS = "CRS"; - public static final String CSC = "CSC"; - public static final String CTM = "CTM"; - public static final String DASH = "DASH"; - public static final String DBL = "DBL"; - public static final String DELTA = "DELTA"; - public static final String DEM = "DEM"; - public static final String DGB = "DGB"; - public static final String DGC = "DGC"; - public static final String DIME = "DIME"; - public static final String DMD = "DMD"; - public static final String DOG = "DOG"; - public static final String DOGE = "DOGE"; - public static final String DOPE = "DOPE"; - public static final String DRK = "DRK"; - public static final String DTC = "DTC"; - public static final String DUCK = "DUCK"; - public static final String DVC = "DVC"; - public static final String EAC = "EAC"; - public static final String ECC = "ECC"; - public static final String ECN = "ECN"; - public static final String ELC = "ELC"; - public static final String ELP = "ELP"; - public static final String EMC2 = "EMC2"; - public static final String EMD = "EMD"; - public static final String EMO = "EMO"; - public static final String ETH = "ETH"; - public static final String ETOK = "ETOK"; - public static final String eTOK = "eTOK"; - public static final String EUC = "EUC"; - public static final String EXC = "EXC"; - public static final String EZC = "EZC"; - public static final String FCK = "FCK"; - public static final String FFC = "FFC"; - public static final String FLAP = "FLAP"; - public static final String FLO = "FLO"; - public static final String FLT = "FLT"; - public static final String FOX = "FOX"; - public static final String FRC = "FRC"; - public static final String FRK = "FRK"; - public static final String FRQ = "FRQ"; - public static final String FRY = "FRY"; - public static final String FRZ = "FRZ"; - public static final String FSC = "FSC"; - public static final String FSS = "FSS"; - public static final String FST = "FST"; - public static final String FTC = "FTC"; - public static final String FUNK = "FUNK"; - public static final String FZ = "FZ"; - public static final String GDC = "GDC"; - public static final String GHS = "GHS"; - public static final String GLB = "GLB"; - public static final String GLC = "GLC"; - public static final String GLD = "GLD"; - public static final String GLX = "GLX"; - public static final String GME = "GME"; - public static final String GOAT = "GOAT"; - public static final String GOX = "GOX"; - public static final String GPUC = "GPUC"; - public static final String GRC = "GRC"; - public static final String GRUMP = "GRUMP"; - public static final String HBN = "HBN"; - public static final String HEX = "HEX"; - public static final String HIRO = "HIRO"; - public static final String HRO = "HRO"; - public static final String HUC = "HUC"; - public static final String HVC = "HVC"; - public static final String HXC = "HXC"; - public static final String HYC = "HYC"; - public static final String I0C = "I0C"; - public static final String ICN = "ICN"; - public static final String IFC = "IFC"; - public static final String IND = "IND"; - public static final String IQD = "IQD"; - public static final String IXC = "IXC"; - public static final String JKC = "JKC"; - public static final String JRY = "JRY"; - public static final String KARM = "KARM"; - public static final String KDC = "KDC"; - public static final String KGC = "KGC"; - public static final String KKC = "KKC"; - public static final String KNC = "KNC"; - public static final String KOI = "KOI"; - public static final String KRN = "KRN"; - public static final String KUN = "KUN"; - public static final String LBW = "LBW"; - public static final String LDC = "LDC"; - public static final String LEAF = "LEAF"; - public static final String LGBT = "LGBT"; - public static final String LGC = "LGC"; - public static final String LK7 = "LK7"; - public static final String LKY = "LKY"; - public static final String LMC = "LMC"; - public static final String LOT = "LOT"; - public static final String LTB = "LTB"; - public static final String LTC = "LTC"; - public static final String mLTC = "mLTC"; - public static final String LYC = "LYC"; - public static final String MAX = "MAX"; - public static final String MCR = "MCR"; - public static final String MCX = "MCX"; - public static final String MEC = "MEC"; - public static final String MEM = "MEM"; - public static final String MEOW = "MEOW"; - public static final String MIM = "MIM"; - public static final String MINT = "MINT"; - public static final String MMC = "MMC"; - public static final String MNC = "MNC"; - public static final String MOON = "MOON"; - public static final String MRC = "MRC"; - public static final String MRS = "MRS"; - public static final String MRY = "MRY"; - public static final String MSC = "MSC"; - public static final String MST = "MST"; - public static final String MTC = "MTC"; - public static final String MTS = "MTS"; - public static final String MXB = "MXB"; - public static final String MXN = "MXN"; - public static final String MYMINER = "MYMINER"; - public static final String MYR = "MYR"; - public static final String MZC = "MZC"; - public static final String NAN = "NAN"; - public static final String NBL = "NBL"; - public static final String NDL = "NDL"; - public static final String NEC = "NEC"; - public static final String NET = "NET"; - public static final String NIB = "NIB"; - public static final String NKA = "NKA"; - public static final String NMC = "NMC"; - public static final String NOBL = "NOBL"; - public static final String NOTE = "NOTE"; - public static final String NRB = "NRB"; - public static final String NUC = "NUC"; - public static final String NVC = "NVC"; - public static final String NXT = "NXT"; - public static final String NYAN = "NYAN"; - public static final String OIL = "OIL"; - public static final String OLY = "OLY"; - public static final String ORB = "ORB"; - public static final String ORG = "ORG"; - public static final String ORO = "ORO"; - public static final String OSC = "OSC"; - public static final String P$ = "P$"; - public static final String PAND = "PAND"; - public static final String PANDA = "PANDA"; - public static final String PCC = "PCC"; - public static final String PCN = "PCN"; - public static final String PENG = "PENG"; - public static final String PHI = "PHI"; - public static final String PHS = "PHS"; - public static final String PIC = "PIC"; - public static final String PLC = "PLC"; - public static final String PLT = "PLT"; - public static final String PMC = "PMC"; - public static final String PND = "PND"; - public static final String POD = "POD"; - public static final String POINTS = "POINTS"; - public static final String POT = "POT"; - public static final String PPC = "PPC"; - public static final String PRC = "PRC"; - public static final String PRT = "PRT"; - public static final String PT = "PT"; - public static final String PTC = "PTC"; - public static final String PTS = "PTS"; - public static final String PWC = "PWC"; - public static final String PWNY = "PWNY"; - public static final String PXC = "PXC"; - public static final String PXL = "PXL"; - public static final String PYC = "PYC"; - public static final String Q2C = "Q2C"; - public static final String QB = "QB"; - public static final String QRK = "QRK"; - public static final String RAD = "RAD"; - public static final String RAIN = "RAIN"; - public static final String RBBT = "RBBT"; - public static final String RCH = "RCH"; - public static final String RDD = "RDD"; - public static final String REC = "REC"; - public static final String RED = "RED"; - public static final String REDD = "REDD"; // RDD - public static final String RIC = "RIC"; - public static final String RON = "RON"; - public static final String RPC = "RPC"; - public static final String RPD = "RPD"; - public static final String RSC = "RSC"; - public static final String RBY = "RBY"; - public static final String RYC = "RYC"; - public static final String SAT = "SAT"; - public static final String SAV = "SAV"; - public static final String SBC = "SBC"; - public static final String SBX = "SBX"; - public static final String SC = "SC"; - public static final String SCO = "SCO"; - public static final String SMC = "SMC"; - public static final String SOC = "SOC"; - public static final String SOCHI = "SOCHI"; - public static final String SPA = "SPA"; - public static final String SPT = "SPT"; - public static final String SRC = "SRC"; - public static final String START = "START"; - public static final String STC = "STC"; - public static final String STL = "STL"; - public static final String STR = "STR"; - public static final String STY = "STY"; - public static final String SUN = "SUN"; - public static final String SXC = "SXC"; - public static final String SYN = "SYN"; - public static final String TAG = "TAG"; - public static final String TAK = "TAK"; - public static final String TEA = "TEA"; - public static final String TEK = "TEK"; - public static final String TEL = "TEL"; - public static final String TES = "TES"; - public static final String TFC = "TFC"; - public static final String TGC = "TGC"; - public static final String TH1 = "TH1"; - public static final String THOR = "THOR"; - public static final String TIPS = "TIPS"; - public static final String TIX = "TIX"; - public static final String TOP = "TOP"; - public static final String TRC = "TRC"; - public static final String TRL = "TRL"; - public static final String TTC = "TTC"; - public static final String UFO = "UFO"; - public static final String UNC = "UNC"; - public static final String UNI = "UNI"; - public static final String UNO = "UNO"; - public static final String USDE = "USDE"; - public static final String USDe = "USDe"; - public static final String UTC = "UTC"; - public static final String VDC = "VDC"; - public static final String VEN = "VEN"; - public static final String VGC = "VGC"; - public static final String VLC = "VLC"; - public static final String VLT = "VLT"; - public static final String VMP = "VMP"; - public static final String VOLT = "VOLT"; - public static final String VTC = "VTC"; - public static final String WDC = "WDC"; - public static final String WIKI = "WIKI"; - public static final String WOLF = "WOLF"; - public static final String XBT = "XBT"; // BTC - public static final String XCP = "XCP"; - public static final String XDG = "XDG"; // DOGE - public static final String XIV = "XIV"; - public static final String XJO = "XJO"; - public static final String XNC = "XNC"; - public static final String XPM = "XPM"; - public static final String XPY = "XPY"; - public static final String XRP = "XRP"; - public static final String XVN = "XVN"; // VEN - public static final String XXL = "XXL"; - public static final String YAC = "YAC"; - public static final String YANG = "YANG"; - public static final String YBC = "YBC"; - public static final String YIN = "YIN"; - public static final String ZCC = "ZCC"; - public static final String ZED = "ZED"; - public static final String ZEIT = "ZEIT"; - public static final String ZET = "ZET"; - public static final String ZEU = "ZEU"; - public static final String ZMB = "ZMB"; - public static final String ZTC = "ZTC"; -} +package com.mobnetic.coinguardian.model.currency; + +public class VirtualCurrency { + + public static final String _10_5 = "10-5"; + public static final String _21 = "21"; + public static final String _42 = "42"; + public static final String _66 = "66"; + public static final String _888 = "888"; + public static final String ADT = "ADT"; + public static final String ALB = "ALB"; + public static final String ALF = "ALF"; + public static final String ALP = "ALP"; + public static final String ALT = "ALT"; + public static final String AMC = "AMC"; + public static final String ANC = "ANC"; + public static final String ANI = "ANI"; + public static final String ANT = "ANT"; + public static final String ARG = "ARG"; + public static final String ASC = "ASC"; + public static final String AUR = "AUR"; + public static final String BAT = "BAT"; + public static final String BC = "BC"; + public static final String BCC = "BCC"; + public static final String BCX = "BCX"; + public static final String BEE = "BEE"; + public static final String BEER = "BEER"; + public static final String BELA = "BELA"; + public static final String BELI = "BELI"; + public static final String BEN = "BEN"; + public static final String BET = "BET"; + public static final String BF1 = "BF1"; + public static final String BIL = "BIL"; + public static final String BLA = "BLA"; + public static final String BLC = "BLC"; + public static final String BQC = "BQC"; + public static final String BTB = "BTB"; + public static final String BTC = "BTC"; + public static final String mBTC = "mBTC"; + public static final String uBTC = "µBTC"; + public static final String Satoshi = "Satoshi"; + public static final String BTCS = "BTCS"; + public static final String BTE = "BTE"; + public static final String BTG = "BTG"; + public static final String BTP = "BTP"; + public static final String BTQ = "BTQ"; + public static final String BTR = "BTR"; + public static final String BUK = "BUK"; + public static final String BUR = "BUR"; + public static final String C2 = "C2"; + public static final String CACH = "CACH"; + public static final String CAGE = "CAGE"; + public static final String CAP = "CAP"; + public static final String CARB = "CARB"; + public static final String CASH = "CASH"; + public static final String CAT = "CAT"; + public static final String CDC = "CDC"; + public static final String CENT = "CENT"; + public static final String CGA = "CGA"; + public static final String CGB = "CGB"; + public static final String CIN = "CIN"; + public static final String CL = "CL"; + public static final String CLR = "CLR"; + public static final String CMC = "CMC"; + public static final String CNC = "CNC"; + public static final String CNOTE = "CNOTE"; + public static final String COIN = "COIN"; + public static final String COINO = "COINO"; + public static final String COL = "COL"; + public static final String COLA = "COLA"; + public static final String CON = "CON"; + public static final String CORG = "CORG"; + public static final String CPR = "CPR"; + public static final String CR = "CR"; + public static final String CRA = "CRA"; + public static final String CRC = "CRC"; + public static final String CRD = "CRD"; + public static final String CREA = "CREA"; + public static final String CRN = "CRN"; + public static final String CRS = "CRS"; + public static final String CSC = "CSC"; + public static final String CTM = "CTM"; + public static final String DASH = "DASH"; + public static final String DBL = "DBL"; + public static final String DELTA = "DELTA"; + public static final String DEM = "DEM"; + public static final String DGB = "DGB"; + public static final String DGC = "DGC"; + public static final String DIME = "DIME"; + public static final String DMD = "DMD"; + public static final String DOG = "DOG"; + public static final String DOGE = "DOGE"; + public static final String DOPE = "DOPE"; + public static final String DRK = "DRK"; + public static final String DTC = "DTC"; + public static final String DUCK = "DUCK"; + public static final String DVC = "DVC"; + public static final String EAC = "EAC"; + public static final String ECC = "ECC"; + public static final String ECN = "ECN"; + public static final String ELC = "ELC"; + public static final String ELP = "ELP"; + public static final String EMC2 = "EMC2"; + public static final String EMD = "EMD"; + public static final String EMO = "EMO"; + public static final String ETH = "ETH"; + public static final String ETOK = "ETOK"; + public static final String eTOK = "eTOK"; + public static final String EUC = "EUC"; + public static final String EXC = "EXC"; + public static final String EZC = "EZC"; + public static final String FCK = "FCK"; + public static final String FFC = "FFC"; + public static final String FLAP = "FLAP"; + public static final String FLO = "FLO"; + public static final String FLT = "FLT"; + public static final String FOX = "FOX"; + public static final String FRC = "FRC"; + public static final String FRK = "FRK"; + public static final String FRQ = "FRQ"; + public static final String FRY = "FRY"; + public static final String FRZ = "FRZ"; + public static final String FSC = "FSC"; + public static final String FSS = "FSS"; + public static final String FST = "FST"; + public static final String FTC = "FTC"; + public static final String FUNK = "FUNK"; + public static final String FZ = "FZ"; + public static final String GDC = "GDC"; + public static final String GHS = "GHS"; + public static final String GLB = "GLB"; + public static final String GLC = "GLC"; + public static final String GLD = "GLD"; + public static final String GLX = "GLX"; + public static final String GME = "GME"; + public static final String GOAT = "GOAT"; + public static final String GOX = "GOX"; + public static final String GPUC = "GPUC"; + public static final String GRC = "GRC"; + public static final String GRUMP = "GRUMP"; + public static final String HBN = "HBN"; + public static final String HEX = "HEX"; + public static final String HIRO = "HIRO"; + public static final String HRO = "HRO"; + public static final String HUC = "HUC"; + public static final String HVC = "HVC"; + public static final String HXC = "HXC"; + public static final String HYC = "HYC"; + public static final String I0C = "I0C"; + public static final String ICN = "ICN"; + public static final String IFC = "IFC"; + public static final String IND = "IND"; + public static final String IQD = "IQD"; + public static final String IXC = "IXC"; + public static final String JKC = "JKC"; + public static final String JRY = "JRY"; + public static final String KARM = "KARM"; + public static final String KDC = "KDC"; + public static final String KGC = "KGC"; + public static final String KKC = "KKC"; + public static final String KNC = "KNC"; + public static final String KOI = "KOI"; + public static final String KRN = "KRN"; + public static final String KUN = "KUN"; + public static final String LBW = "LBW"; + public static final String LDC = "LDC"; + public static final String LEAF = "LEAF"; + public static final String LGBT = "LGBT"; + public static final String LGC = "LGC"; + public static final String LK7 = "LK7"; + public static final String LKY = "LKY"; + public static final String LMC = "LMC"; + public static final String LOT = "LOT"; + public static final String LTB = "LTB"; + public static final String LTC = "LTC"; + public static final String mLTC = "mLTC"; + public static final String LYC = "LYC"; + public static final String MAX = "MAX"; + public static final String MCR = "MCR"; + public static final String MCX = "MCX"; + public static final String MEC = "MEC"; + public static final String MEM = "MEM"; + public static final String MEOW = "MEOW"; + public static final String MIM = "MIM"; + public static final String MINT = "MINT"; + public static final String MMC = "MMC"; + public static final String MNC = "MNC"; + public static final String MOON = "MOON"; + public static final String MRC = "MRC"; + public static final String MRS = "MRS"; + public static final String MRY = "MRY"; + public static final String MSC = "MSC"; + public static final String MST = "MST"; + public static final String MTC = "MTC"; + public static final String MTS = "MTS"; + public static final String MXB = "MXB"; + public static final String MXN = "MXN"; + public static final String MYMINER = "MYMINER"; + public static final String MYR = "MYR"; + public static final String MZC = "MZC"; + public static final String NAN = "NAN"; + public static final String NBL = "NBL"; + public static final String NDL = "NDL"; + public static final String NEC = "NEC"; + public static final String NET = "NET"; + public static final String NIB = "NIB"; + public static final String NKA = "NKA"; + public static final String NMC = "NMC"; + public static final String NOBL = "NOBL"; + public static final String NOTE = "NOTE"; + public static final String NRB = "NRB"; + public static final String NUC = "NUC"; + public static final String NVC = "NVC"; + public static final String NXT = "NXT"; + public static final String NYAN = "NYAN"; + public static final String OIL = "OIL"; + public static final String OLY = "OLY"; + public static final String ORB = "ORB"; + public static final String ORG = "ORG"; + public static final String ORO = "ORO"; + public static final String OSC = "OSC"; + public static final String P$ = "P$"; + public static final String PAND = "PAND"; + public static final String PANDA = "PANDA"; + public static final String PCC = "PCC"; + public static final String PCN = "PCN"; + public static final String PENG = "PENG"; + public static final String PHI = "PHI"; + public static final String PHS = "PHS"; + public static final String PIC = "PIC"; + public static final String PLC = "PLC"; + public static final String PLT = "PLT"; + public static final String PMC = "PMC"; + public static final String PND = "PND"; + public static final String POD = "POD"; + public static final String POINTS = "POINTS"; + public static final String POT = "POT"; + public static final String PPC = "PPC"; + public static final String PRC = "PRC"; + public static final String PRT = "PRT"; + public static final String PT = "PT"; + public static final String PTC = "PTC"; + public static final String PTS = "PTS"; + public static final String PWC = "PWC"; + public static final String PWNY = "PWNY"; + public static final String PXC = "PXC"; + public static final String PXL = "PXL"; + public static final String PYC = "PYC"; + public static final String Q2C = "Q2C"; + public static final String QB = "QB"; + public static final String QRK = "QRK"; + public static final String RAD = "RAD"; + public static final String RAIN = "RAIN"; + public static final String RBBT = "RBBT"; + public static final String RCH = "RCH"; + public static final String RDD = "RDD"; + public static final String REC = "REC"; + public static final String RED = "RED"; + public static final String REDD = "REDD"; // RDD + public static final String RIC = "RIC"; + public static final String RON = "RON"; + public static final String RPC = "RPC"; + public static final String RPD = "RPD"; + public static final String RSC = "RSC"; + public static final String RBY = "RBY"; + public static final String RYC = "RYC"; + public static final String SAT = "SAT"; + public static final String SAV = "SAV"; + public static final String SBC = "SBC"; + public static final String SBX = "SBX"; + public static final String SC = "SC"; + public static final String SCO = "SCO"; + public static final String SMC = "SMC"; + public static final String SOC = "SOC"; + public static final String SOCHI = "SOCHI"; + public static final String SPA = "SPA"; + public static final String SPT = "SPT"; + public static final String SRC = "SRC"; + public static final String START = "START"; + public static final String STC = "STC"; + public static final String STL = "STL"; + public static final String STR = "STR"; + public static final String STY = "STY"; + public static final String SUN = "SUN"; + public static final String SXC = "SXC"; + public static final String SYN = "SYN"; + public static final String TAG = "TAG"; + public static final String TAK = "TAK"; + public static final String TEA = "TEA"; + public static final String TEK = "TEK"; + public static final String TEL = "TEL"; + public static final String TES = "TES"; + public static final String TFC = "TFC"; + public static final String TGC = "TGC"; + public static final String TH1 = "TH1"; + public static final String THOR = "THOR"; + public static final String TIPS = "TIPS"; + public static final String TIX = "TIX"; + public static final String TOP = "TOP"; + public static final String TRC = "TRC"; + public static final String TRL = "TRL"; + public static final String TTC = "TTC"; + public static final String UFO = "UFO"; + public static final String UNC = "UNC"; + public static final String UNI = "UNI"; + public static final String UNO = "UNO"; + public static final String USDE = "USDE"; + public static final String USDe = "USDe"; + public static final String UTC = "UTC"; + public static final String VDC = "VDC"; + public static final String VEN = "VEN"; + public static final String VGC = "VGC"; + public static final String VLC = "VLC"; + public static final String VLT = "VLT"; + public static final String VMP = "VMP"; + public static final String VOLT = "VOLT"; + public static final String VTC = "VTC"; + public static final String WDC = "WDC"; + public static final String WIKI = "WIKI"; + public static final String WOLF = "WOLF"; + public static final String XBT = "XBT"; // BTC + public static final String XCP = "XCP"; + public static final String XDG = "XDG"; // DOGE + public static final String XIV = "XIV"; + public static final String XJO = "XJO"; + public static final String XNC = "XNC"; + public static final String XPM = "XPM"; + public static final String XPY = "XPY"; + public static final String XRP = "XRP"; + public static final String XVN = "XVN"; // VEN + public static final String XXL = "XXL"; + public static final String YAC = "YAC"; + public static final String YANG = "YANG"; + public static final String YBC = "YBC"; + public static final String YIN = "YIN"; + public static final String ZCC = "ZCC"; + public static final String ZED = "ZED"; + public static final String ZEIT = "ZEIT"; + public static final String ZET = "ZET"; + public static final String ZEU = "ZEU"; + public static final String ZMB = "ZMB"; + public static final String ZTC = "ZTC"; +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/AllCoin.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/AllCoin.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/AllCoin.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/AllCoin.java index 585d1c8d..ed3d54c8 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/AllCoin.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/AllCoin.java @@ -1,74 +1,74 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.util.ParseUtils; -import com.mobnetic.coinguardiandatamodule.R; - -public class AllCoin extends Market { - - private final static String NAME = "AllCoin"; - private final static String TTS_NAME = "All Coin"; - private final static String URL = "https://www.allcoin.com/api2/pair/%1$s_%2$s"; - private final static String URL_CURRENCY_PAIRS = "https://www.allcoin.com/api2/pairs"; - - public AllCoin() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - ticker.bid = ParseUtils.getDoubleFromString(dataJsonObject, "top_bid"); - ticker.ask = ParseUtils.getDoubleFromString(dataJsonObject, "top_ask"); - ticker.vol = ParseUtils.getDoubleFromString(dataJsonObject, "volume_24h_"+checkerInfo.getCurrencyBase()); - ticker.high = ParseUtils.getDoubleFromString(dataJsonObject, "max_24h_price"); - ticker.low = ParseUtils.getDoubleFromString(dataJsonObject, "min_24h_price"); - ticker.last = ParseUtils.getDoubleFromString(dataJsonObject, "trade_price"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("error_info"); - } - - @Override - public int getCautionResId() { - return R.string.market_caution_allcoin; - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - - final JSONArray pairsJsonArray = dataJsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + + final JSONArray pairsJsonArray = dataJsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.HKD, - Currency.EUR, - Currency.CAD, - Currency.AUD, - Currency.SGD, - Currency.JPY, - Currency.CHF, - Currency.GBP, - Currency.NZD - }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ - VirtualCurrency.BTC, - Currency.USD, - Currency.HKD, - Currency.EUR, - Currency.CAD, - Currency.AUD, - Currency.SGD, - Currency.JPY, - Currency.CHF, - Currency.GBP, - Currency.NZD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.USD, - Currency.HKD, - Currency.EUR, - Currency.CAD, - Currency.AUD, - Currency.SGD, - Currency.JPY, - Currency.CHF, - Currency.GBP, - Currency.NZD - }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC, - Currency.USD, - Currency.HKD, - Currency.EUR, - Currency.CAD, - Currency.AUD, - Currency.SGD, - Currency.JPY, - Currency.CHF, - Currency.GBP, - Currency.NZD - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC, - Currency.USD, - Currency.HKD, - Currency.EUR, - Currency.CAD, - Currency.AUD, - Currency.SGD, - Currency.JPY, - Currency.CHF, - Currency.GBP, - Currency.NZD - }); - } - - public Anxpro() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataObject = jsonObject.getJSONObject("data"); - - ticker.bid = getPriceValueFromObject(dataObject, "buy"); - ticker.ask = getPriceValueFromObject(dataObject, "sell"); - ticker.vol = getPriceValueFromObject(dataObject, "vol"); - ticker.high = getPriceValueFromObject(dataObject, "high"); - ticker.low = getPriceValueFromObject(dataObject, "low"); - ticker.last = getPriceValueFromObject(dataObject, "last"); - ticker.timestamp = dataObject.getLong("now")/TimeUtils.NANOS_IN_MILLIS; - } - - private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { - final JSONObject innerObject = jsonObject.getJSONObject(key); - return innerObject.getDouble("value"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Anxpro extends Market { + + private final static String NAME = "Anxpro"; + private final static String TTS_NAME = "ANX Pro"; + private final static String URL = "https://anxpro.com/api/2/%1$s%2$s/money/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.HKD, + Currency.EUR, + Currency.CAD, + Currency.AUD, + Currency.SGD, + Currency.JPY, + Currency.CHF, + Currency.GBP, + Currency.NZD + }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ + VirtualCurrency.BTC, + Currency.USD, + Currency.HKD, + Currency.EUR, + Currency.CAD, + Currency.AUD, + Currency.SGD, + Currency.JPY, + Currency.CHF, + Currency.GBP, + Currency.NZD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.USD, + Currency.HKD, + Currency.EUR, + Currency.CAD, + Currency.AUD, + Currency.SGD, + Currency.JPY, + Currency.CHF, + Currency.GBP, + Currency.NZD + }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC, + Currency.USD, + Currency.HKD, + Currency.EUR, + Currency.CAD, + Currency.AUD, + Currency.SGD, + Currency.JPY, + Currency.CHF, + Currency.GBP, + Currency.NZD + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC, + Currency.USD, + Currency.HKD, + Currency.EUR, + Currency.CAD, + Currency.AUD, + Currency.SGD, + Currency.JPY, + Currency.CHF, + Currency.GBP, + Currency.NZD + }); + } + + public Anxpro() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataObject = jsonObject.getJSONObject("data"); + + ticker.bid = getPriceValueFromObject(dataObject, "buy"); + ticker.ask = getPriceValueFromObject(dataObject, "sell"); + ticker.vol = getPriceValueFromObject(dataObject, "vol"); + ticker.high = getPriceValueFromObject(dataObject, "high"); + ticker.low = getPriceValueFromObject(dataObject, "low"); + ticker.last = getPriceValueFromObject(dataObject, "last"); + ticker.timestamp = dataObject.getLong("now")/TimeUtils.NANOS_IN_MILLIS; + } + + private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { + final JSONObject innerObject = jsonObject.getJSONObject(key); + return innerObject.getDouble("value"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Basebit.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Basebit.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Basebit.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Basebit.java index a1af69fc..d5563cb9 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Basebit.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Basebit.java @@ -1,66 +1,66 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Basebit extends Market { - - private final static String NAME = "Basebit"; - private final static String TTS_NAME = "Base Bit"; - private final static String URL = "http://www.basebit.com.br/quote-%1$s"; - private final static String URL_CURRENCY_PAIRS = "http://www.basebit.com.br/listpairs"; - - public Basebit() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject resultJsonObject = jsonObject.getJSONObject("result"); - ticker.vol = resultJsonObject.getDouble("volume24h"); - ticker.high = resultJsonObject.getDouble("high"); - ticker.low = resultJsonObject.getDouble("low"); - ticker.last = resultJsonObject.getDouble("last"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("errorMessage"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray pairsJsonArray = new JSONArray(responseString); - - for(int i=0; i=2) { - pairs.add(new CurrencyPairInfo( - currencyNames[0], - currencyNames[1], - pairName)); - } - } - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; + +public class Basebit extends Market { + + private final static String NAME = "Basebit"; + private final static String TTS_NAME = "Base Bit"; + private final static String URL = "http://www.basebit.com.br/quote-%1$s"; + private final static String URL_CURRENCY_PAIRS = "http://www.basebit.com.br/listpairs"; + + public Basebit() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyPairId()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject resultJsonObject = jsonObject.getJSONObject("result"); + ticker.vol = resultJsonObject.getDouble("volume24h"); + ticker.high = resultJsonObject.getDouble("high"); + ticker.low = resultJsonObject.getDouble("low"); + ticker.last = resultJsonObject.getDouble("last"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("errorMessage"); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { + final JSONArray pairsJsonArray = new JSONArray(responseString); + + for(int i=0; i=2) { + pairs.add(new CurrencyPairInfo( + currencyNames[0], + currencyNames[1], + pairName)); + } + } + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bit2c.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bit2c.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bit2c.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bit2c.java index 0e1a8667..28e4999d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bit2c.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bit2c.java @@ -1,45 +1,45 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Bit2c extends Market { - - private final static String NAME = "Bit2c"; - private final static String TTS_NAME = "Bit 2c"; - private final static String URL = "https://www.bit2c.co.il/Exchanges/%1$s%2$s/Ticker.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.NIS - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC - }); - } - - public Bit2c() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("h"); - ticker.ask = jsonObject.getDouble("l"); - ticker.vol = jsonObject.getDouble("a"); - ticker.last = jsonObject.getDouble("ll"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Bit2c extends Market { + + private final static String NAME = "Bit2c"; + private final static String TTS_NAME = "Bit 2c"; + private final static String URL = "https://www.bit2c.co.il/Exchanges/%1$s%2$s/Ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.NIS + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC + }); + } + + public Bit2c() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("h"); + ticker.ask = jsonObject.getDouble("l"); + ticker.vol = jsonObject.getDouble("a"); + ticker.last = jsonObject.getDouble("ll"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitBay.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitBay.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitBay.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitBay.java index c2ed1e69..169354e7 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitBay.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitBay.java @@ -1,52 +1,52 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitBay extends Market { - - private final static String NAME = "BitBay.net"; - private final static String TTS_NAME = "Bit Bay"; - private final static String URL = "https://bitbay.net/API/Public/%1$s%2$s/ticker.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.PLN, - Currency.USD, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.PLN, - Currency.USD, - Currency.EUR - }); - } - - public BitBay() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("max"); - ticker.low = jsonObject.getDouble("min"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitBay extends Market { + + private final static String NAME = "BitBay.net"; + private final static String TTS_NAME = "Bit Bay"; + private final static String URL = "https://bitbay.net/API/Public/%1$s%2$s/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.PLN, + Currency.USD, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.PLN, + Currency.USD, + Currency.EUR + }); + } + + public BitBay() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("max"); + ticker.low = jsonObject.getDouble("min"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitCore.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitCore.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitCore.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitCore.java index e7c22b6f..5dffc0f1 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitCore.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitCore.java @@ -1,40 +1,40 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitCore extends Market { - - private final static String NAME = "BitCore"; - private final static String TTS_NAME = "Bit Core"; - private final static String URL = "http://api.bitcore.co.kr/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.KRW - }); - } - - public BitCore() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.vol = jsonObject.getDouble("volume"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitCore extends Market { + + private final static String NAME = "BitCore"; + private final static String TTS_NAME = "Bit Core"; + private final static String URL = "http://api.bitcore.co.kr/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.KRW + }); + } + + public BitCore() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.vol = jsonObject.getDouble("volume"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitKonan.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitKonan.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitKonan.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitKonan.java index 6291adfb..f647ac0c 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitKonan.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitKonan.java @@ -1,52 +1,52 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitKonan extends Market { - - private final static String NAME = "BitKonan"; - private final static String TTS_NAME = "Bit Konan"; - private final static String URL_BTC = "https://bitkonan.com/api/ticker"; - private final static String URL_LTC = "https://bitkonan.com/api/ltc_ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD - }); - } - - public BitKonan() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(VirtualCurrency.BTC.equals(checkerInfo.getCurrencyBase())) { - return URL_BTC; - } else { - return URL_LTC; - } - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitKonan extends Market { + + private final static String NAME = "BitKonan"; + private final static String TTS_NAME = "Bit Konan"; + private final static String URL_BTC = "https://bitkonan.com/api/ticker"; + private final static String URL_LTC = "https://bitkonan.com/api/ltc_ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD + }); + } + + public BitKonan() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(VirtualCurrency.BTC.equals(checkerInfo.getCurrencyBase())) { + return URL_BTC; + } else { + return URL_LTC; + } + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMarket24PL.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarket24PL.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitMarket24PL.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarket24PL.java index 596861b8..4681aeab 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMarket24PL.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarket24PL.java @@ -1,58 +1,58 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitMarket24PL extends Market { - - private final static String NAME = "BitMarket24.pl"; - private final static String TTS_NAME = "Bit Market 24"; - private final static String URL = "https://bitmarket24.pl/api/%1$s_%2$s/status.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.PLN - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.PLN - }); - } - - public BitMarket24PL() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - if (!jsonObject.isNull("bid")) { - ticker.bid = jsonObject.getDouble("bid"); - } - if (!jsonObject.isNull("ask")) { - ticker.ask = jsonObject.getDouble("ask"); - } - if (!jsonObject.isNull("volume")) { - ticker.vol = jsonObject.getDouble("volume"); - } - if (!jsonObject.isNull("high")) { - ticker.high = jsonObject.getDouble("high"); - } - if (!jsonObject.isNull("low")) { - ticker.low = jsonObject.getDouble("low"); - } - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitMarket24PL extends Market { + + private final static String NAME = "BitMarket24.pl"; + private final static String TTS_NAME = "Bit Market 24"; + private final static String URL = "https://bitmarket24.pl/api/%1$s_%2$s/status.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.PLN + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.PLN + }); + } + + public BitMarket24PL() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + if (!jsonObject.isNull("bid")) { + ticker.bid = jsonObject.getDouble("bid"); + } + if (!jsonObject.isNull("ask")) { + ticker.ask = jsonObject.getDouble("ask"); + } + if (!jsonObject.isNull("volume")) { + ticker.vol = jsonObject.getDouble("volume"); + } + if (!jsonObject.isNull("high")) { + ticker.high = jsonObject.getDouble("high"); + } + if (!jsonObject.isNull("low")) { + ticker.low = jsonObject.getDouble("low"); + } + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMarketPL.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarketPL.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitMarketPL.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarketPL.java index 6976bb86..2dfac92e 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMarketPL.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMarketPL.java @@ -1,47 +1,47 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitMarketPL extends Market { - - private final static String NAME = "BitMarket.pl"; - private final static String TTS_NAME = "Bit Market"; - private final static String URL = "https://www.bitmarket.pl/json/%1$s%2$s/ticker.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.PLN - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.PLN - }); - } - - public BitMarketPL() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitMarketPL extends Market { + + private final static String NAME = "BitMarket.pl"; + private final static String TTS_NAME = "Bit Market"; + private final static String URL = "https://www.bitmarket.pl/json/%1$s%2$s/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.PLN + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.PLN + }); + } + + public BitMarketPL() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMaszyna.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMaszyna.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitMaszyna.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMaszyna.java index f55af998..4d701a0f 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitMaszyna.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitMaszyna.java @@ -1,47 +1,47 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitMaszyna extends Market { - - private final static String NAME = "BitMaszyna.pl"; - private final static String TTS_NAME = "Bit Maszyna"; - private final static String URL = "https://bitmaszyna.pl/api/%1$s%2$s/ticker.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.PLN - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.PLN - }); - } - - public BitMaszyna() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume1"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitMaszyna extends Market { + + private final static String NAME = "BitMaszyna.pl"; + private final static String TTS_NAME = "Bit Maszyna"; + private final static String URL = "https://bitmaszyna.pl/api/%1$s%2$s/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.PLN + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.PLN + }); + } + + public BitMaszyna() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume1"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitTrex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitTrex.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitTrex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitTrex.java index c3c33b34..fdb819db 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitTrex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitTrex.java @@ -1,57 +1,57 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class BitTrex extends Market { - - private final static String NAME = "BitTrex"; - private final static String TTS_NAME = "Bit Trex"; - private final static String URL = "https://bittrex.com/api/v1.1/public/getticker?market=%1$s-%2$s"; - private final static String URL_CURRENCY_PAIRS = "https://bittrex.com/api/v1.1/public/getmarkets"; - - public BitTrex() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounter(), checkerInfo.getCurrencyBase()); // reversed - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject resultJsonObject = jsonObject.getJSONObject("result"); - ticker.bid = resultJsonObject.getDouble("Bid"); - ticker.ask = resultJsonObject.getDouble("Ask"); - ticker.last = resultJsonObject.getDouble("Last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray resultJsonArray = jsonObject.getJSONArray("result"); - - for(int i=0; i pairs) throws Exception { + final JSONArray resultJsonArray = jsonObject.getJSONArray("result"); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.NAD, - Currency.KES, - Currency.MYR, - Currency.ZAR - }); - } - - public BitX() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - String currencyBase = fixCurrency(checkerInfo.getCurrencyBase()); - String currencyCounter = checkerInfo.getCurrencyCounter(); - - return String.format(URL, currencyBase, currencyCounter); - } - - private String fixCurrency(String currency) { - if(VirtualCurrency.BTC.equals(currency)) - return VirtualCurrency.XBT; - - return currency; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("rolling_24_hour_volume"); - ticker.last = jsonObject.getDouble("last_trade"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitX extends Market { + + private final static String NAME = "BitX.co"; + private final static String TTS_NAME = "Bit X"; + private final static String URL = "https://api.mybitx.com/api/1/ticker?pair=%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.NAD, + Currency.KES, + Currency.MYR, + Currency.ZAR + }); + } + + public BitX() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + String currencyBase = fixCurrency(checkerInfo.getCurrencyBase()); + String currencyCounter = checkerInfo.getCurrencyCounter(); + + return String.format(URL, currencyBase, currencyCounter); + } + + private String fixCurrency(String currency) { + if(VirtualCurrency.BTC.equals(currency)) + return VirtualCurrency.XBT; + + return currency; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("rolling_24_hour_volume"); + ticker.last = jsonObject.getDouble("last_trade"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinAverage.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinAverage.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinAverage.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinAverage.java index 85876296..ed959972 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinAverage.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinAverage.java @@ -1,59 +1,59 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitcoinAverage extends Market { - - private final static String NAME = "BitcoinAverage"; - private final static String TTS_NAME = "Bitcoin Average"; - private final static String URL = "https://api.bitcoinaverage.com/ticker/%1$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.AUD, - Currency.BRL, - Currency.CAD, - Currency.CHF, - Currency.CNY, - Currency.CZK, - Currency.EUR, - Currency.GBP, - Currency.ILS, - Currency.JPY, - Currency.NOK, - Currency.NZD, - Currency.PLN, - Currency.RUB, - Currency.SEK, - Currency.SGD, - Currency.USD, - Currency.ZAR, - }); - } - - public BitcoinAverage() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("total_vol"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitcoinAverage extends Market { + + private final static String NAME = "BitcoinAverage"; + private final static String TTS_NAME = "Bitcoin Average"; + private final static String URL = "https://api.bitcoinaverage.com/ticker/%1$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.AUD, + Currency.BRL, + Currency.CAD, + Currency.CHF, + Currency.CNY, + Currency.CZK, + Currency.EUR, + Currency.GBP, + Currency.ILS, + Currency.JPY, + Currency.NOK, + Currency.NZD, + Currency.PLN, + Currency.RUB, + Currency.SEK, + Currency.SGD, + Currency.USD, + Currency.ZAR, + }); + } + + public BitcoinAverage() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("total_vol"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java index 9e51ce22..819f237b 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCentralNet.java @@ -1,44 +1,44 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitcoinCentralNet extends Market { - - private final static String NAME = "Bitcoin-Central"; - private final static String TTS_NAME = "Bitcoin Central"; - private final static String URL = "https://bitcoin-central.net/api/data/eur/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR - }); - } - - public BitcoinCentralNet() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("price"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitcoinCentralNet extends Market { + + private final static String NAME = "Bitcoin-Central"; + private final static String TTS_NAME = "Bitcoin Central"; + private final static String URL = "https://bitcoin-central.net/api/data/eur/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR + }); + } + + public BitcoinCentralNet() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("price"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCoId.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCoId.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCoId.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCoId.java index 25654772..09cc85ed 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinCoId.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinCoId.java @@ -1,71 +1,71 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class BitcoinCoId extends Market { - - private final static String NAME = "Bitcoin.co.id"; - private final static String TTS_NAME = "Bitcoin co id"; - private final static String URL = "https://vip.bitcoin.co.id/api/%1$s/ticker/"; - private final static String URL_CURRENCY_PAIRS = "https://vip.bitcoin.co.id/api/summaries"; - - public BitcoinCoId() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - String pairId = checkerInfo.getCurrencyPairId(); - if (pairId == null) { - pairId = String.format("%1$s_%2$s", checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - return String.format(URL, pairId); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol_btc"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - ticker.timestamp = tickerJsonObject.getLong("server_time"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject tickersJsonObject = jsonObject.getJSONObject("tickers"); - final JSONArray tickerNamesArray = tickersJsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONObject tickersJsonObject = jsonObject.getJSONObject("tickers"); + final JSONArray tickerNamesArray = tickersJsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.BRL - }); - } - - public BitcoinToYou() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitcoinToYou extends Market { + + private final static String NAME = "BitcoinToYou"; + private final static String TTS_NAME = "Bitcoin To You"; + private final static String URL = "https://www.bitcointoyou.com/api/ticker.aspx"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.BRL + }); + } + + public BitcoinToYou() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + ticker.bid = tickerJsonObject.getDouble("buy"); + ticker.ask = tickerJsonObject.getDouble("sell"); + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java index bbb4515f..fc427b93 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitcoinVenezuela.java @@ -1,63 +1,63 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitcoinVenezuela extends Market { - - private final static String NAME = "BitcoinVenezuela"; - private final static String TTS_NAME = "Bitcoin Venezuela"; - private final static String URL = "http://api.bitcoinvenezuela.com/?html=no¤cy=%1$s&amount=1&to=%2$s"; - private final static String URL_CURRENCY_PAIRS = "http://api.bitcoinvenezuela.com/"; - - public BitcoinVenezuela() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.last = Double.parseDouble(responseString.trim()); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - parseCurrencyPairsFromCurrencyBase(VirtualCurrency.BTC, jsonObject, pairs); - parseCurrencyPairsFromCurrencyBase(VirtualCurrency.LTC, jsonObject, pairs); - parseCurrencyPairsFromCurrencyBase(VirtualCurrency.MSC, jsonObject, pairs); - } - - private void parseCurrencyPairsFromCurrencyBase(String currencyBase, JSONObject jsonObject, List pairs) throws Exception { - if(!jsonObject.has(currencyBase)) - return; - - final JSONObject currencyBaseJsonObject = jsonObject.getJSONObject(currencyBase); - final JSONArray counterCurrencyNames = currencyBaseJsonObject.names(); - for(int i=0; i pairs) throws Exception { + parseCurrencyPairsFromCurrencyBase(VirtualCurrency.BTC, jsonObject, pairs); + parseCurrencyPairsFromCurrencyBase(VirtualCurrency.LTC, jsonObject, pairs); + parseCurrencyPairsFromCurrencyBase(VirtualCurrency.MSC, jsonObject, pairs); + } + + private void parseCurrencyPairsFromCurrencyBase(String currencyBase, JSONObject jsonObject, List pairs) throws Exception { + if(!jsonObject.has(currencyBase)) + return; + + final JSONObject currencyBaseJsonObject = jsonObject.getJSONObject(currencyBase); + final JSONArray counterCurrencyNames = currencyBaseJsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.PLN, - Currency.EUR - }); - } - - public Bitcurex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = parsePrice(jsonObject.getDouble("best_ask")); - ticker.ask = parsePrice(jsonObject.getDouble("best_bid")); - ticker.vol = parseBTC(jsonObject.getDouble("total_volume")); - ticker.high = parsePrice(jsonObject.getDouble("highest_tx_price")); - ticker.low = parsePrice(jsonObject.getDouble("lowest_tx_price")); - ticker.last = parsePrice(jsonObject.getDouble("last_tx_price")); - } - - private double parsePrice(double price) { - return price/10000; - } - - private double parseBTC(double satoshi) { - return satoshi/100000000; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Bitcurex extends Market { + + private final static String NAME = "Bitcurex"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://bitcurex.com/api/%1$s/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.PLN, + Currency.EUR + }); + } + + public Bitcurex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = parsePrice(jsonObject.getDouble("best_ask")); + ticker.ask = parsePrice(jsonObject.getDouble("best_bid")); + ticker.vol = parseBTC(jsonObject.getDouble("total_volume")); + ticker.high = parsePrice(jsonObject.getDouble("highest_tx_price")); + ticker.low = parsePrice(jsonObject.getDouble("lowest_tx_price")); + ticker.last = parsePrice(jsonObject.getDouble("last_tx_price")); + } + + private double parsePrice(double price) { + return price/10000; + } + + private double parseBTC(double satoshi) { + return satoshi/100000000; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitexLa.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitexLa.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitexLa.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitexLa.java index cff9b3da..271e76f5 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitexLa.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitexLa.java @@ -1,44 +1,44 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitexLa extends Market { - - private final static String NAME = "Bitex.la"; - private final static String TTS_NAME = "Bitex"; - private final static String URL = "https://bitex.la/api-v1/rest/btc/market/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public BitexLa() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitexLa extends Market { + + private final static String NAME = "Bitex.la"; + private final static String TTS_NAME = "Bitex"; + private final static String URL = "https://bitex.la/api-v1/rest/btc/market/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public BitexLa() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitfinex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitfinex.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bitfinex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitfinex.java index 14920ba9..9f810763 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitfinex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitfinex.java @@ -1,55 +1,55 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardian.util.ParseUtils; -import com.mobnetic.coinguardian.util.TimeUtils; - -public class Bitfinex extends Market { - - private final static String NAME = "Bitfinex"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.bitfinex.com/v1/pubticker/%1$s%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.ETH, new String[]{ - VirtualCurrency.BTC, - Currency.USD - }); - } - - public Bitfinex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); - ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); - ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); - ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); - ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last_price"); - ticker.timestamp = (long) (jsonObject.getDouble("timestamp")*TimeUtils.MILLIS_IN_SECOND); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Bitfinex extends Market { + + private final static String NAME = "Bitfinex"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.bitfinex.com/v1/pubticker/%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.ETH, new String[]{ + VirtualCurrency.BTC, + Currency.USD + }); + } + + public Bitfinex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); + ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); + ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); + ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); + ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); + ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last_price"); + ticker.timestamp = (long) (jsonObject.getDouble("timestamp")*TimeUtils.MILLIS_IN_SECOND); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitoEX.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitoEX.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitoEX.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitoEX.java index 975b1a32..79411d24 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitoEX.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitoEX.java @@ -1,43 +1,43 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONArray; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitoEX extends Market { - - private final static String NAME = "BitoEX"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.bitoex.com/sync/dashboard/%1$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.TWD - }); - } - - public BitoEX() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, System.currentTimeMillis()); - } - - @Override - protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - JSONArray jsonArray = new JSONArray(responseString); - ticker.ask = Double.parseDouble(jsonArray.getString(0).replaceAll(",", "")); - ticker.bid = Double.parseDouble(jsonArray.getString(1).replaceAll(",", "")); - ticker.last = ticker.ask; - ticker.timestamp = Long.valueOf(jsonArray.getString(2)); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONArray; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitoEX extends Market { + + private final static String NAME = "BitoEX"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.bitoex.com/sync/dashboard/%1$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.TWD + }); + } + + public BitoEX() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, System.currentTimeMillis()); + } + + @Override + protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + JSONArray jsonArray = new JSONArray(responseString); + ticker.ask = Double.parseDouble(jsonArray.getString(0).replaceAll(",", "")); + ticker.bid = Double.parseDouble(jsonArray.getString(1).replaceAll(",", "")); + ticker.last = ticker.ask; + ticker.timestamp = Long.valueOf(jsonArray.getString(2)); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitorado.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitorado.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bitorado.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitorado.java index a36eb42c..7ea09298 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitorado.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitorado.java @@ -1,66 +1,66 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Bitorado extends Market -{ - private final static String NAME = "Bitorado"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.bitorado.com/api/market/%1$s-%2$s/ticker"; - private final static String URL_CURRENCY_PAIRS = "https://www.bitorado.com/api/ticker"; - - public Bitorado() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject resultObject = jsonObject.getJSONObject("result"); - ticker.bid = resultObject.optDouble("buy", Ticker.NO_DATA); - ticker.ask = resultObject.optDouble("sell", Ticker.NO_DATA); - ticker.vol = resultObject.optDouble("vol", Ticker.NO_DATA); - ticker.high = resultObject.optDouble("high", Ticker.NO_DATA); - ticker.low = resultObject.optDouble("low", Ticker.NO_DATA); - ticker.last = resultObject.optDouble("last", 0); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject result = jsonObject.getJSONObject("result"); - final JSONObject markets = result.getJSONObject("markets"); - final JSONArray pairNames = markets.names(); - - for(int i=0; i pairs) throws Exception { + final JSONObject result = jsonObject.getJSONObject("result"); + final JSONObject markets = result.getJSONObject("markets"); + final JSONArray pairNames = markets.names(); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(1); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.MXN - }); - } - - public Bitso() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyBaseLowerCase()+"_"+checkerInfo.getCurrencyCounterLowerCase()); - ticker.bid = ParseUtils.getDoubleFromString(pairJsonObject, "buy"); - ticker.ask = ParseUtils.getDoubleFromString(pairJsonObject, "sell"); - ticker.vol = ParseUtils.getDoubleFromString(pairJsonObject, "volume"); - ticker.last = ParseUtils.getDoubleFromString(pairJsonObject, "rate"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; + +public class Bitso extends Market { + + private final static String NAME = "Bitso"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.bitso.com/public/info"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(1); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.MXN + }); + } + + public Bitso() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyBaseLowerCase()+"_"+checkerInfo.getCurrencyCounterLowerCase()); + ticker.bid = ParseUtils.getDoubleFromString(pairJsonObject, "buy"); + ticker.ask = ParseUtils.getDoubleFromString(pairJsonObject, "sell"); + ticker.vol = ParseUtils.getDoubleFromString(pairJsonObject, "volume"); + ticker.last = ParseUtils.getDoubleFromString(pairJsonObject, "rate"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitstamp.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitstamp.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bitstamp.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitstamp.java index e78ae5db..79fa4569 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bitstamp.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bitstamp.java @@ -1,45 +1,45 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Bitstamp extends Market { - - private final static String NAME = "Bitstamp"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.bitstamp.net/api/ticker/"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public Bitstamp() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Bitstamp extends Market { + + private final static String NAME = "Bitstamp"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.bitstamp.net/api/ticker/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public Bitstamp() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BitxCom.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitxCom.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BitxCom.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitxCom.java index 04b8b059..0a8e51ac 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BitxCom.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BitxCom.java @@ -1,67 +1,67 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BitxCom extends Market { - - private final static String NAME = "bit-x.com"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://bit-x.com/api/public/ticker?pair=%1$s%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR, - Currency.GBP, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.EUR, - Currency.GBP, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.GHS, new String[]{ - VirtualCurrency.BTC, - Currency.EUR, - Currency.GBP, - VirtualCurrency.LTC, - Currency.USD - }); - CURRENCY_PAIRS.put(Currency.EUR, new String[]{ - Currency.GBP, - Currency.USD - }); - CURRENCY_PAIRS.put(Currency.GBP, new String[]{ - Currency.USD - }); - } - - public BitxCom() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - ticker.bid = dataJsonObject.getDouble("buy"); - ticker.ask = dataJsonObject.getDouble("sell"); - ticker.vol = dataJsonObject.getDouble("volume"); - ticker.high = dataJsonObject.getDouble("high"); - ticker.low = dataJsonObject.getDouble("low"); - ticker.last = dataJsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BitxCom extends Market { + + private final static String NAME = "bit-x.com"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://bit-x.com/api/public/ticker?pair=%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR, + Currency.GBP, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.EUR, + Currency.GBP, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.GHS, new String[]{ + VirtualCurrency.BTC, + Currency.EUR, + Currency.GBP, + VirtualCurrency.LTC, + Currency.USD + }); + CURRENCY_PAIRS.put(Currency.EUR, new String[]{ + Currency.GBP, + Currency.USD + }); + CURRENCY_PAIRS.put(Currency.GBP, new String[]{ + Currency.USD + }); + } + + public BitxCom() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + ticker.bid = dataJsonObject.getDouble("buy"); + ticker.ask = dataJsonObject.getDouble("sell"); + ticker.vol = dataJsonObject.getDouble("volume"); + ticker.high = dataJsonObject.getDouble("high"); + ticker.low = dataJsonObject.getDouble("low"); + ticker.last = dataJsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bleutrade.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bleutrade.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bleutrade.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bleutrade.java index fe144639..8dd2a727 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bleutrade.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bleutrade.java @@ -1,73 +1,73 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Bleutrade extends Market { - - private final static String NAME = "Bleutrade"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://bleutrade.com/api/v2/public/getticker?market=%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://bleutrade.com/api/v2/public/getmarkets"; - - public Bleutrade() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final Object resultObject = jsonObject.get("result"); - JSONObject resultsJsonObject = null; - if (resultObject instanceof JSONArray) { - resultsJsonObject = ((JSONArray)resultObject).getJSONObject(0); - } else { - resultsJsonObject = (JSONObject)resultObject; - } - ticker.bid = resultsJsonObject.getDouble("Bid"); - ticker.ask = resultsJsonObject.getDouble("Ask"); - ticker.last = resultsJsonObject.getDouble("Last"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("message"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray resultsJsonArray = jsonObject.getJSONArray("result"); - for (int i = 0; i < resultsJsonArray.length(); ++i) { - final JSONObject pairJsonObject = resultsJsonArray.getJSONObject(i); - final String pairId = pairJsonObject.getString("MarketName"); - final String currencyBase = pairJsonObject.getString("MarketCurrency"); - final String currencyCounter = pairJsonObject.getString("BaseCurrency"); - if (pairId != null && currencyBase != null && currencyCounter != null) { - pairs.add(new CurrencyPairInfo( - currencyBase, - currencyCounter, - pairId - )); - } - } - } +package com.mobnetic.coinguardian.model.market; + +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; + +public class Bleutrade extends Market { + + private final static String NAME = "Bleutrade"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://bleutrade.com/api/v2/public/getticker?market=%1$s"; + private final static String URL_CURRENCY_PAIRS = "https://bleutrade.com/api/v2/public/getmarkets"; + + public Bleutrade() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyPairId()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final Object resultObject = jsonObject.get("result"); + JSONObject resultsJsonObject = null; + if (resultObject instanceof JSONArray) { + resultsJsonObject = ((JSONArray)resultObject).getJSONObject(0); + } else { + resultsJsonObject = (JSONObject)resultObject; + } + ticker.bid = resultsJsonObject.getDouble("Bid"); + ticker.ask = resultsJsonObject.getDouble("Ask"); + ticker.last = resultsJsonObject.getDouble("Last"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("message"); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONArray resultsJsonArray = jsonObject.getJSONArray("result"); + for (int i = 0; i < resultsJsonArray.length(); ++i) { + final JSONObject pairJsonObject = resultsJsonArray.getJSONObject(i); + final String pairId = pairJsonObject.getString("MarketName"); + final String currencyBase = pairJsonObject.getString("MarketCurrency"); + final String currencyCounter = pairJsonObject.getString("BaseCurrency"); + if (pairId != null && currencyBase != null && currencyCounter != null) { + pairs.add(new CurrencyPairInfo( + currencyBase, + currencyCounter, + pairId + )); + } + } + } } \ No newline at end of file diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Btc38.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btc38.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Btc38.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btc38.java index d7f047d4..dd80d57d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Btc38.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btc38.java @@ -1,73 +1,73 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Btc38 extends Market { - - private final static String NAME = "Btc38"; - private final static String TTS_NAME = "BTC 38"; - private final static String URL = "http://api.btc38.com/v1/ticker.php?c=%1$s&mk_type=%2$s"; - private final static String URL_CURRENCY_PAIRS = "http://api.btc38.com/v1/ticker.php?c=all&mk_type=%1$s"; - - public Btc38() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public int getCurrencyPairsNumOfRequests() { - return 2; - } - - public String getCurrencyCounter(int requestId) { - return requestId == 0 ? Currency.CNY : VirtualCurrency.BTC; - } - - @Override - public String getCurrencyPairsUrl(int requestId) { - return String.format(URL_CURRENCY_PAIRS, getCurrencyCounter(requestId).toLowerCase(Locale.ENGLISH)); - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final String currencyCounter = getCurrencyCounter(requestId); - final JSONArray currencyBaseList = jsonObject.names(); - for(int i=0; i pairs) throws Exception { + final String currencyCounter = getCurrencyCounter(requestId); + final JSONArray currencyBaseList = jsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.JPY - }); - } - - public BtcBox() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("buy"); - ticker.ask = jsonObject.getDouble("sell"); - ticker.vol = jsonObject.getDouble("vol"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BtcBox extends Market { + + private final static String NAME = "BtcBox"; + private final static String TTS_NAME = "BTC Box"; + private final static String URL = "https://www.btcbox.co.jp/api/v1/ticker/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.JPY + }); + } + + public BtcBox() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("buy"); + ticker.ask = jsonObject.getDouble("sell"); + ticker.vol = jsonObject.getDouble("vol"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BtcMarkets.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcMarkets.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BtcMarkets.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcMarkets.java index 45732943..9d08d1b9 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BtcMarkets.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcMarkets.java @@ -1,50 +1,50 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class BtcMarkets extends Market { - - private final static String NAME = "BtcMarkets.net"; - private final static String TTS_NAME = "BTC Markets net"; - private final static String URL = "https://api.btcmarkets.net/market/%1$s/%2$s/tick"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.AUD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.AUD - }); - CURRENCY_PAIRS.put(VirtualCurrency.ETH, new String[]{ - VirtualCurrency.BTC, - Currency.AUD - }); - } - - public BtcMarkets() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bestBid"); - ticker.ask = jsonObject.getDouble("bestAsk"); - ticker.last = jsonObject.getDouble("lastPrice"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class BtcMarkets extends Market { + + private final static String NAME = "BtcMarkets.net"; + private final static String TTS_NAME = "BTC Markets net"; + private final static String URL = "https://api.btcmarkets.net/market/%1$s/%2$s/tick"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.AUD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.AUD + }); + CURRENCY_PAIRS.put(VirtualCurrency.ETH, new String[]{ + VirtualCurrency.BTC, + Currency.AUD + }); + } + + public BtcMarkets() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bestBid"); + ticker.ask = jsonObject.getDouble("bestAsk"); + ticker.last = jsonObject.getDouble("lastPrice"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/BtcXIndia.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcXIndia.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/BtcXIndia.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcXIndia.java index 6f208f7d..a9f6222e 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/BtcXIndia.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/BtcXIndia.java @@ -1,45 +1,45 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardian.util.ParseUtils; - -public class BtcXIndia extends Market { - - private final static String NAME = "BTCXIndia"; - private final static String TTS_NAME = "BTC X India"; - private final static String URL = "https://btcxindia.com/api/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.INR - }); - } - - public BtcXIndia() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("total_volume_24h"); - ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); - ticker.last = jsonObject.getDouble("last_traded_price"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; + +public class BtcXIndia extends Market { + + private final static String NAME = "BTCXIndia"; + private final static String TTS_NAME = "BTC X India"; + private final static String URL = "https://btcxindia.com/api/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.INR + }); + } + + public BtcXIndia() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("total_volume_24h"); + ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); + ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); + ticker.last = jsonObject.getDouble("last_traded_price"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Btcchina.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btcchina.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Btcchina.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btcchina.java index e632573d..fef9cc36 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Btcchina.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btcchina.java @@ -1,50 +1,50 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Btcchina extends Market { - - private final static String NAME = "BtcChina"; - private final static String TTS_NAME = "BTC China"; - private final static String URL = "https://data.btcchina.com/data/ticker?market=%1$s%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - VirtualCurrency.LTC, - Currency.CNY - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.CNY - }); - } - - public Btcchina() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounterLowerCase(), checkerInfo.getCurrencyBaseLowerCase()); // reversed currencies - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Btcchina extends Market { + + private final static String NAME = "BtcChina"; + private final static String TTS_NAME = "BTC China"; + private final static String URL = "https://data.btcchina.com/data/ticker?market=%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + VirtualCurrency.LTC, + Currency.CNY + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.CNY + }); + } + + public Btcchina() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounterLowerCase(), checkerInfo.getCurrencyBaseLowerCase()); // reversed currencies + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = tickerJsonObject.getDouble("buy"); + ticker.ask = tickerJsonObject.getDouble("sell"); + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Btce.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btce.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Btce.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btce.java index 90a33194..424a33c6 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Btce.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Btce.java @@ -1,120 +1,120 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.config.Settings; -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Btce extends Market { - - private final static String NAME = "Btc-e"; - private final static String TTS_NAME = NAME; - private final static String URL_HOST_COM = "btc-e.com"; - private final static String URL_HOST_NZ = "btc-e.nz"; - private final static String URL = "https://%1$s/api/3/ticker/%2$s"; - private final static String URL_CURRENCY_PAIRS = "https://%1$s/api/3/info"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.RUR, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.USD, - Currency.RUR, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - VirtualCurrency.BTC, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ - VirtualCurrency.BTC, - Currency.USD - }); - CURRENCY_PAIRS.put(Currency.USD, new String[]{ - Currency.RUR - }); - CURRENCY_PAIRS.put(Currency.EUR, new String[]{ - Currency.USD, - Currency.RUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ - VirtualCurrency.BTC, - Currency.USD - }); - } - - public Btce() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - private String detectHost() { - if (Settings.userCountry != null && Settings.userCountry.endsWith("RU")) { - return URL_HOST_NZ; - } - return URL_HOST_COM; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - String pairId = checkerInfo.getCurrencyPairId(); - if(checkerInfo.getCurrencyPairId() == null) { - pairId = String.format("%1$s_%2$s", checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - return String.format(URL, detectHost(), pairId); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONArray names = jsonObject.names(); - JSONObject tickerJsonObject = jsonObject.getJSONObject(names.getString(0)); - - ticker.bid = tickerJsonObject.getDouble("sell"); // REVERSED! - ticker.ask = tickerJsonObject.getDouble("buy"); // REVERSED! - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - ticker.timestamp = tickerJsonObject.getLong("updated"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return String.format(URL_CURRENCY_PAIRS, detectHost()); - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject pairsJsonObject = jsonObject.getJSONObject("pairs"); - final JSONArray pairsNames = pairsJsonObject.names(); - for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.RUR, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.USD, + Currency.RUR, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + VirtualCurrency.BTC, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ + VirtualCurrency.BTC, + Currency.USD + }); + CURRENCY_PAIRS.put(Currency.USD, new String[]{ + Currency.RUR + }); + CURRENCY_PAIRS.put(Currency.EUR, new String[]{ + Currency.USD, + Currency.RUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ + VirtualCurrency.BTC, + Currency.USD + }); + } + + public Btce() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + private String detectHost() { + if (Settings.userCountry != null && Settings.userCountry.endsWith("RU")) { + return URL_HOST_NZ; + } + return URL_HOST_COM; + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + String pairId = checkerInfo.getCurrencyPairId(); + if(checkerInfo.getCurrencyPairId() == null) { + pairId = String.format("%1$s_%2$s", checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + return String.format(URL, detectHost(), pairId); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONArray names = jsonObject.names(); + JSONObject tickerJsonObject = jsonObject.getJSONObject(names.getString(0)); + + ticker.bid = tickerJsonObject.getDouble("sell"); // REVERSED! + ticker.ask = tickerJsonObject.getDouble("buy"); // REVERSED! + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + ticker.timestamp = tickerJsonObject.getLong("updated"); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return String.format(URL_CURRENCY_PAIRS, detectHost()); + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONObject pairsJsonObject = jsonObject.getJSONObject("pairs"); + final JSONArray pairsNames = pairsJsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.TRY - }); - } - - public Btcturk() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = (long) (jsonObject.getDouble("timestamp")*TimeUtils.MILLIS_IN_SECOND); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Btcturk extends Market { + + private final static String NAME = "BtcTurk"; + private final static String TTS_NAME = "Btc Turk"; + private final static String URL = "https://www.btcturk.com/api/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.TRY + }); + } + + public Btcturk() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = (long) (jsonObject.getDouble("timestamp")*TimeUtils.MILLIS_IN_SECOND); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Bter.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bter.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Bter.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bter.java index 241ce8f1..d8065fc3 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Bter.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Bter.java @@ -1,64 +1,64 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Bter extends Market { - - private final static String NAME = "Bter"; - private final static String TTS_NAME = "B ter"; - private final static String URL = "https://data.bter.com/api/1/ticker/%1$s_%2$s"; - private final static String URL_CURRENCY_PAIRS = "https://data.bter.com/api/1/pairs"; - - public Bter() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("buy"); - ticker.ask = jsonObject.getDouble("sell"); - ticker.vol = jsonObject.getDouble("vol_"+checkerInfo.getCurrencyBaseLowerCase()); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - JSONArray jsonArray = new JSONArray(responseString); - for(int i=0; i pairs) throws Exception { + JSONArray jsonArray = new JSONArray(responseString); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public Buttercoin() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Buttercoin extends Market { + + private final static String NAME = "Buttercoin"; + private final static String TTS_NAME = "Butter coin"; + private final static String URL = "https://api.buttercoin.com/v1/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public Buttercoin() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CCex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CCex.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CCex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CCex.java index 19720042..af288556 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CCex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CCex.java @@ -1,65 +1,65 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class CCex extends Market { - - public final static String NAME = "C-CEX"; - public final static String TTS_NAME = "C-Cex"; - public final static String URL = "https://c-cex.com/t/%1$s-%2$s.json"; - public final static String URL_CURRENCY_PAIRS = "https://c-cex.com/t/pairs.json"; - - public CCex() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - JSONObject tickerObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerObject.getDouble("buy"); - ticker.ask = tickerObject.getDouble("sell"); - ticker.high = tickerObject.getDouble("high"); - ticker.low = tickerObject.getDouble("low"); - ticker.last = tickerObject.getDouble("lastprice"); -// ticker.timestamp = tickerObject.getLong("updated"); // strange date? - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray pairsJsonArray = jsonObject.getJSONArray("pairs"); - - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = jsonObject.getJSONArray("pairs"); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public Campbx() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("Best Bid"); - ticker.ask = jsonObject.getDouble("Best Ask"); - ticker.last = jsonObject.getDouble("Last Trade"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Campbx extends Market { + + private final static String NAME = "CampBX"; + private final static String TTS_NAME = "Camp BX"; + private final static String URL = "http://campbx.com/api/xticker.php"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public Campbx() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("Best Bid"); + ticker.ask = jsonObject.getDouble("Best Ask"); + ticker.last = jsonObject.getDouble("Last Trade"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CexIO.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CexIO.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CexIO.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CexIO.java index e9070341..ab17c401 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CexIO.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CexIO.java @@ -1,107 +1,107 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CexIO extends Market { - - private final static String NAME = "CEX.IO"; - private final static String TTS_NAME = "CEX IO"; - private final static String URL = "https://cex.io/api/ticker/%1$s/%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.AUR, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.DGB, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ - Currency.USD, - VirtualCurrency.BTC, - VirtualCurrency.LTC, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.DRK, new String[]{ - Currency.USD, - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.GHS, new String[]{ - Currency.USD, - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.IXC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.MEC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.MYR, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.POT, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.USDE, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ - VirtualCurrency.BTC, - VirtualCurrency.LTC - }); - } - - public CexIO() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - if (jsonObject.has("bid")) { - ticker.bid = jsonObject.getDouble("bid"); - } - if (jsonObject.has("ask")) { - ticker.ask = jsonObject.getDouble("ask"); - } - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CexIO extends Market { + + private final static String NAME = "CEX.IO"; + private final static String TTS_NAME = "CEX IO"; + private final static String URL = "https://cex.io/api/ticker/%1$s/%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.AUR, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.DGB, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ + Currency.USD, + VirtualCurrency.BTC, + VirtualCurrency.LTC, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.DRK, new String[]{ + Currency.USD, + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.GHS, new String[]{ + Currency.USD, + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.IXC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.MEC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.MYR, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.POT, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.USDE, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ + VirtualCurrency.BTC, + VirtualCurrency.LTC + }); + } + + public CexIO() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + if (jsonObject.has("bid")) { + ticker.bid = jsonObject.getDouble("bid"); + } + if (jsonObject.has("ask")) { + ticker.ask = jsonObject.getDouble("ask"); + } + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CleverCoin.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CleverCoin.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CleverCoin.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CleverCoin.java index 77d77f94..f1e7c59d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CleverCoin.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CleverCoin.java @@ -1,44 +1,44 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CleverCoin extends Market { - - private final static String NAME = "CleverCoin"; - private final static String TTS_NAME = "Clever Coin"; - private final static String URL = "https://api.clevercoin.com/v1/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR - }); - } - - public CleverCoin() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CleverCoin extends Market { + + private final static String NAME = "CleverCoin"; + private final static String TTS_NAME = "Clever Coin"; + private final static String URL = "https://api.clevercoin.com/v1/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR + }); + } + + public CleverCoin() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinDesk.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinDesk.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinDesk.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinDesk.java index 1dc3b6ae..fdf5c6c9 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinDesk.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinDesk.java @@ -1,54 +1,54 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CoinDesk extends Market { - - private final static String NAME = "CoinDesk"; - private final static String TTS_NAME = "Coin Desk"; - private final static String URL = "https://api.coindesk.com/v1/bpi/currentprice.json"; - private final static String URL_CURRENCY_PAIRS = URL; - - public CoinDesk() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject bpiJsonObject = jsonObject.getJSONObject("bpi"); - final JSONObject pairJsonObject = bpiJsonObject.getJSONObject(checkerInfo.getCurrencyCounter()); - ticker.last = pairJsonObject.getDouble("rate_float"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject bpiJsonObject = jsonObject.getJSONObject("bpi"); - final JSONArray currencyCounterNames = bpiJsonObject.names(); - - for(int i=0; i pairs) throws Exception { + final JSONObject bpiJsonObject = jsonObject.getJSONObject("bpi"); + final JSONArray currencyCounterNames = bpiJsonObject.names(); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.AUD, - Currency.NZD, - Currency.CAD, - Currency.EUR, - Currency.GBP, - Currency.SGD, - Currency.HKD, - Currency.CHF, - Currency.JPY - }); - } - - public CoinJar() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final String currencyCounter = checkerInfo.getCurrencyCounter(); - ticker.bid = getPriceFromJsonObject(jsonObject, "bid", currencyCounter); - ticker.ask = getPriceFromJsonObject(jsonObject, "ask", currencyCounter); - ticker.last = getPriceFromJsonObject(jsonObject, "spot", currencyCounter); - } - - private double getPriceFromJsonObject(JSONObject jsonObject, String innerObjectName, String currencyCounter) throws Exception { - JSONObject innerJsonObject = jsonObject.getJSONObject(innerObjectName); - return innerJsonObject.getDouble(currencyCounter); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinJar extends Market { + + private final static String NAME = "CoinJar"; + private final static String TTS_NAME = "Coin Jar"; + private final static String URL = "https://coinjar-data.herokuapp.com/fair_rate.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.AUD, + Currency.NZD, + Currency.CAD, + Currency.EUR, + Currency.GBP, + Currency.SGD, + Currency.HKD, + Currency.CHF, + Currency.JPY + }); + } + + public CoinJar() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final String currencyCounter = checkerInfo.getCurrencyCounter(); + ticker.bid = getPriceFromJsonObject(jsonObject, "bid", currencyCounter); + ticker.ask = getPriceFromJsonObject(jsonObject, "ask", currencyCounter); + ticker.last = getPriceFromJsonObject(jsonObject, "spot", currencyCounter); + } + + private double getPriceFromJsonObject(JSONObject jsonObject, String innerObjectName, String currencyCounter) throws Exception { + JSONObject innerJsonObject = jsonObject.getJSONObject(innerObjectName); + return innerJsonObject.getDouble(currencyCounter); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinMarketIO.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMarketIO.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinMarketIO.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMarketIO.java index 2c5b8c7c..e42f1fa7 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinMarketIO.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMarketIO.java @@ -1,84 +1,84 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CoinMarketIO extends Market { - - private final static String NAME = "CoinMarket.io"; - private final static String TTS_NAME = "Coin Market IO"; - private final static String URL = "https://coinmarket.io/ticker/%1$s%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.LEAF, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.USDE, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.DGB, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.KDC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.CON, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.NOBL, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.SMC, new String[]{ - VirtualCurrency.BTC - }); -// CURRENCY_PAIRS.put(VirtualCurrency.PRT, new String[]{ -// VirtualCurrency.BTC -// }); - CURRENCY_PAIRS.put(VirtualCurrency.VTC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.UTC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.KARM, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.RDD, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.RPD, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.ICN, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.PENG, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.MINT, new String[]{ - VirtualCurrency.BTC - }); - } - - public CoinMarketIO() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.vol = jsonObject.getDouble("volume24"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinMarketIO extends Market { + + private final static String NAME = "CoinMarket.io"; + private final static String TTS_NAME = "Coin Market IO"; + private final static String URL = "https://coinmarket.io/ticker/%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.LEAF, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.USDE, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.DGB, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.KDC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.CON, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.NOBL, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.SMC, new String[]{ + VirtualCurrency.BTC + }); +// CURRENCY_PAIRS.put(VirtualCurrency.PRT, new String[]{ +// VirtualCurrency.BTC +// }); + CURRENCY_PAIRS.put(VirtualCurrency.VTC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.UTC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.KARM, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.RDD, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.RPD, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.ICN, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.PENG, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.MINT, new String[]{ + VirtualCurrency.BTC + }); + } + + public CoinMarketIO() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.vol = jsonObject.getDouble("volume24"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinMateIO.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMateIO.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinMateIO.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMateIO.java index 3ccb1adb..fbbecb26 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinMateIO.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinMateIO.java @@ -1,50 +1,50 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CoinMateIO extends Market { - - private final static String NAME = "CoinMate.io"; - private final static String TTS_NAME = "Coin Mate"; - private final static String URL = "https://coinmate.io/api/ticker?currencyPair=%1$s_%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public CoinMateIO() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - ticker.bid = dataJsonObject.getDouble("bid"); - ticker.ask = dataJsonObject.getDouble("ask"); - ticker.vol = dataJsonObject.getDouble("amount"); - ticker.high = dataJsonObject.getDouble("high"); - ticker.low = dataJsonObject.getDouble("low"); - ticker.last = dataJsonObject.getDouble("last"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("errorMessage"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinMateIO extends Market { + + private final static String NAME = "CoinMate.io"; + private final static String TTS_NAME = "Coin Mate"; + private final static String URL = "https://coinmate.io/api/ticker?currencyPair=%1$s_%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public CoinMateIO() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + ticker.bid = dataJsonObject.getDouble("bid"); + ticker.ask = dataJsonObject.getDouble("ask"); + ticker.vol = dataJsonObject.getDouble("amount"); + ticker.high = dataJsonObject.getDouble("high"); + ticker.low = dataJsonObject.getDouble("low"); + ticker.last = dataJsonObject.getDouble("last"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("errorMessage"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinSecure.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSecure.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinSecure.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSecure.java index e1416c4f..feccadd8 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinSecure.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSecure.java @@ -1,49 +1,49 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CoinSecure extends Market { - - private final static String NAME = "CoinSecure"; - private final static String TTS_NAME = "Coin Secure"; - private final static String URL = "https://api.coinsecure.in/v0/noauth/newticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.INR - }); - } - - public CoinSecure() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = parsePrice(jsonObject.getDouble("bid")); - ticker.ask = parsePrice(jsonObject.getDouble("ask")); - ticker.vol = jsonObject.getDouble("coinvolume") / 100000000; - ticker.high = parsePrice(jsonObject.getDouble("high")); - ticker.low = parsePrice(jsonObject.getDouble("low")); - ticker.last = parsePrice(jsonObject.getDouble("lastprice")); -// ticker.timestamp = jsonObject.getLong("timestamp"); - } - - private double parsePrice(double price) { - return price/100; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinSecure extends Market { + + private final static String NAME = "CoinSecure"; + private final static String TTS_NAME = "Coin Secure"; + private final static String URL = "https://api.coinsecure.in/v0/noauth/newticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.INR + }); + } + + public CoinSecure() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = parsePrice(jsonObject.getDouble("bid")); + ticker.ask = parsePrice(jsonObject.getDouble("ask")); + ticker.vol = jsonObject.getDouble("coinvolume") / 100000000; + ticker.high = parsePrice(jsonObject.getDouble("high")); + ticker.low = parsePrice(jsonObject.getDouble("low")); + ticker.last = parsePrice(jsonObject.getDouble("lastprice")); +// ticker.timestamp = jsonObject.getLong("timestamp"); + } + + private double parsePrice(double price) { + return price/100; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinSwap.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSwap.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinSwap.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSwap.java index 7a5e64a9..87675fb6 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinSwap.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinSwap.java @@ -1,57 +1,57 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class CoinSwap extends Market { - - private final static String NAME = "Coin-Swap"; - private final static String TTS_NAME = "Coin Swap"; - private final static String URL = "https://api.coin-swap.net/market/stats/%1$s/%2$s"; - private final static String URL_CURRENCY_PAIRS = "http://api.coin-swap.net/market/summary"; - - public CoinSwap() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("dayvolume"); - ticker.high = jsonObject.getDouble("dayhigh"); - ticker.low = jsonObject.getDouble("daylow"); - ticker.last = jsonObject.getDouble("lastprice"); - } - - // ==================== - // Get currency pairs - // ==================== - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray marketsJsonArray = new JSONArray(responseString); - - for(int i=0; i pairs) throws Exception { + final JSONArray marketsJsonArray = new JSONArray(responseString); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.CAD - }); - } - - public CoinTraderNet() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - final JSONArray dataNamesArray = dataJsonObject.names(); - final JSONObject tickerJsonObject = dataJsonObject.getJSONObject(dataNamesArray.getString(0)); - ticker.bid = tickerJsonObject.getDouble("bid"); - ticker.ask = tickerJsonObject.getDouble("offer"); - ticker.vol = tickerJsonObject.getDouble("volume"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("lastTradePrice"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinTraderNet extends Market { + + private final static String NAME = "CoinTrader.net"; + private final static String TTS_NAME = "Coin Trader"; + private final static String URL = "https://www.cointrader.net/api4/stats/daily/%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.CAD + }); + } + + public CoinTraderNet() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + final JSONArray dataNamesArray = dataJsonObject.names(); + final JSONObject tickerJsonObject = dataJsonObject.getJSONObject(dataNamesArray.getString(0)); + ticker.bid = tickerJsonObject.getDouble("bid"); + ticker.ask = tickerJsonObject.getDouble("offer"); + ticker.vol = tickerJsonObject.getDouble("volume"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("lastTradePrice"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinTree.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinTree.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CoinTree.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinTree.java index 10c2600f..d973d336 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CoinTree.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CoinTree.java @@ -1,41 +1,41 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class CoinTree extends Market { - - private final static String NAME = "CoinTree"; - private final static String TTS_NAME = "Coin Tree"; - private final static String URL = "https://www.cointree.com.au/api/price/btc/aud"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.AUD - }); - } - - public CoinTree() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("Bid"); - ticker.ask = jsonObject.getDouble("Ask"); - ticker.last = jsonObject.getDouble("Spot"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CoinTree extends Market { + + private final static String NAME = "CoinTree"; + private final static String TTS_NAME = "Coin Tree"; + private final static String URL = "https://www.cointree.com.au/api/price/btc/aud"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.AUD + }); + } + + public CoinTree() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("Bid"); + ticker.ask = jsonObject.getDouble("Ask"); + ticker.last = jsonObject.getDouble("Spot"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinapult.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinapult.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Coinapult.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinapult.java index 599825ae..8e331637 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinapult.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinapult.java @@ -1,51 +1,51 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardian.util.TimeUtils; - -public class Coinapult extends Market { - - private final static String NAME = "Coinapult"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.coinapult.com/api/ticker?market=%2$s_%1$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR, - Currency.GBP, - Currency.XAG, - Currency.XAU - }); - } - - public Coinapult() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("error"); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.last = jsonObject.getDouble("index"); - ticker.timestamp = jsonObject.getLong("updatetime") * TimeUtils.MILLIS_IN_SECOND; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Coinapult extends Market { + + private final static String NAME = "Coinapult"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.coinapult.com/api/ticker?market=%2$s_%1$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR, + Currency.GBP, + Currency.XAG, + Currency.XAU + }); + } + + public Coinapult() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("error"); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.last = jsonObject.getDouble("index"); + ticker.timestamp = jsonObject.getLong("updatetime") * TimeUtils.MILLIS_IN_SECOND; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinbase.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinbase.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Coinbase.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinbase.java index 210aa787..65b32ede 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinbase.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinbase.java @@ -1,69 +1,69 @@ -package com.mobnetic.coinguardian.model.market; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -import org.json.JSONArray; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -public class Coinbase extends Market { - - private final static String NAME = "Coinbase"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.exchange.coinbase.com/products/%1$s-%2$s/ticker"; - private final static String URL_CURRENCY_PAIRS = "https://api.exchange.coinbase.com/products/"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR, - Currency.GBP - }); - } - - public Coinbase() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.last = jsonObject.getDouble("price"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray jsonArray = new JSONArray(responseString); - for (int i = 0; i < jsonArray.length(); ++i) { - final JSONObject pairJsonObject = jsonArray.getJSONObject(i); - pairs.add(new CurrencyPairInfo( - pairJsonObject.getString("base_currency"), - pairJsonObject.getString("quote_currency"), - pairJsonObject.getString("id"))); - } - } +package com.mobnetic.coinguardian.model.market; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +public class Coinbase extends Market { + + private final static String NAME = "Coinbase"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.exchange.coinbase.com/products/%1$s-%2$s/ticker"; + private final static String URL_CURRENCY_PAIRS = "https://api.exchange.coinbase.com/products/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR, + Currency.GBP + }); + } + + public Coinbase() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.last = jsonObject.getDouble("price"); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { + final JSONArray jsonArray = new JSONArray(responseString); + for (int i = 0; i < jsonArray.length(); ++i) { + final JSONObject pairJsonObject = jsonArray.getJSONObject(i); + pairs.add(new CurrencyPairInfo( + pairJsonObject.getString("base_currency"), + pairJsonObject.getString("quote_currency"), + pairJsonObject.getString("id"))); + } + } } \ No newline at end of file diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinse.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinse.java similarity index 98% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Coinse.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinse.java index 31824359..211adfbb 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Coinse.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Coinse.java @@ -1,111 +1,111 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardiandatamodule.R; - -public class Coinse extends Market { - - private final static String NAME = "Coins-E"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.coins-e.com/api/v2/markets/data/"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.ALP, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.AMC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ARG, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.BET, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.BQC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.BTG, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.CGB, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.CIN, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.CMC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.COL, new String[]{ VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.CRC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.CSC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.DEM, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.DMD, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.DTC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ELC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ELP, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.EMD, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.EZC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.FLO, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.FRK, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.GDC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.GLC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.GLX, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.HYC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.IFC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC, VirtualCurrency.XPM }); - CURRENCY_PAIRS.put(VirtualCurrency.KGC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.LBW, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.MEC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NAN, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NET, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NIB, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NRB, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NUC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ORB, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.XPM }); - CURRENCY_PAIRS.put(VirtualCurrency.PTS, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.PWC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.PXC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.QRK, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC, VirtualCurrency.XPM }); - CURRENCY_PAIRS.put(VirtualCurrency.RCH, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.REC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.RED, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.SBC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.SPT, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.TAG, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.UNO, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.VLC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ VirtualCurrency.BTC }); - CURRENCY_PAIRS.put(VirtualCurrency.XNC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); - CURRENCY_PAIRS.put(VirtualCurrency.ZET, new String[]{ VirtualCurrency.BTC }); - } - - public Coinse() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public int getCautionResId() { - return R.string.market_caution_much_data; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - JSONObject marketsObject = jsonObject.getJSONObject("markets"); - JSONObject pairObject = marketsObject.getJSONObject(checkerInfo.getCurrencyBase()+"_"+checkerInfo.getCurrencyCounter()); - - JSONObject marketStatObject = pairObject.getJSONObject("marketstat"); - JSONObject inner24hObject = marketStatObject.getJSONObject("24h"); - - ticker.bid = marketStatObject.getDouble("bid"); - ticker.ask = marketStatObject.getDouble("ask"); - ticker.vol = inner24hObject.getDouble("volume"); - ticker.high = inner24hObject.getDouble("h"); - ticker.low = inner24hObject.getDouble("l"); - ticker.last = marketStatObject.getDouble("ltp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardiandatamodule.R; + +public class Coinse extends Market { + + private final static String NAME = "Coins-E"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.coins-e.com/api/v2/markets/data/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.ALP, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.AMC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ARG, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.BET, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.BQC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.BTG, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.CGB, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.CIN, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.CMC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.COL, new String[]{ VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.CRC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.CSC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.DEM, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.DMD, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.DTC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ELC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ELP, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.EMD, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.EZC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.FLO, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.FRK, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.GDC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.GLC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.GLX, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.HYC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.IFC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC, VirtualCurrency.XPM }); + CURRENCY_PAIRS.put(VirtualCurrency.KGC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.LBW, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.MEC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NAN, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NET, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NIB, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NRB, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NUC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ORB, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.XPM }); + CURRENCY_PAIRS.put(VirtualCurrency.PTS, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.PWC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.PXC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.QRK, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC, VirtualCurrency.XPM }); + CURRENCY_PAIRS.put(VirtualCurrency.RCH, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.REC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.RED, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.SBC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.SPT, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.TAG, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.UNO, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.VLC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ VirtualCurrency.BTC }); + CURRENCY_PAIRS.put(VirtualCurrency.XNC, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ VirtualCurrency.BTC, VirtualCurrency.LTC }); + CURRENCY_PAIRS.put(VirtualCurrency.ZET, new String[]{ VirtualCurrency.BTC }); + } + + public Coinse() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public int getCautionResId() { + return R.string.market_caution_much_data; + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + JSONObject marketsObject = jsonObject.getJSONObject("markets"); + JSONObject pairObject = marketsObject.getJSONObject(checkerInfo.getCurrencyBase()+"_"+checkerInfo.getCurrencyCounter()); + + JSONObject marketStatObject = pairObject.getJSONObject("marketstat"); + JSONObject inner24hObject = marketStatObject.getJSONObject("24h"); + + ticker.bid = marketStatObject.getDouble("bid"); + ticker.ask = marketStatObject.getDouble("ask"); + ticker.vol = inner24hObject.getDouble("volume"); + ticker.high = inner24hObject.getDouble("h"); + ticker.low = inner24hObject.getDouble("l"); + ticker.last = marketStatObject.getDouble("ltp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Comkort.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Comkort.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Comkort.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Comkort.java index 241e6e77..d43702e9 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Comkort.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Comkort.java @@ -1,71 +1,71 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Comkort extends Market { - - private final static String NAME = "Comkort"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.comkort.com/v1/public/market/summary?market_alias=%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://api.comkort.com/v1/public/market/list"; - - public Comkort() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject marketsJsonObject = jsonObject.getJSONObject("markets"); - final JSONArray marketNames = marketsJsonObject.names(); - final JSONObject marketJsonObject = marketsJsonObject.getJSONObject(marketNames.getString(0)); - - ticker.bid = getFirstOrderFrom(marketJsonObject, "buy_orders"); - ticker.ask = getFirstOrderFrom(marketJsonObject, "sell_orders"); - ticker.vol = marketJsonObject.getDouble("volume"); - ticker.high = marketJsonObject.getDouble("high"); - ticker.low = marketJsonObject.getDouble("low"); - ticker.last = marketJsonObject.getDouble("last_price"); - } - - private double getFirstOrderFrom(JSONObject marketJsonObject, String arrayName) throws Exception { - final JSONArray ordersJsonArray = marketJsonObject.getJSONArray(arrayName); - if(ordersJsonArray.length()>0) { - return ordersJsonArray.getJSONObject(0).getDouble("price"); - } - return Ticker.NO_DATA; - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray marketsJsonArray = jsonObject.getJSONArray("markets"); - - for(int i=0; i0) { + return ordersJsonArray.getJSONObject(0).getDouble("price"); + } + return Ticker.NO_DATA; + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONArray marketsJsonArray = jsonObject.getJSONArray("markets"); + + for(int i=0; i pairs) throws Exception { - final JSONArray pairsNamesArray = jsonObject.names(); - - for(int i=0; i=2) { - pairs.add(new CurrencyPairInfo(split[0], split[1], pairName)); - } - } - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; + +public class CryptoAltex extends Market { + + private final static String NAME = "CryptoAltex"; + private final static String TTS_NAME = "Crypto Altex"; + private final static String URL = "https://www.cryptoaltex.com/api/public_v2.php"; + + public CryptoAltex() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject pairObject = jsonObject.getJSONObject(checkerInfo.getCurrencyPairId()); + ticker.vol = pairObject.getDouble("24_hours_volume"); + ticker.high = pairObject.getDouble("24_hours_price_high"); + ticker.low = pairObject.getDouble("24_hours_price_low"); + ticker.last = pairObject.getDouble("last_trade"); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL; + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONArray pairsNamesArray = jsonObject.names(); + + for(int i=0; i=2) { + pairs.add(new CurrencyPairInfo(split[0], split[1], pairName)); + } + } + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/CryptoRush.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CryptoRush.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/CryptoRush.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CryptoRush.java index e44db4b5..9bf9afd4 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/CryptoRush.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/CryptoRush.java @@ -1,70 +1,70 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardiandatamodule.R; - -public class CryptoRush extends Market { - - public final static String NAME = "CryptoRush"; - public final static String TTS_NAME = "Crypto Rush"; - public final static String URL = "https://cryptorush.in/marketdata/all.json"; - private final static String URL_CURRENCY_PAIRS = URL; - - public CryptoRush() { - super(NAME, TTS_NAME, null); - } - - @Override - public int getCautionResId() { - return R.string.market_caution_much_data; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyBase()+"/"+checkerInfo.getCurrencyCounter()); - - ticker.bid = pairJsonObject.getDouble("current_bid"); - ticker.ask = pairJsonObject.getDouble("current_ask"); - ticker.vol = pairJsonObject.getDouble("volume_base_24h"); - ticker.high = pairJsonObject.getDouble("highest_24h"); - ticker.low = pairJsonObject.getDouble("lowest_24h"); - ticker.last = pairJsonObject.getDouble("last_trade"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray pairNames = jsonObject.names(); - - for(int i=0; i pairs) throws Exception { + final JSONArray pairNames = jsonObject.names(); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - Currency.USD, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ - Currency.USD, - VirtualCurrency.BTC, - VirtualCurrency.PPC - }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ - Currency.USD, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ - Currency.USD, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.DVC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ - Currency.USD, - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.UTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC - }); - } - - public CryptoTrade() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataObject = jsonObject.getJSONObject("data"); - - ticker.bid = dataObject.getDouble("max_bid"); - ticker.ask = dataObject.getDouble("min_ask"); - ticker.vol = dataObject.getDouble("vol_"+checkerInfo.getCurrencyBaseLowerCase()); - ticker.high = dataObject.getDouble("high"); - ticker.low = dataObject.getDouble("low"); - ticker.last = dataObject.getDouble("last"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("error"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class CryptoTrade extends Market { + + private final static String NAME = "Crypto-Trade"; + private final static String TTS_NAME = "Crypto Trade"; + private final static String URL = "https://crypto-trade.com/api/1/ticker/%1$s_%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + Currency.USD, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ + Currency.USD, + VirtualCurrency.BTC, + VirtualCurrency.PPC + }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ + Currency.USD, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ + Currency.USD, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.DVC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ + Currency.USD, + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.UTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC + }); + } + + public CryptoTrade() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataObject = jsonObject.getJSONObject("data"); + + ticker.bid = dataObject.getDouble("max_bid"); + ticker.ask = dataObject.getDouble("min_ask"); + ticker.vol = dataObject.getDouble("vol_"+checkerInfo.getCurrencyBaseLowerCase()); + ticker.high = dataObject.getDouble("high"); + ticker.low = dataObject.getDouble("low"); + ticker.last = dataObject.getDouble("last"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("error"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Cryptoine.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Cryptoine.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Cryptoine.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Cryptoine.java index 6f279dfd..360aec34 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Cryptoine.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Cryptoine.java @@ -1,72 +1,72 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Cryptoine extends Market { - - private final static String NAME = "Cryptoine"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://cryptoine.com/api/1/ticker/%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://cryptoine.com/api/1/markets"; - - public Cryptoine() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = getDoubleOrZero(jsonObject, "buy"); - ticker.ask = getDoubleOrZero(jsonObject, "sell"); - ticker.vol = getDoubleOrZero(jsonObject, "vol_exchange"); - ticker.high = getDoubleOrZero(jsonObject, "high"); - ticker.low = getDoubleOrZero(jsonObject, "low"); - ticker.last = getDoubleOrZero(jsonObject, "last"); - } - - private double getDoubleOrZero(JSONObject jsonObject, String name) throws Exception { - if(jsonObject.isNull(name)) - return 0; - return jsonObject.getDouble(name); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - final JSONArray pairNames = dataJsonObject.names(); - - for(int i=0; i pairs) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + final JSONArray pairNames = dataJsonObject.names(); + + for(int i=0; i pairs) throws Exception { - final JSONArray pairsJsonArray = new JSONArray(responseString); - JSONArray currenciesJsonArray = null; - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = new JSONArray(responseString); + JSONArray currenciesJsonArray = null; + for(int i=0; i pairs) throws Exception { - final JSONArray dataJsonArray = jsonObject.getJSONArray("Data"); - for(int i=0; i pairs) throws Exception { + final JSONArray dataJsonArray = jsonObject.getJSONArray("Data"); + for(int i=0; i CURRENCY_PAIRS_IDS = new HashMap(151); - static { - // Kept for backward compatibility - CURRENCY_PAIRS_IDS.put("42_BTC", 141); - CURRENCY_PAIRS_IDS.put("ADT_LTC", 94); - CURRENCY_PAIRS_IDS.put("ADT_XPM", 113); - CURRENCY_PAIRS_IDS.put("ALF_BTC", 57); - CURRENCY_PAIRS_IDS.put("AMC_BTC", 43); - CURRENCY_PAIRS_IDS.put("ANC_BTC", 66); - CURRENCY_PAIRS_IDS.put("ANC_LTC", 121); - CURRENCY_PAIRS_IDS.put("ARG_BTC", 48); - CURRENCY_PAIRS_IDS.put("ASC_LTC", 111); - CURRENCY_PAIRS_IDS.put("ASC_XPM", 112); - CURRENCY_PAIRS_IDS.put("AUR_BTC", 160); - CURRENCY_PAIRS_IDS.put("AUR_LTC", 161); - CURRENCY_PAIRS_IDS.put("BCX_BTC", 142); - CURRENCY_PAIRS_IDS.put("BEN_BTC", 157); - CURRENCY_PAIRS_IDS.put("BET_BTC", 129); - CURRENCY_PAIRS_IDS.put("BQC_BTC", 10); - CURRENCY_PAIRS_IDS.put("BTB_BTC", 23); - CURRENCY_PAIRS_IDS.put("BTE_BTC", 49); - CURRENCY_PAIRS_IDS.put("BTG_BTC", 50); - CURRENCY_PAIRS_IDS.put("BUK_BTC", 102); - CURRENCY_PAIRS_IDS.put("CACH_BTC", 154); - CURRENCY_PAIRS_IDS.put("CAP_BTC", 53); - CURRENCY_PAIRS_IDS.put("CASH_BTC", 150); - CURRENCY_PAIRS_IDS.put("CAT_BTC", 136); - CURRENCY_PAIRS_IDS.put("CGB_BTC", 70); - CURRENCY_PAIRS_IDS.put("CGB_LTC", 123); - CURRENCY_PAIRS_IDS.put("CLR_BTC", 95); - CURRENCY_PAIRS_IDS.put("CMC_BTC", 74); - CURRENCY_PAIRS_IDS.put("CNC_BTC", 8); - CURRENCY_PAIRS_IDS.put("CNC_LTC", 17); - CURRENCY_PAIRS_IDS.put("COL_LTC", 109); - CURRENCY_PAIRS_IDS.put("COL_XPM", 110); - CURRENCY_PAIRS_IDS.put("CPR_LTC", 91); - CURRENCY_PAIRS_IDS.put("CRC_BTC", 58); - CURRENCY_PAIRS_IDS.put("CSC_BTC", 68); - CURRENCY_PAIRS_IDS.put("DBL_LTC", 46); - CURRENCY_PAIRS_IDS.put("DEM_BTC", 131); - CURRENCY_PAIRS_IDS.put("DGB_BTC", 167); - CURRENCY_PAIRS_IDS.put("DGC_BTC", 26); - CURRENCY_PAIRS_IDS.put("DGC_LTC", 96); - CURRENCY_PAIRS_IDS.put("DMD_BTC", 72); - CURRENCY_PAIRS_IDS.put("DOGE_BTC", 132); - CURRENCY_PAIRS_IDS.put("DOGE_LTC", 135); - CURRENCY_PAIRS_IDS.put("DRK_BTC", 155); - CURRENCY_PAIRS_IDS.put("DVC_BTC", 40); - CURRENCY_PAIRS_IDS.put("DVC_LTC", 52); - CURRENCY_PAIRS_IDS.put("DVC_XPM", 122); - CURRENCY_PAIRS_IDS.put("EAC_BTC", 139); - CURRENCY_PAIRS_IDS.put("ELC_BTC", 12); - CURRENCY_PAIRS_IDS.put("ELP_LTC", 93); - CURRENCY_PAIRS_IDS.put("EMD_BTC", 69); - CURRENCY_PAIRS_IDS.put("EZC_BTC", 47); - CURRENCY_PAIRS_IDS.put("EZC_LTC", 55); - CURRENCY_PAIRS_IDS.put("FFC_BTC", 138); - CURRENCY_PAIRS_IDS.put("FLAP_BTC", 165); - CURRENCY_PAIRS_IDS.put("FLO_LTC", 61); - CURRENCY_PAIRS_IDS.put("FRC_BTC", 39); - CURRENCY_PAIRS_IDS.put("FRK_BTC", 33); - CURRENCY_PAIRS_IDS.put("FST_BTC", 44); - CURRENCY_PAIRS_IDS.put("FST_LTC", 124); - CURRENCY_PAIRS_IDS.put("FTC_BTC", 5); - CURRENCY_PAIRS_IDS.put("GDC_BTC", 82); - CURRENCY_PAIRS_IDS.put("GLC_BTC", 76); - CURRENCY_PAIRS_IDS.put("GLD_BTC", 30); - CURRENCY_PAIRS_IDS.put("GLD_LTC", 36); - CURRENCY_PAIRS_IDS.put("GLX_BTC", 78); - CURRENCY_PAIRS_IDS.put("GME_LTC", 84); - CURRENCY_PAIRS_IDS.put("HBN_BTC", 80); - CURRENCY_PAIRS_IDS.put("IFC_BTC", 59); - CURRENCY_PAIRS_IDS.put("IFC_LTC", 60); - CURRENCY_PAIRS_IDS.put("IFC_XPM", 105); - CURRENCY_PAIRS_IDS.put("IXC_BTC", 38); - CURRENCY_PAIRS_IDS.put("JKC_BTC", 25); - CURRENCY_PAIRS_IDS.put("JKC_LTC", 35); - CURRENCY_PAIRS_IDS.put("KGC_BTC", 65); - CURRENCY_PAIRS_IDS.put("LEAF_BTC", 148); - CURRENCY_PAIRS_IDS.put("LK7_BTC", 116); - CURRENCY_PAIRS_IDS.put("LKY_BTC", 34); - CURRENCY_PAIRS_IDS.put("LOT_BTC", 137); - CURRENCY_PAIRS_IDS.put("LTC_BTC", 3); - CURRENCY_PAIRS_IDS.put("MAX_BTC", 152); - CURRENCY_PAIRS_IDS.put("MEC_BTC", 45); - CURRENCY_PAIRS_IDS.put("MEC_LTC", 100); - CURRENCY_PAIRS_IDS.put("MEM_LTC", 56); - CURRENCY_PAIRS_IDS.put("MEOW_BTC", 149); - CURRENCY_PAIRS_IDS.put("MINT_BTC", 156); - CURRENCY_PAIRS_IDS.put("MNC_BTC", 7); - CURRENCY_PAIRS_IDS.put("MOON_LTC", 145); - CURRENCY_PAIRS_IDS.put("MST_LTC", 62); - CURRENCY_PAIRS_IDS.put("MZC_BTC", 164); - CURRENCY_PAIRS_IDS.put("NAN_BTC", 64); - CURRENCY_PAIRS_IDS.put("NBL_BTC", 32); - CURRENCY_PAIRS_IDS.put("NEC_BTC", 90); - CURRENCY_PAIRS_IDS.put("NET_BTC", 134); - CURRENCY_PAIRS_IDS.put("NET_LTC", 108); - CURRENCY_PAIRS_IDS.put("NET_XPM", 104); - CURRENCY_PAIRS_IDS.put("NMC_BTC", 29); - CURRENCY_PAIRS_IDS.put("NRB_BTC", 54); - CURRENCY_PAIRS_IDS.put("NVC_BTC", 13); - CURRENCY_PAIRS_IDS.put("NXT_BTC", 159); - CURRENCY_PAIRS_IDS.put("NXT_LTC", 162); - CURRENCY_PAIRS_IDS.put("ORB_BTC", 75); - CURRENCY_PAIRS_IDS.put("OSC_BTC", 144); - CURRENCY_PAIRS_IDS.put("PHS_BTC", 86); - CURRENCY_PAIRS_IDS.put("POINTS_BTC", 120); - CURRENCY_PAIRS_IDS.put("PPC_BTC", 28); - CURRENCY_PAIRS_IDS.put("PPC_LTC", 125); - CURRENCY_PAIRS_IDS.put("PTS_BTC", 119); - CURRENCY_PAIRS_IDS.put("PXC_BTC", 31); - CURRENCY_PAIRS_IDS.put("PXC_LTC", 101); - CURRENCY_PAIRS_IDS.put("PYC_BTC", 92); - CURRENCY_PAIRS_IDS.put("QRK_BTC", 71); - CURRENCY_PAIRS_IDS.put("QRK_LTC", 126); - CURRENCY_PAIRS_IDS.put("RDD_BTC", 169); - CURRENCY_PAIRS_IDS.put("RED_LTC", 87); - CURRENCY_PAIRS_IDS.put("RPC_BTC", 143); - CURRENCY_PAIRS_IDS.put("RYC_BTC", 9); - CURRENCY_PAIRS_IDS.put("RYC_LTC", 37); - CURRENCY_PAIRS_IDS.put("SAT_BTC", 168); - CURRENCY_PAIRS_IDS.put("SBC_BTC", 51); - CURRENCY_PAIRS_IDS.put("SBC_LTC", 128); - CURRENCY_PAIRS_IDS.put("SMC_BTC", 158); - CURRENCY_PAIRS_IDS.put("SPT_BTC", 81); - CURRENCY_PAIRS_IDS.put("SRC_BTC", 88); - CURRENCY_PAIRS_IDS.put("STR_BTC", 83); - CURRENCY_PAIRS_IDS.put("SXC_BTC", 153); - CURRENCY_PAIRS_IDS.put("SXC_LTC", 98); - CURRENCY_PAIRS_IDS.put("TAG_BTC", 117); - CURRENCY_PAIRS_IDS.put("TAK_BTC", 166); - CURRENCY_PAIRS_IDS.put("TEK_BTC", 114); - CURRENCY_PAIRS_IDS.put("TGC_BTC", 130); - CURRENCY_PAIRS_IDS.put("TIPS_LTC", 147); - CURRENCY_PAIRS_IDS.put("TIX_LTC", 107); - CURRENCY_PAIRS_IDS.put("TIX_XPM", 103); - CURRENCY_PAIRS_IDS.put("TRC_BTC", 27); - CURRENCY_PAIRS_IDS.put("UNO_BTC", 133); - CURRENCY_PAIRS_IDS.put("UTC_BTC", 163); - CURRENCY_PAIRS_IDS.put("VTC_BTC", 151); - CURRENCY_PAIRS_IDS.put("WDC_BTC", 14); - CURRENCY_PAIRS_IDS.put("WDC_LTC", 21); - CURRENCY_PAIRS_IDS.put("XJO_BTC", 115); - CURRENCY_PAIRS_IDS.put("XNC_LTC", 67); - CURRENCY_PAIRS_IDS.put("XPM_BTC", 63); - CURRENCY_PAIRS_IDS.put("XPM_LTC", 106); - CURRENCY_PAIRS_IDS.put("YAC_BTC", 11); - CURRENCY_PAIRS_IDS.put("YAC_LTC", 22); - CURRENCY_PAIRS_IDS.put("YBC_BTC", 73); - CURRENCY_PAIRS_IDS.put("ZCC_BTC", 140); - CURRENCY_PAIRS_IDS.put("ZED_BTC", 170); - CURRENCY_PAIRS_IDS.put("ZET_BTC", 85); - CURRENCY_PAIRS_IDS.put("ZET_LTC", 127); - } - - public Cryptsy() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(checkerInfo.getCurrencyPairId()==null) { - final String pairString = String.format("%1$s_%2$s", checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - if(CURRENCY_PAIRS_IDS.containsKey(pairString)) { - return String.format(URL, String.valueOf(CURRENCY_PAIRS_IDS.get(pairString))); - } - } - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); - final JSONObject daySummaryObject = dataJsonObject.getJSONObject("24hr"); - - // ticker.vol = daySummaryObject.getDouble("volume"); TODO enable later when there will be any documentation of real data to test on - ticker.high = daySummaryObject.getDouble("price_high"); - ticker.low = daySummaryObject.getDouble("price_low"); - ticker.last = dataJsonObject.getJSONObject("last_trade").getDouble("price"); - } - - @Override - protected String parseError(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { - if(checkerInfo.getCurrencyPairId()==null) { - return "Perform sync and re-add this Checker"; - } - return super.parseError(requestId, responseString, checkerInfo); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray dataJsonArray = jsonObject.getJSONArray("data"); - for(int i=0; i CURRENCY_PAIRS_IDS = new HashMap(151); + static { + // Kept for backward compatibility + CURRENCY_PAIRS_IDS.put("42_BTC", 141); + CURRENCY_PAIRS_IDS.put("ADT_LTC", 94); + CURRENCY_PAIRS_IDS.put("ADT_XPM", 113); + CURRENCY_PAIRS_IDS.put("ALF_BTC", 57); + CURRENCY_PAIRS_IDS.put("AMC_BTC", 43); + CURRENCY_PAIRS_IDS.put("ANC_BTC", 66); + CURRENCY_PAIRS_IDS.put("ANC_LTC", 121); + CURRENCY_PAIRS_IDS.put("ARG_BTC", 48); + CURRENCY_PAIRS_IDS.put("ASC_LTC", 111); + CURRENCY_PAIRS_IDS.put("ASC_XPM", 112); + CURRENCY_PAIRS_IDS.put("AUR_BTC", 160); + CURRENCY_PAIRS_IDS.put("AUR_LTC", 161); + CURRENCY_PAIRS_IDS.put("BCX_BTC", 142); + CURRENCY_PAIRS_IDS.put("BEN_BTC", 157); + CURRENCY_PAIRS_IDS.put("BET_BTC", 129); + CURRENCY_PAIRS_IDS.put("BQC_BTC", 10); + CURRENCY_PAIRS_IDS.put("BTB_BTC", 23); + CURRENCY_PAIRS_IDS.put("BTE_BTC", 49); + CURRENCY_PAIRS_IDS.put("BTG_BTC", 50); + CURRENCY_PAIRS_IDS.put("BUK_BTC", 102); + CURRENCY_PAIRS_IDS.put("CACH_BTC", 154); + CURRENCY_PAIRS_IDS.put("CAP_BTC", 53); + CURRENCY_PAIRS_IDS.put("CASH_BTC", 150); + CURRENCY_PAIRS_IDS.put("CAT_BTC", 136); + CURRENCY_PAIRS_IDS.put("CGB_BTC", 70); + CURRENCY_PAIRS_IDS.put("CGB_LTC", 123); + CURRENCY_PAIRS_IDS.put("CLR_BTC", 95); + CURRENCY_PAIRS_IDS.put("CMC_BTC", 74); + CURRENCY_PAIRS_IDS.put("CNC_BTC", 8); + CURRENCY_PAIRS_IDS.put("CNC_LTC", 17); + CURRENCY_PAIRS_IDS.put("COL_LTC", 109); + CURRENCY_PAIRS_IDS.put("COL_XPM", 110); + CURRENCY_PAIRS_IDS.put("CPR_LTC", 91); + CURRENCY_PAIRS_IDS.put("CRC_BTC", 58); + CURRENCY_PAIRS_IDS.put("CSC_BTC", 68); + CURRENCY_PAIRS_IDS.put("DBL_LTC", 46); + CURRENCY_PAIRS_IDS.put("DEM_BTC", 131); + CURRENCY_PAIRS_IDS.put("DGB_BTC", 167); + CURRENCY_PAIRS_IDS.put("DGC_BTC", 26); + CURRENCY_PAIRS_IDS.put("DGC_LTC", 96); + CURRENCY_PAIRS_IDS.put("DMD_BTC", 72); + CURRENCY_PAIRS_IDS.put("DOGE_BTC", 132); + CURRENCY_PAIRS_IDS.put("DOGE_LTC", 135); + CURRENCY_PAIRS_IDS.put("DRK_BTC", 155); + CURRENCY_PAIRS_IDS.put("DVC_BTC", 40); + CURRENCY_PAIRS_IDS.put("DVC_LTC", 52); + CURRENCY_PAIRS_IDS.put("DVC_XPM", 122); + CURRENCY_PAIRS_IDS.put("EAC_BTC", 139); + CURRENCY_PAIRS_IDS.put("ELC_BTC", 12); + CURRENCY_PAIRS_IDS.put("ELP_LTC", 93); + CURRENCY_PAIRS_IDS.put("EMD_BTC", 69); + CURRENCY_PAIRS_IDS.put("EZC_BTC", 47); + CURRENCY_PAIRS_IDS.put("EZC_LTC", 55); + CURRENCY_PAIRS_IDS.put("FFC_BTC", 138); + CURRENCY_PAIRS_IDS.put("FLAP_BTC", 165); + CURRENCY_PAIRS_IDS.put("FLO_LTC", 61); + CURRENCY_PAIRS_IDS.put("FRC_BTC", 39); + CURRENCY_PAIRS_IDS.put("FRK_BTC", 33); + CURRENCY_PAIRS_IDS.put("FST_BTC", 44); + CURRENCY_PAIRS_IDS.put("FST_LTC", 124); + CURRENCY_PAIRS_IDS.put("FTC_BTC", 5); + CURRENCY_PAIRS_IDS.put("GDC_BTC", 82); + CURRENCY_PAIRS_IDS.put("GLC_BTC", 76); + CURRENCY_PAIRS_IDS.put("GLD_BTC", 30); + CURRENCY_PAIRS_IDS.put("GLD_LTC", 36); + CURRENCY_PAIRS_IDS.put("GLX_BTC", 78); + CURRENCY_PAIRS_IDS.put("GME_LTC", 84); + CURRENCY_PAIRS_IDS.put("HBN_BTC", 80); + CURRENCY_PAIRS_IDS.put("IFC_BTC", 59); + CURRENCY_PAIRS_IDS.put("IFC_LTC", 60); + CURRENCY_PAIRS_IDS.put("IFC_XPM", 105); + CURRENCY_PAIRS_IDS.put("IXC_BTC", 38); + CURRENCY_PAIRS_IDS.put("JKC_BTC", 25); + CURRENCY_PAIRS_IDS.put("JKC_LTC", 35); + CURRENCY_PAIRS_IDS.put("KGC_BTC", 65); + CURRENCY_PAIRS_IDS.put("LEAF_BTC", 148); + CURRENCY_PAIRS_IDS.put("LK7_BTC", 116); + CURRENCY_PAIRS_IDS.put("LKY_BTC", 34); + CURRENCY_PAIRS_IDS.put("LOT_BTC", 137); + CURRENCY_PAIRS_IDS.put("LTC_BTC", 3); + CURRENCY_PAIRS_IDS.put("MAX_BTC", 152); + CURRENCY_PAIRS_IDS.put("MEC_BTC", 45); + CURRENCY_PAIRS_IDS.put("MEC_LTC", 100); + CURRENCY_PAIRS_IDS.put("MEM_LTC", 56); + CURRENCY_PAIRS_IDS.put("MEOW_BTC", 149); + CURRENCY_PAIRS_IDS.put("MINT_BTC", 156); + CURRENCY_PAIRS_IDS.put("MNC_BTC", 7); + CURRENCY_PAIRS_IDS.put("MOON_LTC", 145); + CURRENCY_PAIRS_IDS.put("MST_LTC", 62); + CURRENCY_PAIRS_IDS.put("MZC_BTC", 164); + CURRENCY_PAIRS_IDS.put("NAN_BTC", 64); + CURRENCY_PAIRS_IDS.put("NBL_BTC", 32); + CURRENCY_PAIRS_IDS.put("NEC_BTC", 90); + CURRENCY_PAIRS_IDS.put("NET_BTC", 134); + CURRENCY_PAIRS_IDS.put("NET_LTC", 108); + CURRENCY_PAIRS_IDS.put("NET_XPM", 104); + CURRENCY_PAIRS_IDS.put("NMC_BTC", 29); + CURRENCY_PAIRS_IDS.put("NRB_BTC", 54); + CURRENCY_PAIRS_IDS.put("NVC_BTC", 13); + CURRENCY_PAIRS_IDS.put("NXT_BTC", 159); + CURRENCY_PAIRS_IDS.put("NXT_LTC", 162); + CURRENCY_PAIRS_IDS.put("ORB_BTC", 75); + CURRENCY_PAIRS_IDS.put("OSC_BTC", 144); + CURRENCY_PAIRS_IDS.put("PHS_BTC", 86); + CURRENCY_PAIRS_IDS.put("POINTS_BTC", 120); + CURRENCY_PAIRS_IDS.put("PPC_BTC", 28); + CURRENCY_PAIRS_IDS.put("PPC_LTC", 125); + CURRENCY_PAIRS_IDS.put("PTS_BTC", 119); + CURRENCY_PAIRS_IDS.put("PXC_BTC", 31); + CURRENCY_PAIRS_IDS.put("PXC_LTC", 101); + CURRENCY_PAIRS_IDS.put("PYC_BTC", 92); + CURRENCY_PAIRS_IDS.put("QRK_BTC", 71); + CURRENCY_PAIRS_IDS.put("QRK_LTC", 126); + CURRENCY_PAIRS_IDS.put("RDD_BTC", 169); + CURRENCY_PAIRS_IDS.put("RED_LTC", 87); + CURRENCY_PAIRS_IDS.put("RPC_BTC", 143); + CURRENCY_PAIRS_IDS.put("RYC_BTC", 9); + CURRENCY_PAIRS_IDS.put("RYC_LTC", 37); + CURRENCY_PAIRS_IDS.put("SAT_BTC", 168); + CURRENCY_PAIRS_IDS.put("SBC_BTC", 51); + CURRENCY_PAIRS_IDS.put("SBC_LTC", 128); + CURRENCY_PAIRS_IDS.put("SMC_BTC", 158); + CURRENCY_PAIRS_IDS.put("SPT_BTC", 81); + CURRENCY_PAIRS_IDS.put("SRC_BTC", 88); + CURRENCY_PAIRS_IDS.put("STR_BTC", 83); + CURRENCY_PAIRS_IDS.put("SXC_BTC", 153); + CURRENCY_PAIRS_IDS.put("SXC_LTC", 98); + CURRENCY_PAIRS_IDS.put("TAG_BTC", 117); + CURRENCY_PAIRS_IDS.put("TAK_BTC", 166); + CURRENCY_PAIRS_IDS.put("TEK_BTC", 114); + CURRENCY_PAIRS_IDS.put("TGC_BTC", 130); + CURRENCY_PAIRS_IDS.put("TIPS_LTC", 147); + CURRENCY_PAIRS_IDS.put("TIX_LTC", 107); + CURRENCY_PAIRS_IDS.put("TIX_XPM", 103); + CURRENCY_PAIRS_IDS.put("TRC_BTC", 27); + CURRENCY_PAIRS_IDS.put("UNO_BTC", 133); + CURRENCY_PAIRS_IDS.put("UTC_BTC", 163); + CURRENCY_PAIRS_IDS.put("VTC_BTC", 151); + CURRENCY_PAIRS_IDS.put("WDC_BTC", 14); + CURRENCY_PAIRS_IDS.put("WDC_LTC", 21); + CURRENCY_PAIRS_IDS.put("XJO_BTC", 115); + CURRENCY_PAIRS_IDS.put("XNC_LTC", 67); + CURRENCY_PAIRS_IDS.put("XPM_BTC", 63); + CURRENCY_PAIRS_IDS.put("XPM_LTC", 106); + CURRENCY_PAIRS_IDS.put("YAC_BTC", 11); + CURRENCY_PAIRS_IDS.put("YAC_LTC", 22); + CURRENCY_PAIRS_IDS.put("YBC_BTC", 73); + CURRENCY_PAIRS_IDS.put("ZCC_BTC", 140); + CURRENCY_PAIRS_IDS.put("ZED_BTC", 170); + CURRENCY_PAIRS_IDS.put("ZET_BTC", 85); + CURRENCY_PAIRS_IDS.put("ZET_LTC", 127); + } + + public Cryptsy() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(checkerInfo.getCurrencyPairId()==null) { + final String pairString = String.format("%1$s_%2$s", checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + if(CURRENCY_PAIRS_IDS.containsKey(pairString)) { + return String.format(URL, String.valueOf(CURRENCY_PAIRS_IDS.get(pairString))); + } + } + return String.format(URL, checkerInfo.getCurrencyPairId()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataJsonObject = jsonObject.getJSONObject("data"); + final JSONObject daySummaryObject = dataJsonObject.getJSONObject("24hr"); + + // ticker.vol = daySummaryObject.getDouble("volume"); TODO enable later when there will be any documentation of real data to test on + ticker.high = daySummaryObject.getDouble("price_high"); + ticker.low = daySummaryObject.getDouble("price_low"); + ticker.last = dataJsonObject.getJSONObject("last_trade").getDouble("price"); + } + + @Override + protected String parseError(int requestId, String responseString, CheckerInfo checkerInfo) throws Exception { + if(checkerInfo.getCurrencyPairId()==null) { + return "Perform sync and re-add this Checker"; + } + return super.parseError(requestId, responseString, checkerInfo); + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONArray dataJsonArray = jsonObject.getJSONArray("data"); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.DASH, new String[]{ - Currency.PLN, - Currency.USD - }); - } - - public Dashcurex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = parsePrice(jsonObject.getDouble("best_ask")); - ticker.ask = parsePrice(jsonObject.getDouble("best_bid")); - ticker.vol = parseBTC(jsonObject.getDouble("total_volume")); - ticker.high = parsePrice(jsonObject.getDouble("highest_tx_price")); - ticker.low = parsePrice(jsonObject.getDouble("lowest_tx_price")); - ticker.last = parsePrice(jsonObject.getDouble("last_tx_price")); - } - - private double parsePrice(double price) { - return price/10000; - } - - private double parseBTC(double satoshi) { - return satoshi/100000000; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Dashcurex extends Market { + + private final static String NAME = "Dashcurex"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://dashcurex.com/api/%1$s/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.DASH, new String[]{ + Currency.PLN, + Currency.USD + }); + } + + public Dashcurex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = parsePrice(jsonObject.getDouble("best_ask")); + ticker.ask = parsePrice(jsonObject.getDouble("best_bid")); + ticker.vol = parseBTC(jsonObject.getDouble("total_volume")); + ticker.high = parsePrice(jsonObject.getDouble("highest_tx_price")); + ticker.low = parsePrice(jsonObject.getDouble("lowest_tx_price")); + ticker.last = parsePrice(jsonObject.getDouble("last_tx_price")); + } + + private double parsePrice(double price) { + return price/10000; + } + + private double parseBTC(double satoshi) { + return satoshi/100000000; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/DolarBlueNet.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/DolarBlueNet.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/DolarBlueNet.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/DolarBlueNet.java index e2a8eec3..a5829c36 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/DolarBlueNet.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/DolarBlueNet.java @@ -1,40 +1,40 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; - -public class DolarBlueNet extends Market { - - private final static String NAME = "DolarBlue.net"; - private final static String TTS_NAME = "Dolar Blue"; - private final static String URL = "http://dolar.bitplanet.info/api.php"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(Currency.USD, new String[]{ - Currency.ARS - }); - } - - public DolarBlueNet() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.ask = jsonObject.getDouble("venta"); - ticker.bid = jsonObject.getDouble("compra"); - ticker.last = ticker.ask; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; + +public class DolarBlueNet extends Market { + + private final static String NAME = "DolarBlue.net"; + private final static String TTS_NAME = "Dolar Blue"; + private final static String URL = "http://dolar.bitplanet.info/api.php"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(Currency.USD, new String[]{ + Currency.ARS + }); + } + + public DolarBlueNet() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.ask = jsonObject.getDouble("venta"); + ticker.bid = jsonObject.getDouble("compra"); + ticker.last = ticker.ask; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/FoscEx.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoscEx.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/FoscEx.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoscEx.java index 28c42961..3cba796d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/FoscEx.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoscEx.java @@ -1,50 +1,50 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardian.util.ParseUtils; -import com.mobnetic.coinguardian.util.TimeUtils; - -public class FoscEx extends Market { - - private final static String NAME = "Fosc-Ex"; - private final static String TTS_NAME = "Fosc Ex"; - private final static String URL = "http://www.fosc-ex.com/api-public-ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.KNC, new String[]{ - Currency.KRW - }); - } - - public FoscEx() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); - ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last"); - ticker.timestamp = jsonObject.getLong("timestamp") * TimeUtils.MILLIS_IN_SECOND; - - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("error"); - } - -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class FoscEx extends Market { + + private final static String NAME = "Fosc-Ex"; + private final static String TTS_NAME = "Fosc Ex"; + private final static String URL = "http://www.fosc-ex.com/api-public-ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.KNC, new String[]{ + Currency.KRW + }); + } + + public FoscEx() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); + ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last"); + ticker.timestamp = jsonObject.getLong("timestamp") * TimeUtils.MILLIS_IN_SECOND; + + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("error"); + } + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/FoxBit.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoxBit.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/FoxBit.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoxBit.java index 25a7339a..7ae1958d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/FoxBit.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FoxBit.java @@ -1,44 +1,44 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class FoxBit extends Market { - - private final static String NAME = "FoxBit.com.br"; - private final static String TTS_NAME = "Fox Bit"; - private final static String URL = "https://api.blinktrade.com/api/v1/%2$s/ticker?crypto_currency=%1$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.BRL - }); - } - - public FoxBit() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("buy"); - ticker.ask = jsonObject.getDouble("sell"); - ticker.vol = jsonObject.getDouble("vol"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class FoxBit extends Market { + + private final static String NAME = "FoxBit.com.br"; + private final static String TTS_NAME = "Fox Bit"; + private final static String URL = "https://api.blinktrade.com/api/v1/%2$s/ticker?crypto_currency=%1$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.BRL + }); + } + + public FoxBit() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("buy"); + ticker.ask = jsonObject.getDouble("sell"); + ticker.vol = jsonObject.getDouble("vol"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Fxbtc.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Fxbtc.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Fxbtc.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Fxbtc.java index 8739c37d..9ed08af3 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Fxbtc.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Fxbtc.java @@ -1,49 +1,49 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Fxbtc extends Market { - - private final static String NAME = "FxBtc"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.fxbtc.com/jport?op=query&type=ticker&symbol=%1$s_%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CNY - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.CNY, - VirtualCurrency.BTC - }); - } - - public Fxbtc() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerObject.getDouble("bid"); - ticker.ask = tickerObject.getDouble("ask"); - ticker.vol = tickerObject.getDouble("vol"); - ticker.high = tickerObject.getDouble("high"); - ticker.low = tickerObject.getDouble("low"); - ticker.last = tickerObject.getDouble("last_rate"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Fxbtc extends Market { + + private final static String NAME = "FxBtc"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.fxbtc.com/jport?op=query&type=ticker&symbol=%1$s_%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CNY + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.CNY, + VirtualCurrency.BTC + }); + } + + public Fxbtc() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = tickerObject.getDouble("bid"); + ticker.ask = tickerObject.getDouble("ask"); + ticker.vol = tickerObject.getDouble("vol"); + ticker.high = tickerObject.getDouble("high"); + ticker.low = tickerObject.getDouble("low"); + ticker.last = tickerObject.getDouble("last_rate"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/FybSE.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSE.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/FybSE.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSE.java index 9c8bcdad..c9d670ec 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/FybSE.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSE.java @@ -1,41 +1,41 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class FybSE extends Market { - - private final static String NAME = "FYB-SE"; - private final static String TTS_NAME = "Fyb SE"; - private final static String URL = "https://www.fybse.se/api/%1$s/ticker.json"; - - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.SEK - }); - } - - public FybSE() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.last = ticker.ask; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class FybSE extends Market { + + private final static String NAME = "FYB-SE"; + private final static String TTS_NAME = "Fyb SE"; + private final static String URL = "https://www.fybse.se/api/%1$s/ticker.json"; + + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.SEK + }); + } + + public FybSE() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.last = ticker.ask; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/FybSG.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSG.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/FybSG.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSG.java index 64de6222..1945de78 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/FybSG.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/FybSG.java @@ -1,41 +1,41 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class FybSG extends Market { - - private final static String NAME = "FYB-SG"; - private final static String TTS_NAME = "Fyb SG"; - private final static String URL = "https://www.fybsg.com/api/%1$s/ticker.json"; - - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.SGD - }); - } - - public FybSG() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.last = ticker.ask; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class FybSG extends Market { + + private final static String NAME = "FYB-SG"; + private final static String TTS_NAME = "Fyb SG"; + private final static String URL = "https://www.fybsg.com/api/%1$s/ticker.json"; + + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.SGD + }); + } + + public FybSG() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.last = ticker.ask; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Gemini.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Gemini.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Gemini.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Gemini.java index c5aebed1..19b1c4e3 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Gemini.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Gemini.java @@ -1,67 +1,67 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Gemini extends Market { - - private final static String NAME = "Gemini"; - private final static String TTS_NAME = "Gemini"; - private final static String URL = "https://api.gemini.com/v1/book/%1$s%2$s?limit_asks=1&limit_bids=1"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - - // Gemini allows dynamic symbol retrieval but returns it in format: [ "btcusd" ] - // This doesn't provide an easy way to programmatically split the currency - // So just define them - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public Gemini() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - //Gemini isn't a traditional tracker, rather it seems to return the X last bids and asks - //We could do something like take the average of the last Y prices - //But I will just take the average of the last bid and asking price - - final JSONArray bidsArray = jsonObject.getJSONArray("bids"); - if (bidsArray != null && bidsArray.length() > 0) { - ticker.bid = bidsArray.getJSONObject(0).getDouble("price"); - } - - final JSONArray asksArray = jsonObject.getJSONArray("asks"); - if (asksArray != null && asksArray.length() > 0) { - ticker.ask = asksArray.getJSONObject(0).getDouble("price"); - } - - if (ticker.bid != Ticker.NO_DATA && ticker.ask != Ticker.NO_DATA) { - ticker.last = (ticker.bid + ticker.ask) / 2.0; - } else if (ticker.bid != Ticker.NO_DATA) { - ticker.last = ticker.bid; - } else if (ticker.ask != Ticker.NO_DATA) { - ticker.last = ticker.ask; - } else { - ticker.last = 0; - } - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; + +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Gemini extends Market { + + private final static String NAME = "Gemini"; + private final static String TTS_NAME = "Gemini"; + private final static String URL = "https://api.gemini.com/v1/book/%1$s%2$s?limit_asks=1&limit_bids=1"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + + // Gemini allows dynamic symbol retrieval but returns it in format: [ "btcusd" ] + // This doesn't provide an easy way to programmatically split the currency + // So just define them + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public Gemini() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + //Gemini isn't a traditional tracker, rather it seems to return the X last bids and asks + //We could do something like take the average of the last Y prices + //But I will just take the average of the last bid and asking price + + final JSONArray bidsArray = jsonObject.getJSONArray("bids"); + if (bidsArray != null && bidsArray.length() > 0) { + ticker.bid = bidsArray.getJSONObject(0).getDouble("price"); + } + + final JSONArray asksArray = jsonObject.getJSONArray("asks"); + if (asksArray != null && asksArray.length() > 0) { + ticker.ask = asksArray.getJSONObject(0).getDouble("price"); + } + + if (ticker.bid != Ticker.NO_DATA && ticker.ask != Ticker.NO_DATA) { + ticker.last = (ticker.bid + ticker.ask) / 2.0; + } else if (ticker.bid != Ticker.NO_DATA) { + ticker.last = ticker.bid; + } else if (ticker.ask != Ticker.NO_DATA) { + ticker.last = ticker.ask; + } else { + ticker.last = 0; + } + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/HitBtc.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/HitBtc.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/HitBtc.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/HitBtc.java index 770a0d41..d28d7550 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/HitBtc.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/HitBtc.java @@ -1,63 +1,63 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.util.ParseUtils; - -public class HitBtc extends Market { - - private final static String NAME = "HitBTC"; - private final static String TTS_NAME = "Hit BTC"; - private final static String URL = "https://api.hitbtc.com/api/1/public/%1$s/ticker"; - private final static String URL_CURRENCY_PAIRS = "https://api.hitbtc.com/api/1/public/symbols"; - - public HitBtc() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); - ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); - ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); - ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); - ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray symbolsJsonArray = jsonObject.getJSONArray("symbols"); - for(int i=0; i pairs) throws Exception { + final JSONArray symbolsJsonArray = jsonObject.getJSONArray("symbols"); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CNY, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.CNY - }); - } - - public Huobi() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { - return URL_LTC; - } else if(Currency.USD.equals(checkerInfo.getCurrencyCounter())) { - return URL_BTC_USD; - } else { - return URL_BTC; - } - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = ParseUtils.getDoubleFromString(tickerJsonObject, "buy"); - ticker.ask = ParseUtils.getDoubleFromString(tickerJsonObject, "sell"); - ticker.vol = ParseUtils.getDoubleFromString(tickerJsonObject, "vol"); - ticker.high = ParseUtils.getDoubleFromString(tickerJsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(tickerJsonObject, "low"); - ticker.last = ParseUtils.getDoubleFromString(tickerJsonObject, "last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; + +public class Huobi extends Market { + + private final static String NAME = "Huobi"; + private final static String TTS_NAME = NAME; + private final static String URL_BTC = "http://api.huobi.com/staticmarket/ticker_btc_json.js"; + private final static String URL_BTC_USD = "http://api.huobi.com/usdmarket/ticker_btc_json.js"; + private final static String URL_LTC = "http://api.huobi.com/staticmarket/ticker_ltc_json.js"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CNY, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.CNY + }); + } + + public Huobi() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { + return URL_LTC; + } else if(Currency.USD.equals(checkerInfo.getCurrencyCounter())) { + return URL_BTC_USD; + } else { + return URL_BTC; + } + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = ParseUtils.getDoubleFromString(tickerJsonObject, "buy"); + ticker.ask = ParseUtils.getDoubleFromString(tickerJsonObject, "sell"); + ticker.vol = ParseUtils.getDoubleFromString(tickerJsonObject, "vol"); + ticker.high = ParseUtils.getDoubleFromString(tickerJsonObject, "high"); + ticker.low = ParseUtils.getDoubleFromString(tickerJsonObject, "low"); + ticker.last = ParseUtils.getDoubleFromString(tickerJsonObject, "last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Igot.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Igot.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Igot.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Igot.java index 80da3b65..d1bd8659 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Igot.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Igot.java @@ -1,60 +1,60 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Igot extends Market { - - private final static String NAME = "igot"; - private final static String TTS_NAME = "igot"; - private final static String URL = "https://www.igot.com/api/v1/stats/buy"; - private final static String URL_CURRENCY_PAIRS = URL; - - public Igot() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyPairId()); - ticker.high = pairJsonObject.getDouble("highest_today"); - ticker.low = pairJsonObject.getDouble("lowest_today"); - ticker.last = pairJsonObject.getDouble("current_rate"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray pairsJsonArray = jsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = jsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.SGD, - Currency.EUR - }); - } - - public ItBit() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - private String fixCurrency(String currency) { - if (VirtualCurrency.BTC.equals(currency)) return VirtualCurrency.XBT; - return currency; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, fixCurrency(checkerInfo.getCurrencyBase()), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume24h"); - ticker.high = jsonObject.getDouble("high24h"); - ticker.low = jsonObject.getDouble("low24h"); - ticker.last = jsonObject.getDouble("lastPrice"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - return jsonObject.getString("message"); // not working? - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class ItBit extends Market { + + private final static String NAME = "itBit"; + private final static String TTS_NAME = "It Bit"; + private final static String URL = "https://api.itbit.com/v1/markets/%1$s%2$s/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.SGD, + Currency.EUR + }); + } + + public ItBit() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + private String fixCurrency(String currency) { + if (VirtualCurrency.BTC.equals(currency)) return VirtualCurrency.XBT; + return currency; + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, fixCurrency(checkerInfo.getCurrencyBase()), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume24h"); + ticker.high = jsonObject.getDouble("high24h"); + ticker.low = jsonObject.getDouble("low24h"); + ticker.last = jsonObject.getDouble("lastPrice"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + return jsonObject.getString("message"); // not working? + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Justcoin.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Justcoin.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Justcoin.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Justcoin.java index 50a13229..6c509a75 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Justcoin.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Justcoin.java @@ -1,72 +1,72 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Justcoin extends Market { - - private final static String NAME = "Justcoin"; - private final static String TTS_NAME = "Just coin"; - private final static String URL = "https://justcoin.com/api/2/%1$s%2$s/money/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR, - Currency.GBP, - Currency.HKD, - Currency.CHF, - Currency.AUD, - Currency.CAD, - Currency.NZD, - Currency.SGD, - Currency.JPY - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.STR, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.XRP, new String[]{ - VirtualCurrency.BTC - }); - } - - public Justcoin() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataObject = jsonObject.getJSONObject("data"); - - ticker.bid = getPriceValueFromObject(dataObject, "buy"); - ticker.ask = getPriceValueFromObject(dataObject, "sell"); - ticker.vol = getPriceValueFromObject(dataObject, "vol"); - ticker.high = getPriceValueFromObject(dataObject, "high"); - ticker.low = getPriceValueFromObject(dataObject, "low"); - ticker.last = getPriceValueFromObject(dataObject, "last"); - } - - private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { - final JSONObject innerObject = jsonObject.getJSONObject(key); - return innerObject.getDouble("value"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Justcoin extends Market { + + private final static String NAME = "Justcoin"; + private final static String TTS_NAME = "Just coin"; + private final static String URL = "https://justcoin.com/api/2/%1$s%2$s/money/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR, + Currency.GBP, + Currency.HKD, + Currency.CHF, + Currency.AUD, + Currency.CAD, + Currency.NZD, + Currency.SGD, + Currency.JPY + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.STR, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.XRP, new String[]{ + VirtualCurrency.BTC + }); + } + + public Justcoin() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataObject = jsonObject.getJSONObject("data"); + + ticker.bid = getPriceValueFromObject(dataObject, "buy"); + ticker.ask = getPriceValueFromObject(dataObject, "sell"); + ticker.vol = getPriceValueFromObject(dataObject, "vol"); + ticker.high = getPriceValueFromObject(dataObject, "high"); + ticker.low = getPriceValueFromObject(dataObject, "low"); + ticker.last = getPriceValueFromObject(dataObject, "last"); + } + + private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { + final JSONObject innerObject = jsonObject.getJSONObject(key); + return innerObject.getDouble("value"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Koinim.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Koinim.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Koinim.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Koinim.java index 8362df12..9c62de6d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Koinim.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Koinim.java @@ -1,51 +1,51 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Koinim extends Market { - - public final static String NAME = "Koinim"; - public final static String TTS_NAME = NAME; - public final static String URL_BTC = "https://koinim.com/ticker/"; - public final static String URL_LTC = "https://koinim.com/ticker/ltc/"; - public final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.TRY - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.TRY - }); - } - - public Koinim() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { - return URL_LTC; - } - return URL_BTC; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("buy"); - ticker.ask = jsonObject.getDouble("sell"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last_order"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Koinim extends Market { + + public final static String NAME = "Koinim"; + public final static String TTS_NAME = NAME; + public final static String URL_BTC = "https://koinim.com/ticker/"; + public final static String URL_LTC = "https://koinim.com/ticker/ltc/"; + public final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.TRY + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.TRY + }); + } + + public Koinim() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { + return URL_LTC; + } + return URL_BTC; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("buy"); + ticker.ask = jsonObject.getDouble("sell"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last_order"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Korbit.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Korbit.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Korbit.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Korbit.java index 3cdf465b..1ff5d399 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Korbit.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Korbit.java @@ -1,45 +1,45 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Korbit extends Market { - - private final static String NAME = "Korbit"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.korbit.co.kr/v1/ticker/detailed"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.KRW - }); - } - - public Korbit() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Korbit extends Market { + + private final static String NAME = "Korbit"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.korbit.co.kr/v1/ticker/detailed"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.KRW + }); + } + + public Korbit() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Kraken.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Kraken.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Kraken.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Kraken.java index ab5d363d..26a41eca 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Kraken.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Kraken.java @@ -1,96 +1,96 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Kraken extends Market { - - private final static String NAME = "Kraken"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.kraken.com/0/public/Ticker?pair=%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://api.kraken.com/0/public/AssetPairs"; - - public Kraken() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(checkerInfo.getCurrencyPairId()!=null) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } else { - final String currencyBase = fixCurrency(checkerInfo.getCurrencyBase()); - final String currencyCounter = fixCurrency(checkerInfo.getCurrencyCounter()); - return String.format(URL, currencyBase+currencyCounter); - } - } - - private String fixCurrency(String currency) { - if (VirtualCurrency.BTC.equals(currency)) return VirtualCurrency.XBT; - if (VirtualCurrency.VEN.equals(currency)) return VirtualCurrency.XVN; - if (VirtualCurrency.DOGE.equals(currency)) return VirtualCurrency.XDG; - return currency; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject resultObject = jsonObject.getJSONObject("result"); - final JSONObject pairObject = resultObject.getJSONObject(resultObject.names().getString(0)); - - ticker.bid = getDoubleFromJsonArrayObject(pairObject, "b"); - ticker.ask = getDoubleFromJsonArrayObject(pairObject, "a"); - ticker.vol = getDoubleFromJsonArrayObject(pairObject, "v"); - ticker.high = getDoubleFromJsonArrayObject(pairObject, "h"); - ticker.low = getDoubleFromJsonArrayObject(pairObject, "l"); - ticker.last = getDoubleFromJsonArrayObject(pairObject, "c"); - } - - private double getDoubleFromJsonArrayObject(JSONObject jsonObject, String arrayKey) throws Exception { - final JSONArray jsonArray = jsonObject.getJSONArray(arrayKey); - return jsonArray!=null && jsonArray.length()>0 ? jsonArray.getDouble(0) : 0; - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject result = jsonObject.getJSONObject("result"); - final JSONArray pairNames = result.names(); - - for(int i=0; i=2) { - currency = currency.substring(1); - } - if (VirtualCurrency.XBT.equals(currency)) return VirtualCurrency.BTC; - if (VirtualCurrency.XVN.equals(currency)) return VirtualCurrency.VEN; - if (VirtualCurrency.XDG.equals(currency)) return VirtualCurrency.DOGE; - return currency; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Kraken extends Market { + + private final static String NAME = "Kraken"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.kraken.com/0/public/Ticker?pair=%1$s"; + private final static String URL_CURRENCY_PAIRS = "https://api.kraken.com/0/public/AssetPairs"; + + public Kraken() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(checkerInfo.getCurrencyPairId()!=null) { + return String.format(URL, checkerInfo.getCurrencyPairId()); + } else { + final String currencyBase = fixCurrency(checkerInfo.getCurrencyBase()); + final String currencyCounter = fixCurrency(checkerInfo.getCurrencyCounter()); + return String.format(URL, currencyBase+currencyCounter); + } + } + + private String fixCurrency(String currency) { + if (VirtualCurrency.BTC.equals(currency)) return VirtualCurrency.XBT; + if (VirtualCurrency.VEN.equals(currency)) return VirtualCurrency.XVN; + if (VirtualCurrency.DOGE.equals(currency)) return VirtualCurrency.XDG; + return currency; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject resultObject = jsonObject.getJSONObject("result"); + final JSONObject pairObject = resultObject.getJSONObject(resultObject.names().getString(0)); + + ticker.bid = getDoubleFromJsonArrayObject(pairObject, "b"); + ticker.ask = getDoubleFromJsonArrayObject(pairObject, "a"); + ticker.vol = getDoubleFromJsonArrayObject(pairObject, "v"); + ticker.high = getDoubleFromJsonArrayObject(pairObject, "h"); + ticker.low = getDoubleFromJsonArrayObject(pairObject, "l"); + ticker.last = getDoubleFromJsonArrayObject(pairObject, "c"); + } + + private double getDoubleFromJsonArrayObject(JSONObject jsonObject, String arrayKey) throws Exception { + final JSONArray jsonArray = jsonObject.getJSONArray(arrayKey); + return jsonArray!=null && jsonArray.length()>0 ? jsonArray.getDouble(0) : 0; + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { + final JSONObject result = jsonObject.getJSONObject("result"); + final JSONArray pairNames = result.names(); + + for(int i=0; i=2) { + currency = currency.substring(1); + } + if (VirtualCurrency.XBT.equals(currency)) return VirtualCurrency.BTC; + if (VirtualCurrency.XVN.equals(currency)) return VirtualCurrency.VEN; + if (VirtualCurrency.XDG.equals(currency)) return VirtualCurrency.DOGE; + return currency; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/LakeBTC.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LakeBTC.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/LakeBTC.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LakeBTC.java index 0ecca229..4884ac41 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/LakeBTC.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LakeBTC.java @@ -1,57 +1,57 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class LakeBTC extends Market { - - private final static String NAME = "LakeBTC"; - private final static String TTS_NAME = "Lake BTC"; - private final static String URL = "https://www.lakebtc.com/api_v1/ticker"; - private final static String URL_CURRENCY_PAIRS = URL; - - public LakeBTC() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyCounter()); - - ticker.bid = pairJsonObject.getDouble("bid"); - ticker.ask = pairJsonObject.getDouble("ask"); - ticker.vol = pairJsonObject.getDouble("volume"); - ticker.high = pairJsonObject.getDouble("high"); - ticker.low = pairJsonObject.getDouble("low"); - ticker.last = pairJsonObject.getDouble("last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray currencyCounterJsonArray = jsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONArray currencyCounterJsonArray = jsonObject.names(); + for(int i=0; i pairs) throws Exception { - final JSONArray tickerArray = new JSONArray(responseString); - - for(int i = 0; i < tickerArray.length(); ++i) { - final JSONObject tickerRow = tickerArray.getJSONObject(i); - final String symbol = tickerRow.getString("symbol"); - final String[] currencyNames = symbol.split("/"); - - if(currencyNames != null && currencyNames.length >= 2) { - pairs.add(new CurrencyPairInfo( - currencyNames[0], - currencyNames[1], - symbol)); - } - } - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; + +public class Livecoin extends Market { + + private final static String NAME = "Livecoin"; + private final static String TTS_NAME = "Live coin"; + private final static String URL = "https://api.livecoin.net/exchange/ticker?currencyPair=%1$s"; + private final static String URL_CURRENCY_PAIRS = "https://api.livecoin.net/exchange/ticker"; + + public Livecoin() { + super(NAME, TTS_NAME, null); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyPairId()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + if (!jsonObject.isNull("best_bid")) { + ticker.bid = jsonObject.getDouble("best_bid"); + } + if (!jsonObject.isNull("best_ask")) { + ticker.ask = jsonObject.getDouble("best_ask"); + } + if (!jsonObject.isNull("volume")) { + ticker.vol = jsonObject.getDouble("volume"); + } + if (!jsonObject.isNull("high")) { + ticker.high = jsonObject.getDouble("high"); + } + if (!jsonObject.isNull("low")) { + ticker.low = jsonObject.getDouble("low"); + } + ticker.last = jsonObject.getDouble("last"); + } + + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { + final JSONArray tickerArray = new JSONArray(responseString); + + for(int i = 0; i < tickerArray.length(); ++i) { + final JSONObject tickerRow = tickerArray.getJSONObject(i); + final String symbol = tickerRow.getString("symbol"); + final String[] currencyNames = symbol.split("/"); + + if(currencyNames != null && currencyNames.length >= 2) { + pairs.add(new CurrencyPairInfo( + currencyNames[0], + currencyNames[1], + symbol)); + } + } + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/LocalBitcoins.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LocalBitcoins.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/LocalBitcoins.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LocalBitcoins.java index fb63519a..a4b06ba9 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/LocalBitcoins.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/LocalBitcoins.java @@ -1,59 +1,59 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class LocalBitcoins extends Market { - - private final static String NAME = "LocalBitcoins"; - private final static String TTS_NAME = "Local Bitcoins"; - private final static String URL = "https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/"; - private final static String URL_CURRENCY_PAIRS = URL; - - public LocalBitcoins() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pairJsonObject = jsonObject.getJSONObject(checkerInfo.getCurrencyPairId()); - ticker.vol = pairJsonObject.getDouble("volume_btc"); - final JSONObject ratesJsonObject = pairJsonObject.getJSONObject("rates"); - ticker.last = ratesJsonObject.getDouble("last"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray pairsJsonArray = jsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = jsonObject.names(); + for(int i=0; i1) { - Node orderNode = orderNodes.item(1); - if(orderNode!=null && orderNode instanceof Element) { - NodeList priceNodes = ((Element)orderNode).getElementsByTagName("p"); - if(priceNodes!=null && priceNodes.getLength()>0) { - return XmlParserUtils.getDoubleNodeValue(priceNodes.item(0)); - } - } - } - } - return Ticker.NO_DATA; - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - InputSource is = new InputSource(); - is.setCharacterStream(new StringReader(responseString)); - Document doc = db.parse(is); - - - final NodeList nodes = doc.getElementsByTagName("cur"); - Element node = null; - if(nodes!=null) { - for(int i=0; i1) { + Node orderNode = orderNodes.item(1); + if(orderNode!=null && orderNode instanceof Element) { + NodeList priceNodes = ((Element)orderNode).getElementsByTagName("p"); + if(priceNodes!=null && priceNodes.getLength()>0) { + return XmlParserUtils.getDoubleNodeValue(priceNodes.item(0)); + } + } + } + } + return Ticker.NO_DATA; + } + + // ==================== + // Get currency pairs + // ==================== + @Override + public String getCurrencyPairsUrl(int requestId) { + return URL_CURRENCY_PAIRS; + } + + @Override + protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(responseString)); + Document doc = db.parse(is); + + + final NodeList nodes = doc.getElementsByTagName("cur"); + Element node = null; + if(nodes!=null) { + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.BRL - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.BRL - }); - } - - public Mercado() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase()) ? URL_LTC : URL_BTC; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - ticker.timestamp = tickerJsonObject.getLong("date")*TimeUtils.MILLIS_IN_SECOND; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Mercado extends Market { + + private final static String NAME = "Mercado Bitcoin"; + private final static String TTS_NAME = "Mercado"; + private final static String URL_BTC = "https://www.mercadobitcoin.com.br/api/ticker/"; + private final static String URL_LTC = "https://www.mercadobitcoin.com.br/api/ticker_litecoin/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.BRL + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.BRL + }); + } + + public Mercado() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase()) ? URL_LTC : URL_BTC; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = tickerJsonObject.getDouble("buy"); + ticker.ask = tickerJsonObject.getDouble("sell"); + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + ticker.timestamp = tickerJsonObject.getLong("date")*TimeUtils.MILLIS_IN_SECOND; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Mexbt.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Mexbt.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Mexbt.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Mexbt.java index 4fa2672a..66ace413 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Mexbt.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Mexbt.java @@ -1,45 +1,45 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Mexbt extends Market { - - private final static String NAME = "meXBT"; - private final static String TTS_NAME = "me XBT"; - private final static String URL = "https://data.mexbt.com/ticker/%1$s%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - VirtualCurrency.MXN, - Currency.USD, - }); - } - - public Mexbt() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume24Hour"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Mexbt extends Market { + + private final static String NAME = "meXBT"; + private final static String TTS_NAME = "me XBT"; + private final static String URL = "https://data.mexbt.com/ticker/%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + VirtualCurrency.MXN, + Currency.USD, + }); + } + + public Mexbt() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume24Hour"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/MintPal.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/MintPal.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/MintPal.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/MintPal.java index ed13caad..f1b85697 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/MintPal.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/MintPal.java @@ -1,62 +1,62 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class MintPal extends Market { - - private final static String NAME = "MintPal"; - private final static String TTS_NAME = "Mint Pal"; - private final static String URL = "https://api.mintpal.com/market/stats/%1$s/%2$s/"; - private final static String URL_CURRENCY_PAIRS = "https://api.mintpal.com/market/summary/"; - - public MintPal() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - parseTickerFromJsonObject(requestId, new JSONArray(responseString).getJSONObject(0), ticker, checkerInfo); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.vol = jsonObject.getDouble("24hvol"); - ticker.high = jsonObject.getDouble("24hhigh"); - ticker.low = jsonObject.getDouble("24hlow"); - ticker.last = jsonObject.getDouble("last_price"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray jsonArray = new JSONArray(responseString); - for(int i=0; i pairs) throws Exception { + final JSONArray jsonArray = new JSONArray(responseString); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR, - Currency.CAD, - Currency.GBP, - Currency.CHF, - Currency.RUB, - Currency.AUD, - Currency.SEK, - Currency.DKK, - Currency.HKD, - Currency.PLN, - Currency.CNY, - Currency.SGD, - Currency.THB, - Currency.NZD, - Currency.JPY - }); - } - - public Mtgox() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject dataObject = jsonObject.getJSONObject("data"); - - ticker.bid = getPriceValueFromObject(dataObject, "buy"); - ticker.ask = getPriceValueFromObject(dataObject, "sell"); - ticker.vol = getPriceValueFromObject(dataObject, "vol"); - ticker.high = getPriceValueFromObject(dataObject, "high"); - ticker.low = getPriceValueFromObject(dataObject, "low"); - ticker.last = getPriceValueFromObject(dataObject, "last_local"); - ticker.timestamp = dataObject.getLong("now")/TimeUtils.NANOS_IN_MILLIS; - } - - private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { - final JSONObject innerObject = jsonObject.getJSONObject(key); - return innerObject.getDouble("value"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.TimeUtils; + +public class Mtgox extends Market { + + private final static String NAME = "Mtgox"; + private final static String TTS_NAME = "MT gox"; + private final static String URL = "https://data.mtgox.com/api/2/%1$s%2$s/money/ticker"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR, + Currency.CAD, + Currency.GBP, + Currency.CHF, + Currency.RUB, + Currency.AUD, + Currency.SEK, + Currency.DKK, + Currency.HKD, + Currency.PLN, + Currency.CNY, + Currency.SGD, + Currency.THB, + Currency.NZD, + Currency.JPY + }); + } + + public Mtgox() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject dataObject = jsonObject.getJSONObject("data"); + + ticker.bid = getPriceValueFromObject(dataObject, "buy"); + ticker.ask = getPriceValueFromObject(dataObject, "sell"); + ticker.vol = getPriceValueFromObject(dataObject, "vol"); + ticker.high = getPriceValueFromObject(dataObject, "high"); + ticker.low = getPriceValueFromObject(dataObject, "low"); + ticker.last = getPriceValueFromObject(dataObject, "last_local"); + ticker.timestamp = dataObject.getLong("now")/TimeUtils.NANOS_IN_MILLIS; + } + + private double getPriceValueFromObject(JSONObject jsonObject, String key) throws Exception { + final JSONObject innerObject = jsonObject.getJSONObject(key); + return innerObject.getDouble("value"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/OKCoinFutures.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/OKCoinFutures.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/OKCoinFutures.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/OKCoinFutures.java index 4bb8bcad..e52a059c 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/OKCoinFutures.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/OKCoinFutures.java @@ -1,67 +1,67 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Futures; -import com.mobnetic.coinguardian.model.FuturesMarket; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class OKCoinFutures extends FuturesMarket { - - private final static String NAME = "OKCoin Futures"; - private final static String TTS_NAME = "OK Coin Futures"; - private final static String URL = "https://www.okcoin.com/api/v1/future_ticker.do?symbol=%1$s_%2$s&contract_type=%3$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - // Currency.CNY, //At this time (2015-09-17) no API exist for www.okcoin.cn. Check https://www.okcoin.cn/about/rest_api.do - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - // Currency.CNY, //At this time (2015-09-17) no API exist for www.okcoin.cn. Check https://www.okcoin.cn/about/rest_api.do - Currency.USD - }); - } - private final static int[] CONTRACT_TYPES = new int[] { - Futures.CONTRACT_TYPE_WEEKLY, - Futures.CONTRACT_TYPE_BIWEEKLY, - Futures.CONTRACT_TYPE_QUARTERLY - }; - - public OKCoinFutures() { - super(NAME, TTS_NAME, CURRENCY_PAIRS, CONTRACT_TYPES); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo, int contractType) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase(), getContractTypeString(contractType)); - } - - private String getContractTypeString(int contractType) { - switch (contractType) { - default: - case Futures.CONTRACT_TYPE_WEEKLY: return "this_week"; - case Futures.CONTRACT_TYPE_BIWEEKLY: return "next_week"; - case Futures.CONTRACT_TYPE_QUARTERLY: return "quarter"; - } - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - } - -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Futures; +import com.mobnetic.coinguardian.model.FuturesMarket; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class OKCoinFutures extends FuturesMarket { + + private final static String NAME = "OKCoin Futures"; + private final static String TTS_NAME = "OK Coin Futures"; + private final static String URL = "https://www.okcoin.com/api/v1/future_ticker.do?symbol=%1$s_%2$s&contract_type=%3$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + // Currency.CNY, //At this time (2015-09-17) no API exist for www.okcoin.cn. Check https://www.okcoin.cn/about/rest_api.do + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + // Currency.CNY, //At this time (2015-09-17) no API exist for www.okcoin.cn. Check https://www.okcoin.cn/about/rest_api.do + Currency.USD + }); + } + private final static int[] CONTRACT_TYPES = new int[] { + Futures.CONTRACT_TYPE_WEEKLY, + Futures.CONTRACT_TYPE_BIWEEKLY, + Futures.CONTRACT_TYPE_QUARTERLY + }; + + public OKCoinFutures() { + super(NAME, TTS_NAME, CURRENCY_PAIRS, CONTRACT_TYPES); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo, int contractType) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase(), getContractTypeString(contractType)); + } + + private String getContractTypeString(int contractType) { + switch (contractType) { + default: + case Futures.CONTRACT_TYPE_WEEKLY: return "this_week"; + case Futures.CONTRACT_TYPE_BIWEEKLY: return "next_week"; + case Futures.CONTRACT_TYPE_QUARTERLY: return "quarter"; + } + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = tickerJsonObject.getDouble("buy"); + ticker.ask = tickerJsonObject.getDouble("sell"); + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + } + +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Okcoin.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Okcoin.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Okcoin.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Okcoin.java index 42d76b58..7144c5cf 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Okcoin.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Okcoin.java @@ -1,55 +1,55 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Okcoin extends Market { - - private final static String NAME = "OKCoin"; - private final static String TTS_NAME = "OK Coin"; - private final static String URL_USD = "https://www.okcoin.com/api/v1/ticker.do?symbol=%1$s_%2$s"; - private final static String URL_CNY = "https://www.okcoin.cn/api/v1/ticker.do?symbol=%1$s_%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CNY, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.CNY, - Currency.USD - }); - } - - public Okcoin() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(Currency.USD.equals(checkerInfo.getCurrencyCounter())) { - return String.format(URL_USD, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } else { - return String.format(URL_CNY, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = tickerJsonObject.getDouble("buy"); - ticker.ask = tickerJsonObject.getDouble("sell"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Okcoin extends Market { + + private final static String NAME = "OKCoin"; + private final static String TTS_NAME = "OK Coin"; + private final static String URL_USD = "https://www.okcoin.com/api/v1/ticker.do?symbol=%1$s_%2$s"; + private final static String URL_CNY = "https://www.okcoin.cn/api/v1/ticker.do?symbol=%1$s_%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CNY, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.CNY, + Currency.USD + }); + } + + public Okcoin() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(Currency.USD.equals(checkerInfo.getCurrencyCounter())) { + return String.format(URL_USD, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } else { + return String.format(URL_CNY, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = tickerJsonObject.getDouble("buy"); + ticker.ask = tickerJsonObject.getDouble("sell"); + ticker.vol = tickerJsonObject.getDouble("vol"); + ticker.high = tickerJsonObject.getDouble("high"); + ticker.low = tickerJsonObject.getDouble("low"); + ticker.last = tickerJsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Paymium.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Paymium.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Paymium.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Paymium.java index dca420a4..d50f6f26 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Paymium.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Paymium.java @@ -1,58 +1,58 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Paymium extends Market { - - private final static String NAME = "Paymium"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://paymium.com/api/v1/data/eur/ticker"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR - }); - } - - public Paymium() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("price"); - } - - @Override - protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { - final StringBuilder stringBuilder = new StringBuilder(); - final JSONArray errorsArray = jsonObject.getJSONArray("errors"); - for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR + }); + } + + public Paymium() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("price"); + } + + @Override + protected String parseErrorFromJsonObject(int requestId, JSONObject jsonObject, CheckerInfo checkerInfo) throws Exception { + final StringBuilder stringBuilder = new StringBuilder(); + final JSONArray errorsArray = jsonObject.getJSONArray("errors"); + for(int i=0; i pairs) throws Exception { - final JSONArray pairNames = jsonObject.names(); - - for(int i=0; i pairs) throws Exception { + final JSONArray pairNames = jsonObject.names(); + + for(int i=0; i pairs) throws Exception { - final JSONArray pairingsArray = jsonObject.getJSONArray("pairings"); - final String currencyCounter = jsonObject.getString("from"); - - for(int i=0; i pairs) throws Exception { + final JSONArray pairingsArray = jsonObject.getJSONArray("pairings"); + final String currencyCounter = jsonObject.getString("from"); + + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CAD - }); - } - - public QuadrigaCX() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class QuadrigaCX extends Market { + + private final static String NAME = "QuadrigaCX"; + private final static String TTS_NAME = "Quadriga CX"; + private final static String URL = "https://api.quadrigacx.com/v2/ticker?book=%1$s_%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CAD + }); + } + + public QuadrigaCX() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBaseLowerCase(), checkerInfo.getCurrencyCounterLowerCase()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Quoine.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Quoine.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Quoine.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Quoine.java index 7fa67739..4d550f46 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Quoine.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Quoine.java @@ -1,68 +1,68 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; - -public class Quoine extends Market { - - private final static String NAME = "Quoine"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.quoine.com/products/code/CASH/%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://api.quoine.com/products/"; - - public Quoine() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("market_bid"); - ticker.ask = jsonObject.getDouble("market_ask"); - ticker.vol = jsonObject.getDouble("volume_24h"); - ticker.high = jsonObject.getDouble("high_market_ask"); - ticker.low = jsonObject.getDouble("low_market_bid"); - ticker.last = jsonObject.getDouble("last_traded_price"); - } - - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray pairsJsonArray = new JSONArray(responseString); - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = new JSONArray(responseString); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.ARS - }); - } - - public Ripio() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject ratesJsonObject = jsonObject.getJSONObject("rates"); - ticker.bid = ratesJsonObject.getDouble("ARS_SELL"); // reversed - ticker.ask = ratesJsonObject.getDouble("ARS_BUY"); // reversed - ticker.last = ticker.ask; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Ripio extends Market { + + private final static String NAME = "Ripio"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.ripio.com/api/v1/rates/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.ARS + }); + } + + public Ripio() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject ratesJsonObject = jsonObject.getJSONObject("rates"); + ticker.bid = ratesJsonObject.getDouble("ARS_SELL"); // reversed + ticker.ask = ratesJsonObject.getDouble("ARS_BUY"); // reversed + ticker.last = ticker.ask; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/SevenNineSix.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/SevenNineSix.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/SevenNineSix.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/SevenNineSix.java index 334734c7..b25213ee 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/SevenNineSix.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/SevenNineSix.java @@ -1,55 +1,55 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardian.util.ParseUtils; - -public class SevenNineSix extends Market { - - private final static String NAME = "796"; - private final static String TTS_NAME = NAME; - private final static String URL_BTC = "http://api.796.com/v3/futures/ticker.html?type=weekly"; - private final static String URL_LTC = "http://api.796.com/v3/futures/ticker.html?type=ltc"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD - }); - } - - public SevenNineSix() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { - return URL_LTC; - } else { - return URL_BTC; - } - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - - ticker.bid = ParseUtils.getDoubleFromString(tickerJsonObject, "buy"); - ticker.ask = ParseUtils.getDoubleFromString(tickerJsonObject, "sell"); - ticker.vol = ParseUtils.getDoubleFromString(tickerJsonObject, "vol"); - ticker.high = ParseUtils.getDoubleFromString(tickerJsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(tickerJsonObject, "low"); - ticker.last = ParseUtils.getDoubleFromString(tickerJsonObject, "last"); - } +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; + +public class SevenNineSix extends Market { + + private final static String NAME = "796"; + private final static String TTS_NAME = NAME; + private final static String URL_BTC = "http://api.796.com/v3/futures/ticker.html?type=weekly"; + private final static String URL_LTC = "http://api.796.com/v3/futures/ticker.html?type=ltc"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD + }); + } + + public SevenNineSix() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + if(VirtualCurrency.LTC.equals(checkerInfo.getCurrencyBase())) { + return URL_LTC; + } else { + return URL_BTC; + } + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + + ticker.bid = ParseUtils.getDoubleFromString(tickerJsonObject, "buy"); + ticker.ask = ParseUtils.getDoubleFromString(tickerJsonObject, "sell"); + ticker.vol = ParseUtils.getDoubleFromString(tickerJsonObject, "vol"); + ticker.high = ParseUtils.getDoubleFromString(tickerJsonObject, "high"); + ticker.low = ParseUtils.getDoubleFromString(tickerJsonObject, "low"); + ticker.last = ParseUtils.getDoubleFromString(tickerJsonObject, "last"); + } } \ No newline at end of file diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/ShapeShift.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/ShapeShift.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/ShapeShift.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/ShapeShift.java index 41aaea8a..f2c0f14b 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/ShapeShift.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/ShapeShift.java @@ -1,69 +1,69 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.ArrayList; -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.util.ParseUtils; - -public class ShapeShift extends Market { - - private final static String NAME = "ShapeShift"; - private final static String TTS_NAME = "Shape Shift"; - private final static String URL = "https://shapeshift.io/rate/%1$s_%2$s"; - private final static String URL_CURRENCY_PAIRS = "https://shapeshift.io/getcoins"; - - public ShapeShift() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.last = ParseUtils.getDoubleFromString(jsonObject, "rate"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONArray jsonCoinNames = jsonObject.names(); - final List availableCoinNames = new ArrayList(jsonCoinNames.length()); - for(int i=0; i pairs) throws Exception { + final JSONArray jsonCoinNames = jsonObject.names(); + final List availableCoinNames = new ArrayList(jsonCoinNames.length()); + for(int i=0; i pairs) throws Exception { - final JSONArray marketsJsonArray = jsonObject.getJSONArray("markets"); - - for(int i=0; i pairs) throws Exception { + final JSONArray marketsJsonArray = jsonObject.getJSONArray("markets"); + + for(int i=0; i pairs) throws Exception { - final JSONArray pairNames = jsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONArray pairNames = jsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR, - Currency.USD, - VirtualCurrency.XRP - }); - CURRENCY_PAIRS.put(Currency.EUR, new String[]{ - VirtualCurrency.DOGE, - VirtualCurrency.XRP - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - VirtualCurrency.BTC, - Currency.EUR, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - VirtualCurrency.BTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ - Currency.EUR - }); - CURRENCY_PAIRS.put(Currency.USD, new String[]{ - VirtualCurrency.XRP - }); - } - - public TheRock() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, fixCurrency(checkerInfo.getCurrencyBase()), fixCurrency(checkerInfo.getCurrencyCounter())); - } - - private String fixCurrency(String currency) { - if(VirtualCurrency.DOGE.equals(currency)) - return VirtualCurrency.DOG; - return currency; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONArray resultArray = jsonObject.getJSONArray("result"); - final JSONObject tickerObject = resultArray.getJSONObject(0); - - ticker.bid = tickerObject.getDouble("bid"); - ticker.ask = tickerObject.getDouble("ask"); - ticker.vol = tickerObject.getDouble("volume"); - ticker.high = tickerObject.getDouble("high"); - ticker.low = tickerObject.getDouble("low"); - ticker.last = tickerObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONArray; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class TheRock extends Market { + + private final static String NAME = "TheRock"; + private final static String TTS_NAME = "The Rock"; + private final static String URL = "https://www.therocktrading.com/api/ticker/%1$s%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR, + Currency.USD, + VirtualCurrency.XRP + }); + CURRENCY_PAIRS.put(Currency.EUR, new String[]{ + VirtualCurrency.DOGE, + VirtualCurrency.XRP + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + VirtualCurrency.BTC, + Currency.EUR, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + VirtualCurrency.BTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ + Currency.EUR + }); + CURRENCY_PAIRS.put(Currency.USD, new String[]{ + VirtualCurrency.XRP + }); + } + + public TheRock() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, fixCurrency(checkerInfo.getCurrencyBase()), fixCurrency(checkerInfo.getCurrencyCounter())); + } + + private String fixCurrency(String currency) { + if(VirtualCurrency.DOGE.equals(currency)) + return VirtualCurrency.DOG; + return currency; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONArray resultArray = jsonObject.getJSONArray("result"); + final JSONObject tickerObject = resultArray.getJSONObject(0); + + ticker.bid = tickerObject.getDouble("bid"); + ticker.ask = tickerObject.getDouble("ask"); + ticker.vol = tickerObject.getDouble("volume"); + ticker.high = tickerObject.getDouble("high"); + ticker.low = tickerObject.getDouble("low"); + ticker.last = tickerObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Unisend.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unisend.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Unisend.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unisend.java index dbf3ee08..881d7d84 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Unisend.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unisend.java @@ -1,42 +1,42 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Unisend extends Market { - - private final static String NAME = "Unisend"; - private final static String TTS_NAME = "Uni send"; - private final static String URL = "https://www.unisend.com/api/price/ar/ars_btc"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.ARS - }); - } - - public Unisend() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject pricesJsonObject = jsonObject.getJSONObject("prices"); - ticker.bid = pricesJsonObject.getDouble("sell"); // reversed! - ticker.ask = pricesJsonObject.getDouble("buy"); // reversed! - ticker.last = ticker.ask; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Unisend extends Market { + + private final static String NAME = "Unisend"; + private final static String TTS_NAME = "Uni send"; + private final static String URL = "https://www.unisend.com/api/price/ar/ars_btc"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.ARS + }); + } + + public Unisend() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject pricesJsonObject = jsonObject.getJSONObject("prices"); + ticker.bid = pricesJsonObject.getDouble("sell"); // reversed! + ticker.ask = pricesJsonObject.getDouble("buy"); // reversed! + ticker.last = ticker.ask; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Unknown.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unknown.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Unknown.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unknown.java index b5ee3f14..30c5ba67 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Unknown.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Unknown.java @@ -1,34 +1,34 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; -import com.mobnetic.coinguardiandatamodule.R; - -public class Unknown extends Market { - - private final static String NAME = "UNKNOWN"; - private final static String TTS_NAME = NAME; - private final static String URL = ""; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ VirtualCurrency.BTC }); - } - - public Unknown() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public int getCautionResId() { - return R.string.market_caution_unknown; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardiandatamodule.R; + +public class Unknown extends Market { + + private final static String NAME = "UNKNOWN"; + private final static String TTS_NAME = NAME; + private final static String URL = ""; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ VirtualCurrency.BTC }); + } + + public Unknown() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public int getCautionResId() { + return R.string.market_caution_unknown; + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Uphold.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Uphold.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Uphold.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Uphold.java index 9a118edc..9469391b 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Uphold.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Uphold.java @@ -1,71 +1,71 @@ -// @joseccnet contribution. -package com.mobnetic.coinguardian.model.market; - -import java.util.List; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.util.ParseUtils; - -public class Uphold extends Market { - - private final static String NAME = "Uphold"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.uphold.com/v0/ticker/%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://api.uphold.com/v0/ticker"; - - public Uphold() { - super(NAME, TTS_NAME, null); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); - ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); - ticker.last = ((ticker.bid+ticker.ask)/2); //This is how Uphold operate on production (as I observed) - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairs(int requestId, String responseString, List pairs) throws Exception { - final JSONArray pairsJsonArray = new JSONArray(responseString); - - for(int i=0; i pairs) throws Exception { + final JSONArray pairsJsonArray = new JSONArray(responseString); + + for(int i=0; i pairs) throws Exception { - final JSONArray dataJsonArray = jsonObject.getJSONArray("data"); - final ArrayList virtualCurrencies = new ArrayList(); - final ArrayList currencies = new ArrayList(); - for(int i=0; i pairs) throws Exception { + final JSONArray dataJsonArray = jsonObject.getJSONArray("data"); + final ArrayList virtualCurrencies = new ArrayList(); + final ArrayList currencies = new ArrayList(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(Currency.GOLD, new String[]{ - VirtualCurrency.BTC - }); - } - - public Vaultoro() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.last = Double.parseDouble(responseString); - } +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Vaultoro extends Market { + + private final static String NAME = "Vaultoro"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.vaultoro.com/latest/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(Currency.GOLD, new String[]{ + VirtualCurrency.BTC + }); + } + + public Vaultoro() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTicker(int requestId, String responseString, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.last = Double.parseDouble(responseString); + } } \ No newline at end of file diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Vircurex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Vircurex.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Vircurex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Vircurex.java index 3e6bc511..79a75032 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Vircurex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Vircurex.java @@ -1,459 +1,459 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Vircurex extends Market { - - private final static String NAME = "Vircurex"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://api.vircurex.com/api/get_info_for_1_currency.json?base=%1$s&alt=%2$s"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.DVC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.FRC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.I0C, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.IXC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.NXT, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.QRK, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.VTC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.WDC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.XPM - }); - CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ - Currency.USD, - Currency.EUR, - VirtualCurrency.BTC, - VirtualCurrency.ANC, - VirtualCurrency.DGC, - VirtualCurrency.DOGE, - VirtualCurrency.DVC, - VirtualCurrency.FRC, - VirtualCurrency.FTC, - VirtualCurrency.I0C, - VirtualCurrency.IXC, - VirtualCurrency.LTC, - VirtualCurrency.NMC, - VirtualCurrency.NVC, - VirtualCurrency.NXT, - VirtualCurrency.PPC, - VirtualCurrency.QRK, - VirtualCurrency.TRC, - VirtualCurrency.VTC, - VirtualCurrency.WDC, - }); - } - - public Vircurex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("highest_bid"); - ticker.ask = jsonObject.getDouble("lowest_ask"); - ticker.vol = jsonObject.getDouble("volume"); -// ticker.high; -// ticker.low; - ticker.last = jsonObject.getDouble("last_trade"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Vircurex extends Market { + + private final static String NAME = "Vircurex"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://api.vircurex.com/api/get_info_for_1_currency.json?base=%1$s&alt=%2$s"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.ANC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.DGC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.DVC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.FRC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.FTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.I0C, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.IXC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.NMC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.NVC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.NXT, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.PPC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.QRK, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.TRC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.VTC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.WDC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.WDC, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.XPM + }); + CURRENCY_PAIRS.put(VirtualCurrency.XPM, new String[]{ + Currency.USD, + Currency.EUR, + VirtualCurrency.BTC, + VirtualCurrency.ANC, + VirtualCurrency.DGC, + VirtualCurrency.DOGE, + VirtualCurrency.DVC, + VirtualCurrency.FRC, + VirtualCurrency.FTC, + VirtualCurrency.I0C, + VirtualCurrency.IXC, + VirtualCurrency.LTC, + VirtualCurrency.NMC, + VirtualCurrency.NVC, + VirtualCurrency.NXT, + VirtualCurrency.PPC, + VirtualCurrency.QRK, + VirtualCurrency.TRC, + VirtualCurrency.VTC, + VirtualCurrency.WDC, + }); + } + + public Vircurex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("highest_bid"); + ticker.ask = jsonObject.getDouble("lowest_ask"); + ticker.vol = jsonObject.getDouble("volume"); +// ticker.high; +// ticker.low; + ticker.last = jsonObject.getDouble("last_trade"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Virtex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Virtex.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Virtex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Virtex.java index 150dd874..dd157033 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Virtex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Virtex.java @@ -1,61 +1,61 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Virtex extends Market { - - private final static String NAME = "CaVirtEx"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://cavirtex.com/api2/ticker.json"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CAD, - VirtualCurrency.LTC - }); - CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ - Currency.CAD - }); - } - - public Virtex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); - final JSONObject pairJsonObject = tickerJsonObject.getJSONObject(checkerInfo.getCurrencyBase()+checkerInfo.getCurrencyCounter()); - - if (!pairJsonObject.isNull("buy")) { - ticker.bid = pairJsonObject.getDouble("buy"); - } - if (!pairJsonObject.isNull("sell")) { - ticker.ask = pairJsonObject.getDouble("sell"); - } - if (!pairJsonObject.isNull("volume")) { - ticker.vol = pairJsonObject.getDouble("volume"); - } - if (!pairJsonObject.isNull("high")) { - ticker.high = pairJsonObject.getDouble("high"); - } - if (!pairJsonObject.isNull("low")) { - ticker.low = pairJsonObject.getDouble("low"); - } - ticker.last = pairJsonObject.getDouble("last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Virtex extends Market { + + private final static String NAME = "CaVirtEx"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://cavirtex.com/api2/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CAD, + VirtualCurrency.LTC + }); + CURRENCY_PAIRS.put(VirtualCurrency.LTC, new String[]{ + Currency.CAD + }); + } + + public Virtex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + final JSONObject tickerJsonObject = jsonObject.getJSONObject("ticker"); + final JSONObject pairJsonObject = tickerJsonObject.getJSONObject(checkerInfo.getCurrencyBase()+checkerInfo.getCurrencyCounter()); + + if (!pairJsonObject.isNull("buy")) { + ticker.bid = pairJsonObject.getDouble("buy"); + } + if (!pairJsonObject.isNull("sell")) { + ticker.ask = pairJsonObject.getDouble("sell"); + } + if (!pairJsonObject.isNull("volume")) { + ticker.vol = pairJsonObject.getDouble("volume"); + } + if (!pairJsonObject.isNull("high")) { + ticker.high = pairJsonObject.getDouble("high"); + } + if (!pairJsonObject.isNull("low")) { + ticker.low = pairJsonObject.getDouble("low"); + } + ticker.last = pairJsonObject.getDouble("last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/Winkdex.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Winkdex.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/Winkdex.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Winkdex.java index 4c42c193..18e938f5 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/Winkdex.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/Winkdex.java @@ -1,42 +1,42 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.HashMap; -import java.util.LinkedHashMap; - -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class Winkdex extends Market { - - private final static String NAME = "Winkdex"; - private final static String TTS_NAME = NAME; - private final static String URL = "http://winkdex.com/static/js/stats.js"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.USD - }); - } - - public Winkdex() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.vol = jsonObject.getDouble("volume_btc_24h"); - ticker.high = jsonObject.getDouble("winkdex_high_24h"); - ticker.low = jsonObject.getDouble("winkdex_low_24h"); - ticker.last = jsonObject.getDouble("winkdex_usd"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class Winkdex extends Market { + + private final static String NAME = "Winkdex"; + private final static String TTS_NAME = NAME; + private final static String URL = "http://winkdex.com/static/js/stats.js"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.USD + }); + } + + public Winkdex() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.vol = jsonObject.getDouble("volume_btc_24h"); + ticker.high = jsonObject.getDouble("winkdex_high_24h"); + ticker.low = jsonObject.getDouble("winkdex_low_24h"); + ticker.last = jsonObject.getDouble("winkdex_usd"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/YoBit.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/YoBit.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/YoBit.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/YoBit.java index 5e6587fc..d1881f6d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/YoBit.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/YoBit.java @@ -1,75 +1,75 @@ -package com.mobnetic.coinguardian.model.market; - -import java.util.List; -import java.util.Locale; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardiandatamodule.R; - -public class YoBit extends Market { - - private final static String NAME = "YoBit"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://yobit.net/api/3/ticker/%1$s"; - private final static String URL_CURRENCY_PAIRS = "https://yobit.net/api/3/info"; - - public YoBit() { - super(NAME, TTS_NAME, null); - } - - @Override - public int getCautionResId() { - return R.string.market_caution_yobit; - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyPairId()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - final JSONArray names = jsonObject.names(); - JSONObject tickerJsonObject = jsonObject.getJSONObject(names.getString(0)); - - ticker.bid = tickerJsonObject.getDouble("sell"); - ticker.ask = tickerJsonObject.getDouble("buy"); - ticker.vol = tickerJsonObject.getDouble("vol"); - ticker.high = tickerJsonObject.getDouble("high"); - ticker.low = tickerJsonObject.getDouble("low"); - ticker.last = tickerJsonObject.getDouble("last"); - ticker.timestamp = tickerJsonObject.getLong("updated"); - } - - // ==================== - // Get currency pairs - // ==================== - @Override - public String getCurrencyPairsUrl(int requestId) { - return URL_CURRENCY_PAIRS; - } - - @Override - protected void parseCurrencyPairsFromJsonObject(int requestId, JSONObject jsonObject, List pairs) throws Exception { - final JSONObject pairsJsonObject = jsonObject.getJSONObject("pairs"); - final JSONArray pairsNames = pairsJsonObject.names(); - for(int i=0; i pairs) throws Exception { + final JSONObject pairsJsonObject = jsonObject.getJSONObject("pairs"); + final JSONArray pairsNames = pairsJsonObject.names(); + for(int i=0; i CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.EUR - }); - } - - public Zaydo() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return URL; - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); - ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); - ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); - ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); - ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); - ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last"); - } -} +package com.mobnetic.coinguardian.model.market; + +import java.util.HashMap; +import java.util.LinkedHashMap; + +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; +import com.mobnetic.coinguardian.util.ParseUtils; + +public class Zaydo extends Market { + + private final static String NAME = "Zaydo"; + private final static String TTS_NAME = NAME; + private final static String URL = "http://chart.zyado.com/ticker.json"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.EUR + }); + } + + public Zaydo() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return URL; + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = ParseUtils.getDoubleFromString(jsonObject, "bid"); + ticker.ask = ParseUtils.getDoubleFromString(jsonObject, "ask"); + ticker.vol = ParseUtils.getDoubleFromString(jsonObject, "volume"); + ticker.high = ParseUtils.getDoubleFromString(jsonObject, "high"); + ticker.low = ParseUtils.getDoubleFromString(jsonObject, "low"); + ticker.last = ParseUtils.getDoubleFromString(jsonObject, "last"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/model/market/example/MarketExample.java b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/example/MarketExample.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/model/market/example/MarketExample.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/model/market/example/MarketExample.java index 0877d02e..34ab3464 100644 --- a/DataModule/src/com/mobnetic/coinguardian/model/market/example/MarketExample.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/model/market/example/MarketExample.java @@ -1,49 +1,49 @@ -package com.mobnetic.coinguardian.model.market.example; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import org.json.JSONObject; - -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.model.currency.Currency; -import com.mobnetic.coinguardian.model.currency.VirtualCurrency; - -public class MarketExample extends Market { - - private final static String NAME = "Market Example"; - private final static String TTS_NAME = NAME; - private final static String URL = "https://www.marketexample.com/api/%1$s_%2$s/ticker/"; - private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); - static { - CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ - Currency.CNY, - Currency.USD - }); - CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ - VirtualCurrency.BTC, - Currency.USD - }); - } - - public MarketExample() { - super(NAME, TTS_NAME, CURRENCY_PAIRS); - } - - @Override - public String getUrl(int requestId, CheckerInfo checkerInfo) { - return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); - } - - @Override - protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { - ticker.bid = jsonObject.getDouble("bid"); - ticker.ask = jsonObject.getDouble("ask"); - ticker.vol = jsonObject.getDouble("volume"); - ticker.high = jsonObject.getDouble("high"); - ticker.low = jsonObject.getDouble("low"); - ticker.last = jsonObject.getDouble("last"); - ticker.timestamp = jsonObject.getLong("timestamp"); - } -} +package com.mobnetic.coinguardian.model.market.example; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import org.json.JSONObject; + +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.model.currency.Currency; +import com.mobnetic.coinguardian.model.currency.VirtualCurrency; + +public class MarketExample extends Market { + + private final static String NAME = "Market Example"; + private final static String TTS_NAME = NAME; + private final static String URL = "https://www.marketexample.com/api/%1$s_%2$s/ticker/"; + private final static HashMap CURRENCY_PAIRS = new LinkedHashMap(); + static { + CURRENCY_PAIRS.put(VirtualCurrency.BTC, new String[]{ + Currency.CNY, + Currency.USD + }); + CURRENCY_PAIRS.put(VirtualCurrency.DOGE, new String[]{ + VirtualCurrency.BTC, + Currency.USD + }); + } + + public MarketExample() { + super(NAME, TTS_NAME, CURRENCY_PAIRS); + } + + @Override + public String getUrl(int requestId, CheckerInfo checkerInfo) { + return String.format(URL, checkerInfo.getCurrencyBase(), checkerInfo.getCurrencyCounter()); + } + + @Override + protected void parseTickerFromJsonObject(int requestId, JSONObject jsonObject, Ticker ticker, CheckerInfo checkerInfo) throws Exception { + ticker.bid = jsonObject.getDouble("bid"); + ticker.ask = jsonObject.getDouble("ask"); + ticker.vol = jsonObject.getDouble("volume"); + ticker.high = jsonObject.getDouble("high"); + ticker.low = jsonObject.getDouble("low"); + ticker.last = jsonObject.getDouble("last"); + ticker.timestamp = jsonObject.getLong("timestamp"); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java index f57638a9..672d2d9a 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyPairsMapHelper.java @@ -1,78 +1,78 @@ -package com.mobnetic.coinguardian.util; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; - -public class CurrencyPairsMapHelper { - - private long date; - private final HashMap currencyPairs; - private final HashMap currencyPairsIds; - private int pairsCount = 0; - - public CurrencyPairsMapHelper(CurrencyPairsListWithDate currencyPairsListWithDate) { - currencyPairs = new LinkedHashMap(); - currencyPairsIds = new HashMap(); - - if(currencyPairsListWithDate==null) - return; - - date = currencyPairsListWithDate.date; - List sortedPairs = currencyPairsListWithDate.pairs; - pairsCount = sortedPairs.size(); - - HashMap currencyGroupSizes = new HashMap(); - for(CurrencyPairInfo currencyPairInfo : sortedPairs) { - Integer currentCurrencyGroupSize = currencyGroupSizes.get(currencyPairInfo.getCurrencyBase()); - if(currentCurrencyGroupSize==null) { - currentCurrencyGroupSize = 1; - } else { - ++currentCurrencyGroupSize; - } - currencyGroupSizes.put(currencyPairInfo.getCurrencyBase(), currentCurrencyGroupSize); - } - - int currentGroupPositionToInsert = 0; - for(CurrencyPairInfo currencyPairInfo : sortedPairs) { - CharSequence[] currencyGroup = currencyPairs.get(currencyPairInfo.getCurrencyBase()); - if(currencyGroup==null) { - currencyGroup = new CharSequence[currencyGroupSizes.get(currencyPairInfo.getCurrencyBase())]; - currencyPairs.put(currencyPairInfo.getCurrencyBase(), currencyGroup); - currentGroupPositionToInsert = 0; - } else { - ++currentGroupPositionToInsert; - } - currencyGroup[currentGroupPositionToInsert] = currencyPairInfo.getCurrencyCounter(); - - if(currencyPairInfo.getCurrencyPairId()!=null) { - currencyPairsIds.put( - createCurrencyPairKey(currencyPairInfo.getCurrencyBase(), currencyPairInfo.getCurrencyCounter()), - currencyPairInfo.getCurrencyPairId()); - } - } - } - - public long getDate() { - return date; - } - - public HashMap getCurrencyPairs() { - return currencyPairs; - } - - public String getCurrencyPairId(String currencyBase, String currencyCounter) { - return currencyPairsIds.get(createCurrencyPairKey(currencyBase, currencyCounter)); - } - - public int getPairsCount() { - return pairsCount; - } - - private String createCurrencyPairKey(String currencyBase, String currencyCounter) { - return String.format("%1$s_%2$s", currencyBase, currencyCounter); - } -} +package com.mobnetic.coinguardian.util; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; + +public class CurrencyPairsMapHelper { + + private long date; + private final HashMap currencyPairs; + private final HashMap currencyPairsIds; + private int pairsCount = 0; + + public CurrencyPairsMapHelper(CurrencyPairsListWithDate currencyPairsListWithDate) { + currencyPairs = new LinkedHashMap(); + currencyPairsIds = new HashMap(); + + if(currencyPairsListWithDate==null) + return; + + date = currencyPairsListWithDate.date; + List sortedPairs = currencyPairsListWithDate.pairs; + pairsCount = sortedPairs.size(); + + HashMap currencyGroupSizes = new HashMap(); + for(CurrencyPairInfo currencyPairInfo : sortedPairs) { + Integer currentCurrencyGroupSize = currencyGroupSizes.get(currencyPairInfo.getCurrencyBase()); + if(currentCurrencyGroupSize==null) { + currentCurrencyGroupSize = 1; + } else { + ++currentCurrencyGroupSize; + } + currencyGroupSizes.put(currencyPairInfo.getCurrencyBase(), currentCurrencyGroupSize); + } + + int currentGroupPositionToInsert = 0; + for(CurrencyPairInfo currencyPairInfo : sortedPairs) { + CharSequence[] currencyGroup = currencyPairs.get(currencyPairInfo.getCurrencyBase()); + if(currencyGroup==null) { + currencyGroup = new CharSequence[currencyGroupSizes.get(currencyPairInfo.getCurrencyBase())]; + currencyPairs.put(currencyPairInfo.getCurrencyBase(), currencyGroup); + currentGroupPositionToInsert = 0; + } else { + ++currentGroupPositionToInsert; + } + currencyGroup[currentGroupPositionToInsert] = currencyPairInfo.getCurrencyCounter(); + + if(currencyPairInfo.getCurrencyPairId()!=null) { + currencyPairsIds.put( + createCurrencyPairKey(currencyPairInfo.getCurrencyBase(), currencyPairInfo.getCurrencyCounter()), + currencyPairInfo.getCurrencyPairId()); + } + } + } + + public long getDate() { + return date; + } + + public HashMap getCurrencyPairs() { + return currencyPairs; + } + + public String getCurrencyPairId(String currencyBase, String currencyCounter) { + return currencyPairsIds.get(createCurrencyPairKey(currencyBase, currencyCounter)); + } + + public int getPairsCount() { + return pairsCount; + } + + private String createCurrencyPairKey(String currencyBase, String currencyCounter) { + return String.format("%1$s_%2$s", currencyBase, currencyCounter); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/CurrencyUtils.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyUtils.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/util/CurrencyUtils.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyUtils.java index f4c3f224..f6372cd3 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/CurrencyUtils.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/CurrencyUtils.java @@ -1,23 +1,23 @@ -package com.mobnetic.coinguardian.util; - -import com.mobnetic.coinguardian.model.CurrencySubunit; -import com.mobnetic.coinguardian.model.CurrencySubunitsMap; -import com.mobnetic.coinguardian.model.currency.CurrenciesSubunits; -import com.mobnetic.coinguardian.model.currency.CurrencySymbols; - -public class CurrencyUtils { - - public static String getCurrencySymbol(String currency) { - return CurrencySymbols.CURRENCY_SYMBOLS.containsKey(currency) ? CurrencySymbols.CURRENCY_SYMBOLS.get(currency) : currency; - } - - public static CurrencySubunit getCurrencySubunit(String currency, long subunitToUnit) { - if(CurrenciesSubunits.CURRENCIES_SUBUNITS.containsKey(currency)) { - CurrencySubunitsMap subunits = CurrenciesSubunits.CURRENCIES_SUBUNITS.get(currency); - if(subunits.containsKey(subunitToUnit)) - return subunits.get(subunitToUnit); - } - - return new CurrencySubunit(currency, 1); - } -} +package com.mobnetic.coinguardian.util; + +import com.mobnetic.coinguardian.model.CurrencySubunit; +import com.mobnetic.coinguardian.model.CurrencySubunitsMap; +import com.mobnetic.coinguardian.model.currency.CurrenciesSubunits; +import com.mobnetic.coinguardian.model.currency.CurrencySymbols; + +public class CurrencyUtils { + + public static String getCurrencySymbol(String currency) { + return CurrencySymbols.CURRENCY_SYMBOLS.containsKey(currency) ? CurrencySymbols.CURRENCY_SYMBOLS.get(currency) : currency; + } + + public static CurrencySubunit getCurrencySubunit(String currency, long subunitToUnit) { + if(CurrenciesSubunits.CURRENCIES_SUBUNITS.containsKey(currency)) { + CurrencySubunitsMap subunits = CurrenciesSubunits.CURRENCIES_SUBUNITS.get(currency); + if(subunits.containsKey(subunitToUnit)) + return subunits.get(subunitToUnit); + } + + return new CurrencySubunit(currency, 1); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/FormatUtilsBase.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/FormatUtilsBase.java similarity index 97% rename from DataModule/src/com/mobnetic/coinguardian/util/FormatUtilsBase.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/FormatUtilsBase.java index 9468cb8f..b359a311 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/FormatUtilsBase.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/FormatUtilsBase.java @@ -1,97 +1,97 @@ -package com.mobnetic.coinguardian.util; - -import java.text.DecimalFormat; -import java.util.Date; - -import android.content.Context; -import android.text.format.DateFormat; -import android.text.format.DateUtils; - -import com.mobnetic.coinguardian.model.CurrencySubunit; - -public class FormatUtilsBase { - - // ==================== - // Double formatting - // ==================== - private final static DecimalFormat FORMAT_TWO_DECIMAL = new DecimalFormat("0.00"); - private final static DecimalFormat FORMAT_THREE_SIGNIFICANT_AT_MOST = new DecimalFormat("@##"); - private final static DecimalFormat FORMAT_EIGHT_SIGNIFICANT_AT_MOST = new DecimalFormat("@#######"); - - // ==================== - // Format methods - // ==================== - public static String formatDouble(double value, boolean isPrice) { - return formatDouble(value<1 ? FORMAT_THREE_SIGNIFICANT_AT_MOST : FORMAT_TWO_DECIMAL, value); - } - - public static String formatDoubleWithThreeMax(double value) { - return formatDouble(FORMAT_THREE_SIGNIFICANT_AT_MOST, value); - } - - protected static String formatDoubleWithEightMax(double value) { - return formatDouble(FORMAT_EIGHT_SIGNIFICANT_AT_MOST, value); - } - - protected final static String formatDouble(DecimalFormat decimalFormat, double value) { - synchronized (decimalFormat) { - try { - return decimalFormat.format(value); - } catch (Exception e) { - e.printStackTrace(); - } - - return String.valueOf(value); - } - } - - // ==================== - // Price formatting - // ==================== - public static String formatPriceWithCurrency(double price, CurrencySubunit subunitDst) { - return formatPriceWithCurrency(price, subunitDst, true); - } - - protected static String formatPriceWithCurrency(double price, CurrencySubunit subunitDst, boolean showCurrencyDst) { - String priceString = formatPriceValueForSubunit(price, subunitDst, false, false); - if(showCurrencyDst) { - priceString = formatPriceWithCurrency(priceString, subunitDst.name); - } - - return priceString; - } - - public static String formatPriceWithCurrency(double value, String currency) { - return formatPriceWithCurrency(formatDouble(value, true), currency); - } - - public static String formatPriceWithCurrency(String priceString, String currency) { - return priceString+" "+CurrencyUtils.getCurrencySymbol(currency); - } - - public static String formatPriceValueForSubunit(double price, CurrencySubunit subunitDst, boolean forceInteger, boolean skipNoSignificantDecimal) { - price *= subunitDst.subunitToUnit; - if(!subunitDst.allowDecimal || forceInteger) - return String.valueOf((long)(price+0.5f)); - else if(skipNoSignificantDecimal) - return formatDoubleWithEightMax(price); - else - return formatDouble(price, true); - } - - // ==================== - // Date && Time formatting - // ==================== - public static String formatSameDayTimeOrDate(Context context, long time) { - if (DateUtils.isToday(time)) { - return DateFormat.getTimeFormat(context).format(new Date(time)); - } else { - return DateFormat.getDateFormat(context).format(new Date(time)); - } - } - - public static String formatDateTime(Context context, long time) { - final Date date = new Date(time); - return DateFormat.getTimeFormat(context).format(date)+", "+DateFormat.getDateFormat(context).format(date); - } -} +package com.mobnetic.coinguardian.util; + +import java.text.DecimalFormat; +import java.util.Date; + +import android.content.Context; +import android.text.format.DateFormat; +import android.text.format.DateUtils; + +import com.mobnetic.coinguardian.model.CurrencySubunit; + +public class FormatUtilsBase { + + // ==================== + // Double formatting + // ==================== + private final static DecimalFormat FORMAT_TWO_DECIMAL = new DecimalFormat("0.00"); + private final static DecimalFormat FORMAT_THREE_SIGNIFICANT_AT_MOST = new DecimalFormat("@##"); + private final static DecimalFormat FORMAT_EIGHT_SIGNIFICANT_AT_MOST = new DecimalFormat("@#######"); + + // ==================== + // Format methods + // ==================== + public static String formatDouble(double value, boolean isPrice) { + return formatDouble(value<1 ? FORMAT_THREE_SIGNIFICANT_AT_MOST : FORMAT_TWO_DECIMAL, value); + } + + public static String formatDoubleWithThreeMax(double value) { + return formatDouble(FORMAT_THREE_SIGNIFICANT_AT_MOST, value); + } + + protected static String formatDoubleWithEightMax(double value) { + return formatDouble(FORMAT_EIGHT_SIGNIFICANT_AT_MOST, value); + } + + protected final static String formatDouble(DecimalFormat decimalFormat, double value) { + synchronized (decimalFormat) { + try { + return decimalFormat.format(value); + } catch (Exception e) { + e.printStackTrace(); + } + + return String.valueOf(value); + } + } + + // ==================== + // Price formatting + // ==================== + public static String formatPriceWithCurrency(double price, CurrencySubunit subunitDst) { + return formatPriceWithCurrency(price, subunitDst, true); + } + + protected static String formatPriceWithCurrency(double price, CurrencySubunit subunitDst, boolean showCurrencyDst) { + String priceString = formatPriceValueForSubunit(price, subunitDst, false, false); + if(showCurrencyDst) { + priceString = formatPriceWithCurrency(priceString, subunitDst.name); + } + + return priceString; + } + + public static String formatPriceWithCurrency(double value, String currency) { + return formatPriceWithCurrency(formatDouble(value, true), currency); + } + + public static String formatPriceWithCurrency(String priceString, String currency) { + return priceString+" "+CurrencyUtils.getCurrencySymbol(currency); + } + + public static String formatPriceValueForSubunit(double price, CurrencySubunit subunitDst, boolean forceInteger, boolean skipNoSignificantDecimal) { + price *= subunitDst.subunitToUnit; + if(!subunitDst.allowDecimal || forceInteger) + return String.valueOf((long)(price+0.5f)); + else if(skipNoSignificantDecimal) + return formatDoubleWithEightMax(price); + else + return formatDouble(price, true); + } + + // ==================== + // Date && Time formatting + // ==================== + public static String formatSameDayTimeOrDate(Context context, long time) { + if (DateUtils.isToday(time)) { + return DateFormat.getTimeFormat(context).format(new Date(time)); + } else { + return DateFormat.getDateFormat(context).format(new Date(time)); + } + } + + public static String formatDateTime(Context context, long time) { + final Date date = new Date(time); + return DateFormat.getTimeFormat(context).format(date)+", "+DateFormat.getDateFormat(context).format(date); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/MarketsConfigUtils.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/MarketsConfigUtils.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/util/MarketsConfigUtils.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/MarketsConfigUtils.java index 67c5a8e9..8c8260fb 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/MarketsConfigUtils.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/MarketsConfigUtils.java @@ -1,40 +1,40 @@ -package com.mobnetic.coinguardian.util; - -import java.util.ArrayList; - -import com.mobnetic.coinguardian.config.MarketsConfig; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.market.Unknown; - -public class MarketsConfigUtils { - - private final static Market UNKNOWN = new Unknown(); - - public static Market getMarketById(int id) { - synchronized (MarketsConfig.MARKETS) { - if(id>=0 && id(MarketsConfig.MARKETS.values()).get(id); - } - } - return UNKNOWN; - } - - public static Market getMarketByKey(String key) { - synchronized (MarketsConfig.MARKETS) { - if(MarketsConfig.MARKETS.containsKey(key)) - return MarketsConfig.MARKETS.get(key); - } - return UNKNOWN; - } - - public static int getMarketIdByKey(String key) { - int i=0; - for(Market market : MarketsConfig.MARKETS.values()){ - if(market.key.equals(key)) - return i; - ++i; - } - - return 0; - } -} +package com.mobnetic.coinguardian.util; + +import java.util.ArrayList; + +import com.mobnetic.coinguardian.config.MarketsConfig; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.market.Unknown; + +public class MarketsConfigUtils { + + private final static Market UNKNOWN = new Unknown(); + + public static Market getMarketById(int id) { + synchronized (MarketsConfig.MARKETS) { + if(id>=0 && id(MarketsConfig.MARKETS.values()).get(id); + } + } + return UNKNOWN; + } + + public static Market getMarketByKey(String key) { + synchronized (MarketsConfig.MARKETS) { + if(MarketsConfig.MARKETS.containsKey(key)) + return MarketsConfig.MARKETS.get(key); + } + return UNKNOWN; + } + + public static int getMarketIdByKey(String key) { + int i=0; + for(Market market : MarketsConfig.MARKETS.values()){ + if(market.key.equals(key)) + return i; + ++i; + } + + return 0; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/ParseUtils.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/ParseUtils.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/util/ParseUtils.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/ParseUtils.java index a127dd3a..0b6bf48b 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/ParseUtils.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/ParseUtils.java @@ -1,11 +1,11 @@ -package com.mobnetic.coinguardian.util; - -import org.json.JSONException; -import org.json.JSONObject; - -public class ParseUtils { - - public static double getDoubleFromString(JSONObject jsonObject, String name) throws NumberFormatException, JSONException { - return Double.parseDouble(jsonObject.getString(name)); - } -} +package com.mobnetic.coinguardian.util; + +import org.json.JSONException; +import org.json.JSONObject; + +public class ParseUtils { + + public static double getDoubleFromString(JSONObject jsonObject, String name) throws NumberFormatException, JSONException { + return Double.parseDouble(jsonObject.getString(name)); + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/TimeUtils.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/TimeUtils.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/util/TimeUtils.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/TimeUtils.java index d6493842..7b60eac8 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/TimeUtils.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/TimeUtils.java @@ -1,19 +1,19 @@ -package com.mobnetic.coinguardian.util; - -public class TimeUtils { - - public final static long NANOS_IN_MILLIS = 1000; - public final static long MILLIS_IN_SECOND = 1000; - public final static long MILLIS_IN_MINUTE = 60*MILLIS_IN_SECOND; - public final static long MILLIS_IN_HOUR = 60*MILLIS_IN_MINUTE; - public final static long MILLIS_IN_DAY = 24*MILLIS_IN_HOUR; - private final static long MILLIS_IN_YEAR = 365*MILLIS_IN_DAY; - - public static long parseTimeToMillis(long time) { - if(time5000*MILLIS_IN_YEAR) - return time/1000; - return time; - } -} +package com.mobnetic.coinguardian.util; + +public class TimeUtils { + + public final static long NANOS_IN_MILLIS = 1000; + public final static long MILLIS_IN_SECOND = 1000; + public final static long MILLIS_IN_MINUTE = 60*MILLIS_IN_SECOND; + public final static long MILLIS_IN_HOUR = 60*MILLIS_IN_MINUTE; + public final static long MILLIS_IN_DAY = 24*MILLIS_IN_HOUR; + private final static long MILLIS_IN_YEAR = 365*MILLIS_IN_DAY; + + public static long parseTimeToMillis(long time) { + if(time5000*MILLIS_IN_YEAR) + return time/1000; + return time; + } +} diff --git a/DataModule/src/com/mobnetic/coinguardian/util/XmlParserUtils.java b/dataModule/src/main/java/com/mobnetic/coinguardian/util/XmlParserUtils.java similarity index 96% rename from DataModule/src/com/mobnetic/coinguardian/util/XmlParserUtils.java rename to dataModule/src/main/java/com/mobnetic/coinguardian/util/XmlParserUtils.java index 1040c612..dd04e89d 100644 --- a/DataModule/src/com/mobnetic/coinguardian/util/XmlParserUtils.java +++ b/dataModule/src/main/java/com/mobnetic/coinguardian/util/XmlParserUtils.java @@ -1,35 +1,35 @@ -package com.mobnetic.coinguardian.util; - -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class XmlParserUtils { - - public static Node getFirstElementByTagName(Document doc, String name) { - NodeList nodes = doc.getElementsByTagName(name); - if(nodes!=null && nodes.getLength()>0) - return nodes.item(0); - return null; - } - - public static double getDoubleNodeValue(Node node) throws Exception { - return Double.parseDouble(getTextNodeValue(node)); - } - - public static String getTextNodeValue(Node node) throws Exception { - Node child; - if (node != null) { - if (node.hasChildNodes()) { - child = node.getFirstChild(); - while(child != null) { - if (child.getNodeType() == Node.TEXT_NODE) { - return child.getNodeValue(); - } - child = child.getNextSibling(); - } - } - } - return ""; - } -} +package com.mobnetic.coinguardian.util; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class XmlParserUtils { + + public static Node getFirstElementByTagName(Document doc, String name) { + NodeList nodes = doc.getElementsByTagName(name); + if(nodes!=null && nodes.getLength()>0) + return nodes.item(0); + return null; + } + + public static double getDoubleNodeValue(Node node) throws Exception { + return Double.parseDouble(getTextNodeValue(node)); + } + + public static String getTextNodeValue(Node node) throws Exception { + Node child; + if (node != null) { + if (node.hasChildNodes()) { + child = node.getFirstChild(); + while(child != null) { + if (child.getNodeType() == Node.TEXT_NODE) { + return child.getNodeValue(); + } + child = child.getNextSibling(); + } + } + } + return ""; + } +} diff --git a/DataModule/res/values/market_cautions.xml b/dataModule/src/main/res/values/market_cautions.xml similarity index 98% rename from DataModule/res/values/market_cautions.xml rename to dataModule/src/main/res/values/market_cautions.xml index 06338bef..52d37863 100644 --- a/DataModule/res/values/market_cautions.xml +++ b/dataModule/src/main/res/values/market_cautions.xml @@ -1,9 +1,9 @@ - - - - Selected market was probably removed and does not exist. Please choose another one. - Caution: Due to this exchange\'s specification checking price on it may consume a lot of mobile data (while on mobile network). Be sure that you understand the possible consequences. - This exchange has limit for 3000 requests per hour. Make sure you don\'t exceed the limit:) - This exchange has limit for 100 requests per minute. Make sure you don\'t exceed the limit:) - - + + + + Selected market was probably removed and does not exist. Please choose another one. + Caution: Due to this exchange\'s specification checking price on it may consume a lot of mobile data (while on mobile network). Be sure that you understand the possible consequences. + This exchange has limit for 3000 requests per hour. Make sure you don\'t exceed the limit:) + This exchange has limit for 100 requests per minute. Make sure you don\'t exceed the limit:) + + diff --git a/dataModuleTester/.gitignore b/dataModuleTester/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/dataModuleTester/.gitignore @@ -0,0 +1 @@ +/build diff --git a/dataModuleTester/build.gradle b/dataModuleTester/build.gradle new file mode 100644 index 00000000..0f5061a7 --- /dev/null +++ b/dataModuleTester/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 23 + buildToolsVersion "24.0.3" + + defaultConfig { + applicationId "com.mobnetic.coinguardiandatamodule.tester" + minSdkVersion 9 + targetSdkVersion 18 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} + +dependencies { + compile project(':dataModule') + compile 'com.google.code.gson:gson:2.2.4' + compile files('libs/volley.jar') +} diff --git a/DataModuleTester/libs/volley.jar b/dataModuleTester/libs/volley.jar similarity index 100% rename from DataModuleTester/libs/volley.jar rename to dataModuleTester/libs/volley.jar diff --git a/DataModuleTester/AndroidManifest.xml b/dataModuleTester/src/main/AndroidManifest.xml similarity index 97% rename from DataModuleTester/AndroidManifest.xml rename to dataModuleTester/src/main/AndroidManifest.xml index e630f59b..986dcfea 100644 --- a/DataModuleTester/AndroidManifest.xml +++ b/dataModuleTester/src/main/AndroidManifest.xml @@ -1,28 +1,28 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java index 2bf7eb40..e0a8cc22 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/MainActivity.java @@ -1,297 +1,297 @@ -package com.mobnetic.coinguardiandatamodule.tester; - -import java.util.HashMap; -import java.util.Map; - -import android.app.Activity; -import android.os.Bundle; -import android.text.SpannableStringBuilder; -import android.text.TextUtils; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.ProgressBar; -import android.widget.Spinner; -import android.widget.SpinnerAdapter; -import android.widget.TextView; - -import com.android.volley.NetworkResponse; -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.VolleyError; -import com.mobnetic.coinguardian.config.MarketsConfig; -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Futures; -import com.mobnetic.coinguardian.model.FuturesMarket; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; -import com.mobnetic.coinguardian.util.FormatUtilsBase; -import com.mobnetic.coinguardian.util.MarketsConfigUtils; -import com.mobnetic.coinguardiandatamodule.tester.dialog.DynamicCurrencyPairsDialog; -import com.mobnetic.coinguardiandatamodule.tester.util.CheckErrorsUtils; -import com.mobnetic.coinguardiandatamodule.tester.util.HttpsHelper; -import com.mobnetic.coinguardiandatamodule.tester.util.MarketCurrencyPairsStore; -import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerErrorParsedError; -import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest; -import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest.TickerWrapper; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseErrorListener; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseListener; - -public class MainActivity extends Activity { - - private RequestQueue requestQueue; - private Spinner marketSpinner; - private View currencySpinnersWrapper; - private View dynamicCurrencyPairsWarningView; - private View dynamicCurrencyPairsInfoView; - private Spinner currencyBaseSpinner; - private Spinner currencyCounterSpinner; - private Spinner futuresContractTypeSpinner; - private View getResultButton; - private ProgressBar progressBar; - private TextView resultView; - - private CurrencyPairsMapHelper currencyPairsMapHelper; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - requestQueue = HttpsHelper.newRequestQueue(this); - - setContentView(R.layout.main_activity); - - marketSpinner = (Spinner)findViewById(R.id.marketSpinner); - currencySpinnersWrapper = findViewById(R.id.currencySpinnersWrapper); - dynamicCurrencyPairsWarningView = findViewById(R.id.dynamicCurrencyPairsWarningView); - dynamicCurrencyPairsInfoView = findViewById(R.id.dynamicCurrencyPairsInfoView); - currencyBaseSpinner = (Spinner)findViewById(R.id.currencyBaseSpinner); - currencyCounterSpinner = (Spinner)findViewById(R.id.currencyCounterSpinner); - futuresContractTypeSpinner = (Spinner)findViewById(R.id.futuresContractTypeSpinner); - getResultButton = findViewById(R.id.getResultButton); - progressBar = (ProgressBar)findViewById(R.id.progressBar); - resultView = (TextView)findViewById(R.id.resultView); - - refreshMarketSpinner(); - Market market = getSelectedMarket(); - currencyPairsMapHelper = new CurrencyPairsMapHelper(MarketCurrencyPairsStore.getPairsForMarket(this, getSelectedMarket().key)); - refreshCurrencySpinners(market); - refreshFuturesContractTypeSpinner(market); - showResultView(true); - - marketSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { - final Market selectedMarket = getSelectedMarket(); - currencyPairsMapHelper = new CurrencyPairsMapHelper(MarketCurrencyPairsStore.getPairsForMarket(MainActivity.this, selectedMarket.key)); - refreshCurrencySpinners(selectedMarket); - refreshFuturesContractTypeSpinner(selectedMarket); - } - public void onNothingSelected(AdapterView arg0) { - // do nothing - } - }); - - dynamicCurrencyPairsInfoView.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - new DynamicCurrencyPairsDialog(MainActivity.this, getSelectedMarket(), currencyPairsMapHelper) { - public void onPairsUpdated(Market market, CurrencyPairsMapHelper currencyPairsMapHelper) { - MainActivity.this.currencyPairsMapHelper = currencyPairsMapHelper; - refreshCurrencySpinners(market); - } - }.show(); - } - }); - - currencyBaseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { - public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { - refreshCurrencyCounterSpinner(getSelectedMarket()); - } - public void onNothingSelected(AdapterView arg0) { - // do nothing - } - }); - - getResultButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - getNewResult(); - } - }); - } - - - // ==================== - // Get selected items - // ==================== - private Market getSelectedMarket() { - return MarketsConfigUtils.getMarketById(marketSpinner.getSelectedItemPosition()); - } - - private String getSelectedCurrencyBase() { - if(currencyBaseSpinner.getAdapter()==null) - return null; - return String.valueOf(currencyBaseSpinner.getSelectedItem()); - } - - private String getSelectedCurrencyCounter() { - if(currencyCounterSpinner.getAdapter()==null) - return null; - return String.valueOf(currencyCounterSpinner.getSelectedItem()); - } - - private int getSelectedContractType(Market market) { - if (market instanceof FuturesMarket) { - final FuturesMarket futuresMarket = (FuturesMarket) market; - int selection = futuresContractTypeSpinner.getSelectedItemPosition(); - return futuresMarket.contractTypes[selection]; - } - return Futures.CONTRACT_TYPE_WEEKLY; - } - - - // ==================== - // Refreshing UI - // ==================== - private void refreshMarketSpinner() { - final CharSequence[] entries = new String[MarketsConfig.MARKETS.size()]; - int i=0; - for(Market market : MarketsConfig.MARKETS.values()) { - entries[i++] = market.name; - } - - marketSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); - } - - private void refreshCurrencySpinners(Market market) { - refreshCurrencyBaseSpinner(market); - refreshCurrencyCounterSpinner(market); - refreshDynamicCurrencyPairsView(market); - - final boolean isCurrencyEmpty = getSelectedCurrencyBase()==null || getSelectedCurrencyCounter()==null; - currencySpinnersWrapper.setVisibility(isCurrencyEmpty ? View.GONE : View.VISIBLE); - dynamicCurrencyPairsWarningView.setVisibility(isCurrencyEmpty ? View.VISIBLE : View.GONE); - getResultButton.setVisibility(isCurrencyEmpty ? View.GONE : View.VISIBLE); - } - - private void refreshDynamicCurrencyPairsView(Market market) { - dynamicCurrencyPairsInfoView.setVisibility(market.getCurrencyPairsUrl(0)!=null ? View.VISIBLE : View.GONE); - } - - private void refreshCurrencyBaseSpinner(Market market) { - final HashMap currencyPairs = getProperCurrencyPairs(market); - if(currencyPairs!=null && currencyPairs.size()>0) { - final CharSequence[] entries = new CharSequence[currencyPairs.size()]; - int i=0; - for(String currency : currencyPairs.keySet()) { - entries[i++] = currency; - } - currencyBaseSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); - } else { - currencyBaseSpinner.setAdapter(null); - } - } - - private void refreshCurrencyCounterSpinner(Market market) { - final HashMap currencyPairs = getProperCurrencyPairs(market); - if(currencyPairs!=null && currencyPairs.size()>0) { - final String selectedCurrencyBase = getSelectedCurrencyBase(); - final CharSequence[] entries = currencyPairs.get(selectedCurrencyBase).clone(); - currencyCounterSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); - } else { - currencyCounterSpinner.setAdapter(null); - } - } - - private void refreshFuturesContractTypeSpinner(Market market) { - SpinnerAdapter spinnerAdapter = null; - if (market instanceof FuturesMarket) { - final FuturesMarket futuresMarket = (FuturesMarket)market; - CharSequence[] entries = new CharSequence[futuresMarket.contractTypes.length]; - for (int i = 0; i(this, android.R.layout.simple_spinner_dropdown_item, entries); - } - futuresContractTypeSpinner.setAdapter(spinnerAdapter); - futuresContractTypeSpinner.setVisibility(spinnerAdapter != null ? View.VISIBLE : View.GONE); - } - - private void showResultView(boolean showResultView) { - getResultButton.setEnabled(showResultView); - progressBar.setVisibility(showResultView ? View.GONE : View.VISIBLE); - resultView.setVisibility(showResultView ? View.VISIBLE : View.GONE); - } - - private HashMap getProperCurrencyPairs(Market market) { - if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getCurrencyPairs()!=null && currencyPairsMapHelper.getCurrencyPairs().size()>0) - return currencyPairsMapHelper.getCurrencyPairs(); - else - return market.currencyPairs; - } - - // ==================== - // Get && display results - // ==================== - private void getNewResult() { - final Market market = getSelectedMarket(); - final String currencyBase = getSelectedCurrencyBase(); - final String currencyCounter = getSelectedCurrencyCounter(); - final String pairId = currencyPairsMapHelper!=null ? currencyPairsMapHelper.getCurrencyPairId(currencyBase, currencyCounter) : null; - final int contractType = getSelectedContractType(market); - final CheckerInfo checkerInfo = new CheckerInfo(currencyBase, currencyCounter, pairId, contractType); - Request request = new CheckerVolleyMainRequest(market, checkerInfo, new ResponseListener() { - @Override - public void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, TickerWrapper tickerWrapper) { - handleNewResult(checkerInfo, tickerWrapper.ticker, url, requestHeaders, networkResponse, responseString, null, null); - } - }, new ResponseErrorListener() { - @Override - public void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error) { - error.printStackTrace(); - - String errorMsg = null; - if(error instanceof CheckerErrorParsedError) { - errorMsg = ((CheckerErrorParsedError)error).getErrorMsg(); - } - - if(TextUtils.isEmpty(errorMsg)) - errorMsg = CheckErrorsUtils.parseVolleyErrorMsg(MainActivity.this, error); - - handleNewResult(checkerInfo, null, url, requestHeaders, networkResponse, responseString, errorMsg, error); - } - }); - requestQueue.add(request); - showResultView(false); - } - - private void handleNewResult(CheckerInfo checkerInfo, Ticker ticker, String url, Map requestHeaders, NetworkResponse networkResponse, String rawResponse, String errorMsg, VolleyError error) { - showResultView(true); - SpannableStringBuilder ssb = new SpannableStringBuilder(); - - if (ticker!=null) { - ssb.append(getString(R.string.ticker_last, FormatUtilsBase.formatPriceWithCurrency(ticker.last, checkerInfo.getCurrencyCounter()))); - ssb.append(createNewPriceLineIfNeeded(R.string.ticker_high, ticker.high, checkerInfo.getCurrencyCounter())); - ssb.append(createNewPriceLineIfNeeded(R.string.ticker_low, ticker.low, checkerInfo.getCurrencyCounter())); - ssb.append(createNewPriceLineIfNeeded(R.string.ticker_bid, ticker.bid, checkerInfo.getCurrencyCounter())); - ssb.append(createNewPriceLineIfNeeded(R.string.ticker_ask, ticker.ask, checkerInfo.getCurrencyCounter())); - ssb.append(createNewPriceLineIfNeeded(R.string.ticker_vol, ticker.vol, checkerInfo.getCurrencyBase())); - ssb.append("\n"+getString(R.string.ticker_timestamp, FormatUtilsBase.formatSameDayTimeOrDate(this, ticker.timestamp))); - } else { - ssb.append(getString(R.string.check_error_generic_prefix, errorMsg!=null ? errorMsg : "UNKNOWN")); - } - - CheckErrorsUtils.formatResponseDebug(this, ssb, url, requestHeaders, networkResponse, rawResponse, error); - - resultView.setText(ssb); - } - - private String createNewPriceLineIfNeeded(int textResId, double price, String currency) { - if(price<=Ticker.NO_DATA) - return ""; - - return "\n"+getString(textResId, FormatUtilsBase.formatPriceWithCurrency(price, currency)); - } -} +package com.mobnetic.coinguardiandatamodule.tester; + +import java.util.HashMap; +import java.util.Map; + +import android.app.Activity; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.ProgressBar; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.VolleyError; +import com.mobnetic.coinguardian.config.MarketsConfig; +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Futures; +import com.mobnetic.coinguardian.model.FuturesMarket; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; +import com.mobnetic.coinguardian.util.FormatUtilsBase; +import com.mobnetic.coinguardian.util.MarketsConfigUtils; +import com.mobnetic.coinguardiandatamodule.tester.dialog.DynamicCurrencyPairsDialog; +import com.mobnetic.coinguardiandatamodule.tester.util.CheckErrorsUtils; +import com.mobnetic.coinguardiandatamodule.tester.util.HttpsHelper; +import com.mobnetic.coinguardiandatamodule.tester.util.MarketCurrencyPairsStore; +import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerErrorParsedError; +import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest; +import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest.TickerWrapper; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseErrorListener; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseListener; + +public class MainActivity extends Activity { + + private RequestQueue requestQueue; + private Spinner marketSpinner; + private View currencySpinnersWrapper; + private View dynamicCurrencyPairsWarningView; + private View dynamicCurrencyPairsInfoView; + private Spinner currencyBaseSpinner; + private Spinner currencyCounterSpinner; + private Spinner futuresContractTypeSpinner; + private View getResultButton; + private ProgressBar progressBar; + private TextView resultView; + + private CurrencyPairsMapHelper currencyPairsMapHelper; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + requestQueue = HttpsHelper.newRequestQueue(this); + + setContentView(R.layout.main_activity); + + marketSpinner = (Spinner)findViewById(R.id.marketSpinner); + currencySpinnersWrapper = findViewById(R.id.currencySpinnersWrapper); + dynamicCurrencyPairsWarningView = findViewById(R.id.dynamicCurrencyPairsWarningView); + dynamicCurrencyPairsInfoView = findViewById(R.id.dynamicCurrencyPairsInfoView); + currencyBaseSpinner = (Spinner)findViewById(R.id.currencyBaseSpinner); + currencyCounterSpinner = (Spinner)findViewById(R.id.currencyCounterSpinner); + futuresContractTypeSpinner = (Spinner)findViewById(R.id.futuresContractTypeSpinner); + getResultButton = findViewById(R.id.getResultButton); + progressBar = (ProgressBar)findViewById(R.id.progressBar); + resultView = (TextView)findViewById(R.id.resultView); + + refreshMarketSpinner(); + Market market = getSelectedMarket(); + currencyPairsMapHelper = new CurrencyPairsMapHelper(MarketCurrencyPairsStore.getPairsForMarket(this, getSelectedMarket().key)); + refreshCurrencySpinners(market); + refreshFuturesContractTypeSpinner(market); + showResultView(true); + + marketSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { + final Market selectedMarket = getSelectedMarket(); + currencyPairsMapHelper = new CurrencyPairsMapHelper(MarketCurrencyPairsStore.getPairsForMarket(MainActivity.this, selectedMarket.key)); + refreshCurrencySpinners(selectedMarket); + refreshFuturesContractTypeSpinner(selectedMarket); + } + public void onNothingSelected(AdapterView arg0) { + // do nothing + } + }); + + dynamicCurrencyPairsInfoView.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + new DynamicCurrencyPairsDialog(MainActivity.this, getSelectedMarket(), currencyPairsMapHelper) { + public void onPairsUpdated(Market market, CurrencyPairsMapHelper currencyPairsMapHelper) { + MainActivity.this.currencyPairsMapHelper = currencyPairsMapHelper; + refreshCurrencySpinners(market); + } + }.show(); + } + }); + + currencyBaseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { + refreshCurrencyCounterSpinner(getSelectedMarket()); + } + public void onNothingSelected(AdapterView arg0) { + // do nothing + } + }); + + getResultButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + getNewResult(); + } + }); + } + + + // ==================== + // Get selected items + // ==================== + private Market getSelectedMarket() { + return MarketsConfigUtils.getMarketById(marketSpinner.getSelectedItemPosition()); + } + + private String getSelectedCurrencyBase() { + if(currencyBaseSpinner.getAdapter()==null) + return null; + return String.valueOf(currencyBaseSpinner.getSelectedItem()); + } + + private String getSelectedCurrencyCounter() { + if(currencyCounterSpinner.getAdapter()==null) + return null; + return String.valueOf(currencyCounterSpinner.getSelectedItem()); + } + + private int getSelectedContractType(Market market) { + if (market instanceof FuturesMarket) { + final FuturesMarket futuresMarket = (FuturesMarket) market; + int selection = futuresContractTypeSpinner.getSelectedItemPosition(); + return futuresMarket.contractTypes[selection]; + } + return Futures.CONTRACT_TYPE_WEEKLY; + } + + + // ==================== + // Refreshing UI + // ==================== + private void refreshMarketSpinner() { + final CharSequence[] entries = new String[MarketsConfig.MARKETS.size()]; + int i=0; + for(Market market : MarketsConfig.MARKETS.values()) { + entries[i++] = market.name; + } + + marketSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); + } + + private void refreshCurrencySpinners(Market market) { + refreshCurrencyBaseSpinner(market); + refreshCurrencyCounterSpinner(market); + refreshDynamicCurrencyPairsView(market); + + final boolean isCurrencyEmpty = getSelectedCurrencyBase()==null || getSelectedCurrencyCounter()==null; + currencySpinnersWrapper.setVisibility(isCurrencyEmpty ? View.GONE : View.VISIBLE); + dynamicCurrencyPairsWarningView.setVisibility(isCurrencyEmpty ? View.VISIBLE : View.GONE); + getResultButton.setVisibility(isCurrencyEmpty ? View.GONE : View.VISIBLE); + } + + private void refreshDynamicCurrencyPairsView(Market market) { + dynamicCurrencyPairsInfoView.setVisibility(market.getCurrencyPairsUrl(0)!=null ? View.VISIBLE : View.GONE); + } + + private void refreshCurrencyBaseSpinner(Market market) { + final HashMap currencyPairs = getProperCurrencyPairs(market); + if(currencyPairs!=null && currencyPairs.size()>0) { + final CharSequence[] entries = new CharSequence[currencyPairs.size()]; + int i=0; + for(String currency : currencyPairs.keySet()) { + entries[i++] = currency; + } + currencyBaseSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); + } else { + currencyBaseSpinner.setAdapter(null); + } + } + + private void refreshCurrencyCounterSpinner(Market market) { + final HashMap currencyPairs = getProperCurrencyPairs(market); + if(currencyPairs!=null && currencyPairs.size()>0) { + final String selectedCurrencyBase = getSelectedCurrencyBase(); + final CharSequence[] entries = currencyPairs.get(selectedCurrencyBase).clone(); + currencyCounterSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)); + } else { + currencyCounterSpinner.setAdapter(null); + } + } + + private void refreshFuturesContractTypeSpinner(Market market) { + SpinnerAdapter spinnerAdapter = null; + if (market instanceof FuturesMarket) { + final FuturesMarket futuresMarket = (FuturesMarket)market; + CharSequence[] entries = new CharSequence[futuresMarket.contractTypes.length]; + for (int i = 0; i(this, android.R.layout.simple_spinner_dropdown_item, entries); + } + futuresContractTypeSpinner.setAdapter(spinnerAdapter); + futuresContractTypeSpinner.setVisibility(spinnerAdapter != null ? View.VISIBLE : View.GONE); + } + + private void showResultView(boolean showResultView) { + getResultButton.setEnabled(showResultView); + progressBar.setVisibility(showResultView ? View.GONE : View.VISIBLE); + resultView.setVisibility(showResultView ? View.VISIBLE : View.GONE); + } + + private HashMap getProperCurrencyPairs(Market market) { + if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getCurrencyPairs()!=null && currencyPairsMapHelper.getCurrencyPairs().size()>0) + return currencyPairsMapHelper.getCurrencyPairs(); + else + return market.currencyPairs; + } + + // ==================== + // Get && display results + // ==================== + private void getNewResult() { + final Market market = getSelectedMarket(); + final String currencyBase = getSelectedCurrencyBase(); + final String currencyCounter = getSelectedCurrencyCounter(); + final String pairId = currencyPairsMapHelper!=null ? currencyPairsMapHelper.getCurrencyPairId(currencyBase, currencyCounter) : null; + final int contractType = getSelectedContractType(market); + final CheckerInfo checkerInfo = new CheckerInfo(currencyBase, currencyCounter, pairId, contractType); + Request request = new CheckerVolleyMainRequest(market, checkerInfo, new ResponseListener() { + @Override + public void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, TickerWrapper tickerWrapper) { + handleNewResult(checkerInfo, tickerWrapper.ticker, url, requestHeaders, networkResponse, responseString, null, null); + } + }, new ResponseErrorListener() { + @Override + public void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error) { + error.printStackTrace(); + + String errorMsg = null; + if(error instanceof CheckerErrorParsedError) { + errorMsg = ((CheckerErrorParsedError)error).getErrorMsg(); + } + + if(TextUtils.isEmpty(errorMsg)) + errorMsg = CheckErrorsUtils.parseVolleyErrorMsg(MainActivity.this, error); + + handleNewResult(checkerInfo, null, url, requestHeaders, networkResponse, responseString, errorMsg, error); + } + }); + requestQueue.add(request); + showResultView(false); + } + + private void handleNewResult(CheckerInfo checkerInfo, Ticker ticker, String url, Map requestHeaders, NetworkResponse networkResponse, String rawResponse, String errorMsg, VolleyError error) { + showResultView(true); + SpannableStringBuilder ssb = new SpannableStringBuilder(); + + if (ticker!=null) { + ssb.append(getString(R.string.ticker_last, FormatUtilsBase.formatPriceWithCurrency(ticker.last, checkerInfo.getCurrencyCounter()))); + ssb.append(createNewPriceLineIfNeeded(R.string.ticker_high, ticker.high, checkerInfo.getCurrencyCounter())); + ssb.append(createNewPriceLineIfNeeded(R.string.ticker_low, ticker.low, checkerInfo.getCurrencyCounter())); + ssb.append(createNewPriceLineIfNeeded(R.string.ticker_bid, ticker.bid, checkerInfo.getCurrencyCounter())); + ssb.append(createNewPriceLineIfNeeded(R.string.ticker_ask, ticker.ask, checkerInfo.getCurrencyCounter())); + ssb.append(createNewPriceLineIfNeeded(R.string.ticker_vol, ticker.vol, checkerInfo.getCurrencyBase())); + ssb.append("\n"+getString(R.string.ticker_timestamp, FormatUtilsBase.formatSameDayTimeOrDate(this, ticker.timestamp))); + } else { + ssb.append(getString(R.string.check_error_generic_prefix, errorMsg!=null ? errorMsg : "UNKNOWN")); + } + + CheckErrorsUtils.formatResponseDebug(this, ssb, url, requestHeaders, networkResponse, rawResponse, error); + + resultView.setText(ssb); + } + + private String createNewPriceLineIfNeeded(int textResId, double price, String currency) { + if(price<=Ticker.NO_DATA) + return ""; + + return "\n"+getString(textResId, FormatUtilsBase.formatPriceWithCurrency(price, currency)); + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java index b6b78370..da5687ef 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/dialog/DynamicCurrencyPairsDialog.java @@ -1,127 +1,127 @@ -package com.mobnetic.coinguardiandatamodule.tester.dialog; - -import java.util.Map; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.text.SpannableStringBuilder; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - -import com.android.volley.NetworkResponse; -import com.android.volley.RequestQueue; -import com.android.volley.VolleyError; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; -import com.mobnetic.coinguardian.util.FormatUtilsBase; -import com.mobnetic.coinguardiandatamodule.tester.R; -import com.mobnetic.coinguardiandatamodule.tester.util.CheckErrorsUtils; -import com.mobnetic.coinguardiandatamodule.tester.util.HttpsHelper; -import com.mobnetic.coinguardiandatamodule.tester.volley.DynamicCurrencyPairsVolleyMainRequest; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseErrorListener; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseListener; - -public abstract class DynamicCurrencyPairsDialog extends AlertDialog implements OnDismissListener { - - private final RequestQueue requestQueue; - private final Market market; - private CurrencyPairsMapHelper currencyPairsMapHelper; - - private View refreshImageView; - private TextView statusView; - private TextView errorView; - - protected DynamicCurrencyPairsDialog(Context context, Market market, CurrencyPairsMapHelper currencyPairsMapHelper) { - super(context); - setInverseBackgroundForced(true); - - this.requestQueue = HttpsHelper.newRequestQueue(context); - this.market = market; - this.currencyPairsMapHelper = currencyPairsMapHelper; - - setTitle(R.string.checker_add_dynamic_currency_pairs_dialog_title); - setOnDismissListener(this); - setButton(BUTTON_NEUTRAL, context.getString(android.R.string.ok), (OnClickListener)null); - - View view = LayoutInflater.from(context).inflate(R.layout.dynamic_currency_pairs_dialog, null); - refreshImageView = view.findViewById(R.id.refreshImageView); - statusView = (TextView)view.findViewById(R.id.statusView); - errorView = (TextView)view.findViewById(R.id.errorView); - refreshImageView.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - startRefreshing(); - } - }); - refreshStatusView(null, null, null, null, null, null); - - setView(view); - } - - @Override - public void onDismiss(DialogInterface dialog) { - requestQueue.cancelAll(this); - currencyPairsMapHelper = null; - } - - private void startRefreshing() { - setCancelable(false); - startRefreshingAnim(); - DynamicCurrencyPairsVolleyMainRequest request = new DynamicCurrencyPairsVolleyMainRequest(getContext(), market, - new ResponseListener() { - @Override - public void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, CurrencyPairsMapHelper currencyPairsMapHelper) { - DynamicCurrencyPairsDialog.this.currencyPairsMapHelper = currencyPairsMapHelper; - refreshStatusView(url, requestHeaders, networkResponse, responseString, null, null); - stopRefreshingAnim(); - onPairsUpdated(market, currencyPairsMapHelper); -// dismiss(); - } - }, new ResponseErrorListener() { - @Override - public void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error) { - error.printStackTrace(); - refreshStatusView(url, requestHeaders, networkResponse, responseString, CheckErrorsUtils.parseVolleyErrorMsg(getContext(), error), error); - stopRefreshingAnim(); - } - }); - request.setTag(this); - requestQueue.add(request); - } - - private void refreshStatusView(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, String errorMsg, VolleyError error) { - String dateString; - if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getDate()>0) - dateString = FormatUtilsBase.formatSameDayTimeOrDate(getContext(), currencyPairsMapHelper.getDate()); - else - dateString = getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_last_sync_never); - - statusView.setText(getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_last_sync, dateString)); - if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getPairsCount()>0) - statusView.append("\n"+getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_pairs, currencyPairsMapHelper.getPairsCount())); - - SpannableStringBuilder ssb = new SpannableStringBuilder(); - - if(errorMsg!=null) { - ssb.append("\n"); - ssb.append(getContext().getString(R.string.check_error_generic_prefix, errorMsg)); - } - - CheckErrorsUtils.formatResponseDebug(getContext(), ssb, url, requestHeaders, networkResponse, responseString, error); - errorView.setText(ssb); - } - - public void startRefreshingAnim() { - setCancelable(false); - refreshImageView.setEnabled(false); - } - - public void stopRefreshingAnim() { - setCancelable(true); - refreshImageView.setEnabled(true); - } - - public abstract void onPairsUpdated(Market market, CurrencyPairsMapHelper currencyPairsMapHelper); -} +package com.mobnetic.coinguardiandatamodule.tester.dialog; + +import java.util.Map; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.text.SpannableStringBuilder; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import com.android.volley.NetworkResponse; +import com.android.volley.RequestQueue; +import com.android.volley.VolleyError; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; +import com.mobnetic.coinguardian.util.FormatUtilsBase; +import com.mobnetic.coinguardiandatamodule.tester.R; +import com.mobnetic.coinguardiandatamodule.tester.util.CheckErrorsUtils; +import com.mobnetic.coinguardiandatamodule.tester.util.HttpsHelper; +import com.mobnetic.coinguardiandatamodule.tester.volley.DynamicCurrencyPairsVolleyMainRequest; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseErrorListener; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.ResponseListener; + +public abstract class DynamicCurrencyPairsDialog extends AlertDialog implements OnDismissListener { + + private final RequestQueue requestQueue; + private final Market market; + private CurrencyPairsMapHelper currencyPairsMapHelper; + + private View refreshImageView; + private TextView statusView; + private TextView errorView; + + protected DynamicCurrencyPairsDialog(Context context, Market market, CurrencyPairsMapHelper currencyPairsMapHelper) { + super(context); + setInverseBackgroundForced(true); + + this.requestQueue = HttpsHelper.newRequestQueue(context); + this.market = market; + this.currencyPairsMapHelper = currencyPairsMapHelper; + + setTitle(R.string.checker_add_dynamic_currency_pairs_dialog_title); + setOnDismissListener(this); + setButton(BUTTON_NEUTRAL, context.getString(android.R.string.ok), (OnClickListener)null); + + View view = LayoutInflater.from(context).inflate(R.layout.dynamic_currency_pairs_dialog, null); + refreshImageView = view.findViewById(R.id.refreshImageView); + statusView = (TextView)view.findViewById(R.id.statusView); + errorView = (TextView)view.findViewById(R.id.errorView); + refreshImageView.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + startRefreshing(); + } + }); + refreshStatusView(null, null, null, null, null, null); + + setView(view); + } + + @Override + public void onDismiss(DialogInterface dialog) { + requestQueue.cancelAll(this); + currencyPairsMapHelper = null; + } + + private void startRefreshing() { + setCancelable(false); + startRefreshingAnim(); + DynamicCurrencyPairsVolleyMainRequest request = new DynamicCurrencyPairsVolleyMainRequest(getContext(), market, + new ResponseListener() { + @Override + public void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, CurrencyPairsMapHelper currencyPairsMapHelper) { + DynamicCurrencyPairsDialog.this.currencyPairsMapHelper = currencyPairsMapHelper; + refreshStatusView(url, requestHeaders, networkResponse, responseString, null, null); + stopRefreshingAnim(); + onPairsUpdated(market, currencyPairsMapHelper); +// dismiss(); + } + }, new ResponseErrorListener() { + @Override + public void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error) { + error.printStackTrace(); + refreshStatusView(url, requestHeaders, networkResponse, responseString, CheckErrorsUtils.parseVolleyErrorMsg(getContext(), error), error); + stopRefreshingAnim(); + } + }); + request.setTag(this); + requestQueue.add(request); + } + + private void refreshStatusView(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, String errorMsg, VolleyError error) { + String dateString; + if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getDate()>0) + dateString = FormatUtilsBase.formatSameDayTimeOrDate(getContext(), currencyPairsMapHelper.getDate()); + else + dateString = getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_last_sync_never); + + statusView.setText(getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_last_sync, dateString)); + if(currencyPairsMapHelper!=null && currencyPairsMapHelper.getPairsCount()>0) + statusView.append("\n"+getContext().getString(R.string.checker_add_dynamic_currency_pairs_dialog_pairs, currencyPairsMapHelper.getPairsCount())); + + SpannableStringBuilder ssb = new SpannableStringBuilder(); + + if(errorMsg!=null) { + ssb.append("\n"); + ssb.append(getContext().getString(R.string.check_error_generic_prefix, errorMsg)); + } + + CheckErrorsUtils.formatResponseDebug(getContext(), ssb, url, requestHeaders, networkResponse, responseString, error); + errorView.setText(ssb); + } + + public void startRefreshingAnim() { + setCancelable(false); + refreshImageView.setEnabled(false); + } + + public void stopRefreshingAnim() { + setCancelable(true); + refreshImageView.setEnabled(true); + } + + public abstract void onPairsUpdated(Market market, CurrencyPairsMapHelper currencyPairsMapHelper); +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java index 4553445e..cb4ccfc6 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/CheckErrorsUtils.java @@ -1,86 +1,86 @@ -package com.mobnetic.coinguardiandatamodule.tester.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Map; - -import android.content.Context; -import android.text.Html; -import android.text.SpannableStringBuilder; - -import com.android.volley.NetworkError; -import com.android.volley.NetworkResponse; -import com.android.volley.ParseError; -import com.android.volley.ServerError; -import com.android.volley.TimeoutError; -import com.android.volley.VolleyError; -import com.mobnetic.coinguardiandatamodule.tester.R; - -public class CheckErrorsUtils { - - private final static int RAW_RESPONSE_CHARS_LIMIT = 5000; - - public final static String parseVolleyErrorMsg(Context context, VolleyError error) { - if(error instanceof NetworkError) - return context.getString(R.string.check_error_network); - else if(error instanceof TimeoutError) - return context.getString(R.string.check_error_timeout); - else if(error instanceof ServerError) - return context.getString(R.string.check_error_server); - else if(error instanceof ParseError) - return context.getString(R.string.check_error_parse); - else - return context.getString(R.string.check_error_unknown); - } - - public final static String formatError(Context context, String errorMsg) { - return context.getString(R.string.check_error_generic_prefix, errorMsg!=null ? errorMsg : "UNKNOWN"); - } - - private static String formatMapToHtmlString(Map headers) { - String output = ""; - for (Map.Entry entry : headers.entrySet()) { - output += String.format("%1$s = %2$s", entry.getKey(), entry.getValue()); - } - return output; - } - - public static SpannableStringBuilder formatResponseDebug(Context context, SpannableStringBuilder ssb, String url, Map requestHeaders, NetworkResponse networkResponse, String rawResponse, Exception exception) { - if(url!=null){ - ssb.append("\n\n"); - ssb.append(context.getString(R.string.ticker_raw_url, url)); - } - - if(requestHeaders!=null){ - ssb.append("\n\n"); - ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_request_headers)+""+CheckErrorsUtils.formatMapToHtmlString(requestHeaders)+"")); - } - - if(networkResponse!=null){ - ssb.append("\n\n"); - ssb.append(context.getString(R.string.ticker_raw_response_code, String.valueOf(networkResponse.statusCode))); - ssb.append("\n\n"); - ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_response_headers)+""+CheckErrorsUtils.formatMapToHtmlString(networkResponse.headers)+"")); - } - if(rawResponse!=null){ - ssb.append("\n\n"); - String limitedRawResponse = rawResponse; - if(rawResponse.length() > RAW_RESPONSE_CHARS_LIMIT) { - limitedRawResponse = rawResponse.substring(0, RAW_RESPONSE_CHARS_LIMIT)+"..."; - } - ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_response)+""+limitedRawResponse+"")); - } - if(exception!=null){ - ssb.append("\n\n"); - ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_stacktrace)+""+printException(exception)+"")); - } - - return ssb; - } - - private static String printException(Exception e) { - StringWriter errors = new StringWriter(); - e.printStackTrace(new PrintWriter(errors)); - return errors.toString(); - } -} +package com.mobnetic.coinguardiandatamodule.tester.util; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Map; + +import android.content.Context; +import android.text.Html; +import android.text.SpannableStringBuilder; + +import com.android.volley.NetworkError; +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.ServerError; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.mobnetic.coinguardiandatamodule.tester.R; + +public class CheckErrorsUtils { + + private final static int RAW_RESPONSE_CHARS_LIMIT = 5000; + + public final static String parseVolleyErrorMsg(Context context, VolleyError error) { + if(error instanceof NetworkError) + return context.getString(R.string.check_error_network); + else if(error instanceof TimeoutError) + return context.getString(R.string.check_error_timeout); + else if(error instanceof ServerError) + return context.getString(R.string.check_error_server); + else if(error instanceof ParseError) + return context.getString(R.string.check_error_parse); + else + return context.getString(R.string.check_error_unknown); + } + + public final static String formatError(Context context, String errorMsg) { + return context.getString(R.string.check_error_generic_prefix, errorMsg!=null ? errorMsg : "UNKNOWN"); + } + + private static String formatMapToHtmlString(Map headers) { + String output = ""; + for (Map.Entry entry : headers.entrySet()) { + output += String.format("%1$s = %2$s", entry.getKey(), entry.getValue()); + } + return output; + } + + public static SpannableStringBuilder formatResponseDebug(Context context, SpannableStringBuilder ssb, String url, Map requestHeaders, NetworkResponse networkResponse, String rawResponse, Exception exception) { + if(url!=null){ + ssb.append("\n\n"); + ssb.append(context.getString(R.string.ticker_raw_url, url)); + } + + if(requestHeaders!=null){ + ssb.append("\n\n"); + ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_request_headers)+""+CheckErrorsUtils.formatMapToHtmlString(requestHeaders)+"")); + } + + if(networkResponse!=null){ + ssb.append("\n\n"); + ssb.append(context.getString(R.string.ticker_raw_response_code, String.valueOf(networkResponse.statusCode))); + ssb.append("\n\n"); + ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_response_headers)+""+CheckErrorsUtils.formatMapToHtmlString(networkResponse.headers)+"")); + } + if(rawResponse!=null){ + ssb.append("\n\n"); + String limitedRawResponse = rawResponse; + if(rawResponse.length() > RAW_RESPONSE_CHARS_LIMIT) { + limitedRawResponse = rawResponse.substring(0, RAW_RESPONSE_CHARS_LIMIT)+"..."; + } + ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_response)+""+limitedRawResponse+"")); + } + if(exception!=null){ + ssb.append("\n\n"); + ssb.append(Html.fromHtml(context.getString(R.string.ticker_raw_stacktrace)+""+printException(exception)+"")); + } + + return ssb; + } + + private static String printException(Exception e) { + StringWriter errors = new StringWriter(); + e.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java similarity index 96% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java index e7addfbc..55865e39 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/HttpsHelper.java @@ -1,51 +1,51 @@ -package com.mobnetic.coinguardiandatamodule.tester.util; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import android.content.Context; - -import com.android.volley.RequestQueue; -import com.android.volley.toolbox.HurlStack; -import com.android.volley.toolbox.Volley; - - -public class HttpsHelper { - - public final static RequestQueue newRequestQueue(Context context) { - return Volley.newRequestQueue(context, new HurlStack(null, HttpsHelper.getMySSLSocketFactory())); - } - - public static SSLSocketFactory getMySSLSocketFactory() { - try { - SSLContext sslContext = SSLContext.getInstance("TLS"); - TrustManager tm = new X509TrustManager() { - @Override - public void checkClientTrusted( - java.security.cert.X509Certificate[] chain, - String authType) - throws java.security.cert.CertificateException { - } - - @Override - public void checkServerTrusted( - java.security.cert.X509Certificate[] chain, - String authType) - throws java.security.cert.CertificateException { - } - - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - }; - sslContext.init(null, new TrustManager[] { tm }, null); - return sslContext.getSocketFactory(); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } -} +package com.mobnetic.coinguardiandatamodule.tester.util; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import android.content.Context; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.HurlStack; +import com.android.volley.toolbox.Volley; + + +public class HttpsHelper { + + public final static RequestQueue newRequestQueue(Context context) { + return Volley.newRequestQueue(context, new HurlStack(null, HttpsHelper.getMySSLSocketFactory())); + } + + public static SSLSocketFactory getMySSLSocketFactory() { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + TrustManager tm = new X509TrustManager() { + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] chain, + String authType) + throws java.security.cert.CertificateException { + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] chain, + String authType) + throws java.security.cert.CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + sslContext.init(null, new TrustManager[] { tm }, null); + return sslContext.getSocketFactory(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java index c016270f..fe347d3d 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/util/MarketCurrencyPairsStore.java @@ -1,37 +1,37 @@ -package com.mobnetic.coinguardiandatamodule.tester.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import com.google.gson.Gson; -import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; - -public class MarketCurrencyPairsStore { - - private static SharedPreferences getSharedPreferences(Context context) { - return context.getApplicationContext().getSharedPreferences("MARKET_CURRENCIY_PAIRS", Context.MODE_PRIVATE); - } - - public final static void savePairsForMarket(Context context, String marketKey, CurrencyPairsListWithDate currencyPairsListWithDate) { - try { - savePairsStringForMarket(context, marketKey, new Gson().toJson(currencyPairsListWithDate)); - } catch (Exception e) { - e.printStackTrace(); - } - } - private final static void savePairsStringForMarket(Context context, String marketKey, String jsonString) { - getSharedPreferences(context).edit().putString(marketKey, jsonString).commit(); - } - - public final static CurrencyPairsListWithDate getPairsForMarket(Context context, String marketKey) { - try { - return new Gson().fromJson(getPairsStringForMarket(context, marketKey), CurrencyPairsListWithDate.class); - } catch (Exception e){ - e.printStackTrace(); - return null; - } - } - private final static String getPairsStringForMarket(Context context, String marketKey) { - return getSharedPreferences(context).getString(marketKey, null); - } -} +package com.mobnetic.coinguardiandatamodule.tester.util; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.google.gson.Gson; +import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; + +public class MarketCurrencyPairsStore { + + private static SharedPreferences getSharedPreferences(Context context) { + return context.getApplicationContext().getSharedPreferences("MARKET_CURRENCIY_PAIRS", Context.MODE_PRIVATE); + } + + public final static void savePairsForMarket(Context context, String marketKey, CurrencyPairsListWithDate currencyPairsListWithDate) { + try { + savePairsStringForMarket(context, marketKey, new Gson().toJson(currencyPairsListWithDate)); + } catch (Exception e) { + e.printStackTrace(); + } + } + private final static void savePairsStringForMarket(Context context, String marketKey, String jsonString) { + getSharedPreferences(context).edit().putString(marketKey, jsonString).commit(); + } + + public final static CurrencyPairsListWithDate getPairsForMarket(Context context, String marketKey) { + try { + return new Gson().fromJson(getPairsStringForMarket(context, marketKey), CurrencyPairsListWithDate.class); + } catch (Exception e){ + e.printStackTrace(); + return null; + } + } + private final static String getPairsStringForMarket(Context context, String marketKey) { + return getSharedPreferences(context).getString(marketKey, null); + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java similarity index 95% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java index 40737729..ef3cfa44 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerErrorParsedError.java @@ -1,19 +1,19 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import com.android.volley.ParseError; - -public class CheckerErrorParsedError extends ParseError { - - private final String errorMsg; - - private static final long serialVersionUID = -8541129282633613311L; - - public CheckerErrorParsedError(String errorMsg) { - super(); - this.errorMsg = errorMsg; - } - - public String getErrorMsg() { - return errorMsg; - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import com.android.volley.ParseError; + +public class CheckerErrorParsedError extends ParseError { + + private final String errorMsg; + + private static final long serialVersionUID = -8541129282633613311L; + + public CheckerErrorParsedError(String errorMsg) { + super(); + this.errorMsg = errorMsg; + } + + public String getErrorMsg() { + return errorMsg; + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java index 41a9dbb3..4c56ee1c 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyMainRequest.java @@ -1,72 +1,72 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import java.util.Map; - -import android.text.TextUtils; - -import com.android.volley.DefaultRetryPolicy; -import com.android.volley.Response.ErrorListener; -import com.android.volley.Response.Listener; -import com.android.volley.toolbox.RequestFuture; -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.model.Ticker; -import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest.TickerWrapper; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GenericCheckerVolleyRequest; - -public class CheckerVolleyMainRequest extends GenericCheckerVolleyRequest { - - private final Market market; - - public CheckerVolleyMainRequest(Market market, CheckerInfo checkerInfo, Listener listener, ErrorListener errorListener) { - super(market.getUrl(0, checkerInfo), checkerInfo, listener, errorListener); - setRetryPolicy(new DefaultRetryPolicy(5000, 3, 1.5f)); - this.market = market; - } - - @Override - protected TickerWrapper parseNetworkResponse(Map headers, String responseString) throws Exception { - TickerWrapper tickerWrapper = new TickerWrapper(); - try { - tickerWrapper.ticker = market.parseTickerMain(0, responseString, new Ticker(), checkerInfo); - } catch (Exception e) { - e.printStackTrace(); - tickerWrapper.ticker = null; - } - - if(tickerWrapper.ticker==null || tickerWrapper.ticker.last<=Ticker.NO_DATA) { - String errorMsg; - try { - errorMsg = market.parseErrorMain(0, responseString, checkerInfo); - } catch (Exception e) { - errorMsg = null; - } - throw new CheckerErrorParsedError(errorMsg); - } - - final int numOfRequests = market.getNumOfRequests(checkerInfo); - if(numOfRequests>1) { - for(int requestId=1; requestId future = RequestFuture.newFuture(); - final String nextUrl = market.getUrl(requestId, checkerInfo); - if(!TextUtils.isEmpty(nextUrl)) { - CheckerVolleyNextRequest request = new CheckerVolleyNextRequest(nextUrl, checkerInfo, future); - getRequestQueue().add(request); - String nextResponse = future.get(); // this will block - market.parseTickerMain(requestId, nextResponse, tickerWrapper.ticker, checkerInfo); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - return tickerWrapper; - } - - public class TickerWrapper { - - public Ticker ticker; - - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import java.util.Map; + +import android.text.TextUtils; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.toolbox.RequestFuture; +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.model.Ticker; +import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerVolleyMainRequest.TickerWrapper; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GenericCheckerVolleyRequest; + +public class CheckerVolleyMainRequest extends GenericCheckerVolleyRequest { + + private final Market market; + + public CheckerVolleyMainRequest(Market market, CheckerInfo checkerInfo, Listener listener, ErrorListener errorListener) { + super(market.getUrl(0, checkerInfo), checkerInfo, listener, errorListener); + setRetryPolicy(new DefaultRetryPolicy(5000, 3, 1.5f)); + this.market = market; + } + + @Override + protected TickerWrapper parseNetworkResponse(Map headers, String responseString) throws Exception { + TickerWrapper tickerWrapper = new TickerWrapper(); + try { + tickerWrapper.ticker = market.parseTickerMain(0, responseString, new Ticker(), checkerInfo); + } catch (Exception e) { + e.printStackTrace(); + tickerWrapper.ticker = null; + } + + if(tickerWrapper.ticker==null || tickerWrapper.ticker.last<=Ticker.NO_DATA) { + String errorMsg; + try { + errorMsg = market.parseErrorMain(0, responseString, checkerInfo); + } catch (Exception e) { + errorMsg = null; + } + throw new CheckerErrorParsedError(errorMsg); + } + + final int numOfRequests = market.getNumOfRequests(checkerInfo); + if(numOfRequests>1) { + for(int requestId=1; requestId future = RequestFuture.newFuture(); + final String nextUrl = market.getUrl(requestId, checkerInfo); + if(!TextUtils.isEmpty(nextUrl)) { + CheckerVolleyNextRequest request = new CheckerVolleyNextRequest(nextUrl, checkerInfo, future); + getRequestQueue().add(request); + String nextResponse = future.get(); // this will block + market.parseTickerMain(requestId, nextResponse, tickerWrapper.ticker, checkerInfo); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return tickerWrapper; + } + + public class TickerWrapper { + + public Ticker ticker; + + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java index d70a30f1..9fc871b2 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/CheckerVolleyNextRequest.java @@ -1,19 +1,19 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import java.util.Map; - -import com.android.volley.toolbox.RequestFuture; -import com.mobnetic.coinguardian.model.CheckerInfo; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GenericCheckerVolleyRequest; - -public class CheckerVolleyNextRequest extends GenericCheckerVolleyRequest { - - public CheckerVolleyNextRequest(String url, CheckerInfo checkerInfo, RequestFuture future) { - super(url, checkerInfo, future, future); - } - - @Override - protected String parseNetworkResponse(Map headers, String responseString) throws Exception { - return responseString; - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import java.util.Map; + +import com.android.volley.toolbox.RequestFuture; +import com.mobnetic.coinguardian.model.CheckerInfo; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GenericCheckerVolleyRequest; + +public class CheckerVolleyNextRequest extends GenericCheckerVolleyRequest { + + public CheckerVolleyNextRequest(String url, CheckerInfo checkerInfo, RequestFuture future) { + super(url, checkerInfo, future, future); + } + + @Override + protected String parseNetworkResponse(Map headers, String responseString) throws Exception { + return responseString; + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java index 3d13e3a1..45464ef2 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyMainRequest.java @@ -1,70 +1,70 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import android.content.Context; -import android.text.TextUtils; - -import com.android.volley.Response.ErrorListener; -import com.android.volley.Response.Listener; -import com.android.volley.toolbox.RequestFuture; -import com.mobnetic.coinguardian.model.CurrencyPairInfo; -import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; -import com.mobnetic.coinguardian.model.Market; -import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; -import com.mobnetic.coinguardiandatamodule.tester.util.MarketCurrencyPairsStore; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GzipVolleyRequest; - -public class DynamicCurrencyPairsVolleyMainRequest extends GzipVolleyRequest { - - private final Context context; - private final Market market; - - public DynamicCurrencyPairsVolleyMainRequest(Context context, Market market, Listener listener, ErrorListener errorListener) { - super(market.getCurrencyPairsUrl(0), listener, errorListener); - - - this.context = context; - this.market = market; - } - - @Override - protected CurrencyPairsMapHelper parseNetworkResponse(Map headers, String responseString) throws Exception { - final List pairs = new ArrayList(); - market.parseCurrencyPairsMain(0, responseString, pairs); - - final int numOfRequests = market.getCurrencyPairsNumOfRequests(); - if(numOfRequests>1) { - final List nextPairs = new ArrayList(); - for(int requestId=1; requestId future = RequestFuture.newFuture(); - final String nextUrl = market.getCurrencyPairsUrl(requestId); - if(!TextUtils.isEmpty(nextUrl)) { - DynamicCurrencyPairsVolleyNextRequest request = new DynamicCurrencyPairsVolleyNextRequest(nextUrl, future); - getRequestQueue().add(request); - String nextResponse = future.get(); // this will block - nextPairs.clear(); - market.parseCurrencyPairsMain(requestId, nextResponse, nextPairs); - pairs.addAll(nextPairs); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - Collections.sort(pairs); - CurrencyPairsListWithDate currencyPairsListWithDate = new CurrencyPairsListWithDate(); - currencyPairsListWithDate.date = System.currentTimeMillis(); - currencyPairsListWithDate.pairs = pairs; - - if(pairs!=null && pairs.size()>0) - MarketCurrencyPairsStore.savePairsForMarket(context, market.key, currencyPairsListWithDate); - - return new CurrencyPairsMapHelper(currencyPairsListWithDate); - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import android.content.Context; +import android.text.TextUtils; + +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.toolbox.RequestFuture; +import com.mobnetic.coinguardian.model.CurrencyPairInfo; +import com.mobnetic.coinguardian.model.CurrencyPairsListWithDate; +import com.mobnetic.coinguardian.model.Market; +import com.mobnetic.coinguardian.util.CurrencyPairsMapHelper; +import com.mobnetic.coinguardiandatamodule.tester.util.MarketCurrencyPairsStore; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GzipVolleyRequest; + +public class DynamicCurrencyPairsVolleyMainRequest extends GzipVolleyRequest { + + private final Context context; + private final Market market; + + public DynamicCurrencyPairsVolleyMainRequest(Context context, Market market, Listener listener, ErrorListener errorListener) { + super(market.getCurrencyPairsUrl(0), listener, errorListener); + + + this.context = context; + this.market = market; + } + + @Override + protected CurrencyPairsMapHelper parseNetworkResponse(Map headers, String responseString) throws Exception { + final List pairs = new ArrayList(); + market.parseCurrencyPairsMain(0, responseString, pairs); + + final int numOfRequests = market.getCurrencyPairsNumOfRequests(); + if(numOfRequests>1) { + final List nextPairs = new ArrayList(); + for(int requestId=1; requestId future = RequestFuture.newFuture(); + final String nextUrl = market.getCurrencyPairsUrl(requestId); + if(!TextUtils.isEmpty(nextUrl)) { + DynamicCurrencyPairsVolleyNextRequest request = new DynamicCurrencyPairsVolleyNextRequest(nextUrl, future); + getRequestQueue().add(request); + String nextResponse = future.get(); // this will block + nextPairs.clear(); + market.parseCurrencyPairsMain(requestId, nextResponse, nextPairs); + pairs.addAll(nextPairs); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + Collections.sort(pairs); + CurrencyPairsListWithDate currencyPairsListWithDate = new CurrencyPairsListWithDate(); + currencyPairsListWithDate.date = System.currentTimeMillis(); + currencyPairsListWithDate.pairs = pairs; + + if(pairs!=null && pairs.size()>0) + MarketCurrencyPairsStore.savePairsForMarket(context, market.key, currencyPairsListWithDate); + + return new CurrencyPairsMapHelper(currencyPairsListWithDate); + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java similarity index 96% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java index 73aa324f..496f6397 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/DynamicCurrencyPairsVolleyNextRequest.java @@ -1,19 +1,19 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import java.util.Map; - -import com.android.volley.toolbox.RequestFuture; -import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GzipVolleyRequest; - -public class DynamicCurrencyPairsVolleyNextRequest extends GzipVolleyRequest { - - public DynamicCurrencyPairsVolleyNextRequest(String url, RequestFuture future) { - super(url, future, future); - } - - @Override - protected String parseNetworkResponse(Map headers, String responseString) throws Exception { - return responseString; - } - -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import java.util.Map; + +import com.android.volley.toolbox.RequestFuture; +import com.mobnetic.coinguardiandatamodule.tester.volley.generic.GzipVolleyRequest; + +public class DynamicCurrencyPairsVolleyNextRequest extends GzipVolleyRequest { + + public DynamicCurrencyPairsVolleyNextRequest(String url, RequestFuture future) { + super(url, future, future); + } + + @Override + protected String parseNetworkResponse(Map headers, String responseString) throws Exception { + return responseString; + } + +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java similarity index 96% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java index 3edd7eae..b25bc99d 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/UnknownVolleyError.java @@ -1,12 +1,12 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley; - -import com.android.volley.VolleyError; - -public class UnknownVolleyError extends VolleyError { - - private static final long serialVersionUID = -8541129282633613311L; - - public UnknownVolleyError(Throwable cause) { - super(cause); - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley; + +import com.android.volley.VolleyError; + +public class UnknownVolleyError extends VolleyError { + + private static final long serialVersionUID = -8541129282633613311L; + + public UnknownVolleyError(Throwable cause) { + super(cause); + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java index 8e1d41c4..aed7f800 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GenericCheckerVolleyRequest.java @@ -1,16 +1,16 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley.generic; - -import com.android.volley.Response.ErrorListener; -import com.android.volley.Response.Listener; -import com.mobnetic.coinguardian.model.CheckerInfo; - -public abstract class GenericCheckerVolleyRequest extends GzipVolleyRequest { - - protected final CheckerInfo checkerInfo; - - public GenericCheckerVolleyRequest(String url, CheckerInfo checkerInfo, Listener listener, ErrorListener errorListener) { - super(url, listener, errorListener); - - this.checkerInfo = checkerInfo; - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley.generic; + +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.mobnetic.coinguardian.model.CheckerInfo; + +public abstract class GenericCheckerVolleyRequest extends GzipVolleyRequest { + + protected final CheckerInfo checkerInfo; + + public GenericCheckerVolleyRequest(String url, CheckerInfo checkerInfo, Listener listener, ErrorListener errorListener) { + super(url, listener, errorListener); + + this.checkerInfo = checkerInfo; + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java similarity index 91% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java index 818ea4ba..b8fee520 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/GzipVolleyRequest.java @@ -1,167 +1,165 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley.generic; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.GZIPInputStream; - -import org.apache.http.HttpStatus; -import org.apache.http.protocol.HTTP; - -import com.android.volley.AuthFailureError; -import com.android.volley.Cache.Entry; -import com.android.volley.NetworkResponse; -import com.android.volley.ParseError; -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.Response; -import com.android.volley.Response.ErrorListener; -import com.android.volley.Response.Listener; -import com.android.volley.VolleyError; -import com.android.volley.toolbox.HttpHeaderParser; -import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerErrorParsedError; -import com.mobnetic.coinguardiandatamodule.tester.volley.UnknownVolleyError; - -public abstract class GzipVolleyRequest extends Request { - - private final Listener listener; - private final ErrorListener errorListener; - private final Map headers; - - private RequestQueue requestQueue; - private String redirectionUrl = null; - private int redirectionCount; - - private Map requestHeaders; - private NetworkResponse networkResponse; - private String responseString; - - private final static int MAX_REDIRECTION_COUNT = 3; - - public GzipVolleyRequest(String url, Listener listener, ErrorListener errorListener) { - super(Method.GET, url, errorListener); - - this.listener = listener; - this.errorListener = errorListener; - - this.headers = new HashMap(); - this.headers.put("Accept-Encoding", "gzip"); - this.headers.put(HTTP.USER_AGENT, "Bitcoin Checker (gzip)"); - } - - public RequestQueue getRequestQueue() { - return requestQueue; - } - - @Override - public String getUrl() { - if(redirectionUrl!=null) - return redirectionUrl; - return super.getUrl(); - } - - @Override - public Map getHeaders() throws AuthFailureError { - requestHeaders = headers!=null ? headers : super.getHeaders(); - return requestHeaders; - } - - @Override - public Request setRequestQueue(RequestQueue requestQueue) { - this.requestQueue = requestQueue; - return super.setRequestQueue(requestQueue); - } - - @Override - public void deliverError(VolleyError error) { - if(error!=null && error.networkResponse!=null) { - final int statusCode = error.networkResponse.statusCode; - if(statusCode==HttpStatus.SC_MOVED_PERMANENTLY || statusCode==HttpStatus.SC_MOVED_TEMPORARILY) { - String location = error.networkResponse.headers.get("Location"); - if(location!=null && redirectionCount)listener).onResponse(getUrl(), requestHeaders, networkResponse, responseString, response); - else - listener.onResponse(response); - } - - protected abstract T parseNetworkResponse(Map headers, String responseString) throws Exception; - - @Override - protected Response parseNetworkResponse(NetworkResponse response) { - try { - networkResponse = response; - String responseString = ""; - final String encoding = response.headers.get(HTTP.CONTENT_ENCODING); - if(encoding!=null && encoding.contains("gzip")) { - responseString = decodeGZip(response.data); - } else { - responseString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); - } - this.responseString = responseString; - final Map headers = response.headers; - final Entry cacheHeaders = HttpHeaderParser.parseCacheHeaders(response); - response = null; - return Response.success(parseNetworkResponse(headers, responseString), cacheHeaders); - } catch (CheckerErrorParsedError checkerErrorParsedError) { - return Response.error(checkerErrorParsedError); - } catch (Exception e) { - return Response.error(new ParseError(e)); - } catch (Throwable e) { - return Response.error(new UnknownVolleyError(e)); - } - } - - private String decodeGZip(byte[] data) throws Exception { - String responseString = ""; - - ByteArrayInputStream bais = null; - GZIPInputStream gzis = null; - InputStreamReader reader = null; - BufferedReader in = null; - - try { - bais = new ByteArrayInputStream(data); - gzis = new GZIPInputStream(bais); - reader = new InputStreamReader(gzis); - in = new BufferedReader(reader); - - String readed; - while ((readed = in.readLine()) != null) { - responseString += readed+"\n"; - } - } catch (Exception e) { - throw e; - } finally { - try { - if(bais!=null) - bais.close(); - if(gzis!=null) - gzis.close(); - if(reader!=null) - reader.close(); - if(in!=null) - in.close(); - } catch (Exception e) {}; - } - - return responseString; - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley.generic; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +import com.android.volley.AuthFailureError; +import com.android.volley.Cache.Entry; +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.HttpHeaderParser; +import com.mobnetic.coinguardiandatamodule.tester.volley.CheckerErrorParsedError; +import com.mobnetic.coinguardiandatamodule.tester.volley.UnknownVolleyError; + +public abstract class GzipVolleyRequest extends Request { + + private final Listener listener; + private final ErrorListener errorListener; + private final Map headers; + + private RequestQueue requestQueue; + private String redirectionUrl = null; + private int redirectionCount; + + private Map requestHeaders; + private NetworkResponse networkResponse; + private String responseString; + + private final static int MAX_REDIRECTION_COUNT = 3; + + public GzipVolleyRequest(String url, Listener listener, ErrorListener errorListener) { + super(Method.GET, url, errorListener); + + this.listener = listener; + this.errorListener = errorListener; + + this.headers = new HashMap(); + this.headers.put("Accept-Encoding", "gzip"); + this.headers.put("User-Agent", "Bitcoin Checker (gzip)"); + } + + public RequestQueue getRequestQueue() { + return requestQueue; + } + + @Override + public String getUrl() { + if(redirectionUrl!=null) + return redirectionUrl; + return super.getUrl(); + } + + @Override + public Map getHeaders() throws AuthFailureError { + requestHeaders = headers!=null ? headers : super.getHeaders(); + return requestHeaders; + } + + @Override + public Request setRequestQueue(RequestQueue requestQueue) { + this.requestQueue = requestQueue; + return super.setRequestQueue(requestQueue); + } + + @Override + public void deliverError(VolleyError error) { + if(error!=null && error.networkResponse!=null) { + final int statusCode = error.networkResponse.statusCode; + if(statusCode==HttpURLConnection.HTTP_MOVED_PERM || statusCode==HttpURLConnection.HTTP_MOVED_TEMP) { + String location = error.networkResponse.headers.get("Location"); + if(location!=null && redirectionCount)listener).onResponse(getUrl(), requestHeaders, networkResponse, responseString, response); + else + listener.onResponse(response); + } + + protected abstract T parseNetworkResponse(Map headers, String responseString) throws Exception; + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + try { + networkResponse = response; + String responseString = ""; + final String encoding = response.headers.get("Content-Encoding"); + if(encoding!=null && encoding.contains("gzip")) { + responseString = decodeGZip(response.data); + } else { + responseString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); + } + this.responseString = responseString; + final Map headers = response.headers; + final Entry cacheHeaders = HttpHeaderParser.parseCacheHeaders(response); + response = null; + return Response.success(parseNetworkResponse(headers, responseString), cacheHeaders); + } catch (CheckerErrorParsedError checkerErrorParsedError) { + return Response.error(checkerErrorParsedError); + } catch (Exception e) { + return Response.error(new ParseError(e)); + } catch (Throwable e) { + return Response.error(new UnknownVolleyError(e)); + } + } + + private String decodeGZip(byte[] data) throws Exception { + String responseString = ""; + + ByteArrayInputStream bais = null; + GZIPInputStream gzis = null; + InputStreamReader reader = null; + BufferedReader in = null; + + try { + bais = new ByteArrayInputStream(data); + gzis = new GZIPInputStream(bais); + reader = new InputStreamReader(gzis); + in = new BufferedReader(reader); + + String readed; + while ((readed = in.readLine()) != null) { + responseString += readed+"\n"; + } + } catch (Exception e) { + throw e; + } finally { + try { + if(bais!=null) + bais.close(); + if(gzis!=null) + gzis.close(); + if(reader!=null) + reader.close(); + if(in!=null) + in.close(); + } catch (Exception e) {}; + } + + return responseString; + } +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java similarity index 96% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java index c54d55e8..cbcc502d 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseErrorListener.java @@ -1,18 +1,18 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley.generic; - -import java.util.Map; - -import com.android.volley.NetworkResponse; -import com.android.volley.Response.ErrorListener; -import com.android.volley.VolleyError; - -public abstract class ResponseErrorListener implements ErrorListener { - - public abstract void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error); - - @Override - public void onErrorResponse(VolleyError error) { - onErrorResponse(null, null, null, null, error); - } - -} +package com.mobnetic.coinguardiandatamodule.tester.volley.generic; + +import java.util.Map; + +import com.android.volley.NetworkResponse; +import com.android.volley.Response.ErrorListener; +import com.android.volley.VolleyError; + +public abstract class ResponseErrorListener implements ErrorListener { + + public abstract void onErrorResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, VolleyError error); + + @Override + public void onErrorResponse(VolleyError error) { + onErrorResponse(null, null, null, null, error); + } + +} diff --git a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java similarity index 97% rename from DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java rename to dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java index 30b77dc4..25b9cf35 100644 --- a/DataModuleTester/src/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java +++ b/dataModuleTester/src/main/java/com/mobnetic/coinguardiandatamodule/tester/volley/generic/ResponseListener.java @@ -1,16 +1,16 @@ -package com.mobnetic.coinguardiandatamodule.tester.volley.generic; - -import java.util.Map; - -import com.android.volley.NetworkResponse; -import com.android.volley.Response.Listener; - -public abstract class ResponseListener implements Listener { - - public abstract void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, T response); - - @Override - public void onResponse(T response) { - onResponse(null, null, null, null, response); - } -} +package com.mobnetic.coinguardiandatamodule.tester.volley.generic; + +import java.util.Map; + +import com.android.volley.NetworkResponse; +import com.android.volley.Response.Listener; + +public abstract class ResponseListener implements Listener { + + public abstract void onResponse(String url, Map requestHeaders, NetworkResponse networkResponse, String responseString, T response); + + @Override + public void onResponse(T response) { + onResponse(null, null, null, null, response); + } +} diff --git a/DataModuleTester/res/drawable-hdpi/ic_action_info.png b/dataModuleTester/src/main/res/drawable-hdpi/ic_action_info.png similarity index 100% rename from DataModuleTester/res/drawable-hdpi/ic_action_info.png rename to dataModuleTester/src/main/res/drawable-hdpi/ic_action_info.png diff --git a/DataModuleTester/res/drawable-hdpi/ic_launcher.png b/dataModuleTester/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from DataModuleTester/res/drawable-hdpi/ic_launcher.png rename to dataModuleTester/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/DataModuleTester/res/drawable-mdpi/ic_action_info.png b/dataModuleTester/src/main/res/drawable-mdpi/ic_action_info.png similarity index 100% rename from DataModuleTester/res/drawable-mdpi/ic_action_info.png rename to dataModuleTester/src/main/res/drawable-mdpi/ic_action_info.png diff --git a/DataModuleTester/res/drawable-mdpi/ic_launcher.png b/dataModuleTester/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from DataModuleTester/res/drawable-mdpi/ic_launcher.png rename to dataModuleTester/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/DataModuleTester/res/drawable-xhdpi/ic_action_info.png b/dataModuleTester/src/main/res/drawable-xhdpi/ic_action_info.png similarity index 100% rename from DataModuleTester/res/drawable-xhdpi/ic_action_info.png rename to dataModuleTester/src/main/res/drawable-xhdpi/ic_action_info.png diff --git a/DataModuleTester/res/drawable-xhdpi/ic_launcher.png b/dataModuleTester/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from DataModuleTester/res/drawable-xhdpi/ic_launcher.png rename to dataModuleTester/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/DataModuleTester/res/drawable-xxhdpi/ic_action_info.png b/dataModuleTester/src/main/res/drawable-xxhdpi/ic_action_info.png similarity index 100% rename from DataModuleTester/res/drawable-xxhdpi/ic_action_info.png rename to dataModuleTester/src/main/res/drawable-xxhdpi/ic_action_info.png diff --git a/DataModuleTester/res/drawable-xxhdpi/ic_launcher.png b/dataModuleTester/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from DataModuleTester/res/drawable-xxhdpi/ic_launcher.png rename to dataModuleTester/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/DataModuleTester/res/drawable-xxxhdpi/ic_launcher.png b/dataModuleTester/src/main/res/drawable-xxxhdpi/ic_launcher.png similarity index 100% rename from DataModuleTester/res/drawable-xxxhdpi/ic_launcher.png rename to dataModuleTester/src/main/res/drawable-xxxhdpi/ic_launcher.png diff --git a/DataModuleTester/res/layout/dynamic_currency_pairs_dialog.xml b/dataModuleTester/src/main/res/layout/dynamic_currency_pairs_dialog.xml similarity index 97% rename from DataModuleTester/res/layout/dynamic_currency_pairs_dialog.xml rename to dataModuleTester/src/main/res/layout/dynamic_currency_pairs_dialog.xml index 131bb24e..3af7d426 100644 --- a/DataModuleTester/res/layout/dynamic_currency_pairs_dialog.xml +++ b/dataModuleTester/src/main/res/layout/dynamic_currency_pairs_dialog.xml @@ -1,32 +1,32 @@ - - - - -