AccountUpdateOperation serialization matches cli_wallet
This commit is contained in:
parent
5f51a1c3e4
commit
e0b0330e54
11 changed files with 168 additions and 80 deletions
|
@ -48,13 +48,17 @@ public class AccountUpdateOperation extends BaseOperation {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement toJsonObject() {
|
public JsonElement toJsonObject() {
|
||||||
|
JsonArray array = new JsonArray();
|
||||||
|
array.add(this.getId());
|
||||||
|
|
||||||
JsonObject accountUpdate = new JsonObject();
|
JsonObject accountUpdate = new JsonObject();
|
||||||
accountUpdate.add(KEY_FEE, fee.toJsonObject());
|
accountUpdate.add(KEY_FEE, fee.toJsonObject());
|
||||||
accountUpdate.add(KEY_ACCOUNT, account.toJsonObject());
|
accountUpdate.addProperty(KEY_ACCOUNT, account.toJsonString());
|
||||||
accountUpdate.add(KEY_OWNER, owner.toJsonObject());
|
accountUpdate.add(KEY_OWNER, owner.toJsonObject());
|
||||||
accountUpdate.add(KEY_ACTIVE, active.toJsonObject());
|
accountUpdate.add(KEY_ACTIVE, active.toJsonObject());
|
||||||
accountUpdate.add(KEY_EXTENSIONS, extensions.toJsonObject());
|
accountUpdate.add(KEY_EXTENSIONS, extensions.toJsonObject());
|
||||||
return accountUpdate;
|
array.add(accountUpdate);
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by nelson on 12/3/16.
|
||||||
|
*/
|
||||||
|
public class AccountUpdateTransactionBuilder {
|
||||||
|
private List<AccountUpdateOperation> operations;
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package com.luminiasoft.bitshares;
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||||
|
@ -13,6 +15,11 @@ import java.util.*;
|
||||||
* Created by nelson on 11/30/16.
|
* Created by nelson on 11/30/16.
|
||||||
*/
|
*/
|
||||||
public class Authority implements JsonSerializable, ByteSerializable {
|
public class Authority implements JsonSerializable, ByteSerializable {
|
||||||
|
public static final String KEY_ACCOUNT_AUTHS = "account_auths";
|
||||||
|
public static final String KEY_KEY_AUTHS = "key_auths";
|
||||||
|
public static final String KEY_WEIGHT_THRESHOLD = "weight_threshold";
|
||||||
|
public static final String KEY_EXTENSIONS = "extensions";
|
||||||
|
|
||||||
private long weight_threshold;
|
private long weight_threshold;
|
||||||
private HashMap<UserAccount, Integer> account_auths;
|
private HashMap<UserAccount, Integer> account_auths;
|
||||||
private HashMap<PublicKey, Integer> key_auths;
|
private HashMap<PublicKey, Integer> key_auths;
|
||||||
|
@ -36,7 +43,29 @@ public class Authority implements JsonSerializable, ByteSerializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement toJsonObject() {
|
public JsonElement toJsonObject() {
|
||||||
return null;
|
JsonObject authority = new JsonObject();
|
||||||
|
authority.addProperty(KEY_WEIGHT_THRESHOLD, weight_threshold);
|
||||||
|
JsonArray keyAuthArray = new JsonArray();
|
||||||
|
JsonArray accountAuthArray = new JsonArray();
|
||||||
|
|
||||||
|
for(PublicKey publicKey : key_auths.keySet()){
|
||||||
|
JsonArray subArray = new JsonArray();
|
||||||
|
Address address = new Address(publicKey.getKey());
|
||||||
|
subArray.add(address.toString());
|
||||||
|
subArray.add(key_auths.get(publicKey));
|
||||||
|
keyAuthArray.add(subArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(UserAccount key : account_auths.keySet()){
|
||||||
|
JsonArray subArray = new JsonArray();
|
||||||
|
subArray.add(key.toString());
|
||||||
|
subArray.add(key_auths.get(key));
|
||||||
|
accountAuthArray.add(subArray);
|
||||||
|
}
|
||||||
|
authority.add(KEY_KEY_AUTHS, keyAuthArray);
|
||||||
|
authority.add(KEY_ACCOUNT_AUTHS, accountAuthArray);
|
||||||
|
authority.add(KEY_EXTENSIONS, extensions.toJsonObject());
|
||||||
|
return authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class Main {
|
||||||
// test.testingInvoiceGeneration();
|
// test.testingInvoiceGeneration();
|
||||||
// test.testCompression();
|
// test.testCompression();
|
||||||
// test.testCreateBinFile();
|
// test.testCreateBinFile();
|
||||||
test.testAccountUpdateOperationSerialization();
|
test.testAccountUpdateSerialization();
|
||||||
|
// test.testAccountUpdateOperationSerialization();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ public class PublicKey implements ByteSerializable {
|
||||||
this.publicKey = key;
|
this.publicKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ECKey getKey(){
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] toBytes() {
|
public byte[] toBytes() {
|
||||||
return publicKey.getPubKey();
|
return publicKey.getPubKey();
|
||||||
|
|
|
@ -432,8 +432,6 @@ public class Test {
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transaction);
|
||||||
|
|
||||||
transactionList.add(transaction);
|
|
||||||
|
|
||||||
SSLContext context = null;
|
SSLContext context = null;
|
||||||
context = NaiveSSLContext.getInstance("TLS");
|
context = NaiveSSLContext.getInstance("TLS");
|
||||||
WebSocketFactory factory = new WebSocketFactory();
|
WebSocketFactory factory = new WebSocketFactory();
|
||||||
|
@ -744,20 +742,76 @@ public class Test {
|
||||||
System.out.println("fileOutput " + Arrays.toString(fileOutput));
|
System.out.println("fileOutput " + Arrays.toString(fileOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAccountUpdateOperationSerialization(){
|
public void testAccountUpdateSerialization() {
|
||||||
UserAccount account = new UserAccount("1.2.138632");
|
UserAccount account = new UserAccount("1.2.138632");
|
||||||
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf("4294967295"), new Asset("1.3.0"));
|
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf("200"), new Asset("1.3.0"));
|
||||||
HashMap<String, Integer> keyAuths = new HashMap<>();
|
HashMap<String, Integer> keyAuths = new HashMap<>();
|
||||||
keyAuths.put("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY", 65535);
|
keyAuths.put("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY", 1);
|
||||||
|
try {
|
||||||
|
BlockData blockData = new BlockData(0, 0, 0);
|
||||||
|
Authority owner = new Authority(1, keyAuths);
|
||||||
|
Authority active = new Authority(1, keyAuths);
|
||||||
|
AccountUpdateOperation operation = new AccountUpdateOperation(account, owner, active, fee);
|
||||||
|
ArrayList<BaseOperation> operations = new ArrayList<BaseOperation>();
|
||||||
|
operations.add(operation);
|
||||||
|
Transaction transaction = new Transaction(Main.WIF, blockData, operations);
|
||||||
|
System.out.println("Json format of transaction");
|
||||||
|
System.out.println(transaction.toJsonString());
|
||||||
|
} catch(MalformedAddressException e){
|
||||||
|
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAccountUpdateOperationBroadcast(){
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UserAccount account = new UserAccount("1.2.138632");
|
||||||
|
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf("200"), new Asset("1.3.0"));
|
||||||
|
HashMap<String, Integer> keyAuths = new HashMap<>();
|
||||||
|
keyAuths.put("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY", 1);
|
||||||
try {
|
try {
|
||||||
Authority owner = new Authority(1, keyAuths);
|
Authority owner = new Authority(1, keyAuths);
|
||||||
Authority active = new Authority(1, keyAuths);
|
Authority active = new Authority(1, keyAuths);
|
||||||
AccountUpdateOperation operation = new AccountUpdateOperation(account, owner, active, fee);
|
AccountUpdateOperation operation = new AccountUpdateOperation(account, owner, active, fee);
|
||||||
byte[] serializedOperation = operation.toBytes();
|
ArrayList<BaseOperation> operations = new ArrayList<BaseOperation>();
|
||||||
System.out.println("serialized operation");
|
operations.add(operation);
|
||||||
System.out.println(Util.bytesToHex(serializedOperation));
|
Transaction transaction = new Transaction(Main.WIF, null, operations);
|
||||||
|
|
||||||
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
|
transactionList.add(transaction);
|
||||||
|
|
||||||
|
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, RPC.VERSION, 1);
|
||||||
|
|
||||||
|
SSLContext context = null;
|
||||||
|
context = NaiveSSLContext.getInstance("TLS");
|
||||||
|
WebSocketFactory factory = new WebSocketFactory();
|
||||||
|
|
||||||
|
// Set the custom SSL context.
|
||||||
|
factory.setSSLContext(context);
|
||||||
|
|
||||||
|
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
||||||
|
|
||||||
|
mWebSocket.addListener(new TransactionBroadcastSequence(transaction, listener));
|
||||||
|
mWebSocket.connect();
|
||||||
} catch (MalformedAddressException e) {
|
} catch (MalformedAddressException e) {
|
||||||
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
|
System.out.println("MalformedAddressException. Msg: "+e.getMessage());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("NoSuchAlgorithmException. Msg: "+e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("IOException. Msg: "+e.getMessage());
|
||||||
|
} catch (WebSocketException e) {
|
||||||
|
System.out.println("WebSocketException. Msg: "+e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonSerializationContext;
|
import com.google.gson.JsonSerializationContext;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.google.gson.JsonSerializer;
|
||||||
|
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||||
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||||
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ import java.util.TimeZone;
|
||||||
public class Transaction implements ByteSerializable, JsonSerializable {
|
public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
private final String TAG = this.getClass().getName();
|
private final String TAG = this.getClass().getName();
|
||||||
|
|
||||||
|
public static final int DEFAULT_EXPIRATION_TIME = 30;
|
||||||
public static final String KEY_EXPIRATION = "expiration";
|
public static final String KEY_EXPIRATION = "expiration";
|
||||||
public static final String KEY_SIGNATURES = "signatures";
|
public static final String KEY_SIGNATURES = "signatures";
|
||||||
public static final String KEY_OPERATIONS = "operations";
|
public static final String KEY_OPERATIONS = "operations";
|
||||||
|
@ -40,19 +42,6 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
private List<BaseOperation> operations;
|
private List<BaseOperation> operations;
|
||||||
private List<Extensions> extensions;
|
private List<Extensions> extensions;
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction constructor.
|
|
||||||
* @param wif: The user's private key in the base58 format.
|
|
||||||
* @param block_data: Block data containing important information used to sign a transaction.
|
|
||||||
* @param operation_list: List of operations to include in the transaction.
|
|
||||||
*/
|
|
||||||
public Transaction(String wif, BlockData block_data, List<BaseOperation> operation_list){
|
|
||||||
this.privateKey = DumpedPrivateKey.fromBase58(null, wif).getKey();
|
|
||||||
this.blockData = block_data;
|
|
||||||
this.operations = operation_list;
|
|
||||||
this.extensions = new ArrayList<Extensions>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction constructor.
|
* Transaction constructor.
|
||||||
* @param privateKey : Instance of a ECKey containing the private key that will be used to sign this transaction.
|
* @param privateKey : Instance of a ECKey containing the private key that will be used to sign this transaction.
|
||||||
|
@ -66,6 +55,20 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
this.extensions = new ArrayList<Extensions>();
|
this.extensions = new ArrayList<Extensions>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction constructor.
|
||||||
|
* @param wif: The user's private key in the base58 format.
|
||||||
|
* @param block_data: Block data containing important information used to sign a transaction.
|
||||||
|
* @param operation_list: List of operations to include in the transaction.
|
||||||
|
*/
|
||||||
|
public Transaction(String wif, BlockData block_data, List<BaseOperation> operation_list){
|
||||||
|
this(DumpedPrivateKey.fromBase58(null, wif).getKey(), block_data, operation_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockData(BlockData blockData){
|
||||||
|
this.blockData = blockData;
|
||||||
|
}
|
||||||
|
|
||||||
public ECKey getPrivateKey(){
|
public ECKey getPrivateKey(){
|
||||||
return this.privateKey;
|
return this.privateKey;
|
||||||
}
|
}
|
||||||
|
@ -87,6 +90,8 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
while(!isGrapheneCanonical) {
|
while(!isGrapheneCanonical) {
|
||||||
byte[] serializedTransaction = this.toBytes();
|
byte[] serializedTransaction = this.toBytes();
|
||||||
|
System.out.println("Signing serialized transaction");
|
||||||
|
System.out.println(Util.bytesToHex(serializedTransaction));
|
||||||
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
||||||
int recId = -1;
|
int recId = -1;
|
||||||
ECKey.ECDSASignature sig = privateKey.sign(hash);
|
ECKey.ECDSASignature sig = privateKey.sign(hash);
|
||||||
|
|
|
@ -58,8 +58,6 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
||||||
public Transaction build() throws MalformedTransactionException {
|
public Transaction build() throws MalformedTransactionException {
|
||||||
if(privateKey == null){
|
if(privateKey == null){
|
||||||
throw new MalformedTransactionException("Missing private key information");
|
throw new MalformedTransactionException("Missing private key information");
|
||||||
}else if(blockData == null){
|
|
||||||
throw new MalformedTransactionException("Missing block data information");
|
|
||||||
}else if(operations == null){
|
}else if(operations == null){
|
||||||
// If the operations list has not been set, we might be able to build one with the
|
// If the operations list has not been set, we might be able to build one with the
|
||||||
// previously provided data. But in order for this to work we have to have all
|
// previously provided data. But in order for this to work we have to have all
|
||||||
|
|
|
@ -45,4 +45,9 @@ public class UserAccount extends GrapheneObject implements ByteSerializable, Jso
|
||||||
public JsonObject toJsonObject() {
|
public JsonObject toJsonObject() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.toJsonString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ public class ApiCall implements JsonSerializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
methodParams.add(array);
|
methodParams.add(array);
|
||||||
|
}else{
|
||||||
|
System.out.println("Skipping parameter of type: "+this.params.get(i).getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paramsArray.add(methodParams);
|
paramsArray.add(methodParams);
|
||||||
|
|
|
@ -2,7 +2,8 @@ package com.luminiasoft.bitshares.ws;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.luminiasoft.bitshares.*;
|
import com.luminiasoft.bitshares.BlockData;
|
||||||
|
import com.luminiasoft.bitshares.RPC;
|
||||||
import com.luminiasoft.bitshares.Transaction;
|
import com.luminiasoft.bitshares.Transaction;
|
||||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||||
import com.luminiasoft.bitshares.models.ApiCall;
|
import com.luminiasoft.bitshares.models.ApiCall;
|
||||||
|
@ -33,17 +34,12 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
private final static int GET_NETWORK_BROADCAST_ID = 2;
|
private final static int GET_NETWORK_BROADCAST_ID = 2;
|
||||||
private final static int GET_NETWORK_DYNAMIC_PARAMETERS = 3;
|
private final static int GET_NETWORK_DYNAMIC_PARAMETERS = 3;
|
||||||
private final static int BROADCAST_TRANSACTION = 4;
|
private final static int BROADCAST_TRANSACTION = 4;
|
||||||
public final static int EXPIRATION_TIME = 30;
|
|
||||||
|
|
||||||
private Transaction transaction;
|
private Transaction transaction;
|
||||||
private long expirationTime;
|
|
||||||
private String headBlockId;
|
|
||||||
private long headBlockNumber;
|
|
||||||
private WitnessResponseListener mListener;
|
private WitnessResponseListener mListener;
|
||||||
|
|
||||||
private int currentId = 1;
|
private int currentId = 1;
|
||||||
private int broadcastApiId = -1;
|
private int broadcastApiId = -1;
|
||||||
private int retries = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of this class. The ids required
|
* Constructor of this class. The ids required
|
||||||
|
@ -62,16 +58,18 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
ArrayList<Serializable> loginParams = new ArrayList<>();
|
ArrayList<Serializable> loginParams = new ArrayList<>();
|
||||||
loginParams.add(null);
|
loginParams.add(null);
|
||||||
loginParams.add(null);
|
loginParams.add(null);
|
||||||
ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, "2.0", currentId);
|
ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, RPC.VERSION, currentId);
|
||||||
websocket.sendText(loginCall.toJsonString());
|
websocket.sendText(loginCall.toJsonString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||||
|
if(frame.isTextFrame())
|
||||||
|
System.out.println("<<< "+frame.getPayloadText());
|
||||||
String response = frame.getPayloadText();
|
String response = frame.getPayloadText();
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class);
|
BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class);
|
||||||
if(baseResponse.error != null && baseResponse.error.message.indexOf("is_canonical") == -1){
|
if(baseResponse.error != null){
|
||||||
mListener.onError(baseResponse.error);
|
mListener.onError(baseResponse.error);
|
||||||
websocket.disconnect();
|
websocket.disconnect();
|
||||||
}else{
|
}else{
|
||||||
|
@ -97,67 +95,45 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
Date date = dateFormat.parse(dynamicProperties.time);
|
Date date = dateFormat.parse(dynamicProperties.time);
|
||||||
|
|
||||||
// Obtained block data
|
// Obtained block data
|
||||||
expirationTime = (date.getTime() / 1000) + EXPIRATION_TIME;
|
long expirationTime = (date.getTime() / 1000) + Transaction.DEFAULT_EXPIRATION_TIME;
|
||||||
headBlockId = dynamicProperties.head_block_id;
|
String headBlockId = dynamicProperties.head_block_id;
|
||||||
headBlockNumber = dynamicProperties.head_block_number;
|
long headBlockNumber = dynamicProperties.head_block_number;
|
||||||
|
transaction.setBlockData(new BlockData(headBlockNumber, headBlockId, expirationTime));
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transaction);
|
||||||
ApiCall call = new ApiCall(broadcastApiId,
|
ApiCall call = new ApiCall(broadcastApiId,
|
||||||
RPC.CALL_BROADCAST_TRANSACTION,
|
RPC.CALL_BROADCAST_TRANSACTION,
|
||||||
transactionList,
|
transactionList,
|
||||||
"2.0",
|
RPC.VERSION,
|
||||||
currentId);
|
currentId);
|
||||||
|
|
||||||
|
System.out.println("Json of transaction");
|
||||||
|
System.out.println(transaction.toJsonString());
|
||||||
|
|
||||||
|
//TODO: Remove this debug code
|
||||||
|
String jsonCall = call.toJsonString();
|
||||||
|
System.out.println("json call");
|
||||||
|
System.out.println(jsonCall);
|
||||||
|
|
||||||
// Finally sending transaction
|
// Finally sending transaction
|
||||||
websocket.sendText(call.toJsonString());
|
// websocket.sendText(call.toJsonString());
|
||||||
}else if(baseResponse.id >= BROADCAST_TRANSACTION){
|
}else if(baseResponse.id >= BROADCAST_TRANSACTION){
|
||||||
Type WitnessResponseType = new TypeToken<WitnessResponse<String>>(){}.getType();
|
Type WitnessResponseType = new TypeToken<WitnessResponse<String>>(){}.getType();
|
||||||
WitnessResponse<WitnessResponse<String>> witnessResponse = gson.fromJson(response, WitnessResponseType);
|
WitnessResponse<WitnessResponse<String>> witnessResponse = gson.fromJson(response, WitnessResponseType);
|
||||||
if(witnessResponse.error == null){
|
mListener.onSuccess(witnessResponse);
|
||||||
mListener.onSuccess(witnessResponse);
|
websocket.disconnect();
|
||||||
websocket.disconnect();
|
|
||||||
}else{
|
|
||||||
if(witnessResponse.error.message.indexOf("is_canonical") != -1 && retries < 10){
|
|
||||||
/*
|
|
||||||
* This is a very ugly hack, but it will do for now.
|
|
||||||
*
|
|
||||||
* The issue is that the witness is complaining about the signature not
|
|
||||||
* being canonical even though the bitcoinj ECKey.ECDSASignature.isCanonical()
|
|
||||||
* method says it is! We'll have to dive deeper into this issue and avoid
|
|
||||||
* this error altogether
|
|
||||||
*
|
|
||||||
* But this MUST BE FIXED! Since this hack will only work for transactions
|
|
||||||
* with ONE transfer operation.
|
|
||||||
*/
|
|
||||||
retries++;
|
|
||||||
List<BaseOperation> operations = this.transaction.getOperations();
|
|
||||||
TransferOperation transfer = (TransferOperation) operations.get(0);
|
|
||||||
transaction = new TransferTransactionBuilder()
|
|
||||||
.setSource(transfer.getFrom())
|
|
||||||
.setDestination(transfer.getTo())
|
|
||||||
.setAmount(transfer.getAmount())
|
|
||||||
.setFee(transfer.getFee())
|
|
||||||
.setBlockData(new BlockData(headBlockNumber, headBlockId, expirationTime + EXPIRATION_TIME))
|
|
||||||
.setPrivateKey(transaction.getPrivateKey())
|
|
||||||
.build();
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
|
||||||
transactionList.add(transaction);
|
|
||||||
ApiCall call = new ApiCall(broadcastApiId,
|
|
||||||
RPC.CALL_BROADCAST_TRANSACTION,
|
|
||||||
transactionList,
|
|
||||||
"2.0",
|
|
||||||
currentId);
|
|
||||||
websocket.sendText(call.toJsonString());
|
|
||||||
}else{
|
|
||||||
mListener.onError(witnessResponse.error);
|
|
||||||
websocket.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||||
|
if(frame.isTextFrame()){
|
||||||
|
System.out.println(">>> "+frame.getPayloadText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
|
public void onError(WebSocket websocket, WebSocketException cause) throws Exception {
|
||||||
mListener.onError(new BaseResponse.Error(cause.getMessage()));
|
mListener.onError(new BaseResponse.Error(cause.getMessage()));
|
||||||
|
|
Loading…
Reference in a new issue