develop
Javier Varona 2018-11-30 21:55:46 -04:00
commit d04e847bba
7 changed files with 131 additions and 142 deletions

View File

@ -35,14 +35,18 @@ public abstract class GetEstimateFee {
call.enqueue(new Callback<JsonObject>() {
@Override
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
public void onFailure(Call<JsonObject> call, Throwable t) {
listener.fail();
listener.estimateFee(-1);
}
});
}catch(Exception e){

View File

@ -97,8 +97,8 @@ class InsightApiServiceGenerator {
return chain.proceed(request);
}
});
sClientBuilder.readTimeout(5, TimeUnit.MINUTES);
sClientBuilder.connectTimeout(5, TimeUnit.MINUTES);
sClientBuilder.readTimeout(30, TimeUnit.SECONDS);
sClientBuilder.connectTimeout(30, TimeUnit.SECONDS);
OkHttpClient client = sClientBuilder.build();
Retrofit retrofit = sBuilder.client(client).build();
return retrofit.create(serviceClass);

View File

@ -52,8 +52,8 @@ public class CrystalApplication extends Application {
public static final String BITCOIN_SERVER_URLS[] ={
"https://testnet.blockexplorer.com/",
"https://test-insight.bitpay.com",
//"https://testnet.blockexplorer.com/",
//"https://insight.bitpay.com/"
};

View File

@ -28,8 +28,6 @@ import android.text.Editable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
@ -139,9 +137,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
private FloatingActionButton fabSend;
private AlertDialog.Builder builder;
/*
Dialog for loading
*/
/* Dialog for loading */
private CrystalDialog crystalDialog;
public static SendTransactionFragment newInstance(long cryptoNetAccountId) {
@ -168,7 +164,6 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
//AlertDialog.Builder
builder = new AlertDialog.Builder(getActivity(), R.style.dialog_theme_full);
//builder.setTitle("Send");
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.send_transaction, null);
@ -176,11 +171,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
this.cryptoNetAccountId = getArguments().getLong("CRYPTO_NET_ACCOUNT_ID",-1);
final Activity activity = getActivity();
/*
* Add style to the spinner android
* */
/* Add style to the spinner android */
spFrom.setBackground(getContext().getDrawable(R.drawable.square_color));
if (this.cryptoNetAccountId != -1) {
@ -191,36 +182,10 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
List<CryptoNetAccount> cryptoNetAccounts = cryptoNetAccountListViewModel.getCryptoNetAccountList();
CryptoNetAccountAdapter fromSpinnerAdapter = new CryptoNetAccountAdapter(this.getContext(), android.R.layout.simple_spinner_item, cryptoNetAccounts);
/*
* If only one account block the control
* */
//if(cryptoNetAccounts.size()==1){
// spFrom.setEnabled(false);
//}
spFrom.setAdapter(fromSpinnerAdapter);
spFrom.setSelection(0);
setAccountUI();
/*
* Custom material spinner implementation
* */
//spFrom.setItems(cryptoNetAccounts);
//spFrom.setSelectedIndex(0);
//spFrom.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener<CryptoNetAccount>() {
// @Override
// public void onItemSelected(MaterialSpinner view, int position, long id, CryptoNetAccount item) {
// sendTransactionValidator.validate();
// }
//});
//spFrom.setOnNothingSelectedListener(new MaterialSpinner.OnNothingSelectedListener() {
// @Override public void onNothingSelected(MaterialSpinner spinner) {
// }
//});
// etFrom.setText(this.grapheneAccount.getName());
}
loadUserImage();
@ -337,12 +302,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
// Force dialog fragment to use the full width of the screen
Window dialogWindow = getDialog().getWindow();
assert dialogWindow != null;
dialogWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
loadUserImage();
}
@ -511,10 +471,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
if (fromAccountSelected.getCryptoNet() == CryptoNet.BITSHARES) {
/*
* this is only for graphene accounts.
*
**/
/* This is only for graphene accounts. */
GrapheneAccount grapheneAccountSelected = new GrapheneAccount(fromAccountSelected);
grapheneAccountSelected.loadInfo(db.grapheneAccountInfoDao().getByAccountId(fromAccountSelected.getId()));
@ -545,6 +502,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
throwable.printStackTrace();
}
} else {
crystalDialog.dismiss();
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
}
}
@ -577,22 +535,19 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
throwable.printStackTrace();
}
} else {
crystalDialog.dismiss();
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
}
}
});
}
/*
* If exists mode scurity show it and valide events in case of success or fail
* */
/* If exists mode security show it and validate events in case of success or fail */
CrystalSecurityMonitor.getInstance(this.getActivity()).callPasswordRequest(this.getActivity(), new OnResponse() {
@Override
public void onSuccess() {
/*
* Show loading dialog
* */
/* Show loading dialog */
crystalDialog = new CrystalDialog((Activity) getContext());
crystalDialog.setText("Sending");
crystalDialog.progress();
@ -623,10 +578,6 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
// Camera Permissions
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static String[] PERMISSIONS_CAMERA = {
Manifest.permission.CAMERA
};
@Override
public void onValidationSucceeded(final ValidationField field) {

View File

@ -241,11 +241,12 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
ccTransaction.setAccountId(address.getAccountId());
ccTransaction.setFrom(addr);
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()));
}
//}
}
if (ccTransaction.getFrom() == null || ccTransaction.getFrom().isEmpty()) {
@ -280,9 +281,9 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
ccTransaction.setTo(addr);
}
if (ccTransaction.getAccountId() == address.getAccountId()) {
//if (ccTransaction.getAccountId() == address.getAccountId()) {
amount += (long) (vout.value * Math.pow(10, cryptoCoin.getPrecision()));
}
//}
} else {
//TOOD multiple send address
if (ccTransaction.getTo() == null || ccTransaction.getTo().isEmpty()) {
@ -374,39 +375,52 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
//TODO check server connection
//TODO validate to address
System.out.println("GeneralAccount Manager Send request, asking fee");
InsightApiGenerator.getEstimateFee(this.cryptoCoin,new ApiRequest(1, new ApiRequestListener() {
@Override
public void success(Object answer, int idPetition) {
Transaction tx = new Transaction(cryptoCoin.getParameters());
long currentAmount = 0;
long fee = -1;
long feeRate = (long)(((double)answer) * Math.pow(10,cryptoCoin.getPrecision()));
fee = 226 * feeRate;
System.out.println("GeneralAccount Manager Send request, fee " + answer.toString());
try {
Transaction tx = new Transaction(cryptoCoin.getParameters());
long currentAmount = 0;
long fee = -1;
long feeRate = (long) (((double) answer) * Math.pow(10, cryptoCoin.getPrecision()));
fee = 226 * feeRate;
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
db.bitcoinTransactionDao();
System.out.println("GeneralAccount Manager Send request getting utxos" );
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){
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));
if (currentAmount < request.getAmount() + fee) {
System.out.println("GeneralAccount Manager Send request no balance" );
request.setStatus(BitcoinSendRequest.StatusCode.NO_BALANCE);
return;
}
//String to an address
Address toAddr = Address.fromBase58(cryptoCoin.getParameters(), request.getToAccount());
tx.addOutput(Coin.valueOf(request.getAmount()), toAddr);
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
Address toAddr = Address.fromBase58(cryptoCoin.getParameters(), request.getToAccount());
tx.addOutput(Coin.valueOf(request.getAmount()), toAddr);
/*if(request.getMemo()!= null && !request.getMemo().isEmpty()){
String memo = request.getMemo();
@ -421,62 +435,74 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
tx.addOutput(Coin.valueOf(0),memoScript);
}*/
//Change address
long remain = currentAmount - request.getAmount() - fee;
if( remain > 0 ) {
long index = db.bitcoinAddressDao().getLastChangeAddress(request.getSourceAccount().getId());
BitcoinAddress btAddress = db.bitcoinAddressDao().getChangeByIndex(index);
Address changeAddr;
if(btAddress != null && db.bitcoinTransactionDao().getGtxIOByAddress(btAddress.getAddress()).size()<=0){
//Change address
long remain = currentAmount - request.getAmount() - fee;
if (remain > 0) {
long index = db.bitcoinAddressDao().getLastChangeAddress(request.getSourceAccount().getId());
BitcoinAddress btAddress = db.bitcoinAddressDao().getChangeByIndex(index);
Address changeAddr;
if (btAddress != null && db.bitcoinTransactionDao().getGtxIOByAddress(btAddress.getAddress()).size() <= 0) {
changeAddr = Address.fromBase58(cryptoCoin.getParameters(), btAddress.getAddress());
}else{
if(btAddress == null){
index = 0;
}else{
index++;
} else {
if (btAddress == null) {
index = 0;
} else {
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();
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);
}
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
public void fail(int idPetition) {
System.out.println("GeneralAccount Manager Send request fee fail" );
request.setStatus(BitcoinSendRequest.StatusCode.NO_FEE);
}

View File

@ -89,7 +89,7 @@ public class BitcoinSendRequest extends CryptoNetInfoRequest {
public void setStatus(StatusCode code){
this.status = code;
this._fireOnCarryOutEvent();
this.validate();
}
public StatusCode getStatus() {

View File

@ -18,6 +18,13 @@
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5"/>
<android.support.constraint.Guideline
android:id="@+id/cameraVerticalGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.65"/>
<View
android:id="@+id/topView"
android:layout_width="match_parent"
@ -217,7 +224,7 @@
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintTop_toBottomOf="@+id/tvScan"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/centeredVerticalGuideline"/>
app:layout_constraintEnd_toStartOf="@id/cameraVerticalGuideline"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabCloseCamera"
@ -225,7 +232,7 @@
android:layout_height="wrap_content"
app:backgroundTint="@color/send_strong_orange"
app:fabCustomSize="32dp"
app:layout_constraintStart_toEndOf="@id/centeredVerticalGuideline"
app:layout_constraintStart_toEndOf="@id/cameraVerticalGuideline"
app:layout_constraintTop_toBottomOf="@+id/tvScan"
app:srcCompat="@drawable/ok" />
@ -247,7 +254,8 @@
android:layout_marginEnd="0dp"
android:background="@drawable/send_transaction_send_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/ivCamera" />
app:layout_constraintTop_toTopOf="@id/viewCamera"
app:layout_constraintBottom_toBottomOf="@id/viewCamera"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/btnSend"