Initial steps to add account_update operation support
This commit is contained in:
parent
e218ba09d6
commit
07dbbca371
10 changed files with 176 additions and 87 deletions
|
@ -1,57 +1,66 @@
|
||||||
package com.luminiasoft.bitshares;
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.google.gson.internal.LinkedTreeMap;
|
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||||
import static com.luminiasoft.bitshares.Test.OPENLEDGER_WITNESS_URL;
|
|
||||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
|
||||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
|
||||||
import com.luminiasoft.bitshares.models.WitnessResponse;
|
|
||||||
import com.luminiasoft.bitshares.test.NaiveSSLContext;
|
|
||||||
import com.luminiasoft.bitshares.ws.GetAccountNameById;
|
|
||||||
import com.luminiasoft.bitshares.ws.GetAccountsByAddress;
|
|
||||||
import com.neovisionaries.ws.client.WebSocket;
|
|
||||||
import com.neovisionaries.ws.client.WebSocketException;
|
|
||||||
import com.neovisionaries.ws.client.WebSocketFactory;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.bitcoinj.core.Base58;
|
import org.bitcoinj.core.Base58;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
||||||
|
import org.spongycastle.math.ec.ECPoint;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.IllegalFormatException;
|
||||||
import javafx.util.Pair;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to encapsulate address-related operations.
|
* Class used to encapsulate address-related operations.
|
||||||
*/
|
*/
|
||||||
public class Address {
|
public class Address {
|
||||||
|
|
||||||
public final static String DEFAULT_PREFIX = "BTS";
|
public final static String BITSHARES_PREFIX = "BTS";
|
||||||
|
|
||||||
private ECKey key;
|
private PublicKey publicKey;
|
||||||
private String prefix;
|
private String prefix;
|
||||||
|
|
||||||
public Address(ECKey key) {
|
public Address(ECKey key) {
|
||||||
this.key = key;
|
this.publicKey = new PublicKey(key);
|
||||||
this.prefix = DEFAULT_PREFIX;
|
this.prefix = BITSHARES_PREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address(ECKey key, String prefix) {
|
public Address(ECKey key, String prefix) {
|
||||||
this.key = key;
|
this.publicKey = new PublicKey(key);
|
||||||
this.prefix = prefix;
|
this.prefix = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Address(String address) throws MalformedAddressException {
|
||||||
|
this.prefix = address.substring(0, 3);
|
||||||
|
byte[] decoded = Base58.decode(address.substring(3, address.length()));
|
||||||
|
byte[] pubKey = Arrays.copyOfRange(decoded, 0, decoded.length - 4);
|
||||||
|
byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length);
|
||||||
|
publicKey = new PublicKey(ECKey.fromPublicOnly(pubKey));
|
||||||
|
byte[] calculatedChecksum = calculateChecksum(pubKey);
|
||||||
|
for(int i = 0; i < calculatedChecksum.length; i++){
|
||||||
|
if(checksum[i] != calculatedChecksum[i]){
|
||||||
|
throw new MalformedAddressException("Checksum error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicKey getPublicKey(){
|
||||||
|
return this.publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
byte[] pubKey = key.getPubKey();
|
byte[] pubKey = this.publicKey.toBytes();
|
||||||
byte[] checksum = new byte[160 / 8];
|
byte[] checksum = calculateChecksum(pubKey);
|
||||||
RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest();
|
byte[] pubKeyChecksummed = Bytes.concat(pubKey, checksum);
|
||||||
ripemd160Digest.update(pubKey, 0, pubKey.length);
|
|
||||||
ripemd160Digest.doFinal(checksum, 0);
|
|
||||||
byte[] pubKeyChecksummed = Bytes.concat(pubKey, Arrays.copyOfRange(checksum, 0, 4));
|
|
||||||
return this.prefix + Base58.encode(pubKeyChecksummed);
|
return this.prefix + Base58.encode(pubKeyChecksummed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] calculateChecksum(byte[] data){
|
||||||
|
byte[] checksum = new byte[160 / 8];
|
||||||
|
RIPEMD160Digest ripemd160Digest = new RIPEMD160Digest();
|
||||||
|
ripemd160Digest.update(data, 0, data.length);
|
||||||
|
ripemd160Digest.doFinal(checksum, 0);
|
||||||
|
return Arrays.copyOfRange(checksum, 0, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
35
src/main/java/com/luminiasoft/bitshares/Authority.java
Normal file
35
src/main/java/com/luminiasoft/bitshares/Authority.java
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||||
|
import com.luminiasoft.bitshares.interfaces.JsonSerializable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by nelson on 11/30/16.
|
||||||
|
*/
|
||||||
|
public class Authority implements JsonSerializable {
|
||||||
|
private long weight_threshold;
|
||||||
|
private HashMap<Address, Long> address_auths;
|
||||||
|
private HashMap<UserAccount, Long> account_auths;
|
||||||
|
private HashMap<PublicKey, Long> key_auths;
|
||||||
|
|
||||||
|
public Authority(HashMap<String, Long> keyAuths) throws MalformedAddressException {
|
||||||
|
key_auths = new HashMap<PublicKey, Long>();
|
||||||
|
for(String key : keyAuths.keySet()){
|
||||||
|
Address address = new Address(key);
|
||||||
|
key_auths.put(address.getPublicKey(), keyAuths.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJsonString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement toJsonObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ public class Main {
|
||||||
// e.printStackTrace();
|
// e.printStackTrace();
|
||||||
// }
|
// }
|
||||||
// test.testCustomSerializer();
|
// test.testCustomSerializer();
|
||||||
test.testUserAccountSerialization();
|
// test.testUserAccountSerialization();
|
||||||
// test.testTransactionSerialization();
|
// test.testTransactionSerialization();
|
||||||
// test.testLoginSerialization();
|
// test.testLoginSerialization();
|
||||||
// test.testNetworkBroadcastSerialization();
|
// test.testNetworkBroadcastSerialization();
|
||||||
|
@ -49,6 +49,7 @@ public class Main {
|
||||||
// test.testTransactionBroadcastSequence();
|
// test.testTransactionBroadcastSequence();
|
||||||
// test.testAccountLookupDeserialization();
|
// test.testAccountLookupDeserialization();
|
||||||
// test.testPrivateKeyManipulations();
|
// test.testPrivateKeyManipulations();
|
||||||
|
test.testPublicKeyManipulations();
|
||||||
// test.testGetAccountByName();
|
// test.testGetAccountByName();
|
||||||
// test.testGetRequiredFees();
|
// test.testGetRequiredFees();
|
||||||
// test.testRandomNumberGeneration();
|
// test.testRandomNumberGeneration();
|
||||||
|
|
20
src/main/java/com/luminiasoft/bitshares/PublicKey.java
Normal file
20
src/main/java/com/luminiasoft/bitshares/PublicKey.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package com.luminiasoft.bitshares;
|
||||||
|
|
||||||
|
import com.luminiasoft.bitshares.interfaces.ByteSerializable;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by nelson on 11/30/16.
|
||||||
|
*/
|
||||||
|
public class PublicKey implements ByteSerializable {
|
||||||
|
private ECKey publicKey;
|
||||||
|
|
||||||
|
public PublicKey(ECKey key) {
|
||||||
|
this.publicKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] toBytes() {
|
||||||
|
return publicKey.getPubKey();
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import com.google.common.primitives.UnsignedLong;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.luminiasoft.bitshares.errors.MalformedAddressException;
|
||||||
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
import com.luminiasoft.bitshares.errors.MalformedTransactionException;
|
||||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||||
import com.luminiasoft.bitshares.models.*;
|
import com.luminiasoft.bitshares.models.*;
|
||||||
|
@ -12,20 +13,14 @@ import com.luminiasoft.bitshares.ws.*;
|
||||||
import com.neovisionaries.ws.client.*;
|
import com.neovisionaries.ws.client.*;
|
||||||
import org.bitcoinj.core.*;
|
import org.bitcoinj.core.*;
|
||||||
import org.spongycastle.crypto.Digest;
|
import org.spongycastle.crypto.Digest;
|
||||||
import org.spongycastle.crypto.digests.RIPEMD128Digest;
|
|
||||||
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
||||||
import org.spongycastle.crypto.digests.SHA512Digest;
|
import org.spongycastle.crypto.digests.SHA512Digest;
|
||||||
import org.spongycastle.crypto.prng.DigestRandomGenerator;
|
import org.spongycastle.crypto.prng.DigestRandomGenerator;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -40,10 +35,10 @@ public class Test {
|
||||||
public static final String OPENLEDGER_WITNESS_URL = "wss://bitshares.openledger.info/ws";
|
public static final String OPENLEDGER_WITNESS_URL = "wss://bitshares.openledger.info/ws";
|
||||||
// public static final String WITNESS_URL = "wss://fr.blockpay.ch:8089";
|
// public static final String WITNESS_URL = "wss://fr.blockpay.ch:8089";
|
||||||
|
|
||||||
private Transaction transaction;
|
private TransferOperation transferOperation;
|
||||||
|
|
||||||
public Transaction getTransaction() {
|
public TransferOperation getTransferOperation() {
|
||||||
return transaction;
|
return transferOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private WitnessResponseListener mListener = new WitnessResponseListener() {
|
private WitnessResponseListener mListener = new WitnessResponseListener() {
|
||||||
|
@ -114,27 +109,27 @@ public class Test {
|
||||||
};
|
};
|
||||||
|
|
||||||
public ECKey.ECDSASignature testSigning() {
|
public ECKey.ECDSASignature testSigning() {
|
||||||
byte[] serializedTransaction = this.transaction.toBytes();
|
byte[] serializedTransaction = this.transferOperation.toBytes();
|
||||||
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
||||||
byte[] bytesDigest = hash.getBytes();
|
byte[] bytesDigest = hash.getBytes();
|
||||||
ECKey sk = transaction.getPrivateKey();
|
ECKey sk = transferOperation.getPrivateKey();
|
||||||
ECKey.ECDSASignature signature = sk.sign(hash);
|
ECKey.ECDSASignature signature = sk.sign(hash);
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String testSigningMessage() {
|
public String testSigningMessage() {
|
||||||
byte[] serializedTransaction = this.transaction.toBytes();
|
byte[] serializedTransaction = this.transferOperation.toBytes();
|
||||||
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
||||||
ECKey sk = transaction.getPrivateKey();
|
ECKey sk = transferOperation.getPrivateKey();
|
||||||
return sk.signMessage(hash.toString());
|
return sk.signMessage(hash.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] signMessage() {
|
public byte[] signMessage() {
|
||||||
byte[] serializedTransaction = this.transaction.toBytes();
|
byte[] serializedTransaction = this.transferOperation.toBytes();
|
||||||
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
Sha256Hash hash = Sha256Hash.wrap(Sha256Hash.hash(serializedTransaction));
|
||||||
System.out.println(">> digest <<");
|
System.out.println(">> digest <<");
|
||||||
System.out.println(Util.bytesToHex(hash.getBytes()));
|
System.out.println(Util.bytesToHex(hash.getBytes()));
|
||||||
ECKey sk = transaction.getPrivateKey();
|
ECKey sk = transferOperation.getPrivateKey();
|
||||||
System.out.println("Private key bytes");
|
System.out.println("Private key bytes");
|
||||||
System.out.println(Util.bytesToHex(sk.getPrivKeyBytes()));
|
System.out.println(Util.bytesToHex(sk.getPrivKeyBytes()));
|
||||||
boolean isCanonical = false;
|
boolean isCanonical = false;
|
||||||
|
@ -189,9 +184,9 @@ public class Test {
|
||||||
AssetAmount amount = new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120"));
|
AssetAmount amount = new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120"));
|
||||||
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf(264174), new Asset("1.3.0"));
|
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf(264174), new Asset("1.3.0"));
|
||||||
operations.add(new Transfer(from, to, amount, fee));
|
operations.add(new Transfer(from, to, amount, fee));
|
||||||
this.transaction = new Transaction(Main.WIF, blockData, operations);
|
this.transferOperation = new TransferOperation(Main.WIF, blockData, operations);
|
||||||
byte[] serializedTransaction = this.transaction.toBytes();
|
byte[] serializedTransaction = this.transferOperation.toBytes();
|
||||||
System.out.println("Serialized transaction");
|
System.out.println("Serialized transferOperation");
|
||||||
System.out.println(Util.bytesToHex(serializedTransaction));
|
System.out.println(Util.bytesToHex(serializedTransaction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +335,7 @@ public class Test {
|
||||||
|
|
||||||
public void testTransactionSerialization() {
|
public void testTransactionSerialization() {
|
||||||
try {
|
try {
|
||||||
Transaction transaction = new TransferTransactionBuilder()
|
TransferOperation transferOperation = new TransferTransactionBuilder()
|
||||||
.setSource(new UserAccount("1.2.138632"))
|
.setSource(new UserAccount("1.2.138632"))
|
||||||
.setDestination(new UserAccount("1.2.129848"))
|
.setDestination(new UserAccount("1.2.129848"))
|
||||||
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
||||||
|
@ -350,9 +345,9 @@ public class Test {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transferOperation);
|
||||||
|
|
||||||
byte[] signature = transaction.getGrapheneSignature();
|
byte[] signature = transferOperation.getGrapheneSignature();
|
||||||
System.out.println(Util.bytesToHex(signature));
|
System.out.println(Util.bytesToHex(signature));
|
||||||
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, "2.0", 1);
|
ApiCall call = new ApiCall(4, "call", "broadcast_transaction", transactionList, "2.0", 1);
|
||||||
String jsonCall = call.toJsonString();
|
String jsonCall = call.toJsonString();
|
||||||
|
@ -425,7 +420,7 @@ public class Test {
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Transaction transaction = new TransferTransactionBuilder()
|
TransferOperation transferOperation = new TransferTransactionBuilder()
|
||||||
.setSource(new UserAccount("1.2.138632"))
|
.setSource(new UserAccount("1.2.138632"))
|
||||||
.setDestination(new UserAccount("1.2.129848"))
|
.setDestination(new UserAccount("1.2.129848"))
|
||||||
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
.setAmount(new AssetAmount(UnsignedLong.valueOf(100), new Asset("1.3.120")))
|
||||||
|
@ -435,9 +430,9 @@ public class Test {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transferOperation);
|
||||||
|
|
||||||
transactionList.add(transaction);
|
transactionList.add(transferOperation);
|
||||||
|
|
||||||
SSLContext context = null;
|
SSLContext context = null;
|
||||||
context = NaiveSSLContext.getInstance("TLS");
|
context = NaiveSSLContext.getInstance("TLS");
|
||||||
|
@ -448,7 +443,7 @@ public class Test {
|
||||||
|
|
||||||
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
WebSocket mWebSocket = factory.createSocket(OPENLEDGER_WITNESS_URL);
|
||||||
|
|
||||||
mWebSocket.addListener(new TransactionBroadcastSequence(transaction, listener));
|
mWebSocket.addListener(new TransactionBroadcastSequence(transferOperation, listener));
|
||||||
mWebSocket.connect();
|
mWebSocket.connect();
|
||||||
|
|
||||||
} catch (MalformedTransactionException e) {
|
} catch (MalformedTransactionException e) {
|
||||||
|
@ -474,14 +469,29 @@ public class Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrivateKeyManipulations() {
|
public void testPrivateKeyManipulations() {
|
||||||
ECKey privateKey = DumpedPrivateKey.fromBase58(null, Main.WIF).getKey();
|
String brainKeyWords = "UNMATE AURIGAL NAVET WAVICLE REWOVE ABBOTCY COWHERB OUTKICK STOPPER JUSSORY BEAMLET WIRY";
|
||||||
|
BrainKey brainKey = new BrainKey(brainKeyWords, 0);
|
||||||
|
|
||||||
|
ECKey privateKey = DumpedPrivateKey.fromBase58(null, brainKey.getWalletImportFormat()).getKey();
|
||||||
System.out.println("private key..............: " + Util.bytesToHex(privateKey.getSecretBytes()));
|
System.out.println("private key..............: " + Util.bytesToHex(privateKey.getSecretBytes()));
|
||||||
System.out.println("public key uncompressed..: " + Util.bytesToHex(privateKey.getPubKey()));
|
System.out.println("public key uncompressed..: " + Util.bytesToHex(privateKey.getPubKey()));
|
||||||
System.out.println("public key compressed....: " + Util.bytesToHex(privateKey.getPubKeyPoint().getEncoded(true)));
|
System.out.println("public key compressed....: " + Util.bytesToHex(privateKey.getPubKeyPoint().getEncoded(true)));
|
||||||
System.out.println("base58...................: " + Base58.encode(privateKey.getPubKeyPoint().getEncoded(true)));
|
System.out.println("base58...................: " + Base58.encode(privateKey.getPubKeyPoint().getEncoded(true)));
|
||||||
System.out.println("base58...................: " + Base58.encode(privateKey.getPubKey()));
|
System.out.println("base58...................: " + Base58.encode(privateKey.getPubKey()));
|
||||||
String brainKeyWords = "PUMPER ISOTOME SERE STAINER CLINGER MOONLIT CHAETA UPBRIM AEDILIC BERTHER NIT SHAP SAID SHADING JUNCOUS CHOUGH";
|
}
|
||||||
BrainKey brainKey = new BrainKey(brainKeyWords, 0);
|
|
||||||
|
public void testPublicKeyManipulations(){
|
||||||
|
// PublicKey publicKey = new PublicKey("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY");
|
||||||
|
// System.out.println("Public key bytes");
|
||||||
|
// System.out.println(Util.bytesToHex(publicKey.toBytes()));
|
||||||
|
Address address = null;
|
||||||
|
try {
|
||||||
|
address = new Address("BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY");
|
||||||
|
System.out.println("Public key");
|
||||||
|
System.out.println(Util.bytesToHex(address.getPublicKey().toBytes()));
|
||||||
|
} catch (MalformedAddressException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetAccountByName() {
|
public void testGetAccountByName() {
|
||||||
|
|
|
@ -11,5 +11,5 @@ public abstract class TransactionBuilder {
|
||||||
protected ECKey privateKey;
|
protected ECKey privateKey;
|
||||||
protected BlockData blockData;
|
protected BlockData blockData;
|
||||||
|
|
||||||
public abstract Transaction build() throws MalformedTransactionException;
|
public abstract TransferOperation build() throws MalformedTransactionException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.TimeZone;
|
||||||
/**
|
/**
|
||||||
* Class used to represent a generic graphene transaction.
|
* Class used to represent a generic graphene transaction.
|
||||||
*/
|
*/
|
||||||
public class Transaction implements ByteSerializable, JsonSerializable {
|
public class TransferOperation extends BaseOperation implements ByteSerializable, JsonSerializable {
|
||||||
private final String TAG = this.getClass().getName();
|
private final String TAG = this.getClass().getName();
|
||||||
|
|
||||||
public static final String KEY_EXPIRATION = "expiration";
|
public static final String KEY_EXPIRATION = "expiration";
|
||||||
|
@ -41,12 +41,13 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
private List<Extension> extensions;
|
private List<Extension> extensions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction constructor.
|
* TransferOperation constructor.
|
||||||
* @param wif: The user's private key in the base58 format.
|
* @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 block_data: Block data containing important information used to sign a transaction.
|
||||||
* @param operation_list: List of operations to include in the transaction.
|
* @param operation_list: List of operations to include in the transaction.
|
||||||
*/
|
*/
|
||||||
public Transaction(String wif, BlockData block_data, List<BaseOperation> operation_list){
|
public TransferOperation(String wif, BlockData block_data, List<BaseOperation> operation_list){
|
||||||
|
super(OperationType.transfer_operation);
|
||||||
this.privateKey = DumpedPrivateKey.fromBase58(null, wif).getKey();
|
this.privateKey = DumpedPrivateKey.fromBase58(null, wif).getKey();
|
||||||
this.blockData = block_data;
|
this.blockData = block_data;
|
||||||
this.operations = operation_list;
|
this.operations = operation_list;
|
||||||
|
@ -54,12 +55,13 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction constructor.
|
* TransferOperation 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.
|
||||||
* @param blockData : Block data containing important information used to sign a transaction.
|
* @param blockData : Block data containing important information used to sign a transaction.
|
||||||
* @param operationList : List of operations to include in the transaction.
|
* @param operationList : List of operations to include in the transaction.
|
||||||
*/
|
*/
|
||||||
public Transaction(ECKey privateKey, BlockData blockData, List<BaseOperation> operationList){
|
public TransferOperation(ECKey privateKey, BlockData blockData, List<BaseOperation> operationList){
|
||||||
|
super(OperationType.transfer_operation);
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
this.blockData = blockData;
|
this.blockData = blockData;
|
||||||
this.operations = operationList;
|
this.operations = operationList;
|
||||||
|
@ -117,6 +119,12 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
}
|
}
|
||||||
return sigData;
|
return sigData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getId() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that creates a serialized byte array with compact information about this transaction
|
* Method that creates a serialized byte array with compact information about this transaction
|
||||||
* that is needed for the creation of a signature.
|
* that is needed for the creation of a signature.
|
||||||
|
@ -157,7 +165,7 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
@Override
|
@Override
|
||||||
public String toJsonString() {
|
public String toJsonString() {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(Transaction.class, new TransactionSerializer());
|
gsonBuilder.registerTypeAdapter(TransferOperation.class, new TransactionSerializer());
|
||||||
return gsonBuilder.create().toJson(this);
|
return gsonBuilder.create().toJson(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,11 +208,11 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TransactionSerializer implements JsonSerializer<Transaction> {
|
class TransactionSerializer implements JsonSerializer<TransferOperation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(Transaction transaction, Type type, JsonSerializationContext jsonSerializationContext) {
|
public JsonElement serialize(TransferOperation transferOperation, Type type, JsonSerializationContext jsonSerializationContext) {
|
||||||
return transaction.toJsonObject();
|
return transferOperation.toJsonObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -54,7 +54,7 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transaction build() throws MalformedTransactionException {
|
public TransferOperation 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){
|
}else if(blockData == null){
|
||||||
|
@ -81,6 +81,6 @@ public class TransferTransactionBuilder extends TransactionBuilder {
|
||||||
}
|
}
|
||||||
operations.add(transferOperation);
|
operations.add(transferOperation);
|
||||||
}
|
}
|
||||||
return new Transaction(privateKey, blockData, operations);
|
return new TransferOperation(privateKey, blockData, operations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.luminiasoft.bitshares.errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by nelson on 12/1/16.
|
||||||
|
*/
|
||||||
|
public class MalformedAddressException extends Exception {
|
||||||
|
public MalformedAddressException(String message){
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +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.BaseOperation;
|
import com.luminiasoft.bitshares.*;
|
||||||
import com.luminiasoft.bitshares.BlockData;
|
import com.luminiasoft.bitshares.TransferOperation;
|
||||||
import com.luminiasoft.bitshares.RPC;
|
|
||||||
import com.luminiasoft.bitshares.Transaction;
|
|
||||||
import com.luminiasoft.bitshares.Transfer;
|
|
||||||
import com.luminiasoft.bitshares.TransferTransactionBuilder;
|
|
||||||
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
import com.luminiasoft.bitshares.interfaces.WitnessResponseListener;
|
||||||
import com.luminiasoft.bitshares.models.ApiCall;
|
import com.luminiasoft.bitshares.models.ApiCall;
|
||||||
import com.luminiasoft.bitshares.models.BaseResponse;
|
import com.luminiasoft.bitshares.models.BaseResponse;
|
||||||
|
@ -28,7 +24,7 @@ import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that will handle the transaction publication procedure.
|
* Class that will handle the transferOperation publication procedure.
|
||||||
*/
|
*/
|
||||||
public class TransactionBroadcastSequence extends WebSocketAdapter {
|
public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
private final String TAG = this.getClass().getName();
|
private final String TAG = this.getClass().getName();
|
||||||
|
@ -39,7 +35,7 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
private final static int BROADCAST_TRANSACTION = 4;
|
private final static int BROADCAST_TRANSACTION = 4;
|
||||||
public final static int EXPIRATION_TIME = 30;
|
public final static int EXPIRATION_TIME = 30;
|
||||||
|
|
||||||
private Transaction transaction;
|
private TransferOperation transferOperation;
|
||||||
private long expirationTime;
|
private long expirationTime;
|
||||||
private String headBlockId;
|
private String headBlockId;
|
||||||
private long headBlockNumber;
|
private long headBlockNumber;
|
||||||
|
@ -51,13 +47,13 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor of this class. The ids required
|
* Constructor of this class. The ids required
|
||||||
* @param transaction: The transaction to be broadcasted.
|
* @param transferOperation: The transferOperation to be broadcasted.
|
||||||
* @param listener: A class implementing the WitnessResponseListener interface. This should
|
* @param listener: A class implementing the WitnessResponseListener interface. This should
|
||||||
* be implemented by the party interested in being notified about the success/failure
|
* be implemented by the party interested in being notified about the success/failure
|
||||||
* of the transaction broadcast operation.
|
* of the transferOperation broadcast operation.
|
||||||
*/
|
*/
|
||||||
public TransactionBroadcastSequence(Transaction transaction, WitnessResponseListener listener){
|
public TransactionBroadcastSequence(TransferOperation transferOperation, WitnessResponseListener listener){
|
||||||
this.transaction = transaction;
|
this.transferOperation = transferOperation;
|
||||||
this.mListener = listener;
|
this.mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,14 +102,14 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
headBlockNumber = dynamicProperties.head_block_number;
|
headBlockNumber = dynamicProperties.head_block_number;
|
||||||
|
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transferOperation);
|
||||||
ApiCall call = new ApiCall(broadcastApiId,
|
ApiCall call = new ApiCall(broadcastApiId,
|
||||||
RPC.CALL_BROADCAST_TRANSACTION,
|
RPC.CALL_BROADCAST_TRANSACTION,
|
||||||
transactionList,
|
transactionList,
|
||||||
"2.0",
|
"2.0",
|
||||||
currentId);
|
currentId);
|
||||||
|
|
||||||
// Finally sending transaction
|
// Finally sending transferOperation
|
||||||
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();
|
||||||
|
@ -135,18 +131,18 @@ public class TransactionBroadcastSequence extends WebSocketAdapter {
|
||||||
* with ONE transfer operation.
|
* with ONE transfer operation.
|
||||||
*/
|
*/
|
||||||
retries++;
|
retries++;
|
||||||
List<BaseOperation> operations = this.transaction.getOperations();
|
List<BaseOperation> operations = this.transferOperation.getOperations();
|
||||||
Transfer transfer = (Transfer) operations.get(0);
|
Transfer transfer = (Transfer) operations.get(0);
|
||||||
transaction = new TransferTransactionBuilder()
|
transferOperation = new TransferTransactionBuilder()
|
||||||
.setSource(transfer.getFrom())
|
.setSource(transfer.getFrom())
|
||||||
.setDestination(transfer.getTo())
|
.setDestination(transfer.getTo())
|
||||||
.setAmount(transfer.getAmount())
|
.setAmount(transfer.getAmount())
|
||||||
.setFee(transfer.getFee())
|
.setFee(transfer.getFee())
|
||||||
.setBlockData(new BlockData(headBlockNumber, headBlockId, expirationTime + EXPIRATION_TIME))
|
.setBlockData(new BlockData(headBlockNumber, headBlockId, expirationTime + EXPIRATION_TIME))
|
||||||
.setPrivateKey(transaction.getPrivateKey())
|
.setPrivateKey(transferOperation.getPrivateKey())
|
||||||
.build();
|
.build();
|
||||||
ArrayList<Serializable> transactionList = new ArrayList<>();
|
ArrayList<Serializable> transactionList = new ArrayList<>();
|
||||||
transactionList.add(transaction);
|
transactionList.add(transferOperation);
|
||||||
ApiCall call = new ApiCall(broadcastApiId,
|
ApiCall call = new ApiCall(broadcastApiId,
|
||||||
RPC.CALL_BROADCAST_TRANSACTION,
|
RPC.CALL_BROADCAST_TRANSACTION,
|
||||||
transactionList,
|
transactionList,
|
||||||
|
|
Loading…
Reference in a new issue