package org.ripple.power.txns; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.json.JSONArray; import org.json.JSONObject; import org.ripple.power.config.LSystem; import org.ripple.power.txns.data.AccountResponse; import org.ripple.power.txns.data.ExchangesResponse; import org.ripple.power.txns.data.Meta; import org.ripple.power.txns.data.Take; import org.ripple.power.txns.data.TransactionsResponse; import org.ripple.power.utils.HttpRequest; import com.ripple.core.enums.TransactionFlag; public class RippleDataApi { // PS:Java环境下SSL支持有限,不能使用https读取此站,否则解码协议时会崩……dotNet下无事……我给oracle提交bug没人理我…… private static String DATA_URL = "http://data.ripple.com"; public static void setDataAPI_URL(String url) { DATA_URL = url; } public static String getDataAPI_URL() { return DATA_URL; } private static String open(String site) { HttpRequest request = HttpRequest.get(site); request.acceptGzipEncoding(); String result = null; try { request.uncompress(true); if (request.ok()) { result = request.body(); } } catch (Exception e) { e.printStackTrace(); } return result; } private static String open(String site, Map<?, ?> maps) { HttpRequest request = HttpRequest.get(site, maps, true); request.acceptGzipEncoding(); String result = null; try { request.uncompress(true); if (request.ok()) { result = request.body(); } } catch (Exception e) { e.printStackTrace(); } return result; } public static TransactionsResponse transactions(String address) { if (!AccountFind.isRippleAddress(address)) { return null; } String link = DATA_URL + String.format("/v2/accounts/%s/transactions", address); String result = open(link); if (result != null) { TransactionsResponse response = new TransactionsResponse(); response.from(new JSONObject(result)); return response; } return null; } public static ExchangesResponse exchanges(IssuedCurrency base, IssuedCurrency counter) { return exchanges(base.getTake(), counter.getTake()); } public static ExchangesResponse exchanges(Take base, Take counter) { String link = DATA_URL + String.format("/v2/exchanges/%s/%s", base, counter); String result = open(link); System.out.println(result); if (result != null) { ExchangesResponse response = new ExchangesResponse(); response.from(new JSONObject(result)); return response; } return null; } public static double exchange_rates(Take base, Take counter) { String link = DATA_URL + String.format("/v2/exchange_rates/%s/%s", base, counter); String result = open(link); if (result != null) { System.out.println(result); } return -1; } public static ExchangesResponse exchanges(String address) { if (!AccountFind.isRippleAddress(address)) { return null; } String link = DATA_URL + String.format("/v2/accounts/%s/exchanges", address); String result = open(link); if (result != null) { ExchangesResponse response = new ExchangesResponse(); response.from(new JSONObject(result)); return response; } return null; } public static JSONObject transactionsFind(final AccountInfo accountinfo, final ArrayList<IssuedCurrency> issues, String address) { JSONObject json = null; if (!AccountFind.isRippleAddress(address)) { return json; } String link = DATA_URL + String.format("/v2/accounts/%s/transactions", address); String result = open(link); if (result != null) { json = new JSONObject(result); JSONArray arrays = json.optJSONArray("transactions"); for (int i = 0; i < arrays.length(); i++) { TransactionTx transactionTx = new TransactionTx(); JSONObject transaction = arrays.getJSONObject(i); JSONObject tx = transaction.optJSONObject("tx"); JSONObject meta = transaction.optJSONObject("meta"); String type = tx.optString("TransactionType"); transactionTx.account = tx.optString("Account"); transactionTx.destination = tx.optString("Destination"); // transactionTx.date_number = date; transactionTx.date = transaction.optString("date"); String fee = CurrencyUtils.getRippleToValue(String.valueOf(tx .optLong("Fee"))); transactionTx.fee = fee; transactionTx.hash = tx.optString("hash"); transactionTx.sequence = tx.optLong("Sequence"); transactionTx.offersSequence = tx.optLong("OfferSequence"); transactionTx.inLedger = tx.optLong("inLedger"); transactionTx.ledgerIndex = tx.optLong("ledger_index"); transactionTx.flags = tx.optLong("Flags"); transactionTx.clazz = type; if (transactionTx.flags != 0) { transactionTx.isPartialPayment = (TransactionFlag.PartialPayment == transactionTx.flags); transactionTx.flagsName = TransactionFlagMap .getString(transactionTx.flags); } else { transactionTx.flagsName = "Empty"; } if (tx.has("SendMax")) { transactionTx.sendMax = CurrencyUtils.getIssuedCurrency(tx .get("SendMax")); } transactionTx.signingPubKey = tx.optString("SigningPubKey"); transactionTx.txnSignature = tx.optString("TxnSignature"); if (meta != null) { transactionTx.metaString = meta.toString(); transactionTx.meta = new Meta(); transactionTx.meta.from(meta); if (meta.has("AffectedNodes")) { JSONArray affectedNodes = meta .getJSONArray("AffectedNodes"); int size = affectedNodes.length(); for (int j = 0; j < size; j++) { JSONObject affectedNode = affectedNodes .getJSONObject(j); JSONArray names = affectedNode.names(); for (int n = 0; n < names.length(); n++) { String key = names.getString(n); TransactionTx.AffectedNode node = new TransactionTx.AffectedNode(); transactionTx.affectedNodeList.add(node); node.name = key; JSONObject ledger_node = affectedNode .getJSONObject(key); node.ledgerEntryType = ledger_node .optString("LedgerEntryType"); if (node.ledgerEntryType != null) { node.previousTxnID = ledger_node.optString( "PreviousTxnID"); node.txid = node.previousTxnID != null ? node.previousTxnID : transactionTx.hash; node.ledgerIndex = ledger_node .optString("LedgerIndex"); node.previousTxnLgrSeq = ledger_node .optLong("PreviousTxnLgrSeq"); JSONObject fields = null; if (ledger_node.has("FinalFields")) { fields = ledger_node .optJSONObject("FinalFields"); } else if (ledger_node.has("NewFields")) { fields = ledger_node .optJSONObject("NewFields"); } if (fields != null) { node.account = fields .optString("Account"); node.regularKey = fields .optString("RegularKey"); node.takerGetsIssuer = fields .optString("TakerGetsIssuer"); node.takerPaysIssuer = fields .optString("TakerPaysIssuer"); node.exchangeRate = fields .optString("ExchangeRate"); node.takerPaysCurrency = fields .optString("TakerPaysCurrency"); node.takerGetsCurrency = fields .optString("TakerGetsCurrency"); node.balance = CurrencyUtils .getIssuedCurrency(fields .opt("Balance")); node.highLimit = CurrencyUtils .getIssuedCurrency(fields .opt("HighLimit")); node.lowLimit = CurrencyUtils .getIssuedCurrency(fields .opt("LowLimit")); node.owner = fields.optString("Owner"); node.rootIndex = fields .optString("RootIndex"); node.indexPrevious = fields .optString("IndexPrevious"); node.indexNext = fields .optString("IndexNext"); node.sequence = fields .optLong("Sequence"); node.ownerCount = fields .optLong("OwnerCount"); node.transferRate = fields .optLong("TransferRate"); node.takerGets = CurrencyUtils .getIssuedCurrency(fields .opt("TakerGets")); node.takerPays = CurrencyUtils .getIssuedCurrency(fields .opt("TakerPays")); if (fields.has("Flags")) { node.flags = fields .optLong("Flags"); } else { node.flags = transactionTx.flags; } node.sell = OfferPrice .isSellOrder(node.flags); node.sellOrBuy = node.sell ? "sell" : "buy"; } } } } } } switch (type) { case "Payment": transactionTx.destinationTag = tx.optLong("DestinationTag"); transactionTx.invoiceID = tx.optString("InvoiceID"); IssuedCurrency currency = null; String counterparty = null; if (meta != null && meta.has("DeliveredAmount")) { currency = CurrencyUtils.getIssuedCurrency(meta .opt("DeliveredAmount")); } else { currency = CurrencyUtils.getIssuedCurrency(tx .opt("Amount")); } transactionTx.currency = currency; String flagType; if (address.equals(transactionTx.account)) { if (address.equals(transactionTx.destination)) { flagType = "Exchange"; } else { flagType = "Send"; counterparty = transactionTx.destination; int index = AccountFind.inCredits(issues, currency); if (index >= 0) { } else { issues.add(currency); } } } else if (address.equals(transactionTx.destination)) { flagType = "Receive"; counterparty = transactionTx.account; } else { flagType = "Convert"; } transactionTx.mode = flagType; transactionTx.counterparty = counterparty; break; case "TrustSet": Object limitAmount = tx.opt("LimitAmount"); if (limitAmount != null) { transactionTx.currency = CurrencyUtils .getIssuedCurrency(limitAmount); transactionTx.trusted = transactionTx.currency.issuer .toString(); } break; case "OfferCreate": transactionTx.get = CurrencyUtils.getIssuedCurrency(tx .opt("TakerGets")); transactionTx.pay = CurrencyUtils.getIssuedCurrency(tx .opt("TakerPays")); break; case "OfferCancel": JSONArray affectedNodes = meta .optJSONArray("AffectedNodes"); for (int n = 0; n < affectedNodes.length(); n++) { JSONObject obj = affectedNodes.getJSONObject(n); if (obj.has("DeletedNode")) { JSONObject deleted = obj .getJSONObject("DeletedNode"); String ledgerEntryType = deleted .optString("LedgerEntryType"); if ("Offer".equals(ledgerEntryType)) { JSONObject ff = deleted .optJSONObject("FinalFields"); String ffactount = ff.optString("Account"); if (ffactount.equals(transactionTx.account)) { transactionTx.get = CurrencyUtils .getIssuedCurrency(ff .opt("TakerGets")); transactionTx.pay = CurrencyUtils .getIssuedCurrency(ff .opt("TakerPays")); } } } } break; case "AccountSet": // Ignore break; } accountinfo.transactions.add(transactionTx); } } return json; } public static AccountResponse accounts(String address) { if (!AccountFind.isRippleAddress(address)) { return null; } String link = DATA_URL + String.format("/v2/accounts/%s", address); String result = open(link); if (result != null) { AccountResponse response = new AccountResponse(); response.from(new JSONObject(result)); return response; } return null; } public static CurrencyGateway gateways() { String link = DATA_URL + "/v2/gateways"; String result = open(link); if (result != null) { CurrencyGateway gateway = new CurrencyGateway(); gateway.copyFrom(new JSONObject(result)); return gateway; } return null; } public static CurrencyGateway.Item currencyTogateways(String curName) { return gateways().find(curName); } /** * 以指定网关数据为标准,转换一种货币价格为另外一种的 * * @param amount * @param baseCurrency * @param baseIssuer * @param exCurrency * @param exIssuer * @return */ public static Normalize normalize(double amount, String baseCurrency, String baseIssuer, String exCurrency, String exIssuer) { String link = DATA_URL + "/v2/normalize"; Map<Object, Object> maps = new HashMap<Object, Object>(); maps.put("amount", amount); if (LSystem.nativeCurrency.equalsIgnoreCase(baseCurrency)) { maps.put("currency", LSystem.nativeCurrency.toUpperCase()); } else { maps.put("currency", baseCurrency.toUpperCase()); maps.put("issuer", baseIssuer); } maps.put("exchange_currency", exCurrency.toUpperCase()); maps.put("exchange_issuer", exIssuer.toUpperCase()); String result = open(link, maps); if (result != null) { Normalize normalize = new Normalize(); normalize.copyFrom(new JSONObject(result)); return normalize; } return null; } /** * 以本地默认货币(默认即XRP)获得指定网关货币的汇率 * * @param amount * @param exCurrency * @param exIssuer * @return */ public static Normalize normalizeNative(double amount, String exCurrency, String exIssuer) { return normalize(amount, LSystem.nativeCurrency, null, exCurrency, exIssuer); } // rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B public static void main(String[] args) { System.out.println(RippleDataApi.normalize(100, "BTC", "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", "USD", "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B")); } }