Merge branch 'develop' of https://github.com/Agorise/crystal-wallet-android into develop
# Conflicts: # app/src/main/java/cy/agorise/crystalwallet/activities/ImportSeedActivity.java
This commit is contained in:
commit
c216dfa209
15 changed files with 304 additions and 211 deletions
|
@ -259,52 +259,7 @@ class CreateSeedActivity : CustomActivity() {
|
|||
* */
|
||||
if (result) {
|
||||
|
||||
/*
|
||||
* Show the dialog for connection with the server
|
||||
* */
|
||||
val creatingAccountMaterialDialog = CrystalDialog(globalActivity)
|
||||
creatingAccountMaterialDialog.setText(globalActivity.resources.getString(R.string.window_create_seed_Server_validation))
|
||||
creatingAccountMaterialDialog.progress()
|
||||
creatingAccountMaterialDialog.show()
|
||||
|
||||
/*
|
||||
* Validate the account does not exists
|
||||
* */
|
||||
val request = ValidateExistBitsharesAccountRequest(tietAccountName?.text.toString())
|
||||
request.setListener {
|
||||
|
||||
/*
|
||||
* Dismiss the dialog of loading
|
||||
* */
|
||||
creatingAccountMaterialDialog.dismiss()
|
||||
|
||||
if (request.accountExists) {
|
||||
|
||||
/*
|
||||
* The account exists and is not valid
|
||||
* */
|
||||
tietAccountName.fieldValidatorModel.setInvalid()
|
||||
tietAccountName.fieldValidatorModel.message = tietAccountName.resources.getString(R.string.account_name_already_exist)
|
||||
|
||||
/*
|
||||
* Disaible button create
|
||||
* */
|
||||
disableCreate()
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Passed all validations
|
||||
* */
|
||||
tietAccountName.fieldValidatorModel.setValid()
|
||||
|
||||
/*
|
||||
* Enable button create
|
||||
* */
|
||||
enableCreate()
|
||||
}
|
||||
}
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request)
|
||||
|
||||
} else {
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package cy.agorise.crystalwallet.activities;
|
|||
import android.app.Activity;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
|
@ -12,7 +11,6 @@ import android.view.View;
|
|||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
|
@ -23,7 +21,6 @@ import butterknife.ButterKnife;
|
|||
import butterknife.OnClick;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.CrystalLoading;
|
||||
import cy.agorise.crystalwallet.dialogs.material.DialogMaterial;
|
||||
import cy.agorise.crystalwallet.dialogs.material.NegativeResponse;
|
||||
|
@ -32,7 +29,6 @@ import cy.agorise.crystalwallet.dialogs.material.QuestionDialog;
|
|||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.ImportSeedValidator;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener;
|
||||
|
@ -78,6 +74,11 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
|
||||
final Activity activity = this;
|
||||
|
||||
/*
|
||||
* Flag to check correct PIN equality
|
||||
* */
|
||||
private boolean pinsOK = false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -128,20 +129,20 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
validatePINS();
|
||||
|
||||
/*
|
||||
* If all is ready to continue enable the button, contrarie case disable it
|
||||
* */
|
||||
if(allFieldsAreFill()){
|
||||
if(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
validatePINS();
|
||||
}
|
||||
});
|
||||
etPinConfirmation.addTextChangedListener(new TextWatcher() {
|
||||
|
@ -158,20 +159,20 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
validatePINS();
|
||||
|
||||
/*
|
||||
* If all is ready to continue enable the button, contrarie case disable it
|
||||
* */
|
||||
if(allFieldsAreFill()){
|
||||
if(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
validatePINS();
|
||||
}
|
||||
});
|
||||
etSeedWords.addTextChangedListener(new TextWatcher() {
|
||||
|
@ -188,10 +189,15 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
validatePINS();
|
||||
|
||||
/*
|
||||
* If all is ready to continue enable the button, contrarie case disable it
|
||||
* */
|
||||
if(allFieldsAreFill()){
|
||||
if(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
|
@ -201,7 +207,7 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
/*
|
||||
* Hide error field
|
||||
* */
|
||||
txtErrorAccount.setVisibility(View.INVISIBLE);
|
||||
clearErrors();
|
||||
}
|
||||
});
|
||||
/*
|
||||
|
@ -219,10 +225,15 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
//
|
||||
// Validate that PINs are equals
|
||||
//
|
||||
validatePINS();
|
||||
|
||||
//
|
||||
// If all is ready to continue enable the button, contrarie case disable it
|
||||
//
|
||||
if(allFieldsAreFill()){
|
||||
if(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
|
@ -237,6 +248,13 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
importSeedValidator.setListener(this);
|
||||
}
|
||||
|
||||
|
||||
private void clearErrors(){
|
||||
txtErrorPIN.setVisibility(View.INVISIBLE);
|
||||
txtErrorAccount.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
|
@ -246,30 +264,35 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
final String confirmoPIN = etPinConfirmation.getText().toString().trim();
|
||||
if(!pin.isEmpty() && !confirmoPIN.isEmpty()){
|
||||
if(pin.compareTo(confirmoPIN)!=0){
|
||||
pinsOK = false;
|
||||
txtErrorPIN.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else{
|
||||
txtErrorPIN.setVisibility(View.INVISIBLE);
|
||||
pinsOK = true;
|
||||
clearErrors();
|
||||
}
|
||||
}
|
||||
else{
|
||||
txtErrorPIN.setVisibility(View.INVISIBLE);
|
||||
pinsOK = false;
|
||||
clearErrors();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Method to validate if all the fields are fill
|
||||
* Method to validate if all the fields are fill and correctly
|
||||
* */
|
||||
private boolean allFieldsAreFill(){
|
||||
private boolean allFieldsAreOK(){
|
||||
|
||||
boolean complete = false;
|
||||
if( etPin.getText().toString().trim().compareTo("")!=0 &&
|
||||
etPinConfirmation.getText().toString().trim().compareTo("")!=0 &&
|
||||
etSeedWords.getText().toString().trim().compareTo("")!=0 /*&&
|
||||
etAccountName.getText().toString().trim().compareTo("")!=0*/){
|
||||
if(pinsOK){
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
return complete;
|
||||
}
|
||||
|
||||
|
@ -327,6 +350,11 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
final CrystalLoading crystalLoading = new CrystalLoading(activity);
|
||||
crystalLoading.show();
|
||||
|
||||
/*
|
||||
* Final service connection
|
||||
* */
|
||||
finalStep(crystalLoading);
|
||||
|
||||
/*
|
||||
* Validate mnemonic with the server
|
||||
* */
|
||||
|
@ -334,13 +362,10 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if(request.getStatus().equals(ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED)){
|
||||
if(request.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED)){
|
||||
|
||||
//Correct
|
||||
|
||||
/*
|
||||
* Final service connection
|
||||
* */
|
||||
finalStep(crystalLoading);
|
||||
|
||||
}
|
||||
|
@ -380,27 +405,58 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
* */
|
||||
crystalLoading.dismiss();
|
||||
|
||||
if (!validatorRequest.getStatus().equals(ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED)) {
|
||||
String errorText = "An error ocurred attempting to import the account";
|
||||
if (!validatorRequest.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED)) {
|
||||
|
||||
switch (validatorRequest.getStatus()){
|
||||
case PETITION_FAILED:
|
||||
case NO_INTERNET:
|
||||
case NO_SERVER_CONNECTION:
|
||||
errorText = "There was an error with the connection. Try again later";
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.NO_SERVER_CONNECTION));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case ACCOUNT_DOESNT_EXIST:
|
||||
errorText = "The account doesn't exists";
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.ACCOUNT_DOESNT_EXIST));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BAD_SEED:
|
||||
errorText = "The seed is not valid";
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.BAD_SEED));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case NO_ACCOUNT_DATA:
|
||||
errorText = "The account doesn't have any data";
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.NO_ACCOUNT_DATA));
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.ERROR_UNRECOGNIZABLE));
|
||||
|
||||
}
|
||||
|
||||
Toast.makeText(thisActivity.getApplicationContext(),errorText,Toast.LENGTH_LONG).show();
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
//Toast.makeText(thisActivity.getApplicationContext(),errorText,Toast.LENGTH_LONG).show();
|
||||
|
||||
} else {
|
||||
Intent intent = new Intent(thisActivity, BoardActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
|
|
|
@ -36,6 +36,19 @@ public class PatternRequestActivity extends AppCompatActivity {
|
|||
@BindView(R.id.tvPatternText)
|
||||
TextView tvPatternText;
|
||||
|
||||
@BindView(R.id.txtBadtry)
|
||||
TextView txtBadtry;
|
||||
|
||||
/*
|
||||
* Contains the bad tries
|
||||
* */
|
||||
private int tries = 0;
|
||||
|
||||
/*
|
||||
* Seconds counter
|
||||
* */
|
||||
private int seconds = 15;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -111,10 +124,69 @@ public class PatternRequestActivity extends AppCompatActivity {
|
|||
|
||||
private void incorrect(){
|
||||
|
||||
/*
|
||||
* One more bad try
|
||||
* */
|
||||
++tries;
|
||||
|
||||
final Activity activity = this;
|
||||
|
||||
/*
|
||||
* User can not go more up to 5 bad tries
|
||||
* */
|
||||
if(tries==4) {
|
||||
tries = 0;
|
||||
|
||||
patternLockView.setEnabled(false);
|
||||
txtBadtry.setVisibility(View.VISIBLE);
|
||||
txtBadtry.setText(txtBadtry.getText().toString().replace("%%",String.valueOf(seconds)));
|
||||
|
||||
final Timer t = new Timer();
|
||||
//Set the schedule function and rate
|
||||
t.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
--seconds;
|
||||
|
||||
if(seconds==0){
|
||||
t.cancel();
|
||||
|
||||
seconds = 15;
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
patternLockView.setEnabled(true);
|
||||
txtBadtry.setVisibility(View.INVISIBLE);
|
||||
patternLockView.clearPattern();
|
||||
patternLockView.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtBadtry.setText(activity.getResources().getString(R.string.wrong_pin_wait).replace("%%",String.valueOf(seconds)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
//Set how long before to start calling the TimerTask (in milliseconds)
|
||||
1000,
|
||||
//Set the amount of time between each execution (in milliseconds)
|
||||
1000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Show error
|
||||
* */
|
||||
final Activity activity = this;
|
||||
tvPatternText.setText(activity.getResources().getString(R.string.Incorrect_pattern));
|
||||
tvPatternText.setTextColor(Color.RED);
|
||||
tvPatternText.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -18,11 +18,9 @@ public class InsightApiGenerator {
|
|||
* Fecth all the transaciton for a giving address
|
||||
* @param cryptoCoin the crypto net of the address
|
||||
* @param address The address String
|
||||
* @param request the request api to response
|
||||
* @param subscribe If needs to follow the address (Real time)
|
||||
*/
|
||||
public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address,
|
||||
ApiRequest request, boolean subscribe){
|
||||
public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address, boolean subscribe){
|
||||
if(!transactionGetters.containsKey(cryptoCoin)){
|
||||
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' ")
|
||||
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)
|
||||
public long[] insertBitcoinAddresses(BitcoinAddress... addresses);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import butterknife.OnTextChanged;
|
|||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.util.ChildViewPager;
|
||||
import cy.agorise.crystalwallet.util.PasswordManager;
|
||||
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.PinSecurityValidator;
|
||||
|
@ -45,9 +46,17 @@ public class PatternSecurityFragment extends Fragment {
|
|||
@BindView(R.id.tvPatternText)
|
||||
TextView tvPatternText;
|
||||
|
||||
/*
|
||||
* Contains the ChildViewPager to block the viewpager when the user is using the pattern control
|
||||
* */
|
||||
private ChildViewPager childViewPager;
|
||||
|
||||
private PatternLockViewListener actualPatternListener;
|
||||
private String patternEntered;
|
||||
|
||||
|
||||
|
||||
|
||||
public PatternSecurityFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
@ -80,6 +89,11 @@ public class PatternSecurityFragment extends Fragment {
|
|||
return patternString;
|
||||
}
|
||||
|
||||
public void setChildViewPager(ChildViewPager childViewPager) {
|
||||
this.childViewPager = childViewPager;
|
||||
}
|
||||
|
||||
|
||||
public void removePatternListener(){
|
||||
if (actualPatternListener != null){
|
||||
patternLockView.removePatternLockListener(actualPatternListener);
|
||||
|
@ -96,7 +110,6 @@ public class PatternSecurityFragment extends Fragment {
|
|||
actualPatternListener = new PatternLockViewListener() {
|
||||
@Override
|
||||
public void onStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -193,8 +206,8 @@ public class PatternSecurityFragment extends Fragment {
|
|||
* */
|
||||
tvPatternText.setText(getActivity().getResources().getString(R.string.Pattern_set_correctly));
|
||||
tvPatternText.setTextColor(Color.GREEN);
|
||||
final Timer t = new Timer();
|
||||
t.scheduleAtFixedRate(new TimerTask() {
|
||||
final Timer t_ = new Timer();
|
||||
t_.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -203,7 +216,7 @@ public class PatternSecurityFragment extends Fragment {
|
|||
@Override
|
||||
public void run() {
|
||||
|
||||
t.cancel();
|
||||
t_.cancel();
|
||||
showNewPatternUI();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -83,6 +83,11 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_security_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* For now this will not be implemented
|
||||
* */
|
||||
sPocketSecurity.setEnabled(false);
|
||||
|
||||
securityPagerAdapter = new SecurityPagerAdapter(getChildFragmentManager());
|
||||
mPager.setAdapter(securityPagerAdapter);
|
||||
|
||||
|
@ -96,7 +101,6 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
default:
|
||||
mPager.setCurrentItem(0);
|
||||
}
|
||||
mPager.setSwipeLocked(true);
|
||||
|
||||
TabLayout tabLayout = v.findViewById(R.id.tabs);
|
||||
|
||||
|
@ -134,7 +138,9 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
case 1:
|
||||
return new PinSecurityFragment();
|
||||
case 2:
|
||||
return new PatternSecurityFragment();
|
||||
final PatternSecurityFragment patternSecurityFragment = new PatternSecurityFragment();
|
||||
patternSecurityFragment.setChildViewPager(mPager);
|
||||
return patternSecurityFragment;
|
||||
}
|
||||
|
||||
return null; //new OnConstructionFragment();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package cy.agorise.crystalwallet.manager;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.Context;
|
||||
|
||||
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.Vin;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.models.Vout;
|
||||
import cy.agorise.crystalwallet.application.CrystalApplication;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
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.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GTxIO;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAddress;
|
||||
import cy.agorise.crystalwallet.requestmanagers.BitcoinSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CreateBitcoinAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.GeneralAccountSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.NextBitcoinAccountAddressRequest;
|
||||
import cy.agorise.graphenej.Util;
|
||||
|
||||
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||
|
@ -85,9 +83,14 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
|
||||
@Override
|
||||
public void onNewRequest(CryptoNetInfoRequest request) {
|
||||
if(Arrays.asList(SUPPORTED_COINS).contains(request.getCoin())){
|
||||
if(request instanceof GeneralAccountSendRequest){
|
||||
this.send((GeneralAccountSendRequest)request);
|
||||
//if(Arrays.asList(SUPPORTED_COINS).contains(request.getCoin())){
|
||||
if(request.getCoin().equals(this.cryptoCoin)){
|
||||
if(request instanceof BitcoinSendRequest) {
|
||||
this.send((BitcoinSendRequest) request);
|
||||
}else if(request instanceof CreateBitcoinAccountRequest){
|
||||
|
||||
}else if(request instanceof NextBitcoinAccountAddressRequest){
|
||||
this.getNextAddress((NextBitcoinAccountAddressRequest) request);
|
||||
}else{
|
||||
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
|
||||
}
|
||||
|
@ -255,7 +258,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance);
|
||||
}
|
||||
|
||||
public void send(final GeneralAccountSendRequest request){
|
||||
public void send(final BitcoinSendRequest request){
|
||||
//TODO check server connection
|
||||
//TODO validate to address
|
||||
|
||||
|
@ -271,19 +274,19 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||
db.bitcoinTransactionDao();
|
||||
|
||||
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getAccount().getId(),db);
|
||||
List<BitcoinTransactionGTxIO> utxos = getUtxos(request.getSourceAccount().getId(),db);
|
||||
|
||||
if(currentAmount< request.getAmount() + fee){
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.NO_BALANCE);
|
||||
request.setStatus(BitcoinSendRequest.StatusCode.NO_BALANCE);
|
||||
return;
|
||||
}
|
||||
AccountSeed seed = db.accountSeedDao().findById(request.getAccount().getSeedId());
|
||||
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.getAccount().getAccountIndex(), true));
|
||||
new ChildNumber(request.getSourceAccount().getAccountIndex(), true));
|
||||
DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||
new ChildNumber(0, false));
|
||||
DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||
|
@ -309,7 +312,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
//Change address
|
||||
long remain = currentAmount - request.getAmount() - fee;
|
||||
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);
|
||||
Address changeAddr;
|
||||
if(btAddress != null && db.bitcoinTransactionDao().getGtxIOByAddress(btAddress.getAddress()).size()<=0){
|
||||
|
@ -323,7 +326,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
}
|
||||
btAddress = new BitcoinAddress();
|
||||
btAddress.setIndex(index);
|
||||
btAddress.setAccountId(request.getAccount().getId());
|
||||
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);
|
||||
|
@ -342,7 +345,7 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
if(btAddress.isChange()){
|
||||
addrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) btAddress.getIndex(), false));
|
||||
}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);
|
||||
}
|
||||
|
@ -350,24 +353,51 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
InsightApiGenerator.broadcastTransaction(cryptoCoin,Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.SUCCEEDED);
|
||||
request.setStatus(BitcoinSendRequest.StatusCode.SUCCEEDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.PETITION_FAILED);
|
||||
request.setStatus(BitcoinSendRequest.StatusCode.PETITION_FAILED);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
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){
|
||||
List<BitcoinTransactionGTxIO> answer = new ArrayList<>();
|
||||
List<BitcoinTransactionGTxIO> bTGTxI = new ArrayList<>();
|
||||
|
|
|
@ -21,6 +21,8 @@ public class BitcoinSendRequest extends CryptoNetInfoRequest {
|
|||
SUCCEEDED,
|
||||
NO_INTERNET,
|
||||
NO_SERVER_CONNECTION,
|
||||
NO_BALANCE,
|
||||
NO_FEE,
|
||||
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 Context context;
|
||||
|
||||
private String address = null;
|
||||
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
|
@ -62,4 +64,12 @@ public class NextBitcoinAccountAddressRequest extends CryptoNetInfoRequest {
|
|||
public StatusCode getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import android.content.Context;
|
|||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.Scroller;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Created by xd on 1/18/18.
|
||||
|
@ -14,36 +18,47 @@ import android.view.MotionEvent;
|
|||
|
||||
public class ChildViewPager extends ViewPager {
|
||||
|
||||
private boolean swipeLocked;
|
||||
|
||||
public ChildViewPager(Context context) {
|
||||
super(context);
|
||||
|
||||
setMyScroller();
|
||||
}
|
||||
|
||||
public ChildViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public boolean getSwipeLocked() {
|
||||
return swipeLocked;
|
||||
}
|
||||
|
||||
public void setSwipeLocked(boolean swipeLocked) {
|
||||
this.swipeLocked = swipeLocked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return !swipeLocked && super.onTouchEvent(event);
|
||||
// stop swipe
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||
return !swipeLocked && super.onInterceptTouchEvent(event);
|
||||
// stop switching pages
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setMyScroller() {
|
||||
try {
|
||||
Class<?> viewpager = ViewPager.class;
|
||||
Field scroller = viewpager.getDeclaredField("mScroller");
|
||||
scroller.setAccessible(true);
|
||||
scroller.set(this, new MyScroller(getContext()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public class MyScroller extends Scroller {
|
||||
public MyScroller(Context context) {
|
||||
super(context, new DecelerateInterpolator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally(int direction) {
|
||||
return !swipeLocked && super.canScrollHorizontally(direction);
|
||||
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
|
||||
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -101,6 +101,7 @@ class BitsharesAccountNameValidation : CustomValidationField, UIValidator {
|
|||
result = false
|
||||
accountNameField.fieldValidatorModel.setInvalid()
|
||||
accountNameField.fieldValidatorModel.message = this.accountNameField.resources.getString(R.string.create_account_window_err_at_least_one_character)
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
|
|
|
@ -21,4 +21,15 @@
|
|||
android:layout_centerInParent="true"
|
||||
android:background="@drawable/gradient"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtBadtry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/patternLockView"
|
||||
android:text="@string/wrong_pin_wait"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textColor="@color/red"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -91,6 +91,12 @@
|
|||
<string name="save">SAVE</string>
|
||||
<string name="next">NEXT</string>
|
||||
|
||||
<string name="ERROR_UNRECOGNIZABLE">An error ocurred attempting to import the account</string>
|
||||
<string name="NO_ACCOUNT_DATA">The account does not have any data</string>
|
||||
<string name="BAD_SEED">The seed is not valid</string>
|
||||
<string name="ACCOUNT_DOESNT_EXIST">The account does not exists</string>
|
||||
<string name="NO_SERVER_CONNECTION">There was an error with the connection. Try again later</string>
|
||||
|
||||
<string name="ASK_PERMISSION">A permission need to be granted before to continue</string>
|
||||
|
||||
<string name="please_enter_brainkey">Please enter brainkey</string>
|
||||
|
@ -214,7 +220,7 @@
|
|||
<string name="fee_capital">Fee</string>
|
||||
<string name="ok">OK</string>
|
||||
|
||||
<string name="wrong_pin_wait">Wrong PIN you have to wait %% seconds ...</string>
|
||||
<string name="wrong_pin_wait">Wrong match you have to wait %% seconds ...</string>
|
||||
|
||||
<string name="loading">Loading...</string>
|
||||
<string name="pay_to">Pay to</string>
|
||||
|
|
Loading…
Reference in a new issue