package api; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import controller.Controller; import qora.account.Account; import qora.block.Block; import qora.crypto.Base58; import qora.crypto.Crypto; import qora.transaction.Transaction; import utils.Pair; @Path("transactions") @Produces(MediaType.APPLICATION_JSON) public class TransactionsResource { @GET public String getTransactions() { return this.getTransactionsLimited(50); } @GET @Path("/{address}") public String getTransactions(@PathParam("address") String address) { return this.getTransactionsLimited(address, 50); } @GET @Path("address/{address}") public String getTransactionsTwo(@PathParam("address") String address) { return this.getTransactions(address); } @SuppressWarnings("unchecked") @GET @Path("limit/{limit}") public String getTransactionsLimited(@PathParam("limit") int limit) { //CHECK IF WALLET EXISTS if(!Controller.getInstance().doesWalletExists()) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_WALLET_NO_EXISTS); } //GET TRANSACTIONS List<Pair<Account, Transaction>> transactions = Controller.getInstance().getLastTransactions(limit); //ORGANIZE TRANSACTIONS Map<Account, List<Transaction>> orderedTransactions = new HashMap<Account, List<Transaction>>(); for(Pair<Account, Transaction> transaction: transactions) { if(!orderedTransactions.containsKey(transaction.getA())) { orderedTransactions.put(transaction.getA(), new ArrayList<Transaction>()); } orderedTransactions.get(transaction.getA()).add(transaction.getB()); } //CREATE JSON OBJECT JSONArray orderedTransactionsJSON = new JSONArray(); for(Account account: orderedTransactions.keySet()) { JSONArray transactionsJSON = new JSONArray(); for(Transaction transaction: orderedTransactions.get(account)) { transactionsJSON.add(transaction.toJson()); } JSONObject accountTransactionsJSON = new JSONObject(); accountTransactionsJSON.put("account", account.getAddress()); accountTransactionsJSON.put("transactions", transactionsJSON); orderedTransactionsJSON.add(accountTransactionsJSON); } return orderedTransactionsJSON.toJSONString(); } @SuppressWarnings("unchecked") @GET @Path("address/{address}/limit/{limit}") public String getTransactionsLimited(@PathParam("address") String address, @PathParam("limit") int limit) { //CHECK IF WALLET EXISTS if(!Controller.getInstance().doesWalletExists()) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_WALLET_NO_EXISTS); } //CHECK ADDRESS if(!Crypto.getInstance().isValidAddress(address)) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_INVALID_ADDRESS); } //CHECK ACCOUNT IN WALLET Account account = Controller.getInstance().getAccountByAddress(address); if(account == null) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_WALLET_ADDRESS_NO_EXISTS); } JSONArray array = new JSONArray(); for(Transaction transaction: Controller.getInstance().getLastTransactions(account, limit)) { array.add(transaction.toJson()); } return array.toJSONString(); } @GET @Path("signature/{signature}") public String getTransactionsBySignature(@PathParam("signature") String signature) throws Exception { //DECODE SIGNATURE byte[] signatureBytes; try { signatureBytes = Base58.decode(signature); } catch(Exception e) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_INVALID_SIGNATURE); } //GET TRANSACTION Transaction transaction = Controller.getInstance().getTransaction(signatureBytes); //CHECK IF TRANSACTION EXISTS if(transaction == null) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_TRANSACTION_NO_EXISTS); } return transaction.toJson().toJSONString(); } @SuppressWarnings("unchecked") @GET @Path("/network") public String getNetworkTransactions() { List<Transaction> transactions = Controller.getInstance().getUnconfirmedTransactions(); JSONArray array = new JSONArray(); for(Transaction transaction: transactions) { array.add(transaction.toJson()); } return array.toJSONString(); } @SuppressWarnings("unchecked") @POST @Path("/scan") public String scanTransactions(String x) { try { //READ JSON JSONObject jsonObject = (JSONObject) JSONValue.parse(x); //GET BLOCK Block block = null; if(jsonObject.containsKey("start")) { byte[] signatureBytes; try { String signature = (String) jsonObject.get("start"); signatureBytes = Base58.decode(signature); } catch(Exception e) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_INVALID_SIGNATURE); } block = Controller.getInstance().getBlock(signatureBytes); //CHECK IF BLOCK EXISTS if(block == null) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_BLOCK_NO_EXISTS); } } //CHECK FOR BLOCKLIMIT int blockLimit = -1; try { blockLimit = ((Long) jsonObject.get("blocklimit")).intValue(); } catch(NullPointerException e) { //OPTION DOES NOT EXIST } catch(ClassCastException e) { //JSON EXCEPTION throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } //CHECK FOR TRANSACTIONLIMIT int transactionLimit = -1; try { transactionLimit = ((Long) jsonObject.get("transactionlimit")).intValue(); } catch(NullPointerException e) { //OPTION DOES NOT EXIST } catch(ClassCastException e) { //JSON EXCEPTION throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } //CHECK FOR TYPE int type = -1; try { type = ((Long) jsonObject.get("type")).intValue(); } catch(NullPointerException e) { //OPTION DOES NOT EXIST } catch(ClassCastException e) { //JSON EXCEPTION throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } //CHECK FOR SERVICE int service = -1; try { service = ((Long) jsonObject.get("service")).intValue(); } catch(NullPointerException e) { //OPTION DOES NOT EXIST } catch(ClassCastException e) { //JSON EXCEPTION throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } //CHECK FOR ACCOUNT Account account = null; try { if(jsonObject.containsKey("address")) { String address = (String) jsonObject.get("address"); //CHECK ADDRESS if(!Crypto.getInstance().isValidAddress(address)) { throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_INVALID_ADDRESS); } account = new Account(address); } } catch(NullPointerException e) { //OPTION DOES NOT EXIST } catch(ClassCastException e) { //JSON EXCEPTION throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } //SCAN Pair<Block, List<Transaction>> result = Controller.getInstance().scanTransactions(block, blockLimit, transactionLimit, type, service, account); //CONVERT RESULT TO JSON JSONObject json = new JSONObject(); json.put("lastscanned", Base58.encode(result.getA().getSignature())); if(block != null) { json.put("amount", result.getA().getHeight() - block.getHeight() + 1); } else { json.put("amount", result.getA().getHeight()); } JSONArray transactions = new JSONArray(); for(Transaction transaction: result.getB()) { transactions.add(transaction.toJson()); } json.put("transactions", transactions); //RETURN return json.toJSONString(); } catch(NullPointerException e) { //JSON EXCEPTION e.printStackTrace(); throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } catch(ClassCastException e) { //JSON EXCEPTION e.printStackTrace(); throw ApiErrorFactory.getInstance().createError(ApiErrorFactory.ERROR_JSON); } } }