Fix send bad request
Change Send manager to send only the required amount from gtxio added error capture for estimatefee
This commit is contained in:
parent
618e71a6ac
commit
08df53730b
6 changed files with 115 additions and 83 deletions
|
@ -35,14 +35,18 @@ public abstract class GetEstimateFee {
|
||||||
call.enqueue(new Callback<JsonObject>() {
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
listener.estimateFee((double) (response.body().get("2").getAsDouble()));
|
try {
|
||||||
|
listener.estimateFee((double) (response.body().get("2").getAsDouble()));
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
listener.fail();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
listener.fail();
|
listener.fail();
|
||||||
listener.estimateFee(-1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
|
|
@ -97,8 +97,8 @@ class InsightApiServiceGenerator {
|
||||||
return chain.proceed(request);
|
return chain.proceed(request);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sClientBuilder.readTimeout(5, TimeUnit.MINUTES);
|
sClientBuilder.readTimeout(30, TimeUnit.SECONDS);
|
||||||
sClientBuilder.connectTimeout(5, TimeUnit.MINUTES);
|
sClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
|
||||||
OkHttpClient client = sClientBuilder.build();
|
OkHttpClient client = sClientBuilder.build();
|
||||||
Retrofit retrofit = sBuilder.client(client).build();
|
Retrofit retrofit = sBuilder.client(client).build();
|
||||||
return retrofit.create(serviceClass);
|
return retrofit.create(serviceClass);
|
||||||
|
|
|
@ -52,8 +52,8 @@ public class CrystalApplication extends Application {
|
||||||
|
|
||||||
|
|
||||||
public static final String BITCOIN_SERVER_URLS[] ={
|
public static final String BITCOIN_SERVER_URLS[] ={
|
||||||
|
"https://testnet.blockexplorer.com/",
|
||||||
"https://test-insight.bitpay.com",
|
"https://test-insight.bitpay.com",
|
||||||
//"https://testnet.blockexplorer.com/",
|
|
||||||
//"https://insight.bitpay.com/"
|
//"https://insight.bitpay.com/"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -545,6 +545,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
||||||
throwable.printStackTrace();
|
throwable.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
crystalDialog.dismiss();
|
||||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -577,6 +578,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
||||||
throwable.printStackTrace();
|
throwable.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
crystalDialog.dismiss();
|
||||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,11 +241,12 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
ccTransaction.setAccountId(address.getAccountId());
|
ccTransaction.setAccountId(address.getAccountId());
|
||||||
ccTransaction.setFrom(addr);
|
ccTransaction.setFrom(addr);
|
||||||
ccTransaction.setInput(false);
|
ccTransaction.setInput(false);
|
||||||
|
amount -= (long) (txi.fee * Math.pow(10, cryptoCoin.getPrecision()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccTransaction.getAccountId() == address.getAccountId()) {
|
//if (ccTransaction.getAccountId() == address.getAccountId()) {
|
||||||
amount -= (long) (vin.value * Math.pow(10, cryptoCoin.getPrecision()));
|
amount -= (long) (vin.value * Math.pow(10, cryptoCoin.getPrecision()));
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccTransaction.getFrom() == null || ccTransaction.getFrom().isEmpty()) {
|
if (ccTransaction.getFrom() == null || ccTransaction.getFrom().isEmpty()) {
|
||||||
|
@ -280,9 +281,9 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
ccTransaction.setTo(addr);
|
ccTransaction.setTo(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ccTransaction.getAccountId() == address.getAccountId()) {
|
//if (ccTransaction.getAccountId() == address.getAccountId()) {
|
||||||
amount += (long) (vout.value * Math.pow(10, cryptoCoin.getPrecision()));
|
amount += (long) (vout.value * Math.pow(10, cryptoCoin.getPrecision()));
|
||||||
}
|
//}
|
||||||
} else {
|
} else {
|
||||||
//TOOD multiple send address
|
//TOOD multiple send address
|
||||||
if (ccTransaction.getTo() == null || ccTransaction.getTo().isEmpty()) {
|
if (ccTransaction.getTo() == null || ccTransaction.getTo().isEmpty()) {
|
||||||
|
@ -374,39 +375,52 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
//TODO check server connection
|
//TODO check server connection
|
||||||
//TODO validate to address
|
//TODO validate to address
|
||||||
|
|
||||||
|
System.out.println("GeneralAccount Manager Send request, asking fee");
|
||||||
InsightApiGenerator.getEstimateFee(this.cryptoCoin,new ApiRequest(1, new ApiRequestListener() {
|
InsightApiGenerator.getEstimateFee(this.cryptoCoin,new ApiRequest(1, new ApiRequestListener() {
|
||||||
@Override
|
@Override
|
||||||
public void success(Object answer, int idPetition) {
|
public void success(Object answer, int idPetition) {
|
||||||
Transaction tx = new Transaction(cryptoCoin.getParameters());
|
System.out.println("GeneralAccount Manager Send request, fee " + answer.toString());
|
||||||
long currentAmount = 0;
|
try {
|
||||||
long fee = -1;
|
Transaction tx = new Transaction(cryptoCoin.getParameters());
|
||||||
long feeRate = (long)(((double)answer) * Math.pow(10,cryptoCoin.getPrecision()));
|
long currentAmount = 0;
|
||||||
fee = 226 * feeRate;
|
long fee = -1;
|
||||||
|
long feeRate = (long) (((double) answer) * Math.pow(10, cryptoCoin.getPrecision()));
|
||||||
|
fee = 226 * feeRate;
|
||||||
|
|
||||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
System.out.println("GeneralAccount Manager Send request getting utxos" );
|
||||||
db.bitcoinTransactionDao();
|
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||||
|
db.bitcoinTransactionDao();
|
||||||
|
|
||||||
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getSourceAccount().getId(),db);
|
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getSourceAccount().getId(), db);
|
||||||
|
System.out.println("GeneralAccount Manager Send request utxos found " + utxos.size() );
|
||||||
|
for(BitcoinTransactionGTxIO utxo : utxos){
|
||||||
|
currentAmount += utxo.getAmount();
|
||||||
|
if(currentAmount >= request.getAmount() + fee) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(currentAmount< request.getAmount() + fee){
|
if (currentAmount < request.getAmount() + fee) {
|
||||||
request.setStatus(BitcoinSendRequest.StatusCode.NO_BALANCE);
|
System.out.println("GeneralAccount Manager Send request no balance" );
|
||||||
return;
|
request.setStatus(BitcoinSendRequest.StatusCode.NO_BALANCE);
|
||||||
}
|
return;
|
||||||
AccountSeed seed = db.accountSeedDao().findById(request.getSourceAccount().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.getSourceAccount().getAccountIndex(), true));
|
|
||||||
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
|
||||||
new ChildNumber(0, false));
|
|
||||||
DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
|
||||||
new ChildNumber(1, false));
|
|
||||||
|
|
||||||
//String to an address
|
AccountSeed seed = db.accountSeedDao().findById(request.getSourceAccount().getSeedId());
|
||||||
Address toAddr = Address.fromBase58(cryptoCoin.getParameters(), request.getToAccount());
|
DeterministicKey purposeKey = HDKeyDerivation.deriveChildKey((DeterministicKey) seed.getPrivateKey(),
|
||||||
tx.addOutput(Coin.valueOf(request.getAmount()), toAddr);
|
new ChildNumber(44, true));
|
||||||
|
DeterministicKey coinKey = HDKeyDerivation.deriveChildKey(purposeKey,
|
||||||
|
new ChildNumber(cryptoCoin.getCoinNumber(), true));
|
||||||
|
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinKey,
|
||||||
|
new ChildNumber(request.getSourceAccount().getAccountIndex(), true));
|
||||||
|
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||||
|
new ChildNumber(0, false));
|
||||||
|
DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||||
|
new ChildNumber(1, false));
|
||||||
|
|
||||||
|
//String to an address
|
||||||
|
Address toAddr = Address.fromBase58(cryptoCoin.getParameters(), request.getToAccount());
|
||||||
|
tx.addOutput(Coin.valueOf(request.getAmount()), toAddr);
|
||||||
|
|
||||||
/*if(request.getMemo()!= null && !request.getMemo().isEmpty()){
|
/*if(request.getMemo()!= null && !request.getMemo().isEmpty()){
|
||||||
String memo = request.getMemo();
|
String memo = request.getMemo();
|
||||||
|
@ -421,62 +435,74 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
||||||
tx.addOutput(Coin.valueOf(0),memoScript);
|
tx.addOutput(Coin.valueOf(0),memoScript);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//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.getSourceAccount().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) {
|
||||||
changeAddr = Address.fromBase58(cryptoCoin.getParameters(), btAddress.getAddress());
|
changeAddr = Address.fromBase58(cryptoCoin.getParameters(), btAddress.getAddress());
|
||||||
|
|
||||||
}else{
|
} else {
|
||||||
if(btAddress == null){
|
if (btAddress == null) {
|
||||||
index = 0;
|
index = 0;
|
||||||
}else{
|
} else {
|
||||||
index++;
|
index++;
|
||||||
|
}
|
||||||
|
btAddress = new BitcoinAddress();
|
||||||
|
btAddress.setIndex(index);
|
||||||
|
btAddress.setAccountId(request.getSourceAccount().getId());
|
||||||
|
btAddress.setChange(true);
|
||||||
|
btAddress.setAddress(HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false)).toAddress(cryptoCoin.getParameters()).toString());
|
||||||
|
db.bitcoinAddressDao().insertBitcoinAddresses(btAddress);
|
||||||
|
changeAddr = Address.fromBase58(cryptoCoin.getParameters(), btAddress.getAddress());
|
||||||
}
|
}
|
||||||
btAddress = new BitcoinAddress();
|
tx.addOutput(Coin.valueOf(remain), changeAddr);
|
||||||
btAddress.setIndex(index);
|
|
||||||
btAddress.setAccountId(request.getSourceAccount().getId());
|
|
||||||
btAddress.setChange(true);
|
|
||||||
btAddress.setAddress(HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false)).toAddress(cryptoCoin.getParameters()).toString());
|
|
||||||
db.bitcoinAddressDao().insertBitcoinAddresses(btAddress);
|
|
||||||
changeAddr = Address.fromBase58(cryptoCoin.getParameters(), btAddress.getAddress());
|
|
||||||
}
|
}
|
||||||
tx.addOutput(Coin.valueOf(remain), changeAddr);
|
|
||||||
|
for (BitcoinTransactionGTxIO utxo : utxos) {
|
||||||
|
Sha256Hash txHash = Sha256Hash.wrap(utxo.getOriginalTxId());
|
||||||
|
Script script = new Script(Util.hexToBytes(utxo.getScriptHex()));
|
||||||
|
TransactionOutPoint outPoint = new TransactionOutPoint(cryptoCoin.getParameters(), utxo.getIndex(), txHash);
|
||||||
|
BitcoinAddress btAddress = db.bitcoinAddressDao().getdadress(utxo.getAddress());
|
||||||
|
ECKey addrKey;
|
||||||
|
|
||||||
|
if (btAddress.isChange()) {
|
||||||
|
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false));
|
||||||
|
} else {
|
||||||
|
addrKey = HDKeyDerivation.deriveChildKey(externalKey, new ChildNumber((int) btAddress.getIndex(), true));
|
||||||
|
}
|
||||||
|
tx.addSignedInput(outPoint, script, addrKey, Transaction.SigHash.ALL, true);
|
||||||
|
currentAmount -= utxo.getAmount();
|
||||||
|
if(currentAmount<= 0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("GeneralAccount Manager Send request rawtx " +Util.bytesToHex(tx.bitcoinSerialize()) );
|
||||||
|
InsightApiGenerator.broadcastTransaction(cryptoCoin, Util.bytesToHex(tx.bitcoinSerialize()), new ApiRequest(1, new ApiRequestListener() {
|
||||||
|
@Override
|
||||||
|
public void success(Object answer, int idPetition) {
|
||||||
|
System.out.println("GeneralAccount MAnager succed send");
|
||||||
|
request.setStatus(BitcoinSendRequest.StatusCode.SUCCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fail(int idPetition) {
|
||||||
|
System.out.println("GeneralAccount MAnager succed fail");
|
||||||
|
request.setStatus(BitcoinSendRequest.StatusCode.PETITION_FAILED);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}catch(Exception e){
|
||||||
|
System.out.println("GeneralAccount Manager Send request error ");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(BitcoinTransactionGTxIO utxo: utxos) {
|
|
||||||
Sha256Hash txHash = Sha256Hash.wrap(utxo.getOriginalTxId());
|
|
||||||
Script script = new Script(Util.hexToBytes(utxo.getScriptHex()));
|
|
||||||
TransactionOutPoint outPoint = new TransactionOutPoint(cryptoCoin.getParameters(), utxo.getIndex(), txHash);
|
|
||||||
BitcoinAddress btAddress = db.bitcoinAddressDao().getdadress(utxo.getAddress());
|
|
||||||
ECKey addrKey;
|
|
||||||
|
|
||||||
if(btAddress.isChange()){
|
|
||||||
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false));
|
|
||||||
}else{
|
|
||||||
addrKey = HDKeyDerivation.deriveChildKey(externalKey, new ChildNumber((int) btAddress.getIndex(), true));
|
|
||||||
}
|
|
||||||
tx.addSignedInput(outPoint, script, addrKey, Transaction.SigHash.ALL, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
InsightApiGenerator.broadcastTransaction(cryptoCoin,Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
|
|
||||||
@Override
|
|
||||||
public void success(Object answer, int idPetition) {
|
|
||||||
request.setStatus(BitcoinSendRequest.StatusCode.SUCCEEDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fail(int idPetition) {
|
|
||||||
request.setStatus(BitcoinSendRequest.StatusCode.PETITION_FAILED);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fail(int idPetition) {
|
public void fail(int idPetition) {
|
||||||
|
System.out.println("GeneralAccount Manager Send request fee fail" );
|
||||||
request.setStatus(BitcoinSendRequest.StatusCode.NO_FEE);
|
request.setStatus(BitcoinSendRequest.StatusCode.NO_FEE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class BitcoinSendRequest extends CryptoNetInfoRequest {
|
||||||
|
|
||||||
public void setStatus(StatusCode code){
|
public void setStatus(StatusCode code){
|
||||||
this.status = code;
|
this.status = code;
|
||||||
this._fireOnCarryOutEvent();
|
this.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StatusCode getStatus() {
|
public StatusCode getStatus() {
|
||||||
|
|
Loading…
Reference in a new issue