From 6b957d21159da507677e862789240bec7d9e2f42 Mon Sep 17 00:00:00 2001 From: Artur Kowalski Date: Wed, 9 May 2018 12:53:32 +0200 Subject: [PATCH] prepare futurocoin --- .../batm/server/extensions/ICurrencies.java | 1 + .../FuturocoinAddressValidator.java | 34 +++++ .../extra/futurocoin/FuturocoinExtension.java | 133 ++++++++++++++++++ .../sources/FixPriceRateSource.java | 50 +++++++ .../futurocoin/sources/yobit/IYobitAPI.java | 18 +++ .../sources/yobit/YobitRateSource.java | 49 +++++++ .../futurocoin/sources/yobit/dto/Ticker.java | 87 ++++++++++++ .../sources/yobit/dto/YobitResponse.java | 13 ++ .../futurocoind/FuturocoinRPCWallet.java | 100 +++++++++++++ .../src/main/resources/fto.png | Bin 0 -> 22187 bytes 10 files changed, 485 insertions(+) create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinAddressValidator.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinExtension.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/FixPriceRateSource.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/IYobitAPI.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/YobitRateSource.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/Ticker.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/YobitResponse.java create mode 100644 server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/wallets/futurocoind/FuturocoinRPCWallet.java create mode 100644 server_extensions_extra/src/main/resources/fto.png diff --git a/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/ICurrencies.java b/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/ICurrencies.java index 0548431..f4b8439 100644 --- a/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/ICurrencies.java +++ b/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/ICurrencies.java @@ -29,6 +29,7 @@ public interface ICurrencies { public static final String DASH = "DASH"; public static final String DOGE = "DOGE"; public static final String FLASH = "FLASH";// FLASH Coin + public static final String FTO = "FTO"; public static final String MAX = "MAX"; public static final String LEO = "LEO"; public static final String NLG = "NLG"; diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinAddressValidator.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinAddressValidator.java new file mode 100644 index 0000000..bf270d5 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinAddressValidator.java @@ -0,0 +1,34 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin; + +import com.generalbytes.batm.server.coinutil.AddressFormatException; +import com.generalbytes.batm.server.coinutil.Base58; +import com.generalbytes.batm.server.extensions.ICryptoAddressValidator; + +public class FuturocoinAddressValidator implements ICryptoAddressValidator { + + @Override + public boolean isAddressValid(String address) { + if (address.startsWith("F") || address.startsWith("6")) { + try { + Base58.decodeToBigInteger(address); + Base58.decodeChecked(address); + } catch (AddressFormatException e) { + e.printStackTrace(); + return false; + } + return true; + }else{ + return false; + } + } + + @Override + public boolean mustBeBase58Address() { + return true; + } + + @Override + public boolean isPaperWalletSupported() { + return false; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinExtension.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinExtension.java new file mode 100644 index 0000000..df9c5be --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/FuturocoinExtension.java @@ -0,0 +1,133 @@ +/************************************************************************************* + * Copyright (C) 2014-2016 GENERAL BYTES s.r.o. All rights reserved. + * + * This software may be distributed and modified under the terms of the GNU + * General Public License version 2 (GPL2) as published by the Free Software + * Foundation and appearing in the file GPL2.TXT included in the packaging of + * this file. Please note that GPL2 Section 2[b] requires that all works based + * on this software must also be made publicly available under the terms of + * the GPL2 ("Copyleft"). + * + * Contact information + * ------------------- + * + * GENERAL BYTES s.r.o. + * Web : http://www.generalbytes.com + * + ************************************************************************************/ +package com.generalbytes.batm.server.extensions.extra.futurocoin; + +import com.generalbytes.batm.server.extensions.*; +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.FixPriceRateSource; +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.YobitRateSource; +import com.generalbytes.batm.server.extensions.extra.futurocoin.wallets.futurocoind.FuturocoinRPCWallet; +import com.generalbytes.batm.server.extensions.watchlist.IWatchList; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; +import java.util.StringTokenizer; + +//import com.generalbytes.batm.server.extensions.extra.dogecoin.sources.chainso.ChainSoRateSource; +//import com.generalbytes.batm.server.extensions.extra.dogecoin.wallets.blockio.BlockIOWallet; + +public class FuturocoinExtension implements IExtension{ + @Override + public String getName() { + return "BATM Futurocoin extra extension"; + } + + @Override + public IExchange createExchange(String exchangeLogin) { + return null; + } + + @Override + public IPaymentProcessor createPaymentProcessor(String paymentProcessorLogin) { + return null; //no payment processors available + } + + @Override + public IWallet createWallet(String walletLogin) { + if (walletLogin !=null && !walletLogin.trim().isEmpty()) { + StringTokenizer st = new StringTokenizer(walletLogin,":"); + String walletType = st.nextToken(); + + if ("futurocoind".equalsIgnoreCase(walletType)) { + String protocol = st.nextToken(); + String username = st.nextToken(); + String password = st.nextToken(); + String hostname = st.nextToken(); + String port = st.nextToken(); + String accountName =""; + if (st.hasMoreTokens()) { + accountName = st.nextToken(); + } + + + if (protocol != null && username != null && password != null && hostname !=null && port != null && accountName != null) { + String rpcURL = protocol +"://" + username +":" + password + "@" + hostname +":" + port; + return new FuturocoinRPCWallet(rpcURL,accountName); + } + } + + } + return null; + } + + @Override + public ICryptoAddressValidator createAddressValidator(String cryptoCurrency) { + if (ICurrencies.FTO.equalsIgnoreCase(cryptoCurrency)) { + return new FuturocoinAddressValidator(); + } + return null; + } + + @Override + public IPaperWalletGenerator createPaperWalletGenerator(String cryptoCurrency) { + return null; + } + + @Override + public IRateSource createRateSource(String sourceLogin) { + if (sourceLogin != null && !sourceLogin.trim().isEmpty()) { + StringTokenizer st = new StringTokenizer(sourceLogin, ":"); + String exchangeType = st.nextToken(); + + if ("futurocoinfix".equalsIgnoreCase(exchangeType)) { + BigDecimal rate = BigDecimal.ZERO; + if (st.hasMoreTokens()) { + try { + rate = new BigDecimal(st.nextToken()); + } catch (Throwable e) { + } + } + String preferedFiatCurrency = ICurrencies.USD; + if (st.hasMoreTokens()) { + preferedFiatCurrency = st.nextToken().toUpperCase(); + } + return new FixPriceRateSource(rate, preferedFiatCurrency); + } else if ("yobit".equalsIgnoreCase(exchangeType)) { + return new YobitRateSource(); + } + } + return null; + } + + @Override + public Set getSupportedCryptoCurrencies() { + Set result = new HashSet(); + result.add(ICurrencies.FTO); + return result; + } + + @Override + public Set getSupportedWatchListsNames() { + return null; + } + + @Override + public IWatchList getWatchList(String name) { + return null; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/FixPriceRateSource.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/FixPriceRateSource.java new file mode 100644 index 0000000..849909f --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/FixPriceRateSource.java @@ -0,0 +1,50 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.sources; + +import com.generalbytes.batm.server.extensions.ICurrencies; +import com.generalbytes.batm.server.extensions.IRateSource; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; + +/** + * Created by woolly_sammoth on 11/12/14. + */ +public class FixPriceRateSource implements IRateSource { + private BigDecimal rate = BigDecimal.ZERO; + + private String preferedFiatCurrency = ICurrencies.USD; + + public FixPriceRateSource(BigDecimal rate, String preferedFiatCurrency) { + this.rate = rate; + if (ICurrencies.USD.equalsIgnoreCase(preferedFiatCurrency)) { + this.preferedFiatCurrency = ICurrencies.USD; + } + } + + @Override + public Set getCryptoCurrencies() { + Set result = new HashSet(); + result.add(ICurrencies.FTO); + return result; + } + + @Override + public BigDecimal getExchangeRateLast(String cryptoCurrency, String fiatCurrency) { + if (ICurrencies.FTO.equalsIgnoreCase(cryptoCurrency)) { + return rate; + } + return null; + } + + @Override + public Set getFiatCurrencies() { + Set result = new HashSet(); + result.add(ICurrencies.USD); + return result; + } + @Override + public String getPreferredFiatCurrency() { + return preferedFiatCurrency; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/IYobitAPI.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/IYobitAPI.java new file mode 100644 index 0000000..731fcfd --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/IYobitAPI.java @@ -0,0 +1,18 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit; + +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto.Ticker; +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto.YobitResponse; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/api/3/") +@Produces(MediaType.APPLICATION_JSON) +public interface IYobitAPI { + @GET + @Path("ticker/{cryptocurrency}_{fiatcurrency}") + YobitResponse getTicker(@PathParam("cryptocurrency") String cryptoCurrency, @PathParam("fiatcurrency") String fiatCurrency); +} \ No newline at end of file diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/YobitRateSource.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/YobitRateSource.java new file mode 100644 index 0000000..31a2542 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/YobitRateSource.java @@ -0,0 +1,49 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit; + +import com.generalbytes.batm.server.extensions.ICurrencies; +import com.generalbytes.batm.server.extensions.IRateSource; +import com.generalbytes.batm.server.extensions.extra.bitcoin.sources.bity.IBity; +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto.Ticker; +import com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto.YobitResponse; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; + +public class YobitRateSource implements IRateSource { + + private IYobitAPI api; + + public YobitRateSource() { + api = RestProxyFactory.createProxy(IBity.class, "https://yobit.net"); + } + + @Override + public Set getCryptoCurrencies() { + Set result = new HashSet(); + result.add(ICurrencies.FTO); + return result; + } + + @Override + public Set getFiatCurrencies() { + Set result = new HashSet(); + result.add(ICurrencies.USD); + return result; + } + + @Override + public BigDecimal getExchangeRateLast(String cryptoCurrency, String fiatCurrency) { + if (!getFiatCurrencies().contains(fiatCurrency) || !getCryptoCurrencies().contains(cryptoCurrency)) { + return null; + } + + YobitResponse response = api.getTicker(cryptoCurrency.toLowerCase(), fiatCurrency.toLowerCase()); + return response.getFot_usd().getLast(); + } + + @Override + public String getPreferredFiatCurrency() { + return ICurrencies.USD; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/Ticker.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/Ticker.java new file mode 100644 index 0000000..f9579ab --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/Ticker.java @@ -0,0 +1,87 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto; + +import java.math.BigDecimal; + +public class Ticker { + private BigDecimal high; + private BigDecimal low; + private BigDecimal avg; + private BigDecimal vol; + private BigDecimal vol_cur; + private BigDecimal last; + private BigDecimal buy; + private BigDecimal sell; + private long updated; + + public BigDecimal getHigh() { + return high; + } + + public void setHigh(BigDecimal high) { + this.high = high; + } + + public BigDecimal getLow() { + return low; + } + + public void setLow(BigDecimal low) { + this.low = low; + } + + public BigDecimal getAvg() { + return avg; + } + + public void setAvg(BigDecimal avg) { + this.avg = avg; + } + + public BigDecimal getVol() { + return vol; + } + + public void setVol(BigDecimal vol) { + this.vol = vol; + } + + public BigDecimal getVol_cur() { + return vol_cur; + } + + public void setVol_cur(BigDecimal vol_cur) { + this.vol_cur = vol_cur; + } + + public BigDecimal getLast() { + return last; + } + + public void setLast(BigDecimal last) { + this.last = last; + } + + public BigDecimal getBuy() { + return buy; + } + + public void setBuy(BigDecimal buy) { + this.buy = buy; + } + + public BigDecimal getSell() { + return sell; + } + + public void setSell(BigDecimal sell) { + this.sell = sell; + } + + public long getUpdated() { + return updated; + } + + public void setUpdated(long updated) { + this.updated = updated; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/YobitResponse.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/YobitResponse.java new file mode 100644 index 0000000..642a8e3 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/sources/yobit/dto/YobitResponse.java @@ -0,0 +1,13 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.sources.yobit.dto; + +public class YobitResponse { + private Ticker fot_usd; + + public Ticker getFot_usd() { + return fot_usd; + } + + public void setFot_usd(Ticker fot_usd) { + this.fot_usd = fot_usd; + } +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/wallets/futurocoind/FuturocoinRPCWallet.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/wallets/futurocoind/FuturocoinRPCWallet.java new file mode 100644 index 0000000..29b71c8 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/futurocoin/wallets/futurocoind/FuturocoinRPCWallet.java @@ -0,0 +1,100 @@ +package com.generalbytes.batm.server.extensions.extra.futurocoin.wallets.futurocoind; + +import com.azazar.bitcoin.jsonrpcclient.BitcoinException; +import com.azazar.bitcoin.jsonrpcclient.BitcoinJSONRPCClient; +import com.generalbytes.batm.server.extensions.ICurrencies; +import com.generalbytes.batm.server.extensions.IWallet; +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class FuturocoinRPCWallet implements IWallet { + + private static final Logger log = LoggerFactory.getLogger(FuturocoinRPCWallet.class); + private static final String CRYPTO_CURRENCY = ICurrencies.FTO; + + public FuturocoinRPCWallet(String rpcURL, String accountName) { + this.rpcURL = rpcURL; + this.accountName = accountName; + } + + private String rpcURL; + private String accountName; + + @Override + public Set getCryptoCurrencies() { + Set result = new HashSet(); + result.add(CRYPTO_CURRENCY); + return result; + + } + + @Override + public String getPreferredCryptoCurrency() { + return CRYPTO_CURRENCY; + } + + @Override + public String sendCoins(String destinationAddress, BigDecimal amount, String cryptoCurrency, String description) { + if (!CRYPTO_CURRENCY.equalsIgnoreCase(cryptoCurrency)) { + log.error("Futurocoind wallet error: unknown cryptocurrency."); + return null; + } + + log.info("Futurocoind sending coins from " + accountName + " to: " + destinationAddress + " " + amount); + try { + String result = getClient(rpcURL).sendFrom(accountName, destinationAddress,amount.doubleValue()); + log.debug("result = " + result); + return result; + } catch (BitcoinException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String getCryptoAddress(String cryptoCurrency) { + if (!CRYPTO_CURRENCY.equalsIgnoreCase(cryptoCurrency)) { + log.error("Futurocoind wallet error: unknown cryptocurrency."); + return null; + } + + try { + List addressesByAccount = getClient(rpcURL).getAddressesByAccount(accountName); + if (addressesByAccount == null || addressesByAccount.size() == 0) { + return null; + }else{ + return addressesByAccount.get(0); + } + } catch (BitcoinException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public BigDecimal getCryptoBalance(String cryptoCurrency) { + if (!CRYPTO_CURRENCY.equalsIgnoreCase(cryptoCurrency)) { + log.error("Futurocoind wallet error: unknown cryptocurrency: " + cryptoCurrency); + return null; + } + try { + double balance = getClient(rpcURL).getBalance(accountName); + return BigDecimal.valueOf(balance); + } catch (BitcoinException e) { + e.printStackTrace(); + return null; + } + } + + private BitcoinJSONRPCClient getClient(String rpcURL) { + try { + return new BitcoinJSONRPCClient(rpcURL); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/server_extensions_extra/src/main/resources/fto.png b/server_extensions_extra/src/main/resources/fto.png new file mode 100644 index 0000000000000000000000000000000000000000..350b38ac9e76810e6a85498c67957904b55ef064 GIT binary patch literal 22187 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 Pp+#K2XsA=5WfS;+NDw)Y literal 0 HcmV?d00001