diff --git a/src/main/java/de/bitsharesmunich/graphenej/Asset.java b/src/main/java/de/bitsharesmunich/graphenej/Asset.java index 59c4a41..749c965 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Asset.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Asset.java @@ -42,6 +42,20 @@ public class Asset extends GrapheneObject { this.precision = precision; } + /** + * Constructor + * @param id: The graphene object id. + * @param symbol: The asset symbol. + * @param precision: The asset precision. + * @param issuer: Graphene object id of the issuer. + */ + public Asset(String id, String symbol, int precision, String issuer){ + super(id); + this.symbol = symbol; + this.precision = precision; + this.issuer = issuer; + } + public String getSymbol(){ return this.symbol; } @@ -50,6 +64,10 @@ public class Asset extends GrapheneObject { return this.precision; } + public void setIssuer(String issuer){ this.issuer = issuer; } + + public String getIssuer() { return this.issuer; } + /** * Custom deserializer used to instantiate a simple version of the Asset class from the response of the * 'lookup_asset_symbols' API call. @@ -62,7 +80,8 @@ public class Asset extends GrapheneObject { String id = object.get(KEY_ID).getAsString(); String symbol = object.get(KEY_SYMBOL).getAsString(); int precision = object.get(KEY_PRECISION).getAsInt(); - return new Asset(id, symbol, precision); + String issuer = object.get(KEY_ISSUER).getAsString(); + return new Asset(id, symbol, precision, issuer); } } -} +} \ No newline at end of file diff --git a/src/main/java/de/bitsharesmunich/graphenej/Main.java b/src/main/java/de/bitsharesmunich/graphenej/Main.java index 2caba9a..4298c31 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Main.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Main.java @@ -47,7 +47,7 @@ public class Main { // test.testRandomNumberGeneration(); // test.testBrainKeyOperations(false); // test.testBip39Opertion(); -// test.testAccountNamebyAddress(); + test.testAccountNamebyAddress(); // test.testAccountNameById(); // test.testRelativeAccountHistory(); // test.testingInvoiceGeneration(); @@ -60,6 +60,7 @@ public class Main { // test.testLookupAccounts(); // test.testDecodeMemo(); // test.testGetRelativeAccountHistory(); - test.testLookupAssetSymbols(); +// test.testLookupAssetSymbols(); +// test.testGetBlockHeader(); } } diff --git a/src/main/java/de/bitsharesmunich/graphenej/RPC.java b/src/main/java/de/bitsharesmunich/graphenej/RPC.java index cbcfe15..5ae0052 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/RPC.java +++ b/src/main/java/de/bitsharesmunich/graphenej/RPC.java @@ -8,6 +8,7 @@ public class RPC { public static final String CALL_LOGIN = "login"; public static final String CALL_NETWORK_BROADCAST = "network_broadcast"; public static final String CALL_HISTORY = "history"; + public static final String CALL_DATABASE = "database"; public static final String CALL_GET_ACCOUNT_BY_NAME = "get_account_by_name"; public static final String CALL_GET_DYNAMIC_GLOBAL_PROPERTIES = "get_dynamic_global_properties"; public static final String CALL_BROADCAST_TRANSACTION = "broadcast_transaction"; @@ -17,4 +18,5 @@ public class RPC { public static final String CALL_GET_RELATIVE_ACCOUNT_HISTORY = "get_relative_account_history"; public static final String CALL_LOOKUP_ACCOUNTS = "lookup_accounts"; public static final String CALL_LOOKUP_ASSET_SYMBOLS = "lookup_asset_symbols"; + public static final String CALL_GET_BLOCK_HEADER = "get_block_header"; } diff --git a/src/main/java/de/bitsharesmunich/graphenej/Test.java b/src/main/java/de/bitsharesmunich/graphenej/Test.java index 9bcd9e9..50c37a9 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Test.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Test.java @@ -85,7 +85,9 @@ public class Test { factory.setSSLContext(context); WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL); - mWebSocket.addListener(new GetAccountNameById(accountId, null)); + ArrayList userAccounts = new ArrayList(); + userAccounts.add(new UserAccount(accountId)); + mWebSocket.addListener(new GetAccountNameById(userAccounts, null)); mWebSocket.connect(); } catch (IOException e) { System.out.println("IOException. Msg: " + e.getMessage()); @@ -513,7 +515,7 @@ public class Test { }; BrainKey brainKey = new BrainKey(Main.BILTHON_83_BRAIN_KEY, 0); - Address address = new Address(brainKey.getPrivateKey()); + Address address = new Address(ECKey.fromPublicOnly(brainKey.getPrivateKey().getPubKey())); try { // Create a custom SSL context. SSLContext context = null; @@ -523,7 +525,7 @@ public class Test { // Set the custom SSL context. factory.setSSLContext(context); - WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL); + WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_DE); mWebSocket.addListener(new GetAccountsByAddress(address, listener)); mWebSocket.connect(); } catch (IOException e) { @@ -536,6 +538,18 @@ public class Test { } public void testAccountNameById() { + WitnessResponseListener listener = new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + } + }; + try { // Create a custom SSL context. SSLContext context = null; @@ -545,8 +559,10 @@ public class Test { // Set the custom SSL context. factory.setSSLContext(context); - WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL); - mWebSocket.addListener(new GetAccountNameById("1.2.138632", mListener)); + WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_FR); + ArrayList userAccounts = new ArrayList<>(); + userAccounts.add(new UserAccount("1.2.138632")); + mWebSocket.addListener(new GetAccountNameById(userAccounts, listener)); mWebSocket.connect(); } catch (IOException e) { System.out.println("IOException. Msg: " + e.getMessage()); @@ -750,9 +766,9 @@ public class Test { List transactionHistory = (List) response.result; System.out.println("Number of transactions: "+transactionHistory.size()); for(HistoricalTransfer historical : transactionHistory){ - if(historical.op != null){ - TransferOperation op = historical.op; - System.out.println("from: "+op.getFrom().getObjectId()+", to: "+op.getTo().getObjectId()+", amount: "+op.getAssetAmount().getAmount()+", block #: "+historical.block_num); + if(historical.getOperation() != null){ + TransferOperation op = historical.getOperation(); + System.out.println("from: "+op.getFrom().getObjectId()+", to: "+op.getTo().getObjectId()+", amount: "+op.getAssetAmount().getAmount()+", block #: "+historical.getBlockNum()); } } } @@ -792,7 +808,7 @@ public class Test { System.out.println("onSuccess"); WitnessResponse> resp = response; for(Asset asset : resp.result){ - System.out.println("Asset: "+asset.getObjectId()+", Symbol: "+asset.getSymbol()); + System.out.println("Asset: "+asset.getObjectId()+", Symbol: "+asset.getSymbol()+", supply: "); } } @@ -827,4 +843,40 @@ public class Test { System.out.println("IOException. Msg: " + e.getMessage()); } } + + public void testGetBlockHeader(){ + WitnessResponseListener listener = new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + } + }; + + SSLContext context = null; + try { + context = NaiveSSLContext.getInstance("TLS"); + WebSocketFactory factory = new WebSocketFactory(); + + // Set the custom SSL context. + factory.setSSLContext(context); + + WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_DE); + + + mWebSocket.addListener(new GetBlockHeader(11989481, listener)); + mWebSocket.connect(); + + } catch (NoSuchAlgorithmException e) { + System.out.println("NoSuchAlgorithmException. Msg: " + e.getMessage()); + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (IOException e) { + System.out.println("IOException. Msg: " + e.getMessage()); + } + } } diff --git a/src/main/java/de/bitsharesmunich/graphenej/TransferOperation.java b/src/main/java/de/bitsharesmunich/graphenej/TransferOperation.java index ae9b050..967afc1 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/TransferOperation.java +++ b/src/main/java/de/bitsharesmunich/graphenej/TransferOperation.java @@ -157,12 +157,12 @@ public class TransferOperation extends BaseOperation { JsonObject jsonObject = json.getAsJsonObject(); // Deserializing AssetAmount objects - AssetAmount amount = context.deserialize(jsonObject.get("amount"), AssetAmount.class); - AssetAmount fee = context.deserialize(jsonObject.get("fee"), AssetAmount.class); + AssetAmount amount = context.deserialize(jsonObject.get(KEY_AMOUNT), AssetAmount.class); + AssetAmount fee = context.deserialize(jsonObject.get(KEY_FEE), AssetAmount.class); // Deserializing UserAccount objects - UserAccount from = new UserAccount(jsonObject.get("from").getAsString()); - UserAccount to = new UserAccount(jsonObject.get("to").getAsString()); + UserAccount from = new UserAccount(jsonObject.get(KEY_FROM).getAsString()); + UserAccount to = new UserAccount(jsonObject.get(KEY_TO).getAsString()); TransferOperation transfer = new TransferOperation(from, to, amount, fee); return transfer; } diff --git a/src/main/java/de/bitsharesmunich/graphenej/Util.java b/src/main/java/de/bitsharesmunich/graphenej/Util.java index 1df7493..fa49cc0 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Util.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Util.java @@ -247,4 +247,28 @@ public class Util { } return result.toString(); } + + /** + * Converts a base value to an adjusted one considering the precision of the asset. + * @param assetAmount: The asset amount instance. + * @return: Converts the base + */ + public static float fromBase(AssetAmount assetAmount){ + long value = assetAmount.getAmount().longValue(); + int precision = assetAmount.getAsset().getPrecision(); + if(precision != 0) + return value / precision; + else + return 0; + } + + /** + * Converts a value and its corresponding precision to a base value. + * @param value + * @param precision + * @return + */ + public static long toBase(long value, int precision){ + return (long) (value * Math.pow(10, precision)); + } } diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountNameById.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountNameById.java index f15e441..2068010 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountNameById.java +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountNameById.java @@ -7,6 +7,7 @@ import com.google.gson.reflect.TypeToken; import de.bitsharesmunich.graphenej.AccountOptions; import de.bitsharesmunich.graphenej.Authority; import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.UserAccount; import de.bitsharesmunich.graphenej.interfaces.JsonSerializable; import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; import de.bitsharesmunich.graphenej.models.AccountProperties; @@ -30,11 +31,17 @@ import java.util.Map; */ public class GetAccountNameById extends WebSocketAdapter { - private String accountID; + private String accountId; + private List userAccounts; private WitnessResponseListener mListener; - public GetAccountNameById(String accountID, WitnessResponseListener listener) { - this.accountID = accountID; + public GetAccountNameById(String accountId, WitnessResponseListener listener){ + this.accountId = accountId; + this.mListener = listener; + } + + public GetAccountNameById(List accounts, WitnessResponseListener listener){ + this.userAccounts = accounts; this.mListener = listener; } @@ -42,17 +49,13 @@ public class GetAccountNameById extends WebSocketAdapter { public void onConnected(WebSocket websocket, Map> headers) throws Exception { ArrayList accountParams = new ArrayList(); ArrayList paramAddress = new ArrayList(); - paramAddress.add(new JsonSerializable() { - @Override - public String toJsonString() { - return accountID; + if(accountId == null){ + for(UserAccount account : userAccounts) { + paramAddress.add(account.getObjectId()); } - - @Override - public JsonElement toJsonObject() { - return new JsonParser().parse(accountID); - } - }); + }else{ + paramAddress.add(accountId); + } accountParams.add(paramAddress); ApiCall getAccountByAddress = new ApiCall(0, RPC.CALL_GET_ACCOUNTS, accountParams, RPC.VERSION, 1); websocket.sendText(getAccountByAddress.toJsonString()); @@ -92,7 +95,7 @@ public class GetAccountNameById extends WebSocketAdapter { @Override public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { - System.out.println("handleCallbackError"); + System.out.println("handleCallbackError. Msg: "+cause.getMessage()); StackTraceElement[] stack = cause.getStackTrace(); for(StackTraceElement element : stack) { System.out.println("> "+element.getClassName()+"."+element.getMethodName()+" : "+element.getLineNumber()); diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java index b3c716c..9706fb0 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetAccountsByAddress.java @@ -62,7 +62,7 @@ public class GetAccountsByAddress extends WebSocketAdapter { Gson gson = new Gson(); Type GetAccountByAddressResponse = new TypeToken>>>(){}.getType(); - WitnessResponse>>> witnessResponse = gson.fromJson(response, GetAccountByAddressResponse); + WitnessResponse>> witnessResponse = gson.fromJson(response, GetAccountByAddressResponse); if (witnessResponse.error != null) { this.mListener.onError(witnessResponse.error); } else { diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java new file mode 100644 index 0000000..08bf9a7 --- /dev/null +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetBlockHeader.java @@ -0,0 +1,103 @@ +package de.bitsharesmunich.graphenej.api; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.neovisionaries.ws.client.WebSocket; +import com.neovisionaries.ws.client.WebSocketAdapter; +import com.neovisionaries.ws.client.WebSocketException; +import com.neovisionaries.ws.client.WebSocketFrame; +import com.sun.tools.internal.ws.processor.model.Block; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.*; + +import java.io.Serializable; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Created by nelson on 12/13/16. + */ +public class GetBlockHeader extends WebSocketAdapter { + // Sequence of message ids + private final static int LOGIN_ID = 1; + private final static int GET_DATABASE_ID = 2; + private final static int GET_BLOCK_HEADER_ID = 3; + + private long blockNumber; + private WitnessResponseListener mListener; + + private int currentId = LOGIN_ID; + private int apiId = -1; + + public GetBlockHeader(long blockNumber, WitnessResponseListener listener){ + this.blockNumber = blockNumber; + this.mListener = listener; + } + + @Override + public void onConnected(WebSocket websocket, Map> headers) throws Exception { + ArrayList loginParams = new ArrayList<>(); + loginParams.add(null); + loginParams.add(null); + ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, RPC.VERSION, currentId); + websocket.sendText(loginCall.toJsonString()); + } + + @Override + public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception { + String response = frame.getPayloadText(); + System.out.println("<<< "+response); + + Gson gson = new Gson(); + BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class); + if(baseResponse.error != null){ + mListener.onError(baseResponse.error); + websocket.disconnect(); + }else { + currentId++; + ArrayList emptyParams = new ArrayList<>(); + if(baseResponse.id == LOGIN_ID){ + ApiCall getDatabaseId = new ApiCall(1, RPC.CALL_DATABASE, emptyParams, RPC.VERSION, currentId); + websocket.sendText(getDatabaseId.toJsonString()); + }else if(baseResponse.id == GET_DATABASE_ID){ + Type ApiIdResponse = new TypeToken>() {}.getType(); + WitnessResponse witnessResponse = gson.fromJson(response, ApiIdResponse); + apiId = witnessResponse.result.intValue(); + + ArrayList params = new ArrayList<>(); + String blockNum = String.format("%d", this.blockNumber); + params.add(blockNum); + + ApiCall loginCall = new ApiCall(apiId, RPC.CALL_GET_BLOCK_HEADER, params, RPC.VERSION, currentId); + websocket.sendText(loginCall.toJsonString()); + }else if(baseResponse.id == GET_BLOCK_HEADER_ID){ + Type RelativeAccountHistoryResponse = new TypeToken>(){}.getType(); + WitnessResponse transfersResponse = gson.fromJson(response, RelativeAccountHistoryResponse); + mListener.onSuccess(transfersResponse); + websocket.disconnect(); + } + } + + } + + @Override + public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception { + if(frame.isTextFrame()) + System.out.println(">>> "+frame.getPayloadText()); + } + + @Override + public void onError(WebSocket websocket, WebSocketException cause) throws Exception { + System.out.println("onError. Msg: "+cause.getMessage()); + websocket.disconnect(); + } + + @Override + public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { + System.out.println("handleCallbackError. Msg: "+cause.getMessage()); + websocket.disconnect(); + } +} diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java index 076683f..7a19536 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java @@ -137,10 +137,12 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { @Override public void onError(WebSocket websocket, WebSocketException cause) throws Exception { System.out.println("onError. Msg: "+cause.getMessage()); + websocket.disconnect(); } @Override public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { System.out.println("handleCallbackError. Msg: "+cause.getMessage()); + websocket.disconnect(); } } diff --git a/src/main/java/de/bitsharesmunich/graphenej/models/BlockHeader.java b/src/main/java/de/bitsharesmunich/graphenej/models/BlockHeader.java new file mode 100644 index 0000000..4dc5e4f --- /dev/null +++ b/src/main/java/de/bitsharesmunich/graphenej/models/BlockHeader.java @@ -0,0 +1,12 @@ +package de.bitsharesmunich.graphenej.models; + +/** + * Created by nelson on 12/13/16. + */ +public class BlockHeader { + public String previous; + public String timestamp; + public String witness; + public String transaction_merkle_root; + public Object[] extension; +} diff --git a/src/main/java/de/bitsharesmunich/graphenej/models/HistoricalTransfer.java b/src/main/java/de/bitsharesmunich/graphenej/models/HistoricalTransfer.java index 899a459..1237d65 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/models/HistoricalTransfer.java +++ b/src/main/java/de/bitsharesmunich/graphenej/models/HistoricalTransfer.java @@ -11,11 +11,59 @@ import de.bitsharesmunich.graphenej.TransferOperation; * those will be filtered out of the parsed result. */ public class HistoricalTransfer { - public String id; - public TransferOperation op; + private String id; + private TransferOperation op; public Object[] result; - public long block_num; - public long trx_in_block; - public long op_in_trx; - public long virtual_op; -} + private long block_num; + private long trx_in_block; + private long op_in_trx; + private long virtual_op; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public TransferOperation getOperation() { + return op; + } + + public void setOperation(TransferOperation op) { + this.op = op; + } + + public long getBlockNum() { + return block_num; + } + + public void setBlockNum(long block_num) { + this.block_num = block_num; + } + + public long getTransactionsInBlock() { + return trx_in_block; + } + + public void setTransactionsInBlock(long trx_in_block) { + this.trx_in_block = trx_in_block; + } + + public long getOperationsInTrx() { + return op_in_trx; + } + + public void setOperationsInTrx(long op_in_trx) { + this.op_in_trx = op_in_trx; + } + + public long getVirtualOp() { + return virtual_op; + } + + public void setVirtualOp(long virtual_op) { + this.virtual_op = virtual_op; + } +} \ No newline at end of file