diff --git a/README.md b/README.md index fd098bc..b55dbf1 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Here is the list of functionality that can be extended with extenstions API: Content ======= * **server_extensions_api** - contains extension api that all extensions use to extend BATM Server's functionality. -* **server_extensions_extra** - reference extension implementation that implements BTC, LTC, DGB, DASH, FLASH, DOGE, NLG, ICG, NBT, GRS and MAX coin support functionality. +* **server_extensions_extra** - reference extension implementation that implements BTC, LTC, DGB, DASH, SYS, FLASH, DOGE, NLG, ICG, NBT, GRS and MAX coin support functionality. * **server_extensions_test** - contains tester for testing the extensions without requirement of having a BATM server Note for developers diff --git a/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/Currencies.java b/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/Currencies.java index cdb9376..ee9072a 100644 --- a/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/Currencies.java +++ b/server_extensions_api/src/main/java/com/generalbytes/batm/server/extensions/Currencies.java @@ -45,6 +45,7 @@ public class Currencies { public static final String POT = "POT"; public static final String SMART = "SMART"; public static final String START = "START"; + public static final String SYS = "SYS"; // Syscoin 3 public static final String TKN = "TKN"; public static final String WDC = "WDC"; public static final String XMR = "XMR"; diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CMCTicker.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CMCTicker.java index 92e8c2c..0896e0d 100644 --- a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CMCTicker.java +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CMCTicker.java @@ -14,6 +14,7 @@ public class CMCTicker { private String symbol; private BigDecimal rank; private BigDecimal price_usd; + private BigDecimal price_cad; private BigDecimal price_eur; private BigDecimal price_btc; @@ -76,6 +77,14 @@ public class CMCTicker { this.price_eur = price_eur; } + public BigDecimal getPrice_cad() { + return price_cad; + } + + public void setPrice_cad(BigDecimal price_cad) { + this.price_cad = price_cad; + } + public BigDecimal getPrice_btc() { return price_btc; } diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CoinmarketcapRateSource.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CoinmarketcapRateSource.java index 823df81..ff67016 100644 --- a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CoinmarketcapRateSource.java +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/CoinmarketcapRateSource.java @@ -1,6 +1,5 @@ package com.generalbytes.batm.server.extensions.extra.dash.sources.coinmarketcap; -import com.generalbytes.batm.server.extensions.Currencies; import com.generalbytes.batm.server.extensions.Currencies; import com.generalbytes.batm.server.extensions.IRateSource; @@ -16,7 +15,7 @@ import si.mazi.rescu.RestProxyFactory; public class CoinmarketcapRateSource implements IRateSource { private ICoinmarketcapAPI api; - + private static HashMap coinIDs = new HashMap(); private String preferredFiatCurrency = Currencies.USD; public CoinmarketcapRateSource(String preferedFiatCurrency) { @@ -27,6 +26,19 @@ public class CoinmarketcapRateSource implements IRateSource { if (Currencies.USD.equalsIgnoreCase(preferedFiatCurrency)) { this.preferredFiatCurrency = Currencies.USD; } + if (Currencies.CAD.equalsIgnoreCase(preferedFiatCurrency)) { + this.preferredFiatCurrency = Currencies.CAD; + } + coinIDs.put(Currencies.BTC, 1); + coinIDs.put(Currencies.SYS, 541); + coinIDs.put(Currencies.BCH, 1831); + coinIDs.put(Currencies.BTX, 1654); + coinIDs.put(Currencies.LTC, 2); + coinIDs.put(Currencies.ETH, 1027); + coinIDs.put(Currencies.DASH, 131); + coinIDs.put(Currencies.XMR, 328); + coinIDs.put(Currencies.POT, 122); + coinIDs.put(Currencies.FLASH, 1755); } public CoinmarketcapRateSource() { @@ -37,6 +49,7 @@ public class CoinmarketcapRateSource implements IRateSource { public Set getCryptoCurrencies() { Set result = new HashSet(); result.add(Currencies.BTC); + result.add(Currencies.SYS); result.add(Currencies.BCH); result.add(Currencies.BTX); result.add(Currencies.LTC); @@ -53,6 +66,7 @@ public class CoinmarketcapRateSource implements IRateSource { public Set getFiatCurrencies() { Set result = new HashSet(); result.add(Currencies.USD); + result.add(Currencies.CAD); result.add(Currencies.EUR); return result; } @@ -69,28 +83,25 @@ public class CoinmarketcapRateSource implements IRateSource { if (!getFiatCurrencies().contains(fiatCurrency)) { return null; } - CMCTicker[] tickers; - if(Currencies.FLASH.equalsIgnoreCase(cryptoCurrency)){ - tickers = api.getTickers(cryptoCurrency,fiatCurrency); - }else - tickers = api.getTickers(fiatCurrency); + Integer cryptoId = coinIDs.get(cryptoCurrency); + if(cryptoId == null){ + return null; + } + CMCTicker[] tickers = api.getTickers(cryptoId, fiatCurrency); for (int i = 0; i < tickers.length; i++) { CMCTicker ticker = tickers[i]; if (cryptoCurrency.equalsIgnoreCase(ticker.getSymbol())) { if (Currencies.EUR.equalsIgnoreCase(fiatCurrency)) { return ticker.getPrice_eur(); - }else{ + }else if (Currencies.CAD.equalsIgnoreCase(fiatCurrency)) { + return ticker.getPrice_cad(); + } + else{ return ticker.getPrice_usd(); } } } return null; } - -// public static void main(String[] args) { -// CoinmarketcapRateSource rs = new CoinmarketcapRateSource(Currencies.EUR); -// BigDecimal exchangeRateLast = rs.getExchangeRateLast(Currencies.BTC, Currencies.EUR); -// System.out.println("exchangeRateLast = " + exchangeRateLast); -// } } diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/ICoinmarketcapAPI.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/ICoinmarketcapAPI.java index 230136f..303bb42 100644 --- a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/ICoinmarketcapAPI.java +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/dash/sources/coinmarketcap/ICoinmarketcapAPI.java @@ -20,14 +20,10 @@ package com.generalbytes.batm.server.extensions.extra.dash.sources.coinmarketcap import javax.ws.rs.*; import javax.ws.rs.core.MediaType; -@Path("/v1/ticker") +@Path("/v2/ticker") @Produces(MediaType.APPLICATION_JSON) public interface ICoinmarketcapAPI { @GET - @Path("/") - CMCTicker[] getTickers(@QueryParam("convert") String fiatCurrency); - - @GET - @Path("/{cryptoToGet}/?convert={convert}") - CMCTicker[] getTickers(@PathParam("cryptoToGet") String cryptoToGet,@QueryParam("convert") String fiatCurrency); + @Path("/{id}/") + CMCTicker[] getTickers(@PathParam("id") String id, @QueryParam("convert") String fiatCurrency); } diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinAddressValidator.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinAddressValidator.java new file mode 100644 index 0000000..2c214e1 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinAddressValidator.java @@ -0,0 +1,52 @@ +/************************************************************************************* + * 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.dash; + +import com.generalbytes.batm.server.coinutil.AddressFormatException; +import com.generalbytes.batm.server.coinutil.Base58; +import com.generalbytes.batm.server.extensions.ExtensionsUtil; +import com.generalbytes.batm.server.extensions.ICryptoAddressValidator; + +public class SyscoinAddressValidator implements ICryptoAddressValidator { + @Override + public boolean isAddressValid(String address) { + if (address.startsWith("S")) { + try { + Base58.decodeToBigInteger(address); + Base58.decodeChecked(address); + } catch (AddressFormatException e) { + e.printStackTrace(); + return false; + } + return true; + }else{ + return false; + } + } + + @Override + public boolean isPaperWalletSupported() { + return false; + } + + @Override + public boolean mustBeBase58Address() { + return true; + } + +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinExtension.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinExtension.java new file mode 100644 index 0000000..b4a8b55 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/SyscoinExtension.java @@ -0,0 +1,140 @@ +/************************************************************************************* + * 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.syscoin; + +import com.generalbytes.batm.server.extensions.*; +import com.generalbytes.batm.server.extensions.extra.syscoin.sources.FixPriceRateSource; +import com.generalbytes.batm.server.extensions.extra.dash.sources.coinmarketcap.CoinmarketcapRateSource; +import com.generalbytes.batm.server.extensions.extra.syscoin.wallets.syscoind.SyscoinRPCWallet; +import com.generalbytes.batm.server.extensions.watchlist.IWatchList; + +import java.math.BigDecimal; +import java.util.*; + +public class SyscoinExtension implements IExtension{ + @Override + public String getName() { + return "BATM Syscoin 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 ("syscoind".equalsIgnoreCase(walletType)) { + //"syscoind:protocol:user:password:ip:port:accountname" + + 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 SyscoinRPCWallet(rpcURL,accountName); + } + } + + } + return null; + } + + @Override + public ICryptoAddressValidator createAddressValidator(String cryptoCurrency) { + if (Currencies.SYS.equalsIgnoreCase(cryptoCurrency)) { + return new SyscoinAddressValidator(); + } + 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 ("syscoinfix".equalsIgnoreCase(exchangeType)) { + BigDecimal rate = BigDecimal.ZERO; + if (st.hasMoreTokens()) { + try { + rate = new BigDecimal(st.nextToken()); + } catch (Throwable e) { + } + } + String preferedFiatCurrency = Currencies.USD; + if (st.hasMoreTokens()) { + preferedFiatCurrency = st.nextToken().toUpperCase(); + } + return new FixPriceRateSource(rate, preferedFiatCurrency); + } else if ("coinmarketcap".equalsIgnoreCase(exchangeType)) { + String preferedFiatCurrency = Currencies.USD; + if (st.hasMoreTokens()) { + preferedFiatCurrency = st.nextToken().toUpperCase(); + } + return new CoinmarketcapRateSource(preferedFiatCurrency); + } + } + return null; + } + + @Override + public Set getSupportedCryptoCurrencies() { + Set result = new HashSet(); + result.add(Currencies.BTC); + result.add(Currencies.SYS); + result.add(Currencies.BTX); + result.add(Currencies.BCH); + result.add(Currencies.LTC); + result.add(Currencies.XMR); + result.add(Currencies.DASH); + result.add(Currencies.POT); + 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/syscoin/sources/FixPriceRateSource.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/sources/FixPriceRateSource.java new file mode 100644 index 0000000..dbe56b6 --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/sources/FixPriceRateSource.java @@ -0,0 +1,60 @@ +package com.generalbytes.batm.server.extensions.extra.syscoin.sources; + +import com.generalbytes.batm.server.extensions.Currencies; +import com.generalbytes.batm.server.extensions.Currencies; +import com.generalbytes.batm.server.extensions.IRateSource; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.Set; + +/** + * Created by b00lean on 7/31/14. + */ +public class FixPriceRateSource implements IRateSource { + private BigDecimal rate = BigDecimal.ZERO; + + private String preferedFiatCurrency = Currencies.USD; + + public FixPriceRateSource(BigDecimal rate,String preferedFiatCurrency) { + this.rate = rate; + if (Currencies.EUR.equalsIgnoreCase(preferedFiatCurrency)) { + this.preferedFiatCurrency = Currencies.EUR; + } + if (Currencies.USD.equalsIgnoreCase(preferedFiatCurrency)) { + this.preferedFiatCurrency = Currencies.USD; + } + if (Currencies.CAD.equalsIgnoreCase(preferedFiatCurrency)) { + this.preferedFiatCurrency = Currencies.CAD; + } + } + + @Override + public Set getCryptoCurrencies() { + Set result = new HashSet(); + result.add(Currencies.SYS); + return result; + } + + @Override + public BigDecimal getExchangeRateLast(String cryptoCurrency, String fiatCurrency) { + if (Currencies.SYS.equalsIgnoreCase(cryptoCurrency)) { + return rate; + } + return null; + } + + @Override + public Set getFiatCurrencies() { + Set result = new HashSet(); + result.add(Currencies.USD); + result.add(Currencies.CAD); + result.add(Currencies.EUR); + return result; + } + @Override + public String getPreferredFiatCurrency() { + return preferedFiatCurrency; + } + +} diff --git a/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/wallets/syscoind/SyscoinRPCWallet.java b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/wallets/syscoind/SyscoinRPCWallet.java new file mode 100644 index 0000000..7d7c75d --- /dev/null +++ b/server_extensions_extra/src/main/java/com/generalbytes/batm/server/extensions/extra/syscoin/wallets/syscoind/SyscoinRPCWallet.java @@ -0,0 +1,119 @@ +/************************************************************************************* + * 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.syscoin.wallets.syscoind; + +import com.azazar.bitcoin.jsonrpcclient.BitcoinException; +import com.azazar.bitcoin.jsonrpcclient.BitcoinJSONRPCClient; +import com.generalbytes.batm.server.extensions.Currencies; +import com.generalbytes.batm.server.extensions.IWallet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SyscoinPCWallet implements IWallet{ + private static final Logger log = LoggerFactory.getLogger(SyscoinPCWallet.class); + private static final String CRYPTO_CURRENCY = Currencies.SYS; + + public SyscoinPCWallet(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("Syscoind wallet error: unknown cryptocurrency."); + return null; + } + + log.info("Syscoind 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("Syscoind 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("Syscoind 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/batm-extensions.xml b/server_extensions_extra/src/main/resources/batm-extensions.xml index 23ac2c9..9c9e131 100644 --- a/server_extensions_extra/src/main/resources/batm-extensions.xml +++ b/server_extensions_extra/src/main/resources/batm-extensions.xml @@ -57,6 +57,7 @@ BTC + SYS BCH LTC ETH @@ -227,6 +228,22 @@ + + + + + + + + + SYS + + + + SYS + + + diff --git a/server_extensions_extra/src/main/resources/sys.png b/server_extensions_extra/src/main/resources/sys.png new file mode 100644 index 0000000..b57b365 Binary files /dev/null and b/server_extensions_extra/src/main/resources/sys.png differ