Merge branch 'develop' of https://github.com/Agorise/crystal-wallet-android into develop
This commit is contained in:
commit
8e55afad55
6 changed files with 65 additions and 107 deletions
|
@ -18,11 +18,9 @@ public class InsightApiGenerator {
|
||||||
* Fecth all the transaciton for a giving address
|
* Fecth all the transaciton for a giving address
|
||||||
* @param cryptoCoin the crypto net of the address
|
* @param cryptoCoin the crypto net of the address
|
||||||
* @param address The address String
|
* @param address The address String
|
||||||
* @param request the request api to response
|
|
||||||
* @param subscribe If needs to follow the address (Real time)
|
* @param subscribe If needs to follow the address (Real time)
|
||||||
*/
|
*/
|
||||||
public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address,
|
public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address, boolean subscribe){
|
||||||
ApiRequest request, boolean subscribe){
|
|
||||||
if(!transactionGetters.containsKey(cryptoCoin)){
|
if(!transactionGetters.containsKey(cryptoCoin)){
|
||||||
transactionGetters.put(cryptoCoin,new GetTransactionByAddress(cryptoCoin,CryptoNetManager.getURL(cryptoCoin.getCryptoNet())));
|
transactionGetters.put(cryptoCoin,new GetTransactionByAddress(cryptoCoin,CryptoNetManager.getURL(cryptoCoin.getCryptoNet())));
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ public interface BitcoinAddressDao {
|
||||||
@Query("SELECT MAX(ba.address_index) FROM bitcoin_address ba WHERE ba.account_id = :accountId and ba.is_change = 'true' ")
|
@Query("SELECT MAX(ba.address_index) FROM bitcoin_address ba WHERE ba.account_id = :accountId and ba.is_change = 'true' ")
|
||||||
long getLastChangeAddress(long accountId);
|
long getLastChangeAddress(long accountId);
|
||||||
|
|
||||||
|
@Query("SELECT MAX(ba.address_index) FROM bitcoin_address ba WHERE ba.account_id = :accountId and ba.is_change = 'false' ")
|
||||||
|
long getLastExternalAddress(long accountId);
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
public long[] insertBitcoinAddresses(BitcoinAddress... addresses);
|
public long[] insertBitcoinAddresses(BitcoinAddress... addresses);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package cy.agorise.crystalwallet.manager;
|
package cy.agorise.crystalwallet.manager;
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.bitcoinj.core.Address;
|
import org.bitcoinj.core.Address;
|
||||||
|
@ -26,7 +25,6 @@ import cy.agorise.crystalwallet.apigenerator.InsightApiGenerator;
|
||||||
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi;
|
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Txi;
|
||||||
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin;
|
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vin;
|
||||||
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
|
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
|
||||||
import cy.agorise.crystalwallet.application.CrystalApplication;
|
|
||||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||||
|
@ -37,11 +35,11 @@ import cy.agorise.crystalwallet.models.CryptoCoinBalance;
|
||||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||||
import cy.agorise.crystalwallet.models.GTxIO;
|
import cy.agorise.crystalwallet.requestmanagers.BitcoinSendRequest;
|
||||||
import cy.agorise.crystalwallet.models.GeneralCoinAddress;
|
import cy.agorise.crystalwallet.requestmanagers.CreateBitcoinAccountRequest;
|
||||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
||||||
import cy.agorise.crystalwallet.requestmanagers.GeneralAccountSendRequest;
|
import cy.agorise.crystalwallet.requestmanagers.NextBitcoinAccountAddressRequest;
|
||||||
import cy.agorise.graphenej.Util;
|
import cy.agorise.graphenej.Util;
|
||||||
|
|
||||||
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||||
|
@ -85,9 +83,14 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNewRequest(CryptoNetInfoRequest request) {
|
public void onNewRequest(CryptoNetInfoRequest request) {
|
||||||
if(Arrays.asList(SUPPORTED_COINS).contains(request.getCoin())){
|
//if(Arrays.asList(SUPPORTED_COINS).contains(request.getCoin())){
|
||||||
if(request instanceof GeneralAccountSendRequest){
|
if(request.getCoin().equals(this.cryptoCoin)){
|
||||||
this.send((GeneralAccountSendRequest)request);
|
if(request instanceof BitcoinSendRequest) {
|
||||||
|
this.send((BitcoinSendRequest) request);
|
||||||
|
}else if(request instanceof CreateBitcoinAccountRequest){
|
||||||
|
|
||||||
|
}else if(request instanceof NextBitcoinAccountAddressRequest){
|
||||||
|
this.getNextAddress((NextBitcoinAccountAddressRequest) request);
|
||||||
}else{
|
}else{
|
||||||
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
|
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
|
||||||
}
|
}
|
||||||
|
@ -255,7 +258,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance);
|
db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void send(final GeneralAccountSendRequest request){
|
public void send(final BitcoinSendRequest request){
|
||||||
//TODO check server connection
|
//TODO check server connection
|
||||||
//TODO validate to address
|
//TODO validate to address
|
||||||
|
|
||||||
|
@ -271,19 +274,19 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||||
db.bitcoinTransactionDao();
|
db.bitcoinTransactionDao();
|
||||||
|
|
||||||
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getAccount().getId(),db);
|
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getSourceAccount().getId(),db);
|
||||||
|
|
||||||
if(currentAmount< request.getAmount() + fee){
|
if(currentAmount< request.getAmount() + fee){
|
||||||
request.setStatus(GeneralAccountSendRequest.StatusCode.NO_BALANCE);
|
request.setStatus(BitcoinSendRequest.StatusCode.NO_BALANCE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AccountSeed seed = db.accountSeedDao().findById(request.getAccount().getSeedId());
|
AccountSeed seed = db.accountSeedDao().findById(request.getSourceAccount().getSeedId());
|
||||||
DeterministicKey purposeKey = HDKeyDerivation.deriveChildKey((DeterministicKey) seed.getPrivateKey(),
|
DeterministicKey purposeKey = HDKeyDerivation.deriveChildKey((DeterministicKey) seed.getPrivateKey(),
|
||||||
new ChildNumber(44, true));
|
new ChildNumber(44, true));
|
||||||
DeterministicKey coinKey = HDKeyDerivation.deriveChildKey(purposeKey,
|
DeterministicKey coinKey = HDKeyDerivation.deriveChildKey(purposeKey,
|
||||||
new ChildNumber(cryptoCoin.getCoinNumber(), true));
|
new ChildNumber(cryptoCoin.getCoinNumber(), true));
|
||||||
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinKey,
|
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinKey,
|
||||||
new ChildNumber(request.getAccount().getAccountIndex(), true));
|
new ChildNumber(request.getSourceAccount().getAccountIndex(), true));
|
||||||
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||||
new ChildNumber(0, false));
|
new ChildNumber(0, false));
|
||||||
DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||||
|
@ -309,7 +312,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
//Change address
|
//Change address
|
||||||
long remain = currentAmount - request.getAmount() - fee;
|
long remain = currentAmount - request.getAmount() - fee;
|
||||||
if( remain > 0 ) {
|
if( remain > 0 ) {
|
||||||
long index = db.bitcoinAddressDao().getLastChangeAddress(request.getAccount().getId());
|
long index = db.bitcoinAddressDao().getLastChangeAddress(request.getSourceAccount().getId());
|
||||||
BitcoinAddress btAddress = db.bitcoinAddressDao().getChangeByIndex(index);
|
BitcoinAddress btAddress = db.bitcoinAddressDao().getChangeByIndex(index);
|
||||||
Address changeAddr;
|
Address changeAddr;
|
||||||
if(btAddress != null && db.bitcoinTransactionDao().getGtxIOByAddress(btAddress.getAddress()).size()<=0){
|
if(btAddress != null && db.bitcoinTransactionDao().getGtxIOByAddress(btAddress.getAddress()).size()<=0){
|
||||||
|
@ -323,7 +326,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
}
|
}
|
||||||
btAddress = new BitcoinAddress();
|
btAddress = new BitcoinAddress();
|
||||||
btAddress.setIndex(index);
|
btAddress.setIndex(index);
|
||||||
btAddress.setAccountId(request.getAccount().getId());
|
btAddress.setAccountId(request.getSourceAccount().getId());
|
||||||
btAddress.setChange(true);
|
btAddress.setChange(true);
|
||||||
btAddress.setAddress(HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false)).toAddress(cryptoCoin.getParameters()).toString());
|
btAddress.setAddress(HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false)).toAddress(cryptoCoin.getParameters()).toString());
|
||||||
db.bitcoinAddressDao().insertBitcoinAddresses(btAddress);
|
db.bitcoinAddressDao().insertBitcoinAddresses(btAddress);
|
||||||
|
@ -342,7 +345,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
if(btAddress.isChange()){
|
if(btAddress.isChange()){
|
||||||
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false));
|
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false));
|
||||||
}else{
|
}else{
|
||||||
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), true));
|
addrKey = HDKeyDerivation.deriveChildKey(externalKey, new ChildNumber((int) btAddress.getIndex(), true));
|
||||||
}
|
}
|
||||||
tx.addSignedInput(outPoint, script, addrKey, Transaction.SigHash.ALL, true);
|
tx.addSignedInput(outPoint, script, addrKey, Transaction.SigHash.ALL, true);
|
||||||
}
|
}
|
||||||
|
@ -350,24 +353,51 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
InsightApiGenerator.broadcastTransaction(cryptoCoin,Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
|
InsightApiGenerator.broadcastTransaction(cryptoCoin,Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
|
||||||
@Override
|
@Override
|
||||||
public void success(Object answer, int idPetition) {
|
public void success(Object answer, int idPetition) {
|
||||||
request.setStatus(GeneralAccountSendRequest.StatusCode.SUCCEEDED);
|
request.setStatus(BitcoinSendRequest.StatusCode.SUCCEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fail(int idPetition) {
|
public void fail(int idPetition) {
|
||||||
request.setStatus(GeneralAccountSendRequest.StatusCode.PETITION_FAILED);
|
request.setStatus(BitcoinSendRequest.StatusCode.PETITION_FAILED);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fail(int idPetition) {
|
public void fail(int idPetition) {
|
||||||
request.setStatus(GeneralAccountSendRequest.StatusCode.NO_FEE);
|
request.setStatus(BitcoinSendRequest.StatusCode.NO_FEE);
|
||||||
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getNextAddress(NextBitcoinAccountAddressRequest request){
|
||||||
|
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||||
|
long index = db.bitcoinAddressDao().getLastExternalAddress(request.getAccount().getId());
|
||||||
|
index++;
|
||||||
|
AccountSeed seed = db.accountSeedDao().findById(request.getAccount().getSeedId());
|
||||||
|
DeterministicKey purposeKey = HDKeyDerivation.deriveChildKey((DeterministicKey) seed.getPrivateKey(),
|
||||||
|
new ChildNumber(44, true));
|
||||||
|
DeterministicKey coinKey = HDKeyDerivation.deriveChildKey(purposeKey,
|
||||||
|
new ChildNumber(cryptoCoin.getCoinNumber(), true));
|
||||||
|
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinKey,
|
||||||
|
new ChildNumber(request.getAccount().getAccountIndex(), true));
|
||||||
|
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||||
|
new ChildNumber(0, false));
|
||||||
|
ECKey addrKey = HDKeyDerivation.deriveChildKey(externalKey, new ChildNumber((int) index, true));
|
||||||
|
BitcoinAddress address = new BitcoinAddress();
|
||||||
|
address.setChange(false);
|
||||||
|
address.setAccountId(request.getAccount().getId());
|
||||||
|
address.setIndex(index);
|
||||||
|
String addressString =addrKey.toAddress(this.cryptoCoin.getParameters()).toString();
|
||||||
|
address.setAddress(addressString);
|
||||||
|
db.bitcoinAddressDao().insertBitcoinAddresses(address);
|
||||||
|
InsightApiGenerator.getTransactionFromAddress(this.cryptoCoin,addressString,true);
|
||||||
|
|
||||||
|
request.setAddress(addressString);
|
||||||
|
request.setStatus(NextBitcoinAccountAddressRequest.StatusCode.SUCCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
private List<BitcoinTransactionGTxIO> getUtxos(long accountId, CrystalDatabase db){
|
private List<BitcoinTransactionGTxIO> getUtxos(long accountId, CrystalDatabase db){
|
||||||
List<BitcoinTransactionGTxIO> answer = new ArrayList<>();
|
List<BitcoinTransactionGTxIO> answer = new ArrayList<>();
|
||||||
List<BitcoinTransactionGTxIO> bTGTxI = new ArrayList<>();
|
List<BitcoinTransactionGTxIO> bTGTxI = new ArrayList<>();
|
||||||
|
|
|
@ -21,6 +21,8 @@ public class BitcoinSendRequest extends CryptoNetInfoRequest {
|
||||||
SUCCEEDED,
|
SUCCEEDED,
|
||||||
NO_INTERNET,
|
NO_INTERNET,
|
||||||
NO_SERVER_CONNECTION,
|
NO_SERVER_CONNECTION,
|
||||||
|
NO_BALANCE,
|
||||||
|
NO_FEE,
|
||||||
PETITION_FAILED
|
PETITION_FAILED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
package cy.agorise.crystalwallet.requestmanagers;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
|
||||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
|
||||||
|
|
||||||
public class GeneralAccountSendRequest extends CryptoNetInfoRequest {
|
|
||||||
/**
|
|
||||||
* The status code of this request
|
|
||||||
*/
|
|
||||||
public enum StatusCode{
|
|
||||||
NOT_STARTED,
|
|
||||||
SUCCEEDED,
|
|
||||||
NO_INTERNET,
|
|
||||||
NO_SERVER_CONNECTION,
|
|
||||||
BAD_TO_ADDRESS,
|
|
||||||
NO_FEE,
|
|
||||||
NO_BALANCE,
|
|
||||||
PETITION_FAILED
|
|
||||||
}
|
|
||||||
|
|
||||||
// The app context
|
|
||||||
private Context mContext;
|
|
||||||
//The soruce Account
|
|
||||||
private CryptoNetAccount mAccount;
|
|
||||||
// The destination account address
|
|
||||||
private String mToAccount;
|
|
||||||
// The amount of the transaction
|
|
||||||
private long mAmount;
|
|
||||||
// The memo, can be null
|
|
||||||
private String mMemo;
|
|
||||||
// The state of this request
|
|
||||||
private StatusCode status = StatusCode.NOT_STARTED;
|
|
||||||
|
|
||||||
public GeneralAccountSendRequest(CryptoCoin coin, Context context, CryptoNetAccount account, String toAccount, long amount, String memo) {
|
|
||||||
super(coin);
|
|
||||||
this.mContext = context;
|
|
||||||
this.mAccount = account;
|
|
||||||
this.mToAccount = toAccount;
|
|
||||||
this.mAmount = amount;
|
|
||||||
this.mMemo = memo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeneralAccountSendRequest(CryptoCoin coin, Context context, CryptoNetAccount account, String toAccount, long amount) {
|
|
||||||
this(coin,context,account,toAccount,amount,null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context getContext() {
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CryptoNetAccount getAccount() {
|
|
||||||
return mAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToAccount() {
|
|
||||||
return mToAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getAmount() {
|
|
||||||
return mAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMemo() {
|
|
||||||
return mMemo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validate(){
|
|
||||||
if ((this.status != StatusCode.NOT_STARTED)){
|
|
||||||
this._fireOnCarryOutEvent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(StatusCode code){
|
|
||||||
this.status = code;
|
|
||||||
this._fireOnCarryOutEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StatusCode getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,6 +19,8 @@ public class NextBitcoinAccountAddressRequest extends CryptoNetInfoRequest {
|
||||||
private CryptoCoin cryptoCoin;
|
private CryptoCoin cryptoCoin;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
|
private String address = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The status code of this request
|
* The status code of this request
|
||||||
*/
|
*/
|
||||||
|
@ -62,4 +64,12 @@ public class NextBitcoinAccountAddressRequest extends CryptoNetInfoRequest {
|
||||||
public StatusCode getStatus() {
|
public StatusCode getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue