Compare commits
212 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b12b3b9546 | ||
|
d04e847bba | ||
|
fe1068bcdf | ||
|
af4a4aca8b | ||
|
450a7c285b | ||
|
08df53730b | ||
|
618e71a6ac | ||
|
52f75eb3cf | ||
|
4bf1c14bb8 | ||
|
a32f7c9eb0 | ||
|
bfe65ac1a7 | ||
|
ea57899027 | ||
|
2c431ef4e0 | ||
|
a13bbadd2e | ||
|
1514d32457 | ||
|
7ddc2745b2 | ||
|
0dd9aecbf3 | ||
|
56a3c006cc | ||
|
178a0de26b | ||
|
c2575c7ab8 | ||
|
b10b385a83 | ||
|
5ceffbec2f | ||
|
0e2d33848b | ||
|
ddabac3911 | ||
|
a31efc16e4 | ||
|
0ebc6adfe2 | ||
|
93e71887a8 | ||
|
534cee187b | ||
|
469e7b08e4 | ||
|
5b8d12f886 | ||
|
0c8157a659 | ||
|
a0c01d6843 | ||
|
8502272b25 | ||
|
a3c0504265 | ||
|
96881f3292 | ||
|
aec93ddb22 | ||
|
86c96b1c3a | ||
|
c2416e64ad | ||
|
db4827456f | ||
|
0c64e78e89 | ||
|
9a63c25ee4 | ||
|
62541e1863 | ||
|
7367b33bb2 | ||
|
3ac651c0a4 | ||
|
ecf5335ea3 | ||
|
dfca4b8c53 | ||
|
73ba419b66 | ||
|
ce1df325d8 | ||
|
2e2ee01052 | ||
|
5aa7175016 | ||
|
6e4b66a5e3 | ||
|
83c95a35a8 | ||
|
683883ca0e | ||
|
b6cddedbd4 | ||
|
a11f74f6a5 | ||
|
91ef2d0e9a | ||
|
193f426739 | ||
|
719d6769fc | ||
|
0126d6d114 | ||
|
14a405f67c | ||
|
9c6db3a6ea | ||
|
6e81192b37 | ||
|
8ff53de0ae | ||
|
01e67ce258 | ||
|
42c48d31ea | ||
|
0e37879f02 | ||
|
ca4662867d | ||
|
9df1db6669 | ||
|
fa952d9a36 | ||
|
dc6114bb10 | ||
|
e9f77c4981 | ||
|
043325b887 | ||
|
51498192c6 | ||
|
5965528abe | ||
|
6c0d936b67 | ||
|
960dd67394 | ||
|
4cd304d732 | ||
|
36d97e8166 | ||
|
7ae875e208 | ||
|
10cc88c8d3 | ||
|
9a1dc0548d | ||
|
b5bc9e88c7 | ||
|
b426076eea | ||
|
d456ee49a8 | ||
|
c4ac6b4a29 | ||
|
ae3ed3725d | ||
|
71c26c0ddf | ||
|
0bb428a658 | ||
|
753a4a5943 | ||
|
ba96d999ff | ||
|
a21796d2d0 | ||
|
b05cf62daf | ||
|
7889d4f242 | ||
|
2ca94de241 | ||
|
e8ceb88c6e | ||
|
ac95b66511 | ||
|
c216dfa209 | ||
|
04d3a0d2e6 | ||
|
418749ea6a | ||
|
4ba6299822 | ||
|
b3a267fb47 | ||
|
c3c6677faa | ||
|
8e55afad55 | ||
|
41a3b1c172 | ||
|
cd00923ebc | ||
|
2027677956 | ||
|
b3442a511e | ||
|
6b37db9279 | ||
|
4743042c7e | ||
|
0019385827 | ||
|
03e03f2fb1 | ||
|
e24b355281 | ||
|
3c0e2058bb | ||
|
b73c77e86f | ||
|
356300fed4 | ||
|
7681523252 | ||
|
76a53c12e1 | ||
|
8a7b41ad1d | ||
|
3941585740 | ||
|
c554471115 | ||
|
a4c6b1cfb1 | ||
|
d2668bc04e | ||
|
95bdc725c0 | ||
|
91bc799310 | ||
|
ed7dc5424e | ||
|
d367373d8e | ||
|
b8fd519b1a | ||
|
8f2fc92945 | ||
|
319321c94b | ||
|
cd160c9832 | ||
|
013a3b841f | ||
|
3d9d57d0fa | ||
|
f705de8c60 | ||
|
d3a55fae02 | ||
|
ecfe5ce8e5 | ||
|
fe5603c0b7 | ||
|
332eced879 | ||
|
19aa8e6b7f | ||
|
6606e8c238 | ||
|
f403ee22d4 | ||
|
9a75330207 | ||
|
2e13b16a71 | ||
|
3019cc8422 | ||
|
c30fd729be | ||
|
b33bbc11fc | ||
|
ad65111f92 | ||
|
a64c5eff45 | ||
|
9020608a07 | ||
|
046e21d725 | ||
|
b4cc708970 | ||
|
012aea807e | ||
|
074e37076d | ||
|
24dba53c5f | ||
|
09ce271c30 | ||
|
0928a5bc81 | ||
|
bd6a27f15b | ||
|
df04be0a6c | ||
|
4fee5de10b | ||
|
62edb37143 | ||
|
3767483945 | ||
|
7183c0d803 | ||
|
f82b90e0ee | ||
|
64866632d2 | ||
|
493b00c4f8 | ||
|
303011e419 | ||
|
be679e655f | ||
|
d788ceab9a | ||
|
85b1015e9f | ||
|
cf4b1f038d | ||
|
a4819ecd22 | ||
|
ab9df5d786 | ||
|
9fa7ddf178 | ||
|
96feaf31cd | ||
|
62e205ccfe | ||
|
53066696ce | ||
|
86c16bbb7b | ||
|
b55d22324a | ||
|
a54363a9ef | ||
|
1545f0e10b | ||
|
09ae09db1b | ||
|
8b4fb2d69d | ||
|
6a5ac7cc58 | ||
|
f43c6aa1af | ||
|
546db50590 | ||
|
a21446bc7f | ||
|
c1b8c11d74 | ||
|
cc69c2676e | ||
|
5ad7d32bbf | ||
|
05d04b69af | ||
|
d2e388e5de | ||
|
fbfa97754f | ||
|
94267c6cc3 | ||
|
751cb46922 | ||
|
1cc21c73be | ||
|
6b39722f89 | ||
|
d86fe35a6b | ||
|
ad0c14e389 | ||
|
e9a147e344 | ||
|
31f809048f | ||
|
0fc4392a52 | ||
|
17c61b12a7 | ||
|
b1e8e4dfe7 | ||
|
14c307ccbc | ||
|
7db8212ab4 | ||
|
6eab51c89f | ||
|
d16f2d7378 | ||
|
037787afd0 | ||
|
0c583fff18 | ||
|
dae073dc62 | ||
|
2e6c61f88a | ||
|
2c5661c587 | ||
|
53cf2ef25b |
184 changed files with 7638 additions and 2577 deletions
|
@ -1,6 +1,8 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt' // add this line
|
||||
|
||||
|
||||
kapt {
|
||||
generateStubs = true
|
||||
|
@ -9,14 +11,19 @@ kapt {
|
|||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "cy.agorise.crystalwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode 3
|
||||
versionName "0.3M.alpha"
|
||||
targetSdkVersion 28
|
||||
versionCode 5
|
||||
versionName "0.5M.alpha"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
useSupportLibrary true
|
||||
|
@ -28,6 +35,9 @@ android {
|
|||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
resValue("string", "PORT_NUMBER", "8081")
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
|
@ -52,51 +62,44 @@ dependencies {
|
|||
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
implementation( 'com.github.thekhaeng:pushdown-anim-click:1.1.1' ){
|
||||
exclude group: 'com.android.support'
|
||||
}
|
||||
implementation 'com.jaredrummler:material-spinner:1.2.5'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.1.60"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
//testCompile 'com.android.support.test:runner:1.0.1'
|
||||
implementation 'com.afollestad.material-dialogs:core:0.9.6.0' //DTVV Thrusday 31 July 2018
|
||||
implementation 'com.android.support:appcompat-v7:27.1.1'
|
||||
implementation 'com.github.bumptech.glide:glide:4.7.1'
|
||||
// Glide v4 uses this new annotation processor -- see https://bumptech.github.io/glide/doc/generatedapi.html
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
|
||||
implementation 'com.android.support:support-v4:27.1.1'
|
||||
implementation 'com.android.support:design:27.1.1'
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.android.support:cardview-v7:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
implementation 'android.arch.lifecycle:runtime:1.1.1'
|
||||
implementation 'android.arch.lifecycle:extensions:1.1.1'
|
||||
implementation 'android.arch.paging:runtime:1.0.0'
|
||||
implementation 'android.arch.paging:runtime:1.0.1'
|
||||
implementation 'com.idescout.sql:sqlscout-server:2.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.4'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.2.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
|
||||
implementation 'org.bitcoinj:bitcoinj-core:0.14.3'
|
||||
implementation 'com.neovisionaries:nv-websocket-client:1.30'
|
||||
implementation 'org.tukaani:xz:1.6'
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
implementation 'com.github.bilthon:graphenej:0.4.6'
|
||||
implementation 'com.google.zxing:core:3.3.1'
|
||||
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
|
||||
implementation 'com.github.sjaramillo10:AnimatedTabLayout:1.0.3'
|
||||
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
|
||||
//testCompile 'junit:junit: 4.12'
|
||||
testImplementation 'org.mockito:mockito-core:1.10.19'
|
||||
implementation 'android.arch.persistence.room:runtime:1.1.0'
|
||||
testImplementation 'org.mockito:mockito-core:2.19.0'
|
||||
implementation 'android.arch.persistence.room:runtime:1.1.1'
|
||||
|
||||
kapt 'android.arch.persistence.room:runtime:1.1.1'
|
||||
kapt 'android.arch.persistence.room:compiler:1.1.1'
|
||||
|
||||
kapt 'android.arch.persistence.room:runtime:1.1.0'
|
||||
annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
|
||||
kapt 'android.arch.lifecycle:compiler:1.1.1'
|
||||
annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
|
||||
kapt 'android.arch.persistence.room:compiler:1.1.0'
|
||||
annotationProcessor 'android.arch.persistence.room:compiler:1.1.0'
|
||||
kapt 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
|
||||
implementation 'com.squareup.picasso:picasso:2.5.2'
|
||||
implementation 'com.github.esafirm.android-image-picker:imagepicker:1.11.1'
|
||||
implementation 'id.zelory:compressor:2.1.0'
|
||||
implementation 'com.vincent.filepicker:MultiTypeFilePicker:1.0.7'
|
||||
|
@ -108,6 +111,14 @@ dependencies {
|
|||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
|
||||
kapt "android.arch.lifecycle:compiler:1.1.1"
|
||||
kapt "android.arch.persistence.room:compiler:1.1.0"
|
||||
// Glide dependencies
|
||||
implementation 'com.github.bumptech.glide:glide:4.8.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.8.0'
|
||||
|
||||
// Android Debug Database
|
||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
||||
|
||||
implementation 'com.google.zxing:core:3.3.1'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
|
||||
testImplementation 'org.testng:testng:6.9.6'
|
||||
}
|
||||
|
|
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
|
@ -23,3 +23,10 @@
|
|||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<application
|
||||
android:name=".application.CrystalApplication"
|
||||
|
@ -39,6 +40,10 @@
|
|||
</activity>
|
||||
<activity android:name=".activities.AccountSeedsManagementActivity" >
|
||||
</activity>
|
||||
<activity android:name=".activities.AccountSeedSettingsActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
</activity>
|
||||
<activity android:name=".activities.ImportSeedActivity" >
|
||||
</activity>
|
||||
<activity android:name=".activities.SendTransactionActivity" >
|
||||
|
|
1
app/src/main/assets/crystal_eula.html
Normal file
1
app/src/main/assets/crystal_eula.html
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 30 KiB |
|
@ -0,0 +1,134 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.fragments.BitsharesSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.GeneralAccountSeedCoinSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.GeneralAccountSeedFragment;
|
||||
import cy.agorise.crystalwallet.fragments.GeneralCryptoNetAccountSettingsFragment;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountViewModel;
|
||||
|
||||
/**
|
||||
* Created by henry varona on 10/29/18.
|
||||
*
|
||||
*/
|
||||
|
||||
public class AccountSeedSettingsActivity extends AppCompatActivity{
|
||||
|
||||
@BindView(R.id.ivGoBack)
|
||||
public ImageView ivGoBack;
|
||||
|
||||
@BindView(R.id.pager)
|
||||
public ViewPager mPager;
|
||||
|
||||
public SettingsPagerAdapter settingsPagerAdapter;
|
||||
|
||||
|
||||
@BindView(R.id.tvBuildVersion)
|
||||
public TextView tvBuildVersion;
|
||||
|
||||
@BindView(R.id.tabs)
|
||||
public TabLayout tabs;
|
||||
|
||||
private AccountSeed accountSeed;
|
||||
|
||||
@BindView(R.id.ivAppBarAnimation)
|
||||
ImageView ivAppBarAnimation;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.account_seed_activity_settings);
|
||||
ButterKnife.bind(this);
|
||||
final AccountSeedSettingsActivity thisActivity = this;
|
||||
|
||||
long accountSeedId = getIntent().getLongExtra("SEED_ID",-1);
|
||||
|
||||
if (accountSeedId > -1) {
|
||||
AccountSeedViewModel accountSeedViewModel = ViewModelProviders.of(this).get(AccountSeedViewModel.class);
|
||||
accountSeedViewModel.loadSeed(accountSeedId);
|
||||
LiveData<AccountSeed> accountSeedLiveData = accountSeedViewModel.getAccountSeed();
|
||||
|
||||
accountSeedLiveData.observe(this, new Observer<AccountSeed>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable AccountSeed accountSeed) {
|
||||
thisActivity.accountSeed = accountSeed;
|
||||
|
||||
settingsPagerAdapter = new SettingsPagerAdapter(getSupportFragmentManager());
|
||||
mPager.setAdapter(settingsPagerAdapter);
|
||||
|
||||
TabLayout tabLayout = findViewById(R.id.tabs);
|
||||
|
||||
mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mPager));
|
||||
}
|
||||
});
|
||||
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Sets AppBar animation
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAppBarAnimation);
|
||||
|
||||
|
||||
} else {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsPagerAdapter extends FragmentStatePagerAdapter {
|
||||
SettingsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
switch (position){
|
||||
case 0:
|
||||
return GeneralAccountSeedFragment.newInstance(accountSeed.getId());
|
||||
case 1:
|
||||
return GeneralAccountSeedCoinSettingsFragment.newInstance(accountSeed.getId());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
int tabCount = 2;
|
||||
|
||||
return tabCount;
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.ivGoBack)
|
||||
public void goBack(){
|
||||
onBackPressed();
|
||||
}
|
||||
}
|
|
@ -14,6 +14,9 @@ import android.view.SurfaceView;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
@ -37,12 +40,13 @@ public class AccountSettingsActivity extends AppCompatActivity{
|
|||
|
||||
public SettingsPagerAdapter settingsPagerAdapter;
|
||||
|
||||
@BindView(R.id.surface_view)
|
||||
public SurfaceView mSurfaceView;
|
||||
|
||||
@BindView(R.id.tvBuildVersion)
|
||||
public TextView tvBuildVersion;
|
||||
|
||||
@BindView(R.id.ivAppBarAnimation)
|
||||
ImageView ivAppBarAnimation;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -52,27 +56,11 @@ public class AccountSettingsActivity extends AppCompatActivity{
|
|||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Appbar animation
|
||||
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceCreated");
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(AccountSettingsActivity.this, R.raw.appbar_background);
|
||||
mediaPlayer.setDisplay(mSurfaceView.getHolder());
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
||||
//Log.d(TAG,"surfaceChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
// Sets AppBar animation
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAppBarAnimation);
|
||||
|
||||
settingsPagerAdapter = new SettingsPagerAdapter(getSupportFragmentManager());
|
||||
mPager.setAdapter(settingsPagerAdapter);
|
||||
|
|
|
@ -18,10 +18,12 @@ import android.provider.MediaStore;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.esafirm.imagepicker.features.ImagePicker;
|
||||
import com.esafirm.imagepicker.model.Image;
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
//import com.nicdahlquist.pngquant.LibPngQuant;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -55,8 +57,11 @@ public class AccountsActivity extends AppCompatActivity {
|
|||
@BindView(R.id.tvClose)
|
||||
TextView tvClose;
|
||||
|
||||
@BindView(R.id.vAccountList)
|
||||
CryptoNetAccountListView vAccountList;
|
||||
//@BindView(R.id.vAccountList)
|
||||
//CryptoNetAccountListView vAccountList;
|
||||
|
||||
@BindView(R.id.vAccountSeedList)
|
||||
AccountSeedListView vAccountSeedList;
|
||||
|
||||
@BindView(R.id.user_img)
|
||||
CircleImageView userImg;
|
||||
|
@ -74,14 +79,29 @@ public class AccountsActivity extends AppCompatActivity {
|
|||
setContentView(R.layout.activity_accounts);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
CryptoNetAccountListViewModel crytpoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
|
||||
LiveData<List<CryptoNetAccount>> accountData = crytpoNetAccountListViewModel.getCryptoNetAccounts();
|
||||
vAccountList.setData(null);
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(fabAddAccount)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
goToAddAccount();
|
||||
}
|
||||
|
||||
accountData.observe(this, new Observer<List<CryptoNetAccount>>() {
|
||||
} );
|
||||
|
||||
AccountSeedListViewModel accountSeedListViewModel = ViewModelProviders.of(this).get(AccountSeedListViewModel.class);
|
||||
LiveData<List<AccountSeed>> accountSeedLD = accountSeedListViewModel.getAccountSeedList();
|
||||
|
||||
//CryptoNetAccountListViewModel crytpoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
|
||||
//LiveData<List<CryptoNetAccount>> accountData = crytpoNetAccountListViewModel.getCryptoNetAccounts();
|
||||
vAccountSeedList.setData(null);
|
||||
|
||||
accountSeedLD.observe(this, new Observer<List<AccountSeed>>() {
|
||||
@Override
|
||||
public void onChanged(List<CryptoNetAccount> cryptoNetAccounts) {
|
||||
vAccountList.setData(cryptoNetAccounts);
|
||||
public void onChanged(List<AccountSeed> accountsSeeds) {
|
||||
vAccountSeedList.setData(accountsSeeds);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -10,10 +10,14 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
@ -29,10 +33,12 @@ public class BackupSeedActivity extends AppCompatActivity {
|
|||
|
||||
@BindView(R.id.tvBrainKey)
|
||||
TextView textfieldBrainkey;
|
||||
@BindView(R.id.btnCancel)
|
||||
@BindView(R.id.btnOK)
|
||||
Button btnOk;
|
||||
@BindView(R.id.btnCopy)
|
||||
Button btnCopy;
|
||||
@BindView(R.id.btnCancel)
|
||||
Button btnCancel;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -41,6 +47,42 @@ public class BackupSeedActivity extends AppCompatActivity {
|
|||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCancel)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnCancelClick();
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnOk)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnOkClick();
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnCopy)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnCopyClick();
|
||||
}
|
||||
} );
|
||||
/*
|
||||
* If comes from new account creation hide the cancel button
|
||||
* */
|
||||
Bundle b = getIntent().getExtras();
|
||||
boolean newAccount = b.getBoolean("newAccount");
|
||||
if(newAccount ){
|
||||
ViewGroup layout = (ViewGroup) btnOk.getParent();
|
||||
if(null!=layout) //for safety only as you are doing onClick
|
||||
layout.removeView(btnOk);
|
||||
//btnOk.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
long seedId = getIntent().getLongExtra("SEED_ID",-1);
|
||||
|
||||
if (seedId > -1) {
|
||||
|
@ -56,6 +98,14 @@ public class BackupSeedActivity extends AppCompatActivity {
|
|||
accountSeedViewModel.loadSeed(seedId);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
*
|
||||
* The first time you create the account, the "seed" is showed propertly in this window,
|
||||
* but when you want to check it again the "seed" does not exist anymore and
|
||||
* for this cause the program gets into this point and finish the window
|
||||
*
|
||||
* */
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@ import android.content.Intent;
|
|||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.TabLayout;
|
||||
|
@ -20,18 +17,10 @@ import android.support.v4.app.FragmentStatePagerAdapter;
|
|||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Pair;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
@ -48,7 +37,6 @@ import cy.agorise.crystalwallet.fragments.MerchantsFragment;
|
|||
import cy.agorise.crystalwallet.fragments.ReceiveTransactionFragment;
|
||||
import cy.agorise.crystalwallet.fragments.SendTransactionFragment;
|
||||
import cy.agorise.crystalwallet.fragments.TransactionsFragment;
|
||||
import cy.agorise.crystalwallet.views.natives.GIFView;
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetBalanceListViewModel;
|
||||
|
||||
|
@ -73,8 +61,8 @@ public class BoardActivity extends CustomActivity {
|
|||
@BindView(R.id.fabAddContact)
|
||||
public FloatingActionButton fabAddContact;
|
||||
|
||||
@BindView(R.id.imagevieGIF)
|
||||
public GIFView imagevieGIF;
|
||||
@BindView(R.id.ivAppBarAnimation)
|
||||
ImageView ivAppBarAnimation;
|
||||
|
||||
public BoardPagerAdapter boardAdapter;
|
||||
|
||||
|
@ -84,9 +72,6 @@ public class BoardActivity extends CustomActivity {
|
|||
*/
|
||||
long cryptoNetAccountId;
|
||||
|
||||
@BindView(R.id.surface_view)
|
||||
public SurfaceView mSurfaceView;
|
||||
|
||||
@BindView(R.id.toolbar_user_img)
|
||||
public CircleImageView userImage;
|
||||
|
||||
|
@ -110,82 +95,11 @@ public class BoardActivity extends CustomActivity {
|
|||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
/*
|
||||
* Set the bubbles animation
|
||||
* */
|
||||
//imagevieGIF.centerCrop();
|
||||
//imagevieGIF.load(R.raw.burbujas);
|
||||
|
||||
/*
|
||||
* Listener tabLayout to resalt text when clicked
|
||||
* */
|
||||
final TabLayout tabLayoutFinal = tabLayout;
|
||||
// tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
|
||||
// @Override
|
||||
// public void onTabSelected(final TabLayout.Tab tab) {
|
||||
//
|
||||
// globalActivity.runOnUiThread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
//
|
||||
// LinearLayout tabLayout = (LinearLayout)((ViewGroup) tabLayoutFinal.getChildAt(0)).getChildAt(tab.getPosition());
|
||||
// tabLayout.setBackgroundColor(Color.TRANSPARENT);
|
||||
// TextView tabTextView = (TextView) tabLayout.getChildAt(1);
|
||||
// //tabTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP ,50);
|
||||
// Spannable WordtoSpan = new SpannableString(tabTextView.getText());
|
||||
// WordtoSpan.setSpan(new ForegroundColorSpan(Color.WHITE), 0, tabTextView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
// tabTextView.setText(WordtoSpan);
|
||||
// tabTextView.setTypeface(tabTextView.getTypeface(), Typeface.BOLD);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onTabUnselected(final TabLayout.Tab tab) {
|
||||
//
|
||||
// globalActivity.runOnUiThread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
//
|
||||
// LinearLayout tabLayout = (LinearLayout)((ViewGroup) tabLayoutFinal.getChildAt(0)).getChildAt(tab.getPosition());
|
||||
// TextView tabTextView = (TextView) tabLayout.getChildAt(1);
|
||||
// //tabTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP ,50);
|
||||
// Spannable WordtoSpan = new SpannableString(tabTextView.getText());
|
||||
// WordtoSpan.setSpan(new ForegroundColorSpan(globalActivity.getResources().getColor(R.color.lightGrayClear)), 0, tabTextView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
// tabTextView.setText(WordtoSpan);
|
||||
// tabTextView.setTypeface(tabTextView.getTypeface(), Typeface.NORMAL);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onTabReselected(TabLayout.Tab tab) {
|
||||
//
|
||||
//
|
||||
// }
|
||||
// });
|
||||
|
||||
// Appbar animation
|
||||
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceCreated");
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(BoardActivity.this, R.raw.appbar_background);
|
||||
mediaPlayer.setDisplay(mSurfaceView.getHolder());
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
||||
//Log.d(TAG,"surfaceChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
// Sets AppBar animation
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAppBarAnimation);
|
||||
|
||||
boardAdapter = new BoardPagerAdapter(getSupportFragmentManager());
|
||||
mPager.setAdapter(boardAdapter);
|
||||
|
|
|
@ -3,18 +3,17 @@ package cy.agorise.crystalwallet.activities
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.TextInputEditText
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.OnClick
|
||||
import butterknife.OnTextChanged
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim
|
||||
import com.vincent.filepicker.ToastUtil
|
||||
import cy.agorise.crystalwallet.R
|
||||
import cy.agorise.crystalwallet.dialogs.material.*
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateCreateBitsharesAccountRequest
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.interfaces.UIValidatorListener
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.customImpl.validationFields.BitsharesAccountNameValidation.OnAccountExist
|
||||
|
@ -39,11 +38,6 @@ class CreateSeedActivity : CustomActivity() {
|
|||
* */
|
||||
setContentView(R.layout.create_seed)
|
||||
|
||||
/*
|
||||
* Initialice butterknife MVC
|
||||
* */
|
||||
ButterKnife.bind(this)
|
||||
|
||||
/*
|
||||
* Add the controls to the validator
|
||||
* */
|
||||
|
@ -51,6 +45,14 @@ class CreateSeedActivity : CustomActivity() {
|
|||
this.fieldsValidator.add(tietPinConfirmation)
|
||||
this.fieldsValidator.add(tietAccountName)
|
||||
|
||||
/*
|
||||
* Integration of library with button effects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCancel)
|
||||
.setOnClickListener { finish() }
|
||||
PushDownAnim.setPushDownAnimTo(btnCreate)
|
||||
.setOnClickListener { createSeed() }
|
||||
|
||||
/*
|
||||
* Validations listener
|
||||
* */
|
||||
|
@ -87,20 +89,14 @@ class CreateSeedActivity : CustomActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the pin double validation
|
||||
* */
|
||||
//Create the pin double validation
|
||||
val pinDoubleConfirmationValidationField = PinDoubleConfirmationValidationField(this, tietPin, tietPinConfirmation, uiValidatorListener)
|
||||
|
||||
/*
|
||||
* Listener for the validation for success or fail
|
||||
* */
|
||||
// Listener for the validation for success or fail
|
||||
tietPin?.setUiValidator(pinDoubleConfirmationValidationField) //Validator for the field
|
||||
tietPinConfirmation?.setUiValidator(pinDoubleConfirmationValidationField) //Validator for the field
|
||||
|
||||
/*
|
||||
* Account name validator
|
||||
* */
|
||||
// Account name validator
|
||||
val bitsharesAccountNameValidation = BitsharesAccountNameValidation(this, tietAccountName, uiValidatorListener)
|
||||
val onAccountExist = object : OnAccountExist {
|
||||
override fun onAccountExists() {
|
||||
|
@ -114,58 +110,49 @@ class CreateSeedActivity : CustomActivity() {
|
|||
tietAccountName?.setUiValidator(bitsharesAccountNameValidation)
|
||||
|
||||
/*This button should not be enabled till all the fields be correctly filled*/
|
||||
disableCreate()
|
||||
btnCreate.isEnabled = false
|
||||
|
||||
/*
|
||||
* Set the focus on the fisrt field and show keyboard
|
||||
* */
|
||||
// Set the focus on the first field and show keyboard
|
||||
tilPin?.requestFocus()
|
||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.showSoftInput(tilPin, InputMethodManager.SHOW_IMPLICIT)
|
||||
|
||||
tietPin.afterTextChanged {
|
||||
this.fieldsValidator.validate()
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
tietPinConfirmation.afterTextChanged {
|
||||
this.fieldsValidator.validate()
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
tietAccountName.afterTextChanged {
|
||||
this.fieldsValidator.validate()
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
btnCancel.setOnClickListener { finish() }
|
||||
btnCreate.setOnClickListener { createSeed() }
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.tietPin, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
internal fun afterPinChanged(editable: Editable) {
|
||||
this.fieldsValidator.validate()
|
||||
|
||||
/*
|
||||
* Validate continue to create account
|
||||
* */
|
||||
validateFieldsToContinue()
|
||||
/**
|
||||
* Extension function to easily add a text watcher
|
||||
*/
|
||||
fun TextInputEditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
|
||||
this.addTextChangedListener(object :TextWatcher {
|
||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
}
|
||||
|
||||
override fun afterTextChanged(editable: Editable?) {
|
||||
afterTextChanged.invoke(editable.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.tietPinConfirmation, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
internal fun afterPinConfirmationChanged(editable: Editable) {
|
||||
this.fieldsValidator.validate()
|
||||
|
||||
/*
|
||||
* Validate continue to create account
|
||||
* */
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.tietAccountName, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
internal fun afterAccountNameChanged(editable: Editable) {
|
||||
this.fieldsValidator.validate()
|
||||
|
||||
/*
|
||||
* Validate continue to create account
|
||||
* */
|
||||
validateFieldsToContinue()
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnCancel)
|
||||
fun cancel() {
|
||||
|
||||
/*
|
||||
* Exit of the activity
|
||||
* */
|
||||
this.finish()
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnCreate)
|
||||
fun createSeed() {
|
||||
|
||||
/*
|
||||
|
@ -181,11 +168,10 @@ class CreateSeedActivity : CustomActivity() {
|
|||
questionDialog.setOnPositive(object : PositiveResponse{
|
||||
override fun onPositive() {
|
||||
|
||||
// Make request to create a bitshare account
|
||||
// Make request to create a bitshares account
|
||||
var accountName:String = tietAccountName?.getText().toString().trim()
|
||||
val request = ValidateCreateBitsharesAccountRequest(accountName, applicationContext)
|
||||
|
||||
//DTVV: Friday 27 July 2018
|
||||
//Makes dialog to tell the user that the account is been created
|
||||
val creatingAccountMaterialDialog = CrystalDialog(globalActivity)
|
||||
creatingAccountMaterialDialog.setText(globalActivity.resources.getString(R.string.window_create_seed_DialogMessage))
|
||||
|
@ -200,11 +186,12 @@ class CreateSeedActivity : CustomActivity() {
|
|||
val intent = Intent(applicationContext, BackupSeedActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
intent.putExtra("SEED_ID", accountSeed.id)
|
||||
intent.putExtra("newAccount", true)
|
||||
startActivity(intent)
|
||||
}
|
||||
else if (request.status == ValidateCreateBitsharesAccountRequest.StatusCode.ACCOUNT_EXIST) {
|
||||
ToastUtil.getInstance(globalActivity).showToast(globalActivity.getString(R.string.Account_already_exists))
|
||||
disableCreate()
|
||||
btnCreate.isEnabled = false
|
||||
}
|
||||
else {
|
||||
fieldsValidator.validate()
|
||||
|
@ -213,10 +200,7 @@ class CreateSeedActivity : CustomActivity() {
|
|||
|
||||
(object : Thread() {
|
||||
override fun run() {
|
||||
|
||||
/*
|
||||
*
|
||||
* Run thread*/
|
||||
/* Run thread*/
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request)
|
||||
}
|
||||
}).start()
|
||||
|
@ -242,85 +226,7 @@ class CreateSeedActivity : CustomActivity() {
|
|||
result = true //Validation is correct
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If the result is true so the user can continue to the creation of the account
|
||||
* */
|
||||
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 {
|
||||
|
||||
/*
|
||||
* Disaible button create
|
||||
* */
|
||||
disableCreate()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable create button
|
||||
* */
|
||||
private fun enableCreate() {
|
||||
runOnUiThread(Runnable {
|
||||
btnCreate?.setBackgroundColor(resources.getColor(R.color.colorPrimary))
|
||||
btnCreate?.setEnabled(true)
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable create button
|
||||
* */
|
||||
private fun disableCreate() {
|
||||
runOnUiThread(Runnable {
|
||||
btnCreate?.setEnabled(false)
|
||||
btnCreate?.setBackground(resources.getDrawable(R.drawable.disable_style))
|
||||
})
|
||||
// If the result is true so the user can continue to the creation of the account
|
||||
btnCreate.isEnabled = result
|
||||
}
|
||||
}
|
|
@ -2,15 +2,11 @@ package cy.agorise.crystalwallet.activities;
|
|||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
@ -47,7 +43,7 @@ public class CryptoCoinTransactionReceiptActivity extends AppCompatActivity {
|
|||
|
||||
if (this.cryptoCoinTransactionId != -1) {
|
||||
db = CrystalDatabase.getAppDatabase(this);
|
||||
this.cryptoCoinTransactionLiveData = db.transactionDao().getById(this.cryptoCoinTransactionId);
|
||||
this.cryptoCoinTransactionLiveData = db.transactionDao().getByIdLiveData(this.cryptoCoinTransactionId);
|
||||
|
||||
this.cryptoCoinTransactionLiveData.observe(this, new Observer<CryptoCoinTransaction>() {
|
||||
@Override
|
||||
|
|
|
@ -18,12 +18,16 @@ import android.view.SurfaceView;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.fragments.BackupsSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.BitsharesSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.CryptoNetAccountActivationSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.GeneralCryptoNetAccountSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.GeneralSettingsFragment;
|
||||
import cy.agorise.crystalwallet.fragments.SecuritySettingsFragment;
|
||||
|
@ -45,8 +49,6 @@ public class CryptoNetAccountSettingsActivity extends AppCompatActivity{
|
|||
|
||||
public SettingsPagerAdapter settingsPagerAdapter;
|
||||
|
||||
@BindView(R.id.surface_view)
|
||||
public SurfaceView mSurfaceView;
|
||||
|
||||
@BindView(R.id.tvBuildVersion)
|
||||
public TextView tvBuildVersion;
|
||||
|
@ -56,6 +58,9 @@ public class CryptoNetAccountSettingsActivity extends AppCompatActivity{
|
|||
|
||||
private CryptoNetAccount cryptoNetAccount;
|
||||
|
||||
@BindView(R.id.ivAppBarAnimation)
|
||||
ImageView ivAppBarAnimation;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -93,27 +98,11 @@ public class CryptoNetAccountSettingsActivity extends AppCompatActivity{
|
|||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Appbar animation
|
||||
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceCreated");
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(CryptoNetAccountSettingsActivity.this, R.raw.appbar_background);
|
||||
mediaPlayer.setDisplay(mSurfaceView.getHolder());
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
||||
//Log.d(TAG,"surfaceChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
// Sets AppBar animation
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAppBarAnimation);
|
||||
|
||||
|
||||
} else {
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
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;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.enums.SeedType;
|
||||
import cy.agorise.crystalwallet.manager.BitsharesAccountManager;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccountInfo;
|
||||
import cy.agorise.crystalwallet.dialogs.material.CrystalLoading;
|
||||
import cy.agorise.crystalwallet.dialogs.material.DialogMaterial;
|
||||
import cy.agorise.crystalwallet.dialogs.material.NegativeResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.PositiveResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.QuestionDialog;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ImportBackupRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.viewmodels.AccountSeedViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.GrapheneAccountInfoViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.ImportSeedValidator;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.UIValidatorListener;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.validationfields.ValidationField;
|
||||
|
@ -40,23 +41,30 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
|
||||
@BindView(R.id.etPin)
|
||||
EditText etPin;
|
||||
@BindView(R.id.tvPinError)
|
||||
TextView tvPinError;
|
||||
|
||||
@BindView(R.id.txtErrorPIN)
|
||||
TextView txtErrorPIN;
|
||||
|
||||
@BindView(R.id.txtErrorAccount)
|
||||
TextView txtErrorAccount;
|
||||
|
||||
//@BindView(R.id.tvPinError)
|
||||
//TextView tvPinError;
|
||||
|
||||
@BindView(R.id.etPinConfirmation)
|
||||
EditText etPinConfirmation;
|
||||
@BindView(R.id.tvPinConfirmationError)
|
||||
TextView tvPinConfirmationError;
|
||||
//@BindView(R.id.tvPinConfirmationError)
|
||||
//TextView tvPinConfirmationError;
|
||||
|
||||
@BindView(R.id.etSeedWords)
|
||||
EditText etSeedWords;
|
||||
@BindView(R.id.tvSeedWordsError)
|
||||
TextView tvSeedWordsError;
|
||||
//@BindView(R.id.tvSeedWordsError)
|
||||
//TextView tvSeedWordsError;
|
||||
|
||||
@BindView (R.id.etAccountName)
|
||||
EditText etAccountName;
|
||||
@BindView(R.id.tvAccountNameError)
|
||||
TextView tvAccountNameError;
|
||||
//@BindView(R.id.tvAccountNameError)
|
||||
//TextView tvAccountNameError;
|
||||
|
||||
@BindView(R.id.btnImport)
|
||||
Button btnImport;
|
||||
|
@ -64,6 +72,16 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@BindView(R.id.btnCancel)
|
||||
Button btnCancel;
|
||||
|
||||
final Activity activity = this;
|
||||
|
||||
/*
|
||||
* Flag to check correct PIN equality
|
||||
* */
|
||||
private boolean pinsOK = false;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -71,12 +89,213 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
btnImport.setEnabled(false);
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCancel)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
cancel();
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnImport)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
importSeed();
|
||||
}
|
||||
} );
|
||||
|
||||
/*
|
||||
* Initially the button CREATE WALLET should be disabled
|
||||
* */
|
||||
disableCreate();
|
||||
|
||||
/*
|
||||
* When a text change in any of the fields
|
||||
* */
|
||||
etPin.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@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(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
}
|
||||
});
|
||||
etPinConfirmation.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@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(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
}
|
||||
});
|
||||
etSeedWords.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@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(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Hide error field
|
||||
* */
|
||||
clearErrors();
|
||||
}
|
||||
});
|
||||
/*
|
||||
etAccountName.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@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(allFieldsAreOK()){
|
||||
enableCreate();
|
||||
}
|
||||
else{
|
||||
disableCreate();
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
accountSeedViewModel = ViewModelProviders.of(this).get(AccountSeedViewModel.class);
|
||||
importSeedValidator = new ImportSeedValidator(this.getApplicationContext(),etPin,etPinConfirmation,etAccountName,etSeedWords);
|
||||
importSeedValidator.setListener(this);
|
||||
}
|
||||
|
||||
|
||||
private void clearErrors(){
|
||||
txtErrorPIN.setVisibility(View.INVISIBLE);
|
||||
txtErrorAccount.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Validate that PINs are equals
|
||||
* */
|
||||
private void validatePINS(){
|
||||
|
||||
final String pin = etPin.getText().toString().trim();
|
||||
final String confirmoPIN = etPinConfirmation.getText().toString().trim();
|
||||
if(!pin.isEmpty() && !confirmoPIN.isEmpty()){
|
||||
if(pin.compareTo(confirmoPIN)!=0){
|
||||
pinsOK = false;
|
||||
txtErrorPIN.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else{
|
||||
pinsOK = true;
|
||||
clearErrors();
|
||||
}
|
||||
}
|
||||
else{
|
||||
pinsOK = false;
|
||||
clearErrors();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Method to validate if all the fields are fill and correctly
|
||||
* */
|
||||
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;
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.etPin,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterPinChanged(Editable editable) {
|
||||
|
@ -94,13 +313,11 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
void afterSeedWordsChanged(Editable editable) {
|
||||
this.importSeedValidator.validate();
|
||||
}
|
||||
|
||||
|
||||
@OnTextChanged(value = R.id.etAccountName,
|
||||
/*@OnTextChanged(value = R.id.etAccountName,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterAccountNameChanged(Editable editable) {
|
||||
this.importSeedValidator.validate();
|
||||
}
|
||||
}*/
|
||||
|
||||
@OnClick(R.id.btnCancel)
|
||||
public void cancel(){
|
||||
|
@ -113,68 +330,144 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
|
||||
if (this.importSeedValidator.isValid()) {
|
||||
|
||||
final ValidateImportBitsharesAccountRequest validatorRequest =
|
||||
new ValidateImportBitsharesAccountRequest(etAccountName.getText().toString(), etSeedWords.getText().toString(), getApplicationContext(), true);
|
||||
|
||||
validatorRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
/*
|
||||
* Question if continue
|
||||
* */
|
||||
final QuestionDialog questionDialog = new QuestionDialog(activity);
|
||||
questionDialog.setText(activity.getString(R.string.question_continue));
|
||||
questionDialog.setOnNegative(new NegativeResponse() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (!validatorRequest.getStatus().equals(ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED)) {
|
||||
String errorText = "An error ocurred attempting to import the account";
|
||||
|
||||
switch (validatorRequest.getStatus()){
|
||||
case PETITION_FAILED:
|
||||
case NO_INTERNET:
|
||||
case NO_SERVER_CONNECTION:
|
||||
errorText = "There was an error with the connection. Try again later";
|
||||
break;
|
||||
case ACCOUNT_DOESNT_EXIST:
|
||||
errorText = "The account doesn't exists";
|
||||
break;
|
||||
case BAD_SEED:
|
||||
errorText = "The seed is not valid";
|
||||
break;
|
||||
case NO_ACCOUNT_DATA:
|
||||
errorText = "The account doesn't have any data";
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
startActivity(intent);
|
||||
}
|
||||
public void onNegative(@NotNull DialogMaterial dialogMaterial) {
|
||||
}
|
||||
});
|
||||
/*CryptoNetInfoRequests.getInstance().addRequest(validatorRequest);
|
||||
questionDialog.setOnPositive(new PositiveResponse() {
|
||||
@Override
|
||||
public void onPositive() {
|
||||
|
||||
AccountSeed seed = new AccountSeed();
|
||||
/*
|
||||
* Loading dialog
|
||||
* */
|
||||
final CrystalLoading crystalLoading = new CrystalLoading(activity);
|
||||
crystalLoading.show();
|
||||
|
||||
//TODO verify if words are already in the db
|
||||
//TODO check if name has been asigned to other seed
|
||||
seed.setMasterSeed(etSeedWords.getText().toString());
|
||||
seed.setName(etAccountName.getText().toString());
|
||||
seed.setType(SeedType.BRAINKEY);
|
||||
/*
|
||||
* Final service connection
|
||||
* */
|
||||
finalStep(crystalLoading);
|
||||
|
||||
accountSeedViewModel.addSeed(seed);
|
||||
/*
|
||||
* Validate mnemonic with the server
|
||||
* */
|
||||
/*final ImportBitsharesAccountRequest request = new ImportBitsharesAccountRequest(etSeedWords.getText().toString().trim(),activity);
|
||||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if(request.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED)){
|
||||
|
||||
CryptoNetAccountViewModel cryptoNetAccountViewModel = ViewModelProviders.of(this).get(CryptoNetAccountViewModel.class);
|
||||
GrapheneAccountInfoViewModel grapheneAccountInfoViewModel = ViewModelProviders.of(this).get(GrapheneAccountInfoViewModel.class);
|
||||
CryptoNetAccount cryptoNetAccount = new CryptoNetAccount();
|
||||
cryptoNetAccount.setSeedId(seed.getId());
|
||||
cryptoNetAccount.setAccountIndex(0);
|
||||
cryptoNetAccount.setCryptoNet(cy.agorise.crystalwallet.enums.CryptoNet.BITSHARES);
|
||||
cryptoNetAccountViewModel.addCryptoNetAccount(cryptoNetAccount);
|
||||
GrapheneAccountInfo grapheneAccountInfo = new GrapheneAccountInfo(cryptoNetAccount.getId());
|
||||
grapheneAccountInfo.setName(etAccountName.getText().toString());
|
||||
grapheneAccountInfoViewModel.addGrapheneAccountInfo(grapheneAccountInfo);
|
||||
//Correct
|
||||
|
||||
this.finish();*/
|
||||
CryptoNetInfoRequests.getInstance().addRequest(validatorRequest);
|
||||
finalStep(crystalLoading);
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
crystalLoading.dismiss();
|
||||
|
||||
txtErrorAccount.setVisibility(View.VISIBLE);
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.error_invalid_account));
|
||||
}
|
||||
}
|
||||
});
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request);*/
|
||||
|
||||
}
|
||||
});
|
||||
questionDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void finalStep(final CrystalLoading crystalLoading){
|
||||
|
||||
final ImportSeedActivity thisActivity = this;
|
||||
|
||||
final ImportBitsharesAccountRequest validatorRequest =
|
||||
new ImportBitsharesAccountRequest(etSeedWords.getText().toString(), getApplicationContext(), true);
|
||||
|
||||
validatorRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
|
||||
/*
|
||||
* Hide the loading dialog
|
||||
* */
|
||||
crystalLoading.dismiss();
|
||||
|
||||
if (!validatorRequest.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED)) {
|
||||
|
||||
switch (validatorRequest.getStatus()){
|
||||
case PETITION_FAILED:
|
||||
case NO_INTERNET:
|
||||
case NO_SERVER_CONNECTION:
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.NO_SERVER_CONNECTION));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case ACCOUNT_DOESNT_EXIST:
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.ACCOUNT_DOESNT_EXIST));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case BAD_SEED:
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
txtErrorAccount.setText(activity.getResources().getString(R.string.BAD_SEED));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case NO_ACCOUNT_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));
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CryptoNetInfoRequests.getInstance().addRequest(validatorRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValidationSucceeded(final ValidationField field) {
|
||||
final ImportSeedActivity activity = this;
|
||||
|
@ -183,19 +476,19 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
public void run() {
|
||||
|
||||
if (field.getView() == etPin) {
|
||||
tvPinError.setText("");
|
||||
//tvPinError.setText("");
|
||||
} else if (field.getView() == etPinConfirmation){
|
||||
tvPinConfirmationError.setText("");
|
||||
//tvPinConfirmationError.setText("");
|
||||
} else if (field.getView() == etAccountName){
|
||||
tvAccountNameError.setText("");
|
||||
//tvAccountNameError.setText("");
|
||||
} else if (field.getView() == etSeedWords){
|
||||
tvSeedWordsError.setText("");
|
||||
//tvSeedWordsError.setText("");
|
||||
}
|
||||
|
||||
if (activity.importSeedValidator.isValid()){
|
||||
btnImport.setEnabled(true);
|
||||
enableCreate();
|
||||
} else {
|
||||
btnImport.setEnabled(false);
|
||||
disableCreate();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -205,13 +498,40 @@ public class ImportSeedActivity extends AppCompatActivity implements UIValidator
|
|||
@Override
|
||||
public void onValidationFailed(ValidationField field) {
|
||||
if (field.getView() == etPin) {
|
||||
tvPinError.setText(field.getMessage());
|
||||
//tvPinError.setText(field.getMessage());
|
||||
} else if (field.getView() == etPinConfirmation){
|
||||
tvPinConfirmationError.setText(field.getMessage());
|
||||
//tvPinConfirmationError.setText(field.getMessage());
|
||||
} else if (field.getView() == etAccountName){
|
||||
tvAccountNameError.setText(field.getMessage());
|
||||
//tvAccountNameError.setText(field.getMessage());
|
||||
} else if (field.getView() == etSeedWords){
|
||||
tvSeedWordsError.setText(field.getMessage());
|
||||
//tvSeedWordsError.setText(field.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Enable create button
|
||||
* */
|
||||
private void enableCreate() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//btnImport.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
|
||||
btnImport.setEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable create button
|
||||
* */
|
||||
private void disableCreate() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
btnImport.setEnabled(false);
|
||||
//btnImport.setBackground(getDrawable(R.drawable.disable_style));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,55 +2,43 @@ package cy.agorise.crystalwallet.activities;
|
|||
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.util.List;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
||||
import cy.agorise.crystalwallet.application.CrystalApplication;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.dialogs.material.ToastIt;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.fragments.ImportAccountOptionsFragment;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.network.CryptoNetManager;
|
||||
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoCoinBalanceGenerator;
|
||||
import cy.agorise.crystalwallet.randomdatagenerators.RandomCryptoNetAccountGenerator;
|
||||
import cy.agorise.crystalwallet.randomdatagenerators.RandomSeedGenerator;
|
||||
import cy.agorise.crystalwallet.randomdatagenerators.RandomTransactionsGenerator;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.fragments.ImportAccountOptionsFragment;
|
||||
import cy.agorise.crystalwallet.viewmodels.AccountSeedListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel;
|
||||
import cy.agorise.crystalwallet.views.TransactionListView;
|
||||
|
||||
public class IntroActivity extends CustomActivity {
|
||||
|
||||
@BindView(R.id.surface_view)
|
||||
public SurfaceView mSurfaceView;
|
||||
@BindView(R.id.ivAnimation)
|
||||
ImageView ivAnimation;
|
||||
|
||||
@BindView(R.id.btnCreateAccount)
|
||||
public Button btnCreateAccount;
|
||||
Button btnCreateAccount;
|
||||
|
||||
@BindView(R.id.btnImportAccount)
|
||||
public Button btnImportAccount;
|
||||
Button btnImportAccount;
|
||||
|
||||
/*
|
||||
* For the window animation
|
||||
* */
|
||||
// private MediaPlayer mediaPlayer;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -59,50 +47,49 @@ public class IntroActivity extends CustomActivity {
|
|||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
// Appbar animation
|
||||
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceCreated");
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(IntroActivity.this, R.raw.appbar_background);
|
||||
mediaPlayer.setDisplay(mSurfaceView.getHolder());
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAnimation);
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
||||
//Log.d(TAG,"surfaceChanged");
|
||||
}
|
||||
/*
|
||||
* Integration of library with button effects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCreateAccount)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
createAccount();
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnImportAccount)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
importAccount();
|
||||
}
|
||||
} );
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
|
||||
this.getApplication().registerActivityLifecycleCallbacks(CrystalSecurityMonitor.getInstance(this));
|
||||
|
||||
//Checks if the user has any seed created
|
||||
AccountSeedListViewModel accountSeedListViewModel = ViewModelProviders.of(this).get(AccountSeedListViewModel.class);
|
||||
|
||||
|
||||
|
||||
//Checks if the user has any seed created
|
||||
AccountSeedListViewModel accountSeedListViewModel = ViewModelProviders.of(this).get(AccountSeedListViewModel.class);
|
||||
|
||||
if (accountSeedListViewModel.accountSeedsCount() == 0) {
|
||||
//If the user doesn't have any seeds created, then
|
||||
//send the user to create/import an account
|
||||
//Intent intent = new Intent(this, AccountSeedsManagementActivity.class);
|
||||
//Intent intent = new Intent(this, ImportSeedActivity.class);
|
||||
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
||||
//startActivity(intent);
|
||||
} else {
|
||||
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
||||
Intent intent = new Intent(this, BoardActivity.class);
|
||||
//Intent intent = new Intent(this, PocketRequestActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
if (accountSeedListViewModel.accountSeedsCount() == 0) {
|
||||
//If the user doesn't have any seeds created, then
|
||||
//send the user to create/import an account
|
||||
//Intent intent = new Intent(this, AccountSeedsManagementActivity.class);
|
||||
//Intent intent = new Intent(this, ImportSeedActivity.class);
|
||||
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
||||
//startActivity(intent);
|
||||
} else {
|
||||
//Intent intent = new Intent(this, CreateSeedActivity.class);
|
||||
Intent intent = new Intent(this, BoardActivity.class);
|
||||
//Intent intent = new Intent(this, PocketRequestActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/*CrystalDatabase db = CrystalDatabase.getAppDatabase(getApplicationContext());
|
||||
List<AccountSeed> seeds = RandomSeedGenerator.generateSeeds(2);
|
||||
|
|
|
@ -4,7 +4,11 @@ import android.content.Intent;
|
|||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -20,8 +24,17 @@ public class LicenseActivity extends AppCompatActivity {
|
|||
|
||||
@BindView(R.id.wvEULA) WebView wvEULA;
|
||||
|
||||
@BindView(R.id.btnDisAgree)
|
||||
Button btnDisAgree;
|
||||
|
||||
@BindView(R.id.btnAgree)
|
||||
Button btnAgree;
|
||||
|
||||
CrystalDatabase db;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -29,10 +42,23 @@ public class LicenseActivity extends AppCompatActivity {
|
|||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
// TODO check if license has been agreed
|
||||
|
||||
String html = getString(R.string.licence_html);
|
||||
wvEULA.loadData(html, "text/html", "UTF-8");
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnDisAgree)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
onDisagree();
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnAgree)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
onAgree();
|
||||
}
|
||||
} );
|
||||
|
||||
db = CrystalDatabase.getAppDatabase(this.getApplicationContext());
|
||||
int licenseVersion = getResources().getInteger(R.integer.license_version);
|
||||
|
@ -43,6 +69,9 @@ public class LicenseActivity extends AppCompatActivity {
|
|||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
else{
|
||||
wvEULA.loadUrl("file:///android_asset/crystal_eula.html");
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnAgree)
|
||||
|
|
|
@ -1,31 +1,64 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.andrognito.patternlockview.PatternLockView;
|
||||
import com.andrognito.patternlockview.listener.PatternLockViewListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
//import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.util.PasswordManager;
|
||||
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
||||
|
||||
public class PatternRequestActivity extends AppCompatActivity {
|
||||
|
||||
private String patternEncrypted;
|
||||
|
||||
@BindView(R.id.tvPatternText)
|
||||
TextView tvPatternText;
|
||||
|
||||
@BindView(R.id.txtBadtry)
|
||||
TextView txtBadtry;
|
||||
|
||||
/*
|
||||
* External listener for success or fail
|
||||
* */
|
||||
private static OnResponse onResponse;
|
||||
|
||||
/*
|
||||
* Contains the bad tries
|
||||
* */
|
||||
private int tries = 0;
|
||||
|
||||
/*
|
||||
* Seconds counter
|
||||
* */
|
||||
private int seconds = 15;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
//Do nothing to prevent the user to use the back button
|
||||
|
@ -34,12 +67,15 @@ public class PatternRequestActivity extends AppCompatActivity {
|
|||
@BindView(R.id.patternLockView)
|
||||
PatternLockView patternLockView;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_pattern_request);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
//onResponse = null;
|
||||
|
||||
GeneralSettingListViewModel generalSettingListViewModel = ViewModelProviders.of(this).get(GeneralSettingListViewModel.class);
|
||||
LiveData<List<GeneralSetting>> generalSettingsLiveData = generalSettingListViewModel.getGeneralSettingList();
|
||||
|
||||
|
@ -71,13 +107,26 @@ public class PatternRequestActivity extends AppCompatActivity {
|
|||
public void onComplete(List<PatternLockView.Dot> pattern) {
|
||||
if (PasswordManager.checkPassword(patternEncrypted,patternToString(pattern))){
|
||||
if (CrystalSecurityMonitor.getInstance(null).is2ndFactorSet()) {
|
||||
CrystalSecurityMonitor.getInstance(null).call2ndFactor(thisActivity);
|
||||
//CrystalSecurityMonitor.getInstance(null).call2ndFactor(thisActivity);
|
||||
thisActivity.finish();
|
||||
|
||||
/*if(onResponse != null){
|
||||
onResponse.onSuccess();
|
||||
}*/
|
||||
|
||||
} else {
|
||||
thisActivity.finish();
|
||||
|
||||
/*if(onResponse != null){
|
||||
onResponse.onSuccess();
|
||||
}*/
|
||||
}
|
||||
} else {
|
||||
patternLockView.clearPattern();
|
||||
patternLockView.requestFocus();
|
||||
incorrect();
|
||||
|
||||
/*if(onResponse != null){
|
||||
onResponse.onFailed();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +144,104 @@ public class PatternRequestActivity extends AppCompatActivity {
|
|||
});
|
||||
}
|
||||
|
||||
public static void setOnResponse(OnResponse onResponse) {
|
||||
PatternRequestActivity.onResponse = onResponse;
|
||||
}
|
||||
|
||||
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
|
||||
* */
|
||||
tvPatternText.setText(activity.getResources().getString(R.string.Incorrect_pattern));
|
||||
tvPatternText.setTextColor(Color.RED);
|
||||
tvPatternText.setVisibility(View.VISIBLE);
|
||||
final Timer t = new Timer();
|
||||
t.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
t.cancel();
|
||||
tvPatternText.setVisibility(View.INVISIBLE);
|
||||
patternLockView.clearPattern();
|
||||
patternLockView.requestFocus();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
//Set how long before to start calling the TimerTask (in milliseconds)
|
||||
1000,
|
||||
//Set the amount of time between each execution (in milliseconds)
|
||||
1000);
|
||||
}
|
||||
|
||||
public String patternToString(List<PatternLockView.Dot> pattern){
|
||||
String patternString = "";
|
||||
for (PatternLockView.Dot nextDot : pattern){
|
||||
|
|
|
@ -1,21 +1,37 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import butterknife.BindView;
|
||||
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.DialogMaterial;
|
||||
import cy.agorise.crystalwallet.dialogs.material.NegativeResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.PositiveResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.QuestionDialog;
|
||||
import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.util.PasswordManager;
|
||||
|
@ -24,6 +40,29 @@ import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
|||
public class PinRequestActivity extends AppCompatActivity {
|
||||
private String passwordEncrypted;
|
||||
|
||||
@BindView(R.id.btnOK)
|
||||
Button btnOK;
|
||||
|
||||
@BindView(R.id.txtBadtry)
|
||||
TextView txtBadtry;
|
||||
|
||||
/*
|
||||
* Contains the bad tries
|
||||
* */
|
||||
private int tries = 0;
|
||||
|
||||
/*
|
||||
* Seconds counter
|
||||
* */
|
||||
private int seconds = 15;
|
||||
|
||||
/*
|
||||
* External listener for success or fail
|
||||
* */
|
||||
private static OnResponse onResponse;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
//Do nothing to prevent the user to use the back button
|
||||
|
@ -38,6 +77,13 @@ public class PinRequestActivity extends AppCompatActivity {
|
|||
setContentView(R.layout.activity_pin_request);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
//onResponse = null;
|
||||
|
||||
/*
|
||||
* Initially the button is disabled till the user type a valid PIN
|
||||
* */
|
||||
btnOK.setEnabled(false);
|
||||
|
||||
GeneralSettingListViewModel generalSettingListViewModel = ViewModelProviders.of(this).get(GeneralSettingListViewModel.class);
|
||||
LiveData<List<GeneralSetting>> generalSettingsLiveData = generalSettingListViewModel.getGeneralSettingList();
|
||||
generalSettingsLiveData.observe(this, new Observer<List<GeneralSetting>>() {
|
||||
|
@ -59,17 +105,139 @@ public class PinRequestActivity extends AppCompatActivity {
|
|||
});
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.etPassword,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterPasswordChanged(Editable editable) {
|
||||
|
||||
@OnClick(R.id.btnOK)
|
||||
void okClic(final View view) {
|
||||
|
||||
if (PasswordManager.checkPassword(passwordEncrypted, etPassword.getText().toString())) {
|
||||
if (CrystalSecurityMonitor.getInstance(null).is2ndFactorSet()) {
|
||||
CrystalSecurityMonitor.getInstance(null).call2ndFactor(this);
|
||||
|
||||
if(onResponse != null){
|
||||
onResponse.onSuccess();
|
||||
}
|
||||
|
||||
} else {
|
||||
this.finish();
|
||||
|
||||
if(onResponse != null){
|
||||
onResponse.onFailed();
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
/*
|
||||
* One more bad try
|
||||
* */
|
||||
++tries;
|
||||
|
||||
final Activity activity = this;
|
||||
|
||||
etPassword.setTextColor(Color.RED);
|
||||
|
||||
/*
|
||||
* User can not go more up to 5 bad tries
|
||||
* */
|
||||
if(tries==4){
|
||||
tries = 0;
|
||||
|
||||
btnOK.setEnabled(false);
|
||||
etPassword.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() {
|
||||
btnOK.setEnabled(true);
|
||||
etPassword.setEnabled(true);
|
||||
txtBadtry.setVisibility(View.INVISIBLE);
|
||||
etPassword.setText("");
|
||||
etPassword.setTextColor(Color.WHITE);
|
||||
}
|
||||
});
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set in red the rext and reset the password after a period of time
|
||||
* */
|
||||
final Timer t = new Timer();
|
||||
//Set the schedule function and rate
|
||||
t.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//Called each time when 1000 milliseconds (1 second) (the period parameter)
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
etPassword.setText("");
|
||||
etPassword.setTextColor(Color.WHITE);
|
||||
t.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
//Set how long before to start calling the TimerTask (in milliseconds)
|
||||
500,
|
||||
//Set the amount of time between each execution (in milliseconds)
|
||||
500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void setOnResponse(OnResponse onResponse) {
|
||||
PinRequestActivity.onResponse = onResponse;
|
||||
}
|
||||
|
||||
|
||||
@OnTextChanged(value = R.id.etPassword,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterPasswordChanged(Editable editable) {
|
||||
|
||||
/*
|
||||
* If it is valid length enable button
|
||||
* */
|
||||
if(etPassword.getText().length()>=6){
|
||||
btnOK.setEnabled(true);
|
||||
}
|
||||
else{
|
||||
btnOK.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,18 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.jaredrummler.materialspinner.MaterialSpinner;
|
||||
|
||||
|
@ -38,7 +41,7 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali
|
|||
SendTransactionValidator sendTransactionValidator;
|
||||
|
||||
@BindView(R.id.spFrom)
|
||||
MaterialSpinner spFrom;
|
||||
Spinner spFrom;
|
||||
@BindView(R.id.tvFromError)
|
||||
TextView tvFromError;
|
||||
@BindView(R.id.etTo)
|
||||
|
@ -62,6 +65,9 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali
|
|||
//@BindView(R.id.btnCancel)
|
||||
Button btnCancel;
|
||||
|
||||
@BindView(R.id.fabCloseCamera)
|
||||
FloatingActionButton btnCloseCamera;
|
||||
|
||||
private long cryptoNetAccountId;
|
||||
private CryptoNetAccount cryptoNetAccount;
|
||||
private GrapheneAccount grapheneAccount;
|
||||
|
@ -146,6 +152,15 @@ public class SendTransactionActivity extends AppCompatActivity implements UIVali
|
|||
this.finish();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@OnClick(R.id.fabCloseCamera)
|
||||
public void onClicCloseCamera(){
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//@OnClick(R.id.btnSend)
|
||||
public void importSend(){
|
||||
if (this.sendTransactionValidator.isValid()) {
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package cy.agorise.crystalwallet.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sjaramillo10.animatedtablayout.AnimatedTabLayout;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -35,21 +34,22 @@ public class SettingsActivity extends AppCompatActivity{
|
|||
public ImageView ivGoBack;
|
||||
|
||||
@BindView(R.id.tabLayout)
|
||||
public AnimatedTabLayout tabLayout;
|
||||
public TabLayout tabLayout;
|
||||
|
||||
@BindView(R.id.pager)
|
||||
public ViewPager mPager;
|
||||
|
||||
public SettingsPagerAdapter settingsPagerAdapter;
|
||||
|
||||
@BindView(R.id.surface_view)
|
||||
public SurfaceView mSurfaceView;
|
||||
|
||||
@BindView(R.id.tvBuildVersion)
|
||||
public TextView tvBuildVersion;
|
||||
|
||||
private SecuritySettingsFragment securitySettingsFragment;
|
||||
|
||||
@BindView(R.id.ivAppBarAnimation)
|
||||
ImageView ivAppBarAnimation;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -59,27 +59,11 @@ public class SettingsActivity extends AppCompatActivity{
|
|||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Appbar animation
|
||||
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceCreated");
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(SettingsActivity.this, R.raw.appbar_background);
|
||||
mediaPlayer.setDisplay(mSurfaceView.getHolder());
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
||||
//Log.d(TAG,"surfaceChanged");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||
//Log.d(TAG,"surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
// Sets AppBar animation
|
||||
Glide.with(this)
|
||||
.load(R.drawable.appbar_background)
|
||||
.apply(new RequestOptions().centerCrop())
|
||||
.into(ivAppBarAnimation);
|
||||
|
||||
settingsPagerAdapter = new SettingsPagerAdapter(getSupportFragmentManager());
|
||||
mPager.setAdapter(settingsPagerAdapter);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package cy.agorise.crystalwallet.apigenerator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
@ -9,7 +8,6 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.application.constant.BitsharesConstant;
|
||||
import cy.agorise.crystalwallet.dao.BitsharesAssetDao;
|
||||
import cy.agorise.crystalwallet.dao.CryptoCoinBalanceDao;
|
||||
import cy.agorise.crystalwallet.dao.CryptoCurrencyDao;
|
||||
|
@ -82,13 +80,32 @@ public abstract class GrapheneApiGenerator {
|
|||
*/
|
||||
private static HashMap<Long,SubscriptionListener> currentBitsharesListener = new HashMap<>();
|
||||
|
||||
|
||||
// The message broker for Steem
|
||||
private static SubscriptionMessagesHub steemSubscriptionHub = new SubscriptionMessagesHub("", "", true, new NodeErrorListener() {
|
||||
@Override
|
||||
public void onError(BaseResponse.Error error) {
|
||||
//TODO subcription hub error
|
||||
System.out.println("GrapheneAPI error");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The Steem subscription thread for the real time updates
|
||||
*/
|
||||
private static WebSocketThread steemSubscriptionThread = new WebSocketThread(steemSubscriptionHub, CryptoNetManager.getURL(CryptoNet.STEEM));
|
||||
/**
|
||||
* This is used for manager each Steem listener in the subscription thread
|
||||
*/
|
||||
private static HashMap<Long,SubscriptionListener> currentSteemListener = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Retrieves the data of an account searching by it's id
|
||||
*
|
||||
* @param accountId The accountId to retrieve
|
||||
* @param request The Api request object, to answer this petition
|
||||
*/
|
||||
public static void getAccountById(String accountId, final ApiRequest request){
|
||||
public static void getAccountById(String accountId, CryptoNet cryptoNet, final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetAccounts(accountId,
|
||||
new WitnessResponseListener() {
|
||||
@Override
|
||||
|
@ -109,7 +126,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -119,25 +136,37 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param address The address to retrieve
|
||||
* @param request The Api request object, to answer this petition
|
||||
*/
|
||||
public static void getAccountByOwnerOrActiveAddress(Address address, final ApiRequest request){
|
||||
public static void getAccountByOwnerOrActiveAddress(Address address, CryptoNet cryptoNet, final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetKeyReferences(address, true,
|
||||
new WitnessResponseListener() {
|
||||
@Override
|
||||
public void onSuccess(WitnessResponse response) {
|
||||
final List<List<UserAccount>> resp = (List<List<UserAccount>>) response.result;
|
||||
if(resp.size() > 0){
|
||||
List<UserAccount> accounts = resp.get(0);
|
||||
if(accounts.size() > 0){
|
||||
for(UserAccount account : accounts) {
|
||||
request.getListener().success(account,request.getId());}}}
|
||||
request.getListener().fail(request.getId());
|
||||
try {
|
||||
final List<List<UserAccount>> resp = (List<List<UserAccount>>) response.result;
|
||||
if (resp.size() > 0) {
|
||||
List<UserAccount> accounts = resp.get(0);
|
||||
if (accounts.size() > 0) {
|
||||
for (UserAccount account : accounts) {
|
||||
request.getListener().success(account, request.getId());
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
} else {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
@ -152,7 +181,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param request The Api request object, to answer this petition
|
||||
*/
|
||||
public static void getAccountTransaction(String accountGrapheneId, int start, int stop,
|
||||
int limit, final ApiRequest request){
|
||||
int limit, CryptoNet cryptoNet, final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetRelativeAccountHistory(new UserAccount(accountGrapheneId),
|
||||
start, limit, stop, new WitnessResponseListener() {
|
||||
@Override
|
||||
|
@ -164,7 +193,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -174,7 +203,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param accountName The account Name to find
|
||||
* @param request The Api request object, to answer this petition
|
||||
*/
|
||||
public static void getAccountByName(String accountName, final ApiRequest request){
|
||||
public static void getAccountByName(String accountName, CryptoNet cryptoNet,final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetAccountByName(accountName,
|
||||
new WitnessResponseListener() {
|
||||
@Override
|
||||
|
@ -191,7 +220,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -201,7 +230,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param accountName The account Name to find
|
||||
* @param request The Api request object, to answer this petition
|
||||
*/
|
||||
public static void getAccountIdByName(String accountName, final ApiRequest request){
|
||||
public static void getAccountIdByName(String accountName, CryptoNet cryptoNet, final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetAccountByName(accountName,
|
||||
new WitnessResponseListener() {
|
||||
@Override
|
||||
|
@ -218,7 +247,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -252,7 +281,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param assetNames The list of the names of the assets to be retrieve
|
||||
* @param request the api request object, to answer this petition
|
||||
*/
|
||||
public static void getAssetByName(ArrayList<String> assetNames, final ApiRequest request){
|
||||
public static void getAssetByName(ArrayList<String> assetNames, CryptoNet cryptoNet,final ApiRequest request){
|
||||
|
||||
WebSocketThread thread = new WebSocketThread(new LookupAssetSymbols(assetNames,true,
|
||||
new WitnessResponseListener() {
|
||||
|
@ -287,7 +316,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -296,7 +325,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param assetIds The list of the ids to retrieve
|
||||
* @param request the api request object, to answer this petition
|
||||
*/
|
||||
public static void getAssetById(ArrayList<String> assetIds, final ApiRequest request){
|
||||
public static void getAssetById(ArrayList<String> assetIds, CryptoNet cryptoNet, final ApiRequest request){
|
||||
ArrayList<Asset> assets = new ArrayList<>();
|
||||
for(String assetId : assetIds){
|
||||
Asset asset = new Asset(assetId);
|
||||
|
@ -335,7 +364,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -369,7 +398,7 @@ public abstract class GrapheneApiGenerator {
|
|||
if(operation instanceof TransferOperation){
|
||||
final TransferOperation tOperation = (TransferOperation) operation;
|
||||
if(tOperation.getFrom().getObjectId().equals(accountBitsharesId) || tOperation.getTo().getObjectId().equals(accountBitsharesId)){
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountBitsharesId,context);
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountBitsharesId,CryptoNet.BITSHARES,context);
|
||||
final CryptoCoinTransaction transaction = new CryptoCoinTransaction();
|
||||
transaction.setAccountId(accountId);
|
||||
transaction.setAmount(tOperation.getAssetAmount().getAmount().longValue());
|
||||
|
@ -407,7 +436,7 @@ public abstract class GrapheneApiGenerator {
|
|||
});
|
||||
ArrayList<String> assets = new ArrayList<>();
|
||||
assets.add(tOperation.getAssetAmount().getAsset().getObjectId());
|
||||
GrapheneApiGenerator.getAssetById(assets,assetRequest);
|
||||
GrapheneApiGenerator.getAssetById(assets,CryptoNet.BITSHARES,assetRequest);
|
||||
}else{
|
||||
saveTransaction(transaction,cryptoCurrencyDao.getById(info.getCryptoCurrencyId()),accountBitsharesId,tOperation,context);
|
||||
}
|
||||
|
@ -432,6 +461,99 @@ public abstract class GrapheneApiGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe a steem account to receive real time updates
|
||||
*
|
||||
* @param accountId The id opf the database of the account
|
||||
* @param accountSteemId The steem id of the account
|
||||
* @param context The android context of this application
|
||||
*/
|
||||
public static void subscribeSteemAccount(final long accountId, final String accountSteemId,
|
||||
final Context context){
|
||||
if(!currentSteemListener.containsKey(accountId)){
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
final BitsharesAssetDao bitsharesAssetDao = db.bitsharesAssetDao();
|
||||
final CryptoCurrencyDao cryptoCurrencyDao = db.cryptoCurrencyDao();
|
||||
SubscriptionListener balanceListener = new SubscriptionListener() {
|
||||
@Override
|
||||
public ObjectType getInterestObjectType() {
|
||||
return ObjectType.TRANSACTION_OBJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscriptionUpdate(SubscriptionResponse response) {
|
||||
List<Serializable> updatedObjects = (List<Serializable>) response.params.get(1);
|
||||
if(updatedObjects.size() > 0){
|
||||
for(Serializable update : updatedObjects){
|
||||
if(update instanceof BroadcastedTransaction){
|
||||
BroadcastedTransaction transactionUpdate = (BroadcastedTransaction) update;
|
||||
for(BaseOperation operation : transactionUpdate.getTransaction().getOperations()){
|
||||
if(operation instanceof TransferOperation){
|
||||
final TransferOperation tOperation = (TransferOperation) operation;
|
||||
if(tOperation.getFrom().getObjectId().equals(accountSteemId) || tOperation.getTo().getObjectId().equals(accountSteemId)){
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountSteemId,CryptoNet.STEEM,context);
|
||||
final CryptoCoinTransaction transaction = new CryptoCoinTransaction();
|
||||
transaction.setAccountId(accountId);
|
||||
transaction.setAmount(tOperation.getAssetAmount().getAmount().longValue());
|
||||
BitsharesAssetInfo info = bitsharesAssetDao.getBitsharesAssetInfoById(tOperation.getAssetAmount().getAsset().getObjectId());
|
||||
if (info == null) {
|
||||
//The cryptoCurrency is not in the database, queringfor its data
|
||||
ApiRequest assetRequest = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
ArrayList<BitsharesAsset> assets = (ArrayList<BitsharesAsset>) answer;
|
||||
for(BitsharesAsset asset : assets){
|
||||
|
||||
long currencyId = -1;
|
||||
CryptoCurrency cryptoCurrencyDb = cryptoCurrencyDao.getByNameAndCryptoNet(((BitsharesAsset) answer).getName(),((BitsharesAsset) answer).getCryptoNet().name());
|
||||
|
||||
if (cryptoCurrencyDb != null){
|
||||
currencyId = cryptoCurrencyDb.getId();
|
||||
} else {
|
||||
long idCryptoCurrency = cryptoCurrencyDao.insertCryptoCurrency(asset)[0];
|
||||
currencyId = idCryptoCurrency;
|
||||
}
|
||||
|
||||
BitsharesAssetInfo info = new BitsharesAssetInfo(asset);
|
||||
info.setCryptoCurrencyId(currencyId);
|
||||
asset.setId((int)currencyId);
|
||||
bitsharesAssetDao.insertBitsharesAssetInfo(info);
|
||||
saveTransaction(transaction,cryptoCurrencyDao.getById(info.getCryptoCurrencyId()),accountSteemId,tOperation,context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//TODO error retrieving asset
|
||||
}
|
||||
});
|
||||
ArrayList<String> assets = new ArrayList<>();
|
||||
assets.add(tOperation.getAssetAmount().getAsset().getObjectId());
|
||||
GrapheneApiGenerator.getAssetById(assets,CryptoNet.STEEM,assetRequest);
|
||||
}else{
|
||||
saveTransaction(transaction,cryptoCurrencyDao.getById(info.getCryptoCurrencyId()),accountSteemId,tOperation,context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
currentSteemListener.put(accountId,balanceListener);
|
||||
steemSubscriptionHub.addSubscriptionListener(balanceListener);
|
||||
|
||||
if(!steemSubscriptionThread.isConnected()){
|
||||
steemSubscriptionThread.start();
|
||||
}else if(!steemSubscriptionHub.isSubscribed()){
|
||||
steemSubscriptionHub.resubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to save a transaction retrieved from the update
|
||||
* @param transaction The transaction db object
|
||||
|
@ -470,7 +592,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param context The android context of this application
|
||||
*/
|
||||
public static void getAccountBalance(final long accountId, final String accountGrapheneId,
|
||||
final Context context){
|
||||
final CryptoNet cryptoNet, final Context context){
|
||||
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
final CryptoCoinBalanceDao balanceDao = db.cryptoCoinBalanceDao();
|
||||
|
@ -516,7 +638,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void fail(int idPetition) {
|
||||
}
|
||||
});
|
||||
getAssetById(idAssets,getAssetRequest);
|
||||
getAssetById(idAssets,cryptoNet,getAssetRequest);
|
||||
|
||||
}else {
|
||||
|
||||
|
@ -530,7 +652,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
|
||||
thread.start();
|
||||
|
||||
|
@ -542,7 +664,7 @@ public abstract class GrapheneApiGenerator {
|
|||
* @param blockHeader The block header to retrieve the date time
|
||||
* @param request the api request object, to answer this petition
|
||||
*/
|
||||
public static void getBlockHeaderTime(long blockHeader, final ApiRequest request){
|
||||
public static void getBlockHeaderTime(long blockHeader, CryptoNet cryptoNet,final ApiRequest request){
|
||||
WebSocketThread thread = new WebSocketThread(new GetBlockHeader(blockHeader, new WitnessResponseListener() {
|
||||
@Override
|
||||
public void onSuccess(WitnessResponse response) {
|
||||
|
@ -557,7 +679,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
@ -625,7 +747,7 @@ public abstract class GrapheneApiGenerator {
|
|||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
final CryptoCurrencyDao cryptoCurrencyDao = db.cryptoCurrencyDao();
|
||||
final BitsharesAssetDao bitsharesAssetDao = db.bitsharesAssetDao();
|
||||
CryptoCurrency baseCurrency = cryptoCurrencyDao.getByName(baseAssetName);
|
||||
CryptoCurrency baseCurrency = cryptoCurrencyDao.getByName(baseAssetName,CryptoNet.BITSHARES.name());
|
||||
BitsharesAssetInfo info = null;
|
||||
if(baseCurrency != null){
|
||||
info = db.bitsharesAssetDao().getBitsharesAssetInfo(baseCurrency.getId());
|
||||
|
@ -660,7 +782,7 @@ public abstract class GrapheneApiGenerator {
|
|||
});
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
names.add(baseAssetName);
|
||||
GrapheneApiGenerator.getAssetByName(names,getAssetRequest);
|
||||
GrapheneApiGenerator.getAssetByName(names,CryptoNet.BITSHARES,getAssetRequest);
|
||||
|
||||
}else {
|
||||
BitsharesAsset baseAsset = new BitsharesAsset(baseCurrency);
|
||||
|
|
|
@ -1,49 +1,81 @@
|
|||
package cy.agorise.crystalwallet.apigenerator;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.AddressesActivityWatcher;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.BroadcastTransaction;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.GetEstimateFee;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionByAddress;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.GetTransactionData;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.network.CryptoNetManager;
|
||||
|
||||
public class InsightApiGenerator {
|
||||
|
||||
private static HashMap<CryptoNet,BroadcastTransaction> broadcaster = new HashMap();
|
||||
private static HashMap<CryptoNet,GetTransactionByAddress> transactionGetters = new HashMap();
|
||||
private static HashMap<CryptoNet,GetTransactionData> transacitonFollowers = new HashMap();
|
||||
private static HashMap<CryptoCoin,GetTransactionByAddress> transactionGetters = new HashMap();
|
||||
private static HashMap<CryptoCoin,AddressesActivityWatcher> transactionFollowers = new HashMap();
|
||||
|
||||
public static void getTransactionFromAddress(CryptoNet cryptoNet, String address,
|
||||
ApiRequest request, Context context,
|
||||
boolean subscribe){
|
||||
if(!transactionGetters.containsKey(cryptoNet)){
|
||||
//TODO change this line
|
||||
transactionGetters.put(cryptoNet,new GetTransactionByAddress(null,CryptoNetManager.getURL(cryptoNet),context));
|
||||
private static final String PATH = "api";
|
||||
|
||||
/**
|
||||
* Fecth all the transaciton for a giving address
|
||||
* @param cryptoCoin the crypto net of the address
|
||||
* @param address The address String
|
||||
* @param subscribe If needs to follow the address (Real time)
|
||||
*/
|
||||
public static void getTransactionFromAddress(CryptoCoin cryptoCoin, String address, boolean subscribe, HasTransactionListener listener){
|
||||
/*if(!transactionGetters.containsKey(cryptoCoin)){
|
||||
transactionGetters.put(cryptoCoin,new GetTransactionByAddress(cryptoCoin,CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),PATH));
|
||||
}
|
||||
transactionGetters.get(cryptoCoin).addAddress(address);
|
||||
transactionGetters.get(cryptoCoin).start();*/
|
||||
|
||||
}
|
||||
GetTransactionByAddress transByAddr = new GetTransactionByAddress(cryptoCoin,CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),PATH,listener);
|
||||
transByAddr.addAddress(address);
|
||||
transByAddr.start();
|
||||
|
||||
public static void followTransaction(CryptoNet cryptoNet, String txid, Context context){
|
||||
|
||||
}
|
||||
|
||||
public static void broadcastTransaction(CryptoNet cryptoNet, String rawtx, ApiRequest request){
|
||||
if(!broadcaster.containsKey(cryptoNet)){
|
||||
//TODO change to multiple broadcast
|
||||
broadcaster.put(cryptoNet,new BroadcastTransaction(rawtx,null,
|
||||
CryptoNetManager.getURL(cryptoNet),null));
|
||||
broadcaster.get(cryptoNet).start();
|
||||
if(subscribe){
|
||||
if(!transactionFollowers.containsKey(cryptoCoin)){
|
||||
transactionFollowers.put(cryptoCoin,new AddressesActivityWatcher(CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),PATH,cryptoCoin));
|
||||
}
|
||||
transactionFollowers.get(cryptoCoin).addAddress(address);
|
||||
transactionFollowers.get(cryptoCoin).connect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void getEstimateFee(CryptoNet cryptoNet, final ApiRequest request){
|
||||
GetEstimateFee.getEstimateFee(CryptoNetManager.getURL(cryptoNet), new GetEstimateFee.estimateFeeListener() {
|
||||
/**
|
||||
* Broadcast an insight api transaction
|
||||
* @param cryptoCoin The cryptoNet of the transaction
|
||||
* @param rawtx the transaction to be broadcasted
|
||||
*/
|
||||
public static void broadcastTransaction(CryptoCoin cryptoCoin, String rawtx, final ApiRequest request){
|
||||
BroadcastTransaction bTransaction = new BroadcastTransaction(rawtx,
|
||||
CryptoNetManager.getURL(cryptoCoin.getCryptoNet()), PATH, new BroadcastTransaction.BroadCastTransactionListener() {
|
||||
@Override
|
||||
public void estimateFee(long value) {
|
||||
public void onSuccess() {
|
||||
request.getListener().success(true,request.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String msg) {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnecitonFailure() {
|
||||
request.getListener().fail(request.getId());
|
||||
}
|
||||
});
|
||||
bTransaction.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the estimated fee for a transaction
|
||||
*/
|
||||
public static void getEstimateFee(CryptoCoin cryptoCoin, final ApiRequest request){
|
||||
GetEstimateFee.getEstimateFee(CryptoNetManager.getURL(cryptoCoin.getCryptoNet()),
|
||||
new GetEstimateFee.estimateFeeListener() {
|
||||
@Override
|
||||
public void estimateFee(double value) {
|
||||
request.listener.success(value,request.getId());
|
||||
}
|
||||
|
||||
|
@ -53,4 +85,8 @@ public class InsightApiGenerator {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface HasTransactionListener{
|
||||
public void hasTransaction(boolean value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAccount;
|
||||
import io.socket.client.IO;
|
||||
import io.socket.client.Socket;
|
||||
|
@ -24,12 +25,9 @@ import io.socket.emitter.Emitter;
|
|||
*
|
||||
*/
|
||||
|
||||
public class AccountActivityWatcher {
|
||||
public class AddressesActivityWatcher {
|
||||
|
||||
/**
|
||||
* The mAccount to be monitor
|
||||
*/
|
||||
private final GeneralCoinAccount mAccount;
|
||||
private final CryptoCoin cryptoCoin;
|
||||
/**
|
||||
* The list of address to monitor
|
||||
*/
|
||||
|
@ -38,12 +36,9 @@ public class AccountActivityWatcher {
|
|||
* the Socket.IO
|
||||
*/
|
||||
private Socket mSocket;
|
||||
/**
|
||||
* This app mContext, used to save on the DB
|
||||
*/
|
||||
private final Context mContext;
|
||||
|
||||
private final String mServerUrl;
|
||||
private final String mPath;
|
||||
|
||||
/**
|
||||
* Handles the address/transaction notification.
|
||||
|
@ -55,9 +50,9 @@ public class AccountActivityWatcher {
|
|||
try {
|
||||
System.out.println("Receive accountActivtyWatcher " + os[0].toString() );
|
||||
String txid = ((JSONObject) os[0]).getString(InsightApiConstants.sTxTag);
|
||||
new GetTransactionData(txid, mAccount, mServerUrl, mContext).start();
|
||||
new GetTransactionData(txid, mServerUrl, mPath, cryptoCoin).start();
|
||||
} catch (JSONException ex) {
|
||||
Logger.getLogger(AccountActivityWatcher.class.getName()).log(Level.SEVERE, null, ex);
|
||||
Logger.getLogger(AddressesActivityWatcher.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -84,7 +79,9 @@ public class AccountActivityWatcher {
|
|||
private final Emitter.Listener onDisconnect = new Emitter.Listener() {
|
||||
@Override
|
||||
public void call(Object... os) {
|
||||
System.out.println("Disconnected to accountActivityWatcher");
|
||||
try {
|
||||
Thread.sleep(60000);
|
||||
} catch (InterruptedException ignore) {}
|
||||
mSocket.connect();
|
||||
}
|
||||
};
|
||||
|
@ -99,19 +96,21 @@ public class AccountActivityWatcher {
|
|||
for(Object ob : os) {
|
||||
System.out.println("accountActivityWatcher " + ob.toString());
|
||||
}
|
||||
try {
|
||||
Thread.sleep(60000);
|
||||
} catch (InterruptedException ignore) {}
|
||||
mSocket.connect();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Basic constructor
|
||||
*
|
||||
* @param mAccount The mAccount to be monitor
|
||||
* @param mContext This app mContext
|
||||
*/
|
||||
public AccountActivityWatcher(String serverUrl, GeneralCoinAccount mAccount, Context mContext) {
|
||||
public AddressesActivityWatcher(String serverUrl, String path, CryptoCoin cryptoCoin) {
|
||||
this.mPath = path;
|
||||
this.mServerUrl = serverUrl;
|
||||
this.mAccount = mAccount;
|
||||
this.mContext = mContext;
|
||||
this.cryptoCoin = cryptoCoin;
|
||||
try {
|
||||
this.mSocket = IO.socket(serverUrl);
|
||||
this.mSocket.on(Socket.EVENT_CONNECT, onConnect);
|
||||
|
@ -141,13 +140,11 @@ public class AccountActivityWatcher {
|
|||
* Connects the Socket
|
||||
*/
|
||||
public void connect() {
|
||||
//TODO change to use log
|
||||
System.out.println("accountActivityWatcher connecting");
|
||||
try{
|
||||
this.mSocket.connect();
|
||||
}catch(Exception e){
|
||||
//TODO change exception handler
|
||||
System.out.println("accountActivityWatcher exception " + e.getMessage());
|
||||
if(this.mSocket == null || !this.mSocket.connected()) {
|
||||
this.mSocket.connect();
|
||||
}
|
||||
}catch(Exception ignore){
|
||||
}
|
||||
}
|
||||
|
|
@ -22,29 +22,21 @@ public class BroadcastTransaction extends Thread implements Callback<Txi> {
|
|||
* The serviceGenerator to call
|
||||
*/
|
||||
private InsightApiServiceGenerator mServiceGenerator;
|
||||
/**
|
||||
* This app context, used to save on the DB
|
||||
*/
|
||||
private Context mContext;
|
||||
/**
|
||||
* The account who sign the transaction
|
||||
*/
|
||||
private GeneralCoinAccount mAccount;
|
||||
|
||||
private String serverUrl;
|
||||
private String mPath;
|
||||
|
||||
private BroadCastTransactionListener listener;
|
||||
|
||||
/**
|
||||
* Basic Consturctor
|
||||
* @param RawTx The RawTX in Hex String
|
||||
* @param account The account who signs the transaction
|
||||
* @param context This app context
|
||||
*
|
||||
*/
|
||||
public BroadcastTransaction(String RawTx, GeneralCoinAccount account, String serverUrl, Context context){
|
||||
this.serverUrl = serverUrl;
|
||||
public BroadcastTransaction(String RawTx, String serverUrl, String path, BroadCastTransactionListener listener){
|
||||
this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl);
|
||||
this.mContext = context;
|
||||
this.mRawTx = RawTx;
|
||||
this.mAccount = account;
|
||||
this.listener = listener;
|
||||
this.mPath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,13 +46,9 @@ public class BroadcastTransaction extends Thread implements Callback<Txi> {
|
|||
@Override
|
||||
public void onResponse(Call<Txi> call, Response<Txi> response) {
|
||||
if (response.isSuccessful()) {
|
||||
//TODO invalidated send
|
||||
//TODO call getTransactionData
|
||||
GetTransactionData trData = new GetTransactionData(response.body().txid,this.mAccount, this.serverUrl, this.mContext);
|
||||
trData.start();
|
||||
listener.onSuccess();
|
||||
} else {
|
||||
System.out.println("SENDTEST: not succesful " + response.message());
|
||||
//TODO change how to handle invalid transaction
|
||||
listener.onFailure(response.message());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,8 +57,7 @@ public class BroadcastTransaction extends Thread implements Callback<Txi> {
|
|||
*/
|
||||
@Override
|
||||
public void onFailure(Call<Txi> call, Throwable t) {
|
||||
//TODO change how to handle invalid transaction
|
||||
System.out.println("SENDTEST: sendError " + t.getMessage() );
|
||||
listener.onConnecitonFailure();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,8 +65,19 @@ public class BroadcastTransaction extends Thread implements Callback<Txi> {
|
|||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
InsightApiService service = this.mServiceGenerator.getService(InsightApiService.class);
|
||||
Call<Txi> broadcastTransaction = service.broadcastTransaction(InsightApiConstants.getPath(this.mAccount.getCryptoCoin()),this.mRawTx);
|
||||
broadcastTransaction.enqueue(this);
|
||||
try {
|
||||
|
||||
InsightApiService service = this.mServiceGenerator.getService(InsightApiService.class);
|
||||
Call<Txi> broadcastTransaction = service.broadcastTransaction(this.mPath, this.mRawTx);
|
||||
broadcastTransaction.enqueue(this);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public interface BroadCastTransactionListener{
|
||||
void onSuccess();
|
||||
void onFailure(String msg);
|
||||
void onConnecitonFailure();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import retrofit2.Response;
|
|||
|
||||
public abstract class GetEstimateFee {
|
||||
|
||||
private static String PATH = "api";
|
||||
|
||||
/**
|
||||
* The funciton to get the rate for the transaction be included in the next 2 blocks
|
||||
* @param serverUrl The url of the insight server
|
||||
|
@ -29,28 +31,32 @@ public abstract class GetEstimateFee {
|
|||
try {
|
||||
InsightApiServiceGenerator serviceGenerator = new InsightApiServiceGenerator(serverUrl);
|
||||
InsightApiService service = serviceGenerator.getService(InsightApiService.class);
|
||||
Call<JsonObject> call = service.estimateFee(serverUrl);
|
||||
final JsonObject answer = new JsonObject();
|
||||
Call<JsonObject> call = service.estimateFee(PATH);
|
||||
call.enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
listener.estimateFee((long) (answer.get("answer").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){
|
||||
e.printStackTrace();
|
||||
listener.fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static interface estimateFeeListener{
|
||||
public void estimateFee(long value);
|
||||
public void estimateFee(double value);
|
||||
public void fail();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package cy.agorise.crystalwallet.apigenerator.insightapi;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class GetGenesisBlock {
|
||||
|
||||
private static String PATH = "api";
|
||||
|
||||
public GetGenesisBlock(String serverUrl, final genesisBlockListener listener) {
|
||||
try {
|
||||
InsightApiServiceGenerator serviceGenerator = new InsightApiServiceGenerator(serverUrl);
|
||||
InsightApiService service = serviceGenerator.getService(InsightApiService.class);
|
||||
Call<JsonObject> call = service.genesisBlock(PATH);
|
||||
call.enqueue(new Callback<JsonObject>() {
|
||||
@Override
|
||||
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||
try {
|
||||
listener.genesisBlock(response.body().get("blockHash").getAsString());
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
listener.fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||
listener.fail();
|
||||
}
|
||||
});
|
||||
}catch(Exception e){
|
||||
listener.fail();
|
||||
}
|
||||
}
|
||||
|
||||
public interface genesisBlockListener{
|
||||
void genesisBlock(String value);
|
||||
void fail();
|
||||
}
|
||||
}
|
|
@ -1,20 +1,15 @@
|
|||
package cy.agorise.crystalwallet.apigenerator.insightapi;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.InsightApiGenerator;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.models.AddressTxi;
|
||||
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.models.GTxIO;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAccount;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAddress;
|
||||
import cy.agorise.crystalwallet.models.GeneralTransaction;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.manager.GeneralAccountManager;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
@ -25,43 +20,40 @@ import retrofit2.Response;
|
|||
*/
|
||||
|
||||
public class GetTransactionByAddress extends Thread implements Callback<AddressTxi> {
|
||||
/**
|
||||
* The account to be query
|
||||
*/
|
||||
private GeneralCoinAccount mAccount;
|
||||
/**
|
||||
* The list of address to query
|
||||
*/
|
||||
private List<GeneralCoinAddress> mAddresses = new ArrayList<>();
|
||||
private List<String> mAddresses = new ArrayList<>();
|
||||
/**
|
||||
* The serviceGenerator to call
|
||||
*/
|
||||
private InsightApiServiceGenerator mServiceGenerator;
|
||||
/**
|
||||
* This app context, used to save on the DB
|
||||
*/
|
||||
private Context mContext;
|
||||
|
||||
private String serverUrl;
|
||||
private String mServerUrl;
|
||||
|
||||
private String mPath;
|
||||
private CryptoCoin cryptoNet;
|
||||
|
||||
private boolean inProcess = false;
|
||||
|
||||
private InsightApiGenerator.HasTransactionListener listener;
|
||||
|
||||
/**
|
||||
* Basic consturcotr
|
||||
* @param account The account to be query
|
||||
* @param context This app context
|
||||
*/
|
||||
public GetTransactionByAddress(GeneralCoinAccount account, String serverUrl, Context context) {
|
||||
this.serverUrl = serverUrl;
|
||||
this.mAccount = account;
|
||||
public GetTransactionByAddress(CryptoCoin cryptoNet, String serverUrl, String path, InsightApiGenerator.HasTransactionListener listener) {
|
||||
this.mPath = path;
|
||||
this.cryptoNet = cryptoNet;
|
||||
this.mServerUrl = serverUrl;
|
||||
this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl);
|
||||
this.mContext = context;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* add an address to be query
|
||||
* @param address the address to be query
|
||||
*/
|
||||
public void addAddress(GeneralCoinAddress address) {
|
||||
public void addAddress(String address) {
|
||||
this.mAddresses.add(address);
|
||||
}
|
||||
|
||||
|
@ -73,110 +65,23 @@ public class GetTransactionByAddress extends Thread implements Callback<AddressT
|
|||
*/
|
||||
@Override
|
||||
public void onResponse(Call<AddressTxi> call, Response<AddressTxi> response) {
|
||||
inProcess = false;
|
||||
if (response.isSuccessful()) {
|
||||
boolean changed = false;
|
||||
AddressTxi addressTxi = response.body();
|
||||
if(listener != null) {
|
||||
if (addressTxi.items.length > 0 ) {
|
||||
listener.hasTransaction(true);
|
||||
}else{
|
||||
listener.hasTransaction(false);
|
||||
}
|
||||
}
|
||||
|
||||
for (Txi txi : addressTxi.items) {
|
||||
GeneralCoinAccount tempAccount = null;
|
||||
GeneralTransaction transaction = new GeneralTransaction();
|
||||
transaction.setAccount(this.mAccount);
|
||||
transaction.setTxid(txi.txid);
|
||||
transaction.setBlock(txi.blockheight);
|
||||
transaction.setDate(new Date(txi.time * 1000));
|
||||
transaction.setFee((long) (txi.fee * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
|
||||
transaction.setConfirm(txi.confirmations);
|
||||
transaction.setType(this.mAccount.getCryptoCoin());
|
||||
transaction.setBlockHeight(txi.blockheight);
|
||||
|
||||
for (Vin vin : txi.vin) {
|
||||
GTxIO input = new GTxIO();
|
||||
input.setAmount((long) (vin.value * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
|
||||
input.setTransaction(transaction);
|
||||
input.setOut(true);
|
||||
input.setType(this.mAccount.getCryptoCoin());
|
||||
String addr = vin.addr;
|
||||
input.setAddressString(addr);
|
||||
input.setIndex(vin.n);
|
||||
input.setScriptHex(vin.scriptSig.hex);
|
||||
input.setOriginalTxid(vin.txid);
|
||||
for (GeneralCoinAddress address : this.mAddresses) {
|
||||
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
|
||||
input.setAddress(address);
|
||||
tempAccount = address.getAccount();
|
||||
|
||||
if (!address.hasTransactionOutput(input, this.mAccount.getNetworkParam())) {
|
||||
address.getTransactionOutput().add(input);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
transaction.getTxInputs().add(input);
|
||||
}
|
||||
|
||||
for (Vout vout : txi.vout) {
|
||||
if(vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0){
|
||||
// The address is null, this must be a memo
|
||||
String hex = vout.scriptPubKey.hex;
|
||||
int opReturnIndex = hex.indexOf("6a");
|
||||
if(opReturnIndex >= 0) {
|
||||
byte[] memoBytes = new byte[Integer.parseInt(hex.substring(opReturnIndex+2,opReturnIndex+4),16)];
|
||||
for(int i = 0; i < memoBytes.length;i++){
|
||||
memoBytes[i] = Byte.parseByte(hex.substring(opReturnIndex+4+(i*2),opReturnIndex+6+(i*2)),16);
|
||||
}
|
||||
transaction.setMemo(new String(memoBytes));
|
||||
}
|
||||
}else {
|
||||
GTxIO output = new GTxIO();
|
||||
output.setAmount((long) (vout.value * Math.pow(10, this.mAccount.getCryptoCoin().getPrecision())));
|
||||
output.setTransaction(transaction);
|
||||
output.setOut(false);
|
||||
output.setType(this.mAccount.getCryptoCoin());
|
||||
String addr = vout.scriptPubKey.addresses[0];
|
||||
output.setAddressString(addr);
|
||||
output.setIndex(vout.n);
|
||||
output.setScriptHex(vout.scriptPubKey.hex);
|
||||
for (GeneralCoinAddress address : this.mAddresses) {
|
||||
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
|
||||
output.setAddress(address);
|
||||
tempAccount = address.getAccount();
|
||||
|
||||
if (!address.hasTransactionInput(output, this.mAccount.getNetworkParam())) {
|
||||
address.getTransactionInput().add(output);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
transaction.getTxOutputs().add(output);
|
||||
}
|
||||
}
|
||||
if(txi.txlock && txi.confirmations< this.mAccount.getCryptoNet().getConfirmationsNeeded()){
|
||||
transaction.setConfirm(this.mAccount.getCryptoNet().getConfirmationsNeeded());
|
||||
}
|
||||
//TODO database
|
||||
/*SCWallDatabase db = new SCWallDatabase(this.mContext);
|
||||
long idTransaction = db.getGeneralTransactionId(transaction);
|
||||
if (idTransaction == -1) {
|
||||
db.putGeneralTransaction(transaction);
|
||||
} else {
|
||||
transaction.setId(idTransaction);
|
||||
db.updateGeneralTransaction(transaction);
|
||||
}*/
|
||||
|
||||
if (tempAccount != null && transaction.getConfirm() < this.mAccount.getCryptoNet().getConfirmationsNeeded()) {
|
||||
new GetTransactionData(transaction.getTxid(), tempAccount, this.serverUrl, this.mContext, true).start();
|
||||
}
|
||||
for (GeneralCoinAddress address : this.mAddresses) {
|
||||
if (address.updateTransaction(transaction)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
GeneralAccountManager.getAccountManager(this.cryptoNet).processTxi(txi);
|
||||
}
|
||||
|
||||
if(changed) {
|
||||
this.mAccount.balanceChange();
|
||||
}
|
||||
}else{
|
||||
listener.hasTransaction(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +92,7 @@ public class GetTransactionByAddress extends Thread implements Callback<AddressT
|
|||
*/
|
||||
@Override
|
||||
public void onFailure(Call<AddressTxi> call, Throwable t) {
|
||||
inProcess = false;
|
||||
Log.e("GetTransactionByAddress", "Error in json format");
|
||||
}
|
||||
|
||||
|
@ -195,14 +101,15 @@ public class GetTransactionByAddress extends Thread implements Callback<AddressT
|
|||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.mAddresses.size() > 0) {
|
||||
if (this.mAddresses.size() > 0 && !inProcess) {
|
||||
inProcess = true;
|
||||
StringBuilder addressToQuery = new StringBuilder();
|
||||
for (GeneralCoinAddress address : this.mAddresses) {
|
||||
addressToQuery.append(address.getAddressString(this.mAccount.getNetworkParam())).append(",");
|
||||
for (String address : this.mAddresses) {
|
||||
addressToQuery.append(address).append(",");
|
||||
}
|
||||
addressToQuery.deleteCharAt(addressToQuery.length() - 1);
|
||||
InsightApiService service = this.mServiceGenerator.getService(InsightApiService.class);
|
||||
Call<AddressTxi> addressTxiCall = service.getTransactionByAddress(InsightApiConstants.getPath(this.mAccount.getCryptoCoin()),addressToQuery.toString());
|
||||
Call<AddressTxi> addressTxiCall = service.getTransactionByAddress(this.mPath,addressToQuery.toString());
|
||||
addressTxiCall.enqueue(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.Date;
|
|||
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.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.manager.GeneralAccountManager;
|
||||
import cy.agorise.crystalwallet.models.GTxIO;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAccount;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAddress;
|
||||
|
@ -20,10 +22,6 @@ import retrofit2.Response;
|
|||
*/
|
||||
|
||||
public class GetTransactionData extends Thread implements Callback<Txi> {
|
||||
/**
|
||||
* The account to be query
|
||||
*/
|
||||
private final GeneralCoinAccount mAccount;
|
||||
/**
|
||||
* The transaction txid to be query
|
||||
*/
|
||||
|
@ -32,41 +30,38 @@ public class GetTransactionData extends Thread implements Callback<Txi> {
|
|||
* The serviceGenerator to call
|
||||
*/
|
||||
private InsightApiServiceGenerator mServiceGenerator;
|
||||
/**
|
||||
* This app context, used to save on the DB
|
||||
*/
|
||||
private Context mContext;
|
||||
|
||||
private String mServerUrl;
|
||||
|
||||
private String mPath;
|
||||
/**
|
||||
* If has to wait for another confirmation
|
||||
*/
|
||||
private boolean mMustWait = false;
|
||||
|
||||
private CryptoCoin cryptoCoin;
|
||||
|
||||
/**
|
||||
* Constructor used to query for a transaction with unknown confirmations
|
||||
* @param txid The txid of the transaciton to be query
|
||||
* @param account The account to be query
|
||||
* @param context This app Context
|
||||
*/
|
||||
public GetTransactionData(String txid, GeneralCoinAccount account,String serverUrl, Context context) {
|
||||
this(txid, account, serverUrl, context, false);
|
||||
public GetTransactionData(String txid, String serverUrl, String path, CryptoCoin cryptoCoin) {
|
||||
this(txid, serverUrl, path, cryptoCoin, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Consturctor to be used qhen the confirmations of the transaction are known
|
||||
* @param txid The txid of the transaciton to be query
|
||||
* @param account The account to be query
|
||||
* @param context This app Context
|
||||
* @param mustWait If there is less confirmation that needed
|
||||
*/
|
||||
public GetTransactionData(String txid, GeneralCoinAccount account,String serverUrl, Context context, boolean mustWait) {
|
||||
public GetTransactionData(String txid, String serverUrl, String path, CryptoCoin cryptoCoin, boolean mustWait) {
|
||||
this.mPath = path;
|
||||
this.mServerUrl = serverUrl;
|
||||
this.mAccount = account;
|
||||
this.mTxId= txid;
|
||||
this.mServiceGenerator = new InsightApiServiceGenerator(serverUrl);
|
||||
this.mContext = context;
|
||||
this.mMustWait = mustWait;
|
||||
this.cryptoCoin = cryptoCoin;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,104 +79,19 @@ public class GetTransactionData extends Thread implements Callback<Txi> {
|
|||
}
|
||||
|
||||
InsightApiService service = this.mServiceGenerator.getService(InsightApiService.class);
|
||||
Call<Txi> txiCall = service.getTransaction(InsightApiConstants.getPath(this.mAccount.getCryptoCoin()),this.mTxId);
|
||||
Call<Txi> txiCall = service.getTransaction(this.mPath,this.mTxId);
|
||||
txiCall.enqueue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call<Txi> call, Response<Txi> response) {
|
||||
if (response.isSuccessful()) {
|
||||
|
||||
Txi txi = response.body();
|
||||
|
||||
GeneralTransaction transaction = new GeneralTransaction();
|
||||
transaction.setAccount(this.mAccount);
|
||||
transaction.setTxid(txi.txid);
|
||||
transaction.setBlock(txi.blockheight);
|
||||
transaction.setDate(new Date(txi.time * 1000));
|
||||
transaction.setFee((long) (txi.fee * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
|
||||
transaction.setConfirm(txi.confirmations);
|
||||
transaction.setType(this.mAccount.getCryptoCoin());
|
||||
transaction.setBlockHeight(txi.blockheight);
|
||||
|
||||
for (Vin vin : txi.vin) {
|
||||
GTxIO input = new GTxIO();
|
||||
input.setAmount((long) (vin.value * Math.pow(10,this.mAccount.getCryptoCoin().getPrecision())));
|
||||
input.setTransaction(transaction);
|
||||
input.setOut(true);
|
||||
input.setType(this.mAccount.getCryptoCoin());
|
||||
String addr = vin.addr;
|
||||
input.setAddressString(addr);
|
||||
input.setIndex(vin.n);
|
||||
input.setScriptHex(vin.scriptSig.hex);
|
||||
input.setOriginalTxid(vin.txid);
|
||||
for (GeneralCoinAddress address : this.mAccount.getAddresses()) {
|
||||
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
|
||||
input.setAddress(address);
|
||||
if (!address.hasTransactionOutput(input, this.mAccount.getNetworkParam())) {
|
||||
address.getTransactionOutput().add(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction.getTxInputs().add(input);
|
||||
}
|
||||
|
||||
for (Vout vout : txi.vout) {
|
||||
if(vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0){
|
||||
// The address is null, this must be a memo
|
||||
String hex = vout.scriptPubKey.hex;
|
||||
int opReturnIndex = hex.indexOf("6a");
|
||||
if(opReturnIndex >= 0) {
|
||||
byte[] memoBytes = new byte[Integer.parseInt(hex.substring(opReturnIndex+2,opReturnIndex+4),16)];
|
||||
for(int i = 0; i < memoBytes.length;i++){
|
||||
memoBytes[i] = Byte.parseByte(hex.substring(opReturnIndex+4+(i*2),opReturnIndex+6+(i*2)),16);
|
||||
}
|
||||
transaction.setMemo(new String(memoBytes));
|
||||
System.out.println("Memo read : " + transaction.getMemo()); //TODO log this line
|
||||
}
|
||||
|
||||
}else {
|
||||
GTxIO output = new GTxIO();
|
||||
output.setAmount((long) (vout.value * Math.pow(10, this.mAccount.getCryptoCoin().getPrecision())));
|
||||
output.setTransaction(transaction);
|
||||
output.setOut(false);
|
||||
output.setType(this.mAccount.getCryptoCoin());
|
||||
String addr = vout.scriptPubKey.addresses[0];
|
||||
output.setAddressString(addr);
|
||||
output.setIndex(vout.n);
|
||||
output.setScriptHex(vout.scriptPubKey.hex);
|
||||
for (GeneralCoinAddress address : this.mAccount.getAddresses()) {
|
||||
if (address.getAddressString(this.mAccount.getNetworkParam()).equals(addr)) {
|
||||
output.setAddress(address);
|
||||
if (!address.hasTransactionInput(output, this.mAccount.getNetworkParam())) {
|
||||
address.getTransactionInput().add(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction.getTxOutputs().add(output);
|
||||
}
|
||||
}
|
||||
|
||||
// This is for features like dash instantSend
|
||||
if(txi.txlock && txi.confirmations< this.mAccount.getCryptoNet().getConfirmationsNeeded()){
|
||||
transaction.setConfirm(this.mAccount.getCryptoNet().getConfirmationsNeeded());
|
||||
}
|
||||
|
||||
//TODO database
|
||||
/*SCWallDatabase db = new SCWallDatabase(this.mContext);
|
||||
long idTransaction = db.getGeneralTransactionId(transaction);
|
||||
if (idTransaction == -1) {
|
||||
db.putGeneralTransaction(transaction);
|
||||
} else {
|
||||
transaction.setId(idTransaction);
|
||||
db.updateGeneralTransaction(transaction);
|
||||
}*/
|
||||
|
||||
this.mAccount.updateTransaction(transaction);
|
||||
this.mAccount.balanceChange();
|
||||
|
||||
if (transaction.getConfirm() < this.mAccount.getCryptoNet().getConfirmationsNeeded()) {
|
||||
GeneralAccountManager.getAccountManager(this.cryptoCoin).processTxi(txi);
|
||||
if (txi.confirmations < this.cryptoCoin.getCryptoNet().getConfirmationsNeeded()) {
|
||||
//If transaction weren't confirmed, add the transaction to watch for change on the confirmations
|
||||
new GetTransactionData(this.mTxId, this.mAccount, this.mServerUrl, this.mContext, true).start();
|
||||
new GetTransactionData(this.mTxId, this.mServerUrl, this.mPath, this.cryptoCoin, true).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,4 +49,7 @@ interface InsightApiService {
|
|||
@GET("{path}/utils/estimatefee?nbBlocks=2")
|
||||
Call<JsonObject> estimateFee(@Path(value = "path", encoded = true) String path);
|
||||
|
||||
@GET("{path}/block-index/0")
|
||||
Call<JsonObject> genesisBlock(@Path(value = "path", encoded = true) String path);
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -17,6 +17,7 @@ import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
|||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAsset;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAssetInfo;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrencyEquivalence;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.network.CryptoNetManager;
|
||||
|
@ -49,6 +50,27 @@ public class CrystalApplication extends Application {
|
|||
//This is for testing the equivalent values on the testnet TODO remove
|
||||
public static BitsharesAsset bitEURAsset = new BitsharesAsset("EUR",4,"1.3.120",BitsharesAsset.Type.SMART_COIN);
|
||||
|
||||
|
||||
public static final String BITCOIN_SERVER_URLS[] ={
|
||||
"https://testnet.blockexplorer.com/",
|
||||
"https://test-insight.bitpay.com",
|
||||
//"https://insight.bitpay.com/"
|
||||
|
||||
};
|
||||
|
||||
public static final CryptoCurrency BITCOIN_CURRENCY = new CryptoCurrency("BTC",CryptoNet.BITCOIN,8);
|
||||
|
||||
public static String STEEM_URL[] =
|
||||
{
|
||||
"https://api.steemit.com",
|
||||
"https://api.steemitdev.com",
|
||||
"https://api.steemitstage.com",
|
||||
"https://api.steem.house",
|
||||
"https://appbasetest.timcliff.com",
|
||||
|
||||
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
@ -62,10 +84,10 @@ public class CrystalApplication extends Application {
|
|||
|
||||
//This is for testing the equivalent values on the testnet TODO remove
|
||||
if(db.bitsharesAssetDao().getBitsharesAssetInfoById(bitEURAsset.getBitsharesId())== null){
|
||||
if(db.cryptoCurrencyDao().getByName(bitEURAsset.getName())== null){
|
||||
if(db.cryptoCurrencyDao().getByName(bitEURAsset.getName(),bitEURAsset.getCryptoNet().name())== null){
|
||||
db.cryptoCurrencyDao().insertCryptoCurrency(bitEURAsset);
|
||||
}
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(bitEURAsset.getName()).getId();
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(bitEURAsset.getName(),bitEURAsset.getCryptoNet().name()).getId();
|
||||
BitsharesAssetInfo info = new BitsharesAssetInfo(bitEURAsset);
|
||||
info.setCryptoCurrencyId(idCurrency);
|
||||
db.bitsharesAssetDao().insertBitsharesAssetInfo(info);
|
||||
|
@ -74,10 +96,10 @@ public class CrystalApplication extends Application {
|
|||
|
||||
//This is for testing the equivalent values on the testnet TODO remove
|
||||
if(db.bitsharesAssetDao().getBitsharesAssetInfoById(bitUSDAsset.getBitsharesId())== null){
|
||||
if(db.cryptoCurrencyDao().getByName(bitUSDAsset.getName())== null){
|
||||
if(db.cryptoCurrencyDao().getByName(bitUSDAsset.getName(),bitUSDAsset.getCryptoNet().name())== null){
|
||||
db.cryptoCurrencyDao().insertCryptoCurrency(bitUSDAsset);
|
||||
}
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(bitUSDAsset.getName()).getId();
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(bitUSDAsset.getName(),bitUSDAsset.getCryptoNet().name()).getId();
|
||||
BitsharesAssetInfo info = new BitsharesAssetInfo(bitUSDAsset);
|
||||
info.setCryptoCurrencyId(idCurrency);
|
||||
db.bitsharesAssetDao().insertBitsharesAssetInfo(info);
|
||||
|
@ -93,6 +115,16 @@ public class CrystalApplication extends Application {
|
|||
// TODO and hoop over the urls if no connection can be established
|
||||
CryptoNetManager.addCryptoNetURL(CryptoNet.BITSHARES,BITSHARES_URL);
|
||||
|
||||
//Adding Bitcoin info
|
||||
CryptoNetManager.addCryptoNetURL(CryptoNet.BITCOIN,BITCOIN_SERVER_URLS);
|
||||
|
||||
if(db.cryptoCurrencyDao().getByName(BITCOIN_CURRENCY.getName(),BITCOIN_CURRENCY.getCryptoNet().name())== null){
|
||||
db.cryptoCurrencyDao().insertCryptoCurrency(BITCOIN_CURRENCY);
|
||||
}
|
||||
|
||||
CryptoNetManager.addCryptoNetURL(CryptoNet.STEEM,STEEM_URL);
|
||||
|
||||
|
||||
GeneralSetting generalSettingPreferredLanguage = db.generalSettingDao().getSettingByName(GeneralSetting.SETTING_NAME_PREFERRED_LANGUAGE);
|
||||
|
||||
if (generalSettingPreferredLanguage != null) {
|
||||
|
@ -105,6 +137,11 @@ public class CrystalApplication extends Application {
|
|||
resources.updateConfiguration(configuration, dm);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
Intent intent = new Intent(getApplicationContext(), CrystalWalletService.class);
|
||||
startService(intent);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import java.util.List;
|
|||
import cy.agorise.crystalwallet.activities.PatternRequestActivity;
|
||||
import cy.agorise.crystalwallet.activities.PinRequestActivity;
|
||||
import cy.agorise.crystalwallet.activities.PocketRequestActivity;
|
||||
import cy.agorise.crystalwallet.fragments.PatternSecurityFragment;
|
||||
import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.notifiers.CrystalWalletNotifier;
|
||||
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
||||
|
@ -129,7 +131,7 @@ public class CrystalSecurityMonitor implements Application.ActivityLifecycleCall
|
|||
public void onActivityStarted(Activity activity) {
|
||||
if (numStarted == 0) {
|
||||
if (!actualSecurity().equals("")){
|
||||
callPasswordRequest(activity);
|
||||
callPasswordRequest(activity,null);
|
||||
}
|
||||
}
|
||||
numStarted++;
|
||||
|
@ -140,18 +142,41 @@ public class CrystalSecurityMonitor implements Application.ActivityLifecycleCall
|
|||
numStarted--;
|
||||
if (numStarted == 0) {
|
||||
if (!actualSecurity().equals("")){
|
||||
callPasswordRequest(activity);
|
||||
callPasswordRequest(activity,null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void callPasswordRequest(Activity activity){
|
||||
public void callPasswordRequest(Activity activity, final OnResponse onResponsePattern){
|
||||
if ((!activity.getIntent().hasExtra("ACTIVITY_TYPE")) || (!activity.getIntent().getStringExtra("ACTIVITY_TYPE").equals("PASSWORD_REQUEST"))) {
|
||||
Intent intent = null;
|
||||
if ((this.passwordEncrypted != null) && (!this.passwordEncrypted.equals(""))) {
|
||||
|
||||
intent = new Intent(activity, PinRequestActivity.class);
|
||||
|
||||
PinRequestActivity.setOnResponse(null);
|
||||
|
||||
/*
|
||||
* Connect error and success listeners
|
||||
* */
|
||||
if(onResponsePattern != null){
|
||||
PinRequestActivity.setOnResponse(onResponsePattern);
|
||||
}
|
||||
|
||||
} else if ((this.patternEncrypted != null) && (!this.patternEncrypted.equals(""))) {
|
||||
|
||||
intent = new Intent(activity, PatternRequestActivity.class);
|
||||
|
||||
PatternRequestActivity.setOnResponse(null);
|
||||
|
||||
/*
|
||||
* Connect error and success listeners
|
||||
* */
|
||||
if(onResponsePattern != null){
|
||||
PatternRequestActivity.setOnResponse(onResponsePattern);
|
||||
}
|
||||
} else {
|
||||
onResponsePattern.onSuccess();
|
||||
}
|
||||
if (intent != null) {
|
||||
intent.putExtra("ACTIVITY_TYPE", "PASSWORD_REQUEST");
|
||||
|
@ -197,7 +222,4 @@ public class CrystalSecurityMonitor implements Application.ActivityLifecycleCall
|
|||
public void onActivityDestroyed(Activity activity) {
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ public abstract class BitsharesConstant {
|
|||
|
||||
//testnet faucet
|
||||
//public final static String FAUCET_URL = "http://185.208.208.147:5010";
|
||||
public final static String FAUCET_URL = "https://de.palmpay.io";
|
||||
public final static String FAUCET_URL = "https://faucet.palmpay.io";
|
||||
public final static String EQUIVALENT_URL = "wss://bitshares.openledger.info/ws";
|
||||
|
||||
public final static BitsharesAsset[] SMARTCOINS = new BitsharesAsset[]{
|
||||
|
@ -74,10 +74,10 @@ public abstract class BitsharesConstant {
|
|||
public static void addSmartCoins(Context context){
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
for(BitsharesAsset smartcoin : SMARTCOINS){
|
||||
if(db.cryptoCurrencyDao().getByName(smartcoin.getName())== null){
|
||||
if(db.cryptoCurrencyDao().getByName(smartcoin.getName(),CryptoNet.BITSHARES.name())== null){
|
||||
db.cryptoCurrencyDao().insertCryptoCurrency(smartcoin);
|
||||
}
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(smartcoin.getName()).getId();
|
||||
long idCurrency = db.cryptoCurrencyDao().getByName(smartcoin.getName(),CryptoNet.BITSHARES.name()).getId();
|
||||
BitsharesAssetInfo info = new BitsharesAssetInfo(smartcoin);
|
||||
info.setCryptoCurrencyId(idCurrency);
|
||||
db.bitsharesAssetDao().insertBitsharesAssetInfo(info);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package cy.agorise.crystalwallet.dao;
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.persistence.room.Dao;
|
||||
import android.arch.persistence.room.Insert;
|
||||
import android.arch.persistence.room.OnConflictStrategy;
|
||||
import android.arch.persistence.room.Query;
|
||||
|
||||
import cy.agorise.crystalwallet.models.BitcoinAddress;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransactionExtended;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 10/17/2018.
|
||||
*/
|
||||
@Dao
|
||||
public interface BitcoinAddressDao {
|
||||
|
||||
@Query("SELECT * FROM bitcoin_address")
|
||||
LiveData<BitcoinAddress> getAll();
|
||||
|
||||
@Query("SELECT COUNT(*) FROM bitcoin_address ba WHERE ba.address = :address")
|
||||
Boolean addressExists(String address);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_address ba WHERE ba.address = :address")
|
||||
BitcoinAddress getdadress(String address);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_address ba WHERE ba.address_index = :index and ba.is_change = 'true'")
|
||||
BitcoinAddress getChangeByIndex(long index);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_address ba WHERE ba.address_index = :index and ba.is_change = 'false'")
|
||||
BitcoinAddress getExternalByIndex(long index);
|
||||
|
||||
@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);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cy.agorise.crystalwallet.dao;
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.persistence.room.Dao;
|
||||
import android.arch.persistence.room.Insert;
|
||||
import android.arch.persistence.room.OnConflictStrategy;
|
||||
import android.arch.persistence.room.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransactionExtended;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransactionGTxIO;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 10/02/2018.
|
||||
*/
|
||||
@Dao
|
||||
public interface BitcoinTransactionDao {
|
||||
|
||||
@Query("SELECT * FROM crypto_coin_transaction cct, bitcoin_transaction bt WHERE bt.crypto_coin_transaction_id = cct.id")
|
||||
LiveData<BitcoinTransactionExtended> getAll();
|
||||
|
||||
@Query("SELECT * FROM bitcoin_transaction bt WHERE bt.tx_id = :txid")
|
||||
List<BitcoinTransaction> getTransactionsByTxid(String txid);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_transaction bt WHERE bt.crypto_coin_transaction_id = :idCryptoCoinTransaction")
|
||||
BitcoinTransaction getBitcoinTransactionByCryptoCoinTransaction(long idCryptoCoinTransaction);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_transaction_gt_io bt WHERE bt.bitcoin_transaction_id= :idBitcoinTransaction")
|
||||
List<BitcoinTransactionGTxIO> getGtxIOByTransaction(long idBitcoinTransaction);
|
||||
|
||||
@Query("SELECT * FROM bitcoin_transaction_gt_io bt WHERE bt.address= :address")
|
||||
List<BitcoinTransactionGTxIO> getGtxIOByAddress(String address);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public long[] insertBitcoinTransaction(BitcoinTransaction... transactions);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public long[] insertBitcoinTransactionGTxIO(BitcoinTransactionGTxIO... transactiongtxios);
|
||||
}
|
|
@ -23,6 +23,9 @@ public interface CryptoCurrencyDao {
|
|||
@Query("SELECT * FROM crypto_currency WHERE id = :id")
|
||||
CryptoCurrency getById(long id);
|
||||
|
||||
@Query("SELECT * FROM crypto_currency WHERE id = :id")
|
||||
LiveData<CryptoCurrency> getLDById(long id);
|
||||
|
||||
@Query("SELECT * FROM crypto_currency WHERE name = :name AND crypto_net = :cryptoNet")
|
||||
CryptoCurrency getByNameAndCryptoNet(String name,String cryptoNet);
|
||||
|
||||
|
@ -32,8 +35,8 @@ public interface CryptoCurrencyDao {
|
|||
@Query("SELECT * FROM crypto_currency WHERE name = :name")
|
||||
LiveData<CryptoCurrency> getLiveDataByName(String name);
|
||||
|
||||
@Query("SELECT * FROM crypto_currency WHERE name = :name")
|
||||
CryptoCurrency getByName(String name);
|
||||
@Query("SELECT * FROM crypto_currency WHERE name = :name and crypto_net = :cryptoNet")
|
||||
CryptoCurrency getByName(String name, String cryptoNet);
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
public long[] insertCryptoCurrency(CryptoCurrency... currencies);
|
||||
|
|
|
@ -29,6 +29,9 @@ public interface CryptoNetAccountDao {
|
|||
@Query("SELECT cna.* FROM crypto_net_account cna WHERE seed_id = :seedId")
|
||||
List<CryptoNetAccount> getAllCryptoNetAccountBySeed( long seedId);
|
||||
|
||||
@Query("SELECT cna.* FROM crypto_net_account cna WHERE crypto_net == 'BITCOIN'")
|
||||
LiveData<List<CryptoNetAccount>> getAllBitcoins();
|
||||
|
||||
@Query("SELECT * FROM crypto_net_account WHERE id = :accountId")
|
||||
LiveData<CryptoNetAccount> getByIdLiveData( long accountId);
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ import android.content.Context;
|
|||
|
||||
import cy.agorise.crystalwallet.dao.converters.Converters;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.BitcoinAddress;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransactionGTxIO;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAccountNameCache;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAssetInfo;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
|
@ -39,8 +42,11 @@ import cy.agorise.crystalwallet.models.GrapheneAccountInfo;
|
|||
BitsharesAssetInfo.class,
|
||||
BitsharesAccountNameCache.class,
|
||||
CryptoCurrencyEquivalence.class,
|
||||
GeneralSetting.class
|
||||
}, version = 4, exportSchema = false)
|
||||
GeneralSetting.class,
|
||||
BitcoinTransaction.class,
|
||||
BitcoinTransactionGTxIO.class,
|
||||
BitcoinAddress.class
|
||||
}, version = 6, exportSchema = false)
|
||||
@TypeConverters({Converters.class})
|
||||
public abstract class CrystalDatabase extends RoomDatabase {
|
||||
|
||||
|
@ -57,6 +63,8 @@ public abstract class CrystalDatabase extends RoomDatabase {
|
|||
public abstract BitsharesAccountNameCacheDao bitsharesAccountNameCacheDao();
|
||||
public abstract CryptoCurrencyEquivalenceDao cryptoCurrencyEquivalenceDao();
|
||||
public abstract GeneralSettingDao generalSettingDao();
|
||||
public abstract BitcoinTransactionDao bitcoinTransactionDao();
|
||||
public abstract BitcoinAddressDao bitcoinAddressDao();
|
||||
|
||||
public static CrystalDatabase getAppDatabase(Context context) {
|
||||
if (instance == null) {
|
||||
|
@ -64,8 +72,10 @@ public abstract class CrystalDatabase extends RoomDatabase {
|
|||
Room.databaseBuilder(context,
|
||||
CrystalDatabase.class, "CrystalWallet.db")
|
||||
.allowMainThreadQueries()
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
//.addMigrations(MIGRATION_2_3)
|
||||
//.addMigrations(MIGRATION_3_4)
|
||||
//.addMigrations(MIGRATION_4_5)
|
||||
//.addMigrations(MIGRATION_5_6)
|
||||
.build();
|
||||
}
|
||||
return instance;
|
||||
|
@ -91,4 +101,41 @@ public abstract class CrystalDatabase extends RoomDatabase {
|
|||
|
||||
}
|
||||
};
|
||||
|
||||
static final Migration MIGRATION_4_5 = new Migration(4, 5) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE bitcoin_transaction ("
|
||||
+"crypto_coin_transaction_id INTEGER PRIMARY KEY NOT NULL,"
|
||||
+"tx_id TEXT NOT NULL,"
|
||||
+"block INTEGER NOT NULL,"
|
||||
+"fee INTEGER NOT NULL,"
|
||||
+"confirmations INTEGER NOT NULL,"
|
||||
+"FOREIGN KEY (crypto_coin_transaction_id) REFERENCES crypto_coin_transaction(id) ON DELETE CASCADE)");
|
||||
|
||||
database.execSQL("CREATE TABLE bitcoin_transaction_gt_io ("
|
||||
+"bitcoin_transaction_id INTEGER NOT NULL,"
|
||||
+"io_index INTEGER NOT NULL,"
|
||||
+"address TEXT,"
|
||||
+"is_output INTEGER NOT NULL,"
|
||||
+"amount INTEGER NOT NULL,"
|
||||
+"script_hex TEXT,"
|
||||
+"original_txid TEXT,"
|
||||
+"PRIMARY KEY (bitcoin_transaction_id, io_index, is_output),"
|
||||
+"FOREIGN KEY (bitcoin_transaction_id) REFERENCES bitcoin_transaction(crypto_coin_transaction_id) ON DELETE CASCADE)");
|
||||
}
|
||||
};
|
||||
|
||||
static final Migration MIGRATION_5_6 = new Migration(5, 6) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE bitcoin_address ("
|
||||
+"account_id INTEGER NOT NULL,"
|
||||
+"address_index INTEGER NOT NULL,"
|
||||
+"is_change INTEGER NOT NULL,"
|
||||
+"address TEXT NOT NULL,"
|
||||
+"PRIMARY KEY (account_id, address_index, is_change),"
|
||||
+"FOREIGN KEY (account_id) REFERENCES crypto_net_account(id) ON DELETE CASCADE)");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,7 +51,10 @@ public interface TransactionDao {
|
|||
List<CryptoCoinTransaction> getByIdAccount(long idAccount);
|
||||
|
||||
@Query("SELECT * FROM crypto_coin_transaction WHERE id = :id")
|
||||
LiveData<CryptoCoinTransaction> getById(long id);
|
||||
LiveData<CryptoCoinTransaction> getByIdLiveData(long id);
|
||||
|
||||
@Query("SELECT * FROM crypto_coin_transaction WHERE id = :id")
|
||||
CryptoCoinTransaction getById(long id);
|
||||
|
||||
@Query("SELECT * FROM crypto_coin_transaction WHERE date = :date and 'from' = :from and 'to' = :to and amount = :amount ")
|
||||
CryptoCoinTransaction getByTransaction(Date date, String from, String to, long amount);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package cy.agorise.crystalwallet.enums;
|
||||
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -11,21 +13,26 @@ import java.util.List;
|
|||
*/
|
||||
|
||||
public enum CryptoCoin implements Serializable {
|
||||
BITCOIN(CryptoNet.BITCOIN,"BTC",8),
|
||||
BITCOIN_TEST(CryptoNet.BITCOIN_TEST,"BTC",8),
|
||||
LITECOIN(CryptoNet.LITECOIN,"LTC",8),
|
||||
DASH(CryptoNet.DASH,"DASH",8),
|
||||
DOGECOIN(CryptoNet.DOGECOIN,"DOGE",8),
|
||||
BITSHARES(CryptoNet.BITSHARES,"BTS",5);
|
||||
BITCOIN(CryptoNet.BITCOIN,"BTC",8,0,NetworkParameters.fromID(NetworkParameters.ID_TESTNET)),
|
||||
BITCOIN_TEST(CryptoNet.BITCOIN_TEST,"BTC",8,1,NetworkParameters.fromID(NetworkParameters.ID_TESTNET)),
|
||||
LITECOIN(CryptoNet.LITECOIN,"LTC",8,2,null),
|
||||
DASH(CryptoNet.DASH,"DASH",8,5,null),
|
||||
DOGECOIN(CryptoNet.DOGECOIN,"DOGE",8,3,null),
|
||||
BITSHARES(CryptoNet.BITSHARES,"BTS",5,0,null),
|
||||
STEEM(CryptoNet.STEEM,"BTS",5,0,null);
|
||||
|
||||
protected CryptoNet cryptoNet;
|
||||
protected String label;
|
||||
protected int precision;
|
||||
protected int coinNumber;
|
||||
protected NetworkParameters parameters;
|
||||
|
||||
CryptoCoin(CryptoNet cryptoNet, String label, int precision){
|
||||
CryptoCoin(CryptoNet cryptoNet, String label, int precision, int coinNumber, NetworkParameters parameters){
|
||||
this.cryptoNet = cryptoNet;
|
||||
this.label = label;
|
||||
this.precision = precision;
|
||||
this.coinNumber = coinNumber;
|
||||
this.parameters = parameters;
|
||||
|
||||
}
|
||||
|
||||
|
@ -38,6 +45,14 @@ public enum CryptoCoin implements Serializable {
|
|||
public int getPrecision(){
|
||||
return this.precision;
|
||||
}
|
||||
public NetworkParameters getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public int getCoinNumber() {
|
||||
return coinNumber;
|
||||
}
|
||||
|
||||
public static List<CryptoCoin> getByCryptoNet(CryptoNet cryptoNet){
|
||||
List<CryptoCoin> result = new ArrayList<CryptoCoin>();
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.io.Serializable;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import cy.agorise.crystalwallet.R;
|
||||
|
||||
/**
|
||||
* CryptoNet Enumeration, a Crypto Net is define as the net where a CryptoCoin works, iniside the
|
||||
* CrypotNet is where the transaction and balance works, using the CryptoCoin Assets
|
||||
|
@ -11,7 +13,14 @@ import java.util.Map;
|
|||
* Created by Henry Varona on 12/9/2017.
|
||||
*/
|
||||
public enum CryptoNet implements Serializable {
|
||||
UNKNOWN("UNKNOWN",6,-1), BITCOIN("BITCOIN",6,1), BITCOIN_TEST("BITCOIN(TEST)",6,2), LITECOIN("LITECOIN",6,3), DASH("DASH",6,5), DOGECOIN("DOGECOIN",6,4), BITSHARES("BITSHARES",1,6), STEEM("STEEM",1,7);
|
||||
UNKNOWN("UNKNOWN",6,-1,android.R.drawable .ic_menu_help),
|
||||
BITCOIN("BITCOIN",6,1,R.drawable.coin_icon_bitcoin),
|
||||
BITCOIN_TEST("BITCOIN(TEST)",6,2,R.drawable.coin_icon_bitcoin),
|
||||
LITECOIN("LITECOIN",6,3,R.drawable.coin_icon_litecoin),
|
||||
DASH("DASH",6,5,R.drawable.coin_icon_dash),
|
||||
DOGECOIN("DOGECOIN",6,4,R.drawable.coin_icon_doge),
|
||||
BITSHARES("BITSHARES",1,6,R.drawable.bts),
|
||||
STEEM("STEEM",1,7,R.drawable.coin_icon_steem);
|
||||
|
||||
protected String label;
|
||||
|
||||
|
@ -19,6 +28,8 @@ public enum CryptoNet implements Serializable {
|
|||
|
||||
protected int bip44Index;
|
||||
|
||||
protected int iconImageResource;
|
||||
|
||||
private static Map<Integer, CryptoNet> bip44Map = new HashMap<Integer, CryptoNet>();
|
||||
static {
|
||||
for (CryptoNet cryptoNetEnum : CryptoNet.values()) {
|
||||
|
@ -26,10 +37,11 @@ public enum CryptoNet implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
CryptoNet(String label,int confirmationsNeeded, int bip44Index){
|
||||
CryptoNet(String label,int confirmationsNeeded, int bip44Index, int iconImageResource){
|
||||
this.label = label;
|
||||
this.confirmationsNeeded = confirmationsNeeded;
|
||||
this.bip44Index = bip44Index;
|
||||
this.iconImageResource = iconImageResource;
|
||||
}
|
||||
|
||||
public String getLabel(){
|
||||
|
@ -44,6 +56,10 @@ public enum CryptoNet implements Serializable {
|
|||
return this.bip44Index;
|
||||
}
|
||||
|
||||
public int getIconImageResource() {
|
||||
return this.iconImageResource;
|
||||
}
|
||||
|
||||
public static CryptoNet fromBip44Index(int index){
|
||||
if (bip44Map.containsKey(index)) {
|
||||
return bip44Map.get(index);
|
||||
|
|
|
@ -6,5 +6,6 @@ package cy.agorise.crystalwallet.enums;
|
|||
|
||||
public enum SeedType {
|
||||
BIP39,
|
||||
BRAINKEY
|
||||
BRAINKEY,
|
||||
WIF
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@ import android.text.SpannableStringBuilder;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
|
@ -41,6 +44,22 @@ public class AccountsSettingsFragment extends Fragment {
|
|||
@BindView(R.id.tvRemove)
|
||||
public TextView tvRemove;
|
||||
|
||||
@BindView(R.id.btnUpgrade)
|
||||
public Button btnUpgrade;
|
||||
|
||||
@BindView(R.id.btnImport)
|
||||
public Button btnImport;
|
||||
|
||||
@BindView(R.id.btnRefresh)
|
||||
public Button btnRefresh;
|
||||
|
||||
@BindView(R.id.btnRemove)
|
||||
public Button btnRemove;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
@ -53,6 +72,36 @@ public class AccountsSettingsFragment extends Fragment {
|
|||
tvRefresh.setText(makeFirstWordsBold(getResources().getString(R.string.refresh_description)));
|
||||
tvRemove.setText(makeFirstWordsBold(getResources().getString(R.string.remove_description)));
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnUpgrade)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnImport)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnRefresh)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
|
||||
}
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnRemove)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.Manifest;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -16,6 +23,8 @@ import android.widget.Button;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -39,6 +48,11 @@ import cy.agorise.crystalwallet.requestmanagers.FileServiceRequests;
|
|||
*/
|
||||
|
||||
public class BackupsSettingsFragment extends Fragment{
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 1;
|
||||
|
||||
|
||||
|
||||
public BackupsSettingsFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
@ -65,6 +79,7 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
@BindView(R.id.btnBinFile)
|
||||
public Button btnBinFile;
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
@ -72,6 +87,25 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
View v = inflater.inflate(R.layout.fragment_backups_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnBinFile)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
makeBackupFile();
|
||||
}
|
||||
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnBrainkey)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnBrainOnClick();
|
||||
}
|
||||
} );
|
||||
|
||||
tvBinFile.setText(makeFirstWordsBold(getResources().getString(R.string.bin_file_description)));
|
||||
tvBrainkey.setText(makeFirstWordsBold(getResources().getString(R.string.brainkey_description)));
|
||||
tvWIFKey.setText(makeFirstWordsBold(getResources().getString(R.string.wif_key_description)));
|
||||
|
@ -92,12 +126,40 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
public void btnBrainOnClick(){
|
||||
|
||||
Intent intent = new Intent(getContext(), BackupSeedActivity.class);
|
||||
intent. putExtra("SEED_ID","");
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
@OnClick(R.id.btnBinFile)
|
||||
public void makeBackupFile(){
|
||||
|
||||
/*
|
||||
* Check for WRITE_EXTERNAL_STORAGE permission
|
||||
* */
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (checkPermission()) {
|
||||
// Code for above or equal 23 API Oriented Device
|
||||
// Your Permission granted already .Do next code
|
||||
|
||||
makeBackupfileAfterPermission();
|
||||
|
||||
} else {
|
||||
requestPermission(); // Code for permission
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Code for Below 23 API Oriented Device
|
||||
// Do next code
|
||||
|
||||
makeBackupfileAfterPermission();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void makeBackupfileAfterPermission(){
|
||||
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
|
||||
LiveData<GeneralSetting> generalSettingLD = CrystalDatabase.getAppDatabase(getContext()).generalSettingDao().getByName(GeneralSetting.SETTING_PASSWORD);
|
||||
|
@ -105,13 +167,13 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
generalSettingLD.observe(this, new Observer<GeneralSetting>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable GeneralSetting generalSetting) {
|
||||
|
||||
String password = "";
|
||||
if (generalSetting != null) {
|
||||
password = generalSetting.getValue();
|
||||
}
|
||||
|
||||
final CreateBackupRequest backupFileRequest = new CreateBackupRequest(getContext(), password);
|
||||
|
||||
backupFileRequest.setListener(new FileServiceRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
|
@ -132,4 +194,40 @@ public class BackupsSettingsFragment extends Fragment{
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPermission() {
|
||||
int result = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
if (result == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void requestPermission() {
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.Permision_storage), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
switch (requestCode) {
|
||||
case PERMISSION_REQUEST_CODE:
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.e("value", "Permission Granted, Now you can use local drive .");
|
||||
|
||||
} else {
|
||||
Log.e("value", "Permission Denied, You cannot use local drive .");
|
||||
|
||||
makeBackupfileAfterPermission();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,15 @@ package cy.agorise.crystalwallet.fragments;
|
|||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -17,15 +19,20 @@ import butterknife.BindView;
|
|||
import butterknife.ButterKnife;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetBalance;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoCoinBalanceListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetBalanceListViewModel;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetBalanceListView;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetBalanceListAdapter;
|
||||
|
||||
public class BalanceFragment extends Fragment {
|
||||
|
||||
CryptoNetBalanceListViewModel cryptoNetBalanceListViewModel;
|
||||
|
||||
@BindView(R.id.vCryptoNetBalanceListView)
|
||||
CryptoNetBalanceListView vCryptoNetBalanceListView;
|
||||
@BindView(R.id.tvNoBalances)
|
||||
TextView tvNoBalances;
|
||||
|
||||
@BindView(R.id.rvBalances)
|
||||
RecyclerView rvBalances;
|
||||
|
||||
CryptoNetBalanceListAdapter balancesAdapter;
|
||||
|
||||
public BalanceFragment() {
|
||||
// Required empty public constructor
|
||||
|
@ -44,22 +51,33 @@ public class BalanceFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_balance, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
cryptoNetBalanceListViewModel = ViewModelProviders.of(this).get(CryptoNetBalanceListViewModel.class);
|
||||
LiveData<List<CryptoNetBalance>> cryptoNetBalanceData = cryptoNetBalanceListViewModel.getCryptoNetBalanceList();
|
||||
vCryptoNetBalanceListView.setData(null, this);
|
||||
// Configure RecyclerView and its adapter
|
||||
rvBalances.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
balancesAdapter = new CryptoNetBalanceListAdapter(this);
|
||||
rvBalances.setAdapter(balancesAdapter);
|
||||
|
||||
final Fragment fragment = this;
|
||||
//Prevents the UI from an infinite scrolling of balances
|
||||
rvBalances.setNestedScrollingEnabled(false);
|
||||
|
||||
cryptoNetBalanceListViewModel = ViewModelProviders.of(this).get(CryptoNetBalanceListViewModel.class);
|
||||
final LiveData<List<CryptoNetBalance>> cryptoNetBalanceData = cryptoNetBalanceListViewModel.getCryptoNetBalanceList();
|
||||
|
||||
cryptoNetBalanceData.observe(this, new Observer<List<CryptoNetBalance>>() {
|
||||
@Override
|
||||
public void onChanged(List<CryptoNetBalance> cryptoNetBalances) {
|
||||
vCryptoNetBalanceListView.setData(cryptoNetBalances, fragment);
|
||||
balancesAdapter.submitList(cryptoNetBalances);
|
||||
|
||||
if(cryptoNetBalances != null && cryptoNetBalances.size() > 0) {
|
||||
tvNoBalances.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
tvNoBalances.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.widget.Spinner;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
import com.vincent.filepicker.Constant;
|
||||
import com.vincent.filepicker.activity.AudioPickActivity;
|
||||
import com.vincent.filepicker.filter.entity.AudioFile;
|
||||
|
@ -73,6 +74,9 @@ public class BitsharesSettingsFragment extends Fragment {
|
|||
GrapheneAccountInfo grapheneAccountInfo;
|
||||
GrapheneAccount grapheneAccount;
|
||||
|
||||
|
||||
|
||||
|
||||
public BitsharesSettingsFragment() {
|
||||
if (getArguments() != null) {
|
||||
long cryptoNetAcountId = getArguments().getLong("CRYPTO_NET_ACCOUNT_ID", -1);
|
||||
|
@ -114,6 +118,17 @@ public class BitsharesSettingsFragment extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_bitshares_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnUpgradeToLtm)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
upgradeAccountToLtm();
|
||||
}
|
||||
} );
|
||||
|
||||
initAlreadyLtm();
|
||||
|
||||
return v;
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.support.v7.widget.RecyclerView;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -27,6 +28,9 @@ public class ContactsFragment extends Fragment {
|
|||
@BindView(R.id.rvContacts)
|
||||
RecyclerView rvContacts;
|
||||
|
||||
@BindView(R.id.tvNoContacts)
|
||||
TextView tvNoContacts;
|
||||
|
||||
ContactListAdapter adapter;
|
||||
|
||||
FloatingActionButton fabAddContact;
|
||||
|
@ -86,6 +90,13 @@ public class ContactsFragment extends Fragment {
|
|||
@Override
|
||||
public void onChanged(@Nullable PagedList<Contact> contacts) {
|
||||
adapter.submitList(contacts);
|
||||
|
||||
if(contacts != null && contacts.size() > 0){
|
||||
tvNoContacts.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
else{
|
||||
tvNoContacts.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
|
||||
|
||||
/**
|
||||
* Created by xd on 12/28/17.
|
||||
*/
|
||||
|
||||
public class CryptoNetAccountActivationSettingsFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.tvMnemonic)
|
||||
TextView tvMnemonic;
|
||||
|
||||
@BindView(R.id.btnCopy)
|
||||
Button btnCopy;
|
||||
|
||||
CryptoNetAccount cryptoNetAccount;
|
||||
AccountSeed accountSeed;
|
||||
|
||||
|
||||
|
||||
|
||||
public CryptoNetAccountActivationSettingsFragment() {
|
||||
|
||||
if (getArguments() != null) {
|
||||
long cryptoNetAcountId = getArguments().getLong("CRYPTO_NET_ACCOUNT_ID", -1);
|
||||
|
||||
if (cryptoNetAcountId > -1) {
|
||||
this.cryptoNetAccount = CrystalDatabase.getAppDatabase(getContext()).cryptoNetAccountDao().getById(cryptoNetAcountId);
|
||||
this.accountSeed = CrystalDatabase.getAppDatabase(getContext()).accountSeedDao().findById(this.cryptoNetAccount.getSeedId());
|
||||
}
|
||||
}
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
public static CryptoNetAccountActivationSettingsFragment newInstance(long cryptoNetAccountId) {
|
||||
CryptoNetAccountActivationSettingsFragment fragment = new CryptoNetAccountActivationSettingsFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("CRYPTO_NET_ACCOUNT_ID", cryptoNetAccountId);
|
||||
fragment.setArguments(args);
|
||||
|
||||
|
||||
if (cryptoNetAccountId > -1){
|
||||
fragment.cryptoNetAccount = CrystalDatabase.getAppDatabase(fragment.getContext()).cryptoNetAccountDao().getById(cryptoNetAccountId);
|
||||
fragment.accountSeed = CrystalDatabase.getAppDatabase(fragment.getContext()).accountSeedDao().findById(fragment.cryptoNetAccount.getSeedId());
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_general_crypto_net_account_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCopy)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnCopyClick();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
initAlreadyLtm();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public void initAlreadyLtm(){
|
||||
if (this.cryptoNetAccount != null) {
|
||||
tvMnemonic.setText(this.accountSeed.getMasterSeed());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clic on button copy to clipboard
|
||||
* */
|
||||
@OnClick(R.id.btnCopy)
|
||||
public void btnCopyClick(){
|
||||
|
||||
/*
|
||||
* Save to clipboard the brainkey chain
|
||||
* */
|
||||
final Activity activity = getActivity();
|
||||
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(tvMnemonic.getText(), tvMnemonic.getText().toString());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
/*
|
||||
* Success message
|
||||
* */
|
||||
Toast.makeText(activity,getResources().getString(R.string.window_seed_toast_clipboard), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetSelection;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CreateBitcoinAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetSelectionListAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* Created by xd on 12/28/17.
|
||||
*/
|
||||
|
||||
public class GeneralAccountSeedCoinSettingsFragment extends Fragment implements CryptoNetSelectionListAdapter.CryptoNetSelectionListener {
|
||||
|
||||
@BindView(R.id.rvCoinSelection)
|
||||
RecyclerView rvCoinSelection;
|
||||
|
||||
AccountSeed accountSeed;
|
||||
|
||||
ArrayList<CryptoNetSelection> cryptoNetSelectionList;
|
||||
|
||||
public GeneralAccountSeedCoinSettingsFragment() {
|
||||
|
||||
if (getArguments() != null) {
|
||||
long accountSeedId = getArguments().getLong("SEED_ID", -1);
|
||||
|
||||
if (accountSeedId > -1) {
|
||||
this.accountSeed = CrystalDatabase.getAppDatabase(getContext()).accountSeedDao().findById(accountSeedId);
|
||||
}
|
||||
}
|
||||
|
||||
cryptoNetSelectionList = new ArrayList<CryptoNetSelection>();
|
||||
CryptoNetSelection nextCryptoNetSelection;
|
||||
for (CryptoNet nextCryptoNet : CryptoNet.values()){
|
||||
|
||||
if ((nextCryptoNet != CryptoNet.UNKNOWN) && (nextCryptoNet != CryptoNet.BITCOIN_TEST)) {
|
||||
nextCryptoNetSelection = new CryptoNetSelection(nextCryptoNet, false);
|
||||
cryptoNetSelectionList.add(nextCryptoNetSelection);
|
||||
}
|
||||
}
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
public static GeneralAccountSeedCoinSettingsFragment newInstance(long accountSeedId) {
|
||||
GeneralAccountSeedCoinSettingsFragment fragment = new GeneralAccountSeedCoinSettingsFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("SEED_ID", accountSeedId);
|
||||
fragment.setArguments(args);
|
||||
|
||||
|
||||
if (accountSeedId > -1){
|
||||
fragment.accountSeed = CrystalDatabase.getAppDatabase(fragment.getContext()).accountSeedDao().findById(accountSeedId);
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_general_account_seed_coin_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
CryptoNetSelectionListAdapter cryptoNetSelectionListAdapter = new CryptoNetSelectionListAdapter(this.cryptoNetSelectionList);
|
||||
cryptoNetSelectionListAdapter.addListener(this);
|
||||
rvCoinSelection.setAdapter(cryptoNetSelectionListAdapter);
|
||||
LinearLayoutManager llm = new LinearLayoutManager(this.getContext());
|
||||
llm.setOrientation(LinearLayoutManager.VERTICAL);
|
||||
rvCoinSelection.setLayoutManager(llm);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoNetSelectionChecked(CryptoNetSelection source) {
|
||||
//Toast.makeText(this.getContext(),"the coin "+source.getCryptoNet().name()+" was "+(source.getSelected()?"selected":"unselected"),Toast.LENGTH_LONG).show();
|
||||
List<CryptoCoin> cryptoCoins = CryptoCoin.getByCryptoNet(source.getCryptoNet());
|
||||
|
||||
|
||||
final CreateBitcoinAccountRequest request = new CreateBitcoinAccountRequest(this.accountSeed,this.getContext(),cryptoCoins.get(0));
|
||||
|
||||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (request.getStatus() == CreateBitcoinAccountRequest.StatusCode.SUCCEEDED){
|
||||
Toast.makeText(getContext(),"The account was successfully created",Toast.LENGTH_LONG);
|
||||
} else {
|
||||
Toast.makeText(getContext(),"There was an error enabling the account",Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
|
||||
|
||||
/**
|
||||
* Created by xd on 12/28/17.
|
||||
*/
|
||||
|
||||
public class GeneralAccountSeedFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.tvMnemonic)
|
||||
TextView tvMnemonic;
|
||||
|
||||
@BindView(R.id.btnCopy)
|
||||
Button btnCopy;
|
||||
|
||||
AccountSeed accountSeed;
|
||||
|
||||
|
||||
|
||||
|
||||
public GeneralAccountSeedFragment() {
|
||||
|
||||
if (getArguments() != null) {
|
||||
long accountSeedId = getArguments().getLong("SEED_ID", -1);
|
||||
|
||||
if (accountSeedId > -1) {
|
||||
this.accountSeed = CrystalDatabase.getAppDatabase(getContext()).accountSeedDao().findById(accountSeedId);
|
||||
}
|
||||
}
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
public static GeneralAccountSeedFragment newInstance(long accountSeedId) {
|
||||
GeneralAccountSeedFragment fragment = new GeneralAccountSeedFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("SEED_ID", accountSeedId);
|
||||
fragment.setArguments(args);
|
||||
|
||||
|
||||
if (accountSeedId > -1){
|
||||
fragment.accountSeed = CrystalDatabase.getAppDatabase(fragment.getContext()).accountSeedDao().findById(accountSeedId);
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_general_crypto_net_account_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCopy)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnCopyClick();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
initAlreadyLtm();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public void initAlreadyLtm(){
|
||||
tvMnemonic.setText(this.accountSeed.getMasterSeed());
|
||||
}
|
||||
|
||||
/*
|
||||
* Clic on button copy to clipboard
|
||||
* */
|
||||
@OnClick(R.id.btnCopy)
|
||||
public void btnCopyClick(){
|
||||
|
||||
/*
|
||||
* Save to clipboard the brainkey chain
|
||||
* */
|
||||
final Activity activity = getActivity();
|
||||
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(tvMnemonic.getText(), tvMnemonic.getText().toString());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
/*
|
||||
* Success message
|
||||
* */
|
||||
Toast.makeText(activity,getResources().getString(R.string.window_seed_toast_clipboard), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -8,11 +12,15 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
|
@ -30,9 +38,15 @@ public class GeneralCryptoNetAccountSettingsFragment extends Fragment {
|
|||
@BindView(R.id.tvMnemonic)
|
||||
TextView tvMnemonic;
|
||||
|
||||
@BindView(R.id.btnCopy)
|
||||
Button btnCopy;
|
||||
|
||||
CryptoNetAccount cryptoNetAccount;
|
||||
AccountSeed accountSeed;
|
||||
|
||||
|
||||
|
||||
|
||||
public GeneralCryptoNetAccountSettingsFragment() {
|
||||
|
||||
if (getArguments() != null) {
|
||||
|
@ -73,6 +87,18 @@ public class GeneralCryptoNetAccountSettingsFragment extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_general_crypto_net_account_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnCopy)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
btnCopyClick();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
initAlreadyLtm();
|
||||
|
||||
return v;
|
||||
|
@ -83,4 +109,24 @@ public class GeneralCryptoNetAccountSettingsFragment extends Fragment {
|
|||
tvMnemonic.setText(this.accountSeed.getMasterSeed());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clic on button copy to clipboard
|
||||
* */
|
||||
@OnClick(R.id.btnCopy)
|
||||
public void btnCopyClick(){
|
||||
|
||||
/*
|
||||
* Save to clipboard the brainkey chain
|
||||
* */
|
||||
final Activity activity = getActivity();
|
||||
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(tvMnemonic.getText(), tvMnemonic.getText().toString());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
|
||||
/*
|
||||
* Success message
|
||||
* */
|
||||
Toast.makeText(activity,getResources().getString(R.string.window_seed_toast_clipboard), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
import com.vincent.filepicker.Constant;
|
||||
import com.vincent.filepicker.activity.AudioPickActivity;
|
||||
import com.vincent.filepicker.filter.entity.AudioFile;
|
||||
|
@ -71,6 +73,8 @@ public class GeneralSettingsFragment extends Fragment {
|
|||
Spinner spDisplayDateTime;
|
||||
@BindView (R.id.tvReceiveFundsSoundValue)
|
||||
TextView tvReceiveFundsSound;
|
||||
@BindView (R.id.btnContact)
|
||||
Button btnContact;
|
||||
|
||||
public GeneralSettingsFragment() {
|
||||
this.spPreferredLanguageInitialized = false;
|
||||
|
@ -99,6 +103,17 @@ public class GeneralSettingsFragment extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_general_settings, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnContact)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
|
||||
}
|
||||
} );
|
||||
|
||||
generalSettingListViewModel = ViewModelProviders.of(this).get(GeneralSettingListViewModel.class);
|
||||
generalSettingListLiveData = generalSettingListViewModel.getGeneralSettingList();
|
||||
|
||||
|
|
|
@ -5,13 +5,20 @@ import android.app.Dialog;
|
|||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
|
@ -19,11 +26,15 @@ import android.widget.Button;
|
|||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.thekhaeng.pushdownanim.PushDownAnim;
|
||||
import com.vincent.filepicker.ToastUtil;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnTouch;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.activities.BoardActivity;
|
||||
import cy.agorise.crystalwallet.activities.ImportSeedActivity;
|
||||
|
@ -49,7 +60,10 @@ public class ImportAccountOptionsFragment extends DialogFragment {
|
|||
Button btnClose;
|
||||
@BindView(R.id.btnImportBackup)
|
||||
Button btnImportBackup;
|
||||
@BindView(R.id.btnImportSeed)
|
||||
Button btnImportSeed;
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 1;
|
||||
|
||||
/*
|
||||
Dialog for loading
|
||||
|
@ -90,6 +104,34 @@ public class ImportAccountOptionsFragment extends DialogFragment {
|
|||
View view = inflater.inflate(R.layout.fragment_import_account_options, null);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
/*
|
||||
* Integration of library with button efects
|
||||
* */
|
||||
PushDownAnim.setPushDownAnimTo(btnClose)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
cancel();
|
||||
}
|
||||
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnImportBackup)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
importBackup();
|
||||
}
|
||||
|
||||
} );
|
||||
PushDownAnim.setPushDownAnimTo(btnImportSeed)
|
||||
.setOnClickListener( new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick( View view ){
|
||||
importSeed();
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
return builder.setView(view).create();
|
||||
}
|
||||
|
||||
|
@ -110,18 +152,88 @@ public class ImportAccountOptionsFragment extends DialogFragment {
|
|||
|
||||
@OnClick (R.id.btnImportBackup)
|
||||
public void importBackup(){
|
||||
Intent fileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
fileIntent.setType("*/*");
|
||||
fileIntent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
startActivityForResult(fileIntent, FILE_CONTENT_REQUEST_CODE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
|
||||
if (checkPermission()) {
|
||||
|
||||
Intent fileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
fileIntent.setType("*/*");
|
||||
fileIntent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
startActivityForResult(fileIntent, FILE_CONTENT_REQUEST_CODE);
|
||||
|
||||
} else {
|
||||
requestPermission(); // Code for permission
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Intent fileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
fileIntent.setType("*/*");
|
||||
fileIntent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
startActivityForResult(fileIntent, FILE_CONTENT_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick (R.id.btnImportSeed)
|
||||
public void importSeed(){
|
||||
Intent intent = new Intent(this.getActivity(), ImportSeedActivity.class);
|
||||
startActivity(intent);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
|
||||
if (checkPermission()) {
|
||||
|
||||
Intent intent = new Intent(this.getActivity(), ImportSeedActivity.class);
|
||||
startActivity(intent);
|
||||
|
||||
} else {
|
||||
requestPermission(); // Code for permission
|
||||
}
|
||||
}
|
||||
else {
|
||||
Intent intent = new Intent(this.getActivity(), ImportSeedActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean checkPermission() {
|
||||
int result = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
if (result == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void requestPermission() {
|
||||
|
||||
Log.i("log", "requestPermission() entered");
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.Permision_storage), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
// ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
|
||||
requestPermissions(new String[] {android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
|
||||
switch (requestCode) {
|
||||
case PERMISSION_REQUEST_CODE:
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
Intent intent = new Intent(getActivity(), ImportSeedActivity.class);
|
||||
startActivity(intent);
|
||||
|
||||
} else {
|
||||
ToastUtil.getInstance(getActivity()).showToast(getActivity().getString(R.string.Permission_Denied_WRITE_EXTERNAL_STORAGE));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,18 +3,30 @@ package cy.agorise.crystalwallet.fragments;
|
|||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.activities.BoardActivity;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.DialogMaterial;
|
||||
import cy.agorise.crystalwallet.dialogs.material.NegativeResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.PositiveResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.QuestionDialog;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
||||
import cy.agorise.crystalwallet.viewmodels.validators.PinSecurityValidator;
|
||||
|
@ -25,6 +37,12 @@ import cy.agorise.crystalwallet.viewmodels.validators.PinSecurityValidator;
|
|||
|
||||
public class NoneSecurityFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.btnOK)
|
||||
Button btnOK;
|
||||
|
||||
|
||||
|
||||
|
||||
public NoneSecurityFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
@ -43,14 +61,41 @@ public class NoneSecurityFragment extends Fragment {
|
|||
View v = inflater.inflate(R.layout.fragment_none_security, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnClick(R.id.btnOK)
|
||||
public void btnOKClic(){
|
||||
|
||||
/*
|
||||
* Question if user is sure to remove the security
|
||||
* */
|
||||
final QuestionDialog questionDialog = new QuestionDialog(getActivity());
|
||||
questionDialog.setText(getActivity().getString(R.string.question_continue));
|
||||
questionDialog.setOnNegative(new NegativeResponse() {
|
||||
@Override
|
||||
public void onNegative(@NotNull DialogMaterial dialogMaterial) {
|
||||
}
|
||||
});
|
||||
questionDialog.setOnPositive(new PositiveResponse() {
|
||||
@Override
|
||||
public void onPositive() {
|
||||
CrystalSecurityMonitor.getInstance(null).clearSecurity();
|
||||
|
||||
Toast.makeText(getActivity().getBaseContext(),getActivity().getString(R.string.Security_mode_changed_to_none),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
questionDialog.show();
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
CrystalSecurityMonitor.getInstance(null).clearSecurity();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -18,13 +21,19 @@ import com.andrognito.patternlockview.PatternLockView;
|
|||
import com.andrognito.patternlockview.listener.PatternLockViewListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.CrystalDialog;
|
||||
import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
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;
|
||||
|
@ -42,9 +51,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
|
||||
}
|
||||
|
@ -77,6 +94,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);
|
||||
|
@ -87,12 +109,12 @@ public class PatternSecurityFragment extends Fragment {
|
|||
public void showNewPatternUI(){
|
||||
removePatternListener();
|
||||
patternLockView.clearPattern();
|
||||
tvPatternText.setText("Enter new pattern");
|
||||
tvPatternText.setTextColor(Color.WHITE);
|
||||
tvPatternText.setText(getActivity().getResources().getString(R.string.Enter_new_pattern));
|
||||
|
||||
actualPatternListener = new PatternLockViewListener() {
|
||||
@Override
|
||||
public void onStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,7 +140,7 @@ public class PatternSecurityFragment extends Fragment {
|
|||
removePatternListener();
|
||||
patternLockView.clearPattern();
|
||||
patternLockView.requestFocus();
|
||||
tvPatternText.setText("Confirm new pattern");
|
||||
tvPatternText.setText(getActivity().getResources().getString(R.string.Confirm_new_pattern));
|
||||
|
||||
actualPatternListener = new PatternLockViewListener() {
|
||||
@Override
|
||||
|
@ -135,7 +157,9 @@ public class PatternSecurityFragment extends Fragment {
|
|||
public void onComplete(List<PatternLockView.Dot> pattern) {
|
||||
if (patternEntered.equals(patternToString(pattern))){
|
||||
savePattern(patternEntered);
|
||||
showNewPatternUI();
|
||||
}
|
||||
else{
|
||||
resetPattern();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,9 +171,79 @@ public class PatternSecurityFragment extends Fragment {
|
|||
patternLockView.addPatternLockListener(actualPatternListener);
|
||||
}
|
||||
|
||||
private void resetPattern(){
|
||||
|
||||
/*
|
||||
* Show error
|
||||
* */
|
||||
tvPatternText.setText(getActivity().getResources().getString(R.string.Incorrect_pattern));
|
||||
tvPatternText.setTextColor(Color.RED);
|
||||
final Timer t = new Timer();
|
||||
t.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
t.cancel();
|
||||
showNewPatternUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
//Set how long before to start calling the TimerTask (in milliseconds)
|
||||
1000,
|
||||
//Set the amount of time between each execution (in milliseconds)
|
||||
1000);
|
||||
}
|
||||
|
||||
public void savePattern(String pattern){
|
||||
String patternEncripted = PasswordManager.encriptPassword(pattern);
|
||||
CrystalSecurityMonitor.getInstance(null).setPatternEncrypted(patternEncripted);
|
||||
CrystalSecurityMonitor.getInstance(null).callPasswordRequest(this.getActivity());
|
||||
/*CrystalSecurityMonitor.getInstance(null).callPasswordRequest(this.getActivity(), new OnResponse() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
|
||||
Log.i("onSuccess","onSuccess");
|
||||
Toast.makeText(getActivity(), "onSuccess", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed() {
|
||||
Log.i("onFailed","onFailed");
|
||||
Toast.makeText(getActivity(), "onFailed", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});*/
|
||||
|
||||
/*
|
||||
* Show success
|
||||
* */
|
||||
tvPatternText.setText(getActivity().getResources().getString(R.string.Pattern_set_correctly));
|
||||
tvPatternText.setTextColor(Color.GREEN);
|
||||
final Timer t_ = new Timer();
|
||||
t_.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
t_.cancel();
|
||||
showNewPatternUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
//Set how long before to start calling the TimerTask (in milliseconds)
|
||||
1000,
|
||||
//Set the amount of time between each execution (in milliseconds)
|
||||
1000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,35 @@
|
|||
package cy.agorise.crystalwallet.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnFocusChange;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.DialogMaterial;
|
||||
import cy.agorise.crystalwallet.dialogs.material.NegativeResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.PositiveResponse;
|
||||
import cy.agorise.crystalwallet.dialogs.material.QuestionDialog;
|
||||
import cy.agorise.crystalwallet.models.GeneralSetting;
|
||||
import cy.agorise.crystalwallet.util.PasswordManager;
|
||||
import cy.agorise.crystalwallet.viewmodels.GeneralSettingListViewModel;
|
||||
|
@ -42,6 +53,19 @@ public class PinSecurityFragment extends Fragment implements UIValidatorListener
|
|||
@BindView(R.id.tvConfirmPinError)
|
||||
TextView tvConfirmPinError;
|
||||
|
||||
@BindView(R.id.btnOK)
|
||||
Button btnOK;
|
||||
|
||||
/*
|
||||
* Validates the new typing for the patterns
|
||||
* */
|
||||
private boolean first = true;
|
||||
|
||||
/*
|
||||
* Flag to check if validation of fields is correct
|
||||
* */
|
||||
private boolean valid = false;
|
||||
|
||||
GeneralSettingListViewModel generalSettingListViewModel;
|
||||
GeneralSetting passwordGeneralSetting;
|
||||
PinSecurityValidator pinSecurityValidator;
|
||||
|
@ -64,15 +88,117 @@ public class PinSecurityFragment extends Fragment implements UIValidatorListener
|
|||
View v = inflater.inflate(R.layout.fragment_pin_security, container, false);
|
||||
ButterKnife.bind(this, v);
|
||||
|
||||
/*
|
||||
* Initially not enabled til it passes validations
|
||||
* */
|
||||
btnOK.setEnabled(false);
|
||||
|
||||
generalSettingListViewModel = ViewModelProviders.of(this).get(GeneralSettingListViewModel.class);
|
||||
LiveData<List<GeneralSetting>> generalSettingsLiveData = generalSettingListViewModel.getGeneralSettingList();
|
||||
|
||||
pinSecurityValidator = new PinSecurityValidator(this.getContext(), etNewPin, etConfirmPin);
|
||||
pinSecurityValidator.setListener(this);
|
||||
|
||||
/*
|
||||
* If PIN is configured set some text
|
||||
* */
|
||||
final CrystalSecurityMonitor crystalSecurityMonitor = CrystalSecurityMonitor.getInstance(getActivity());
|
||||
switch(CrystalSecurityMonitor.getInstance(getActivity()).actualSecurity()) {
|
||||
case GeneralSetting.SETTING_PASSWORD:
|
||||
|
||||
if(etNewPin!=null && etConfirmPin!=null){
|
||||
etNewPin.setText("123456");
|
||||
etConfirmPin.setText("123456");
|
||||
}
|
||||
|
||||
break;
|
||||
case GeneralSetting.SETTING_PATTERN:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if(etNewPin!=null && etConfirmPin!=null) {
|
||||
etNewPin.setText("");
|
||||
etConfirmPin.setText("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Focus in no where
|
||||
* */
|
||||
tvNewPinError.requestFocus();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
|
||||
first = true;
|
||||
|
||||
/*
|
||||
* If PIN is configured set some text
|
||||
* */
|
||||
final CrystalSecurityMonitor crystalSecurityMonitor = CrystalSecurityMonitor.getInstance(getActivity());
|
||||
switch(CrystalSecurityMonitor.getInstance(getActivity()).actualSecurity()) {
|
||||
case GeneralSetting.SETTING_PASSWORD:
|
||||
|
||||
if(etNewPin!=null && etConfirmPin!=null){
|
||||
etNewPin.setText("123456");
|
||||
etConfirmPin.setText("123456");
|
||||
}
|
||||
|
||||
break;
|
||||
case GeneralSetting.SETTING_PATTERN:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if(etNewPin!=null && etConfirmPin!=null) {
|
||||
etNewPin.setText("");
|
||||
etConfirmPin.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Focus in no where
|
||||
* */
|
||||
if(getActivity()!=null){
|
||||
tvNewPinError.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btnOK)
|
||||
void okClic(final View view) {
|
||||
|
||||
/*
|
||||
* Only can continue if the fields are correctly validated
|
||||
* */
|
||||
if(valid){
|
||||
|
||||
/*
|
||||
* Question if continue or not
|
||||
* */
|
||||
final QuestionDialog questionDialog = new QuestionDialog(getActivity());
|
||||
questionDialog.setText(getActivity().getString(R.string.question_continue));
|
||||
questionDialog.setOnNegative(new NegativeResponse() {
|
||||
@Override
|
||||
public void onNegative(@NotNull DialogMaterial dialogMaterial) {
|
||||
}
|
||||
});
|
||||
questionDialog.setOnPositive(new PositiveResponse() {
|
||||
@Override
|
||||
public void onPositive() {
|
||||
savePassword();
|
||||
}
|
||||
});
|
||||
questionDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.etNewPin,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterNewPinChanged(Editable editable) {
|
||||
|
@ -94,6 +220,16 @@ public class PinSecurityFragment extends Fragment implements UIValidatorListener
|
|||
}
|
||||
}
|
||||
|
||||
@OnFocusChange({R.id.etNewPin,R.id.etConfirmPin})
|
||||
public void focusChangePIN(View view, boolean hasFocus){
|
||||
if(hasFocus){
|
||||
if(first){
|
||||
first = false;
|
||||
clearFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValidationSucceeded(final ValidationField field) {
|
||||
final PinSecurityFragment fragment = this;
|
||||
|
@ -108,29 +244,64 @@ public class PinSecurityFragment extends Fragment implements UIValidatorListener
|
|||
}
|
||||
|
||||
if (pinSecurityValidator.isValid()){
|
||||
CharSequence text = "Your password has been sucessfully changed!";
|
||||
int duration = Toast.LENGTH_SHORT;
|
||||
//savePassword();
|
||||
|
||||
Toast toast = Toast.makeText(getContext(), text, duration);
|
||||
toast.show();
|
||||
if(!first){
|
||||
|
||||
savePassword(etNewPin.getText().toString());
|
||||
//Now is valid
|
||||
valid = true;
|
||||
|
||||
/*
|
||||
* Enable ok button to continue
|
||||
* */
|
||||
btnOK.setEnabled(true);
|
||||
}
|
||||
|
||||
clearFields();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void savePassword(){
|
||||
|
||||
savePassword(etNewPin.getText().toString());
|
||||
|
||||
CharSequence text = "Your password has been sucessfully changed!";
|
||||
int duration = Toast.LENGTH_SHORT;
|
||||
Toast toast = Toast.makeText(getContext(), text, duration);
|
||||
toast.show();
|
||||
|
||||
etNewPin.setText("123456");
|
||||
etConfirmPin.setText("123456");
|
||||
|
||||
first = true;
|
||||
|
||||
btnOK.setEnabled(false);
|
||||
|
||||
/*
|
||||
* Focus in no where
|
||||
* */
|
||||
tvNewPinError.requestFocus();
|
||||
}
|
||||
|
||||
public void savePassword(String password) {
|
||||
String passwordEncripted = PasswordManager.encriptPassword(password);
|
||||
CrystalSecurityMonitor.getInstance(null).setPasswordSecurity(passwordEncripted);
|
||||
CrystalSecurityMonitor.getInstance(null).callPasswordRequest(this.getActivity());
|
||||
CrystalSecurityMonitor.getInstance(getActivity()).setPasswordSecurity(passwordEncripted);
|
||||
|
||||
//CrystalSecurityMonitor.getInstance(getActivity()).callPasswordRequest(this.getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValidationFailed(final ValidationField field) {
|
||||
|
||||
//Still false
|
||||
valid = false;
|
||||
|
||||
/*
|
||||
* Disable til it passes validations
|
||||
* */
|
||||
btnOK.setEnabled(false);
|
||||
|
||||
this.getActivity().runOnUiThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.ContextWrapper;
|
|||
import android.content.DialogInterface;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -22,18 +23,28 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder;
|
||||
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CalculateBitcoinUriRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.requestmanagers.NextBitcoinAccountAddressRequest;
|
||||
import cy.agorise.crystalwallet.util.CircularImageView;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountListViewModel;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetAccountAdapter;
|
||||
|
@ -75,6 +86,8 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
TextView tvAssetError;
|
||||
@BindView(R.id.ivQrCode)
|
||||
ImageView ivQrCode;
|
||||
@BindView(R.id.pbQrCode)
|
||||
ProgressBar pbQrCode;
|
||||
@BindView(R.id.tvCancel)
|
||||
TextView tvCancel;
|
||||
|
||||
|
@ -95,6 +108,10 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
|
||||
private FloatingActionButton fabReceive;
|
||||
|
||||
private AsyncTask qrCodeTask;
|
||||
|
||||
private Double lastAmount = -1.0;
|
||||
|
||||
public static ReceiveTransactionFragment newInstance(long cryptoNetAccountId) {
|
||||
ReceiveTransactionFragment f = new ReceiveTransactionFragment();
|
||||
|
||||
|
@ -132,36 +149,13 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
db = CrystalDatabase.getAppDatabase(this.getContext());
|
||||
this.cryptoNetAccount = db.cryptoNetAccountDao().getById(this.cryptoNetAccountId);
|
||||
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
this.grapheneAccount = new GrapheneAccount(this.cryptoNetAccount);
|
||||
this.grapheneAccount.loadInfo(db.grapheneAccountInfoDao().getByAccountId(this.cryptoNetAccountId));
|
||||
|
||||
final LiveData<List<CryptoCoinBalance>> balancesList = db.cryptoCoinBalanceDao().getBalancesFromAccount(cryptoNetAccountId);
|
||||
balancesList.observe(this, new Observer<List<CryptoCoinBalance>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<CryptoCoinBalance> cryptoCoinBalances) {
|
||||
ArrayList<Long> assetIds = new ArrayList<Long>();
|
||||
for (CryptoCoinBalance nextBalance : balancesList.getValue()) {
|
||||
assetIds.add(nextBalance.getCryptoCurrencyId());
|
||||
}
|
||||
List<CryptoCurrency> cryptoCurrencyList = db.cryptoCurrencyDao().getByIds(assetIds);
|
||||
|
||||
CryptoCurrencyAdapter assetAdapter = new CryptoCurrencyAdapter(getContext(), android.R.layout.simple_spinner_item, cryptoCurrencyList);
|
||||
spAsset.setAdapter(assetAdapter);
|
||||
}
|
||||
});
|
||||
|
||||
receiveTransactionValidator = new ReceiveTransactionValidator(this.getContext(), this.cryptoNetAccount, spAsset, etAmount);
|
||||
receiveTransactionValidator.setListener(this);
|
||||
|
||||
CryptoNetAccountListViewModel cryptoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
|
||||
List<CryptoNetAccount> cryptoNetAccounts = cryptoNetAccountListViewModel.getCryptoNetAccountList();
|
||||
CryptoNetAccountAdapter toSpinnerAdapter = new CryptoNetAccountAdapter(this.getContext(), android.R.layout.simple_spinner_item, cryptoNetAccounts);
|
||||
spTo.setAdapter(toSpinnerAdapter);
|
||||
spTo.setSelection(0);
|
||||
|
||||
setAccountUI();
|
||||
}
|
||||
|
||||
builder.setView(view);
|
||||
|
@ -234,8 +228,59 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
}
|
||||
}
|
||||
|
||||
public void setAccountUI(){
|
||||
if (this.cryptoNetAccount.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
this.grapheneAccount = new GrapheneAccount(this.cryptoNetAccount);
|
||||
this.grapheneAccount.loadInfo(db.grapheneAccountInfoDao().getByAccountId(this.cryptoNetAccountId));
|
||||
|
||||
final LiveData<List<CryptoCoinBalance>> balancesList = db.cryptoCoinBalanceDao().getBalancesFromAccount(cryptoNetAccountId);
|
||||
balancesList.observe(this, new Observer<List<CryptoCoinBalance>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<CryptoCoinBalance> cryptoCoinBalances) {
|
||||
ArrayList<Long> assetIds = new ArrayList<Long>();
|
||||
for (CryptoCoinBalance nextBalance : balancesList.getValue()) {
|
||||
assetIds.add(nextBalance.getCryptoCurrencyId());
|
||||
}
|
||||
List<CryptoCurrency> cryptoCurrencyList = db.cryptoCurrencyDao().getByIds(assetIds);
|
||||
|
||||
/*
|
||||
* Test
|
||||
* */
|
||||
//CryptoCurrency crypto1 = new CryptoCurrency();
|
||||
//crypto1.setId(1);
|
||||
//crypto1.setName("BITCOIN");
|
||||
//crypto1.setPrecision(1);
|
||||
//cryptoCurrencyList.add(crypto1);
|
||||
|
||||
|
||||
CryptoCurrencyAdapter assetAdapter = new CryptoCurrencyAdapter(getContext(), android.R.layout.simple_spinner_item, cryptoCurrencyList);
|
||||
spAsset.setAdapter(assetAdapter);
|
||||
}
|
||||
});
|
||||
|
||||
receiveTransactionValidator = new ReceiveTransactionValidator(this.getContext(), this.cryptoNetAccount, spAsset, etAmount);
|
||||
receiveTransactionValidator.setListener(this);
|
||||
} else {
|
||||
CryptoCoin cryptoCoin = CryptoCoin.getByCryptoNet(this.cryptoNetAccount.getCryptoNet()).get(0);
|
||||
|
||||
List<String> currencyList = new ArrayList<>();
|
||||
currencyList.add(cryptoCoin.getLabel());
|
||||
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this.getContext(),android.R.layout.simple_list_item_1,currencyList);
|
||||
spAsset.setAdapter(arrayAdapter);
|
||||
|
||||
receiveTransactionValidator = new ReceiveTransactionValidator(this.getContext(), this.cryptoNetAccount, spAsset, etAmount);
|
||||
receiveTransactionValidator.setListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@OnItemSelected(R.id.spTo)
|
||||
public void afterToSelected(Spinner spinner, int position) {
|
||||
this.cryptoNetAccount = (CryptoNetAccount)spinner.getSelectedItem();
|
||||
setAccountUI();
|
||||
this.receiveTransactionValidator.validate();
|
||||
}
|
||||
|
||||
|
@ -247,7 +292,10 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
|
||||
@OnItemSelected(R.id.spAsset)
|
||||
public void afterAssetSelected(Spinner spinner, int position) {
|
||||
this.cryptoCurrency = (CryptoCurrency)spinner.getSelectedItem();
|
||||
if (spinner.getSelectedItem() instanceof CryptoCurrency) {
|
||||
this.cryptoCurrency = (CryptoCurrency) spinner.getSelectedItem();
|
||||
}
|
||||
|
||||
this.receiveTransactionValidator.validate();
|
||||
}
|
||||
|
||||
|
@ -295,71 +343,147 @@ public class ReceiveTransactionFragment extends DialogFragment implements UIVali
|
|||
}
|
||||
|
||||
public void createQrCode(){
|
||||
Double amount = 0.0;
|
||||
final Double amount;
|
||||
try{
|
||||
amount = Double.valueOf(this.etAmount.getText().toString());
|
||||
|
||||
} catch(NumberFormatException e){
|
||||
lastAmount = -1.0;
|
||||
Log.e("ReceiveFragment","Amount casting error.");
|
||||
return;
|
||||
}
|
||||
|
||||
CryptoNetAccount toAccountSelected = (CryptoNetAccount) spTo.getSelectedItem();
|
||||
if (!amount.equals(lastAmount)) {
|
||||
pbQrCode.setVisibility(View.VISIBLE);
|
||||
lastAmount = amount;
|
||||
CryptoNetAccount toAccountSelected = (CryptoNetAccount) spTo.getSelectedItem();
|
||||
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
GrapheneAccount grapheneAccountSelected = new GrapheneAccount(toAccountSelected);
|
||||
grapheneAccountSelected.loadInfo(db.grapheneAccountInfoDao().getByAccountId(toAccountSelected.getId()));
|
||||
if (this.qrCodeTask != null) {
|
||||
this.qrCodeTask.cancel(true);
|
||||
}
|
||||
|
||||
if (this.cryptoNetAccount.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
GrapheneAccount grapheneAccountSelected = new GrapheneAccount(toAccountSelected);
|
||||
grapheneAccountSelected.loadInfo(db.grapheneAccountInfoDao().getByAccountId(toAccountSelected.getId()));
|
||||
|
||||
|
||||
this.invoiceItems.clear();
|
||||
this.invoiceItems.add(
|
||||
new LineItem("transfer", 1, amount)
|
||||
);
|
||||
this.invoiceItems.clear();
|
||||
this.invoiceItems.add(
|
||||
new LineItem("transfer", 1, amount)
|
||||
);
|
||||
|
||||
LineItem items[] = new LineItem[this.invoiceItems.size()];
|
||||
items = this.invoiceItems.toArray(items);
|
||||
this.invoice.setLineItems(items);
|
||||
this.invoice.setTo(grapheneAccountSelected.getName());
|
||||
this.invoice.setCurrency(this.cryptoCurrency.getName());
|
||||
LineItem items[] = new LineItem[this.invoiceItems.size()];
|
||||
items = this.invoiceItems.toArray(items);
|
||||
this.invoice.setLineItems(items);
|
||||
this.invoice.setTo(grapheneAccountSelected.getName());
|
||||
this.invoice.setCurrency(this.cryptoCurrency.getName());
|
||||
|
||||
try {
|
||||
Bitmap bitmap = textToImageEncode(Invoice.toQrCode(invoice));
|
||||
ivQrCode.setImageBitmap(bitmap);
|
||||
} catch (WriterException e) {
|
||||
Log.e("ReceiveFragment", "Error creating QrCode");
|
||||
//if (this.qrCodeTask != null) {
|
||||
// this.qrCodeTask.cancel(true);
|
||||
//}
|
||||
|
||||
this.qrCodeTask = new AsyncTask<Object, Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Object... voids) {
|
||||
try {
|
||||
final Bitmap bitmap = textToImageEncode(Invoice.toQrCode(invoice));
|
||||
|
||||
if (!this.isCancelled()) {
|
||||
ReceiveTransactionFragment.this.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ivQrCode.setImageBitmap(bitmap);
|
||||
pbQrCode.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (WriterException e) {
|
||||
Log.e("ReceiveFragment", "Error creating QrCode");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
this.qrCodeTask.execute(null, null, null);
|
||||
} else {
|
||||
final CryptoCoin cryptoCoin = CryptoCoin.getByCryptoNet(this.cryptoNetAccount.getCryptoNet()).get(0);
|
||||
|
||||
final CalculateBitcoinUriRequest uriRequest = new CalculateBitcoinUriRequest(cryptoCoin, cryptoNetAccount, getContext(), amount);
|
||||
|
||||
uriRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (uriRequest.getUri() != null) {
|
||||
qrCodeTask = new AsyncTask<Object, Void, Void>() {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Object... voids) {
|
||||
try {
|
||||
final Bitmap bitmap = textToImageEncode(uriRequest.getUri());
|
||||
|
||||
if (!this.isCancelled()) {
|
||||
ReceiveTransactionFragment.this.getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//Double amountNow = -1.0;
|
||||
//try{
|
||||
// amountNow = Double.valueOf(etAmount.getText().toString());
|
||||
//} catch(NumberFormatException e){
|
||||
//}
|
||||
//if (amountNow >= 0) {
|
||||
if (amount.equals(lastAmount)) {
|
||||
if (!isCancelled()) {
|
||||
ivQrCode.setImageBitmap(bitmap);
|
||||
pbQrCode.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (WriterException e) {
|
||||
Log.e("ReceiveFragment", "Error creating QrCode");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
qrCodeTask.execute(null, null, null);
|
||||
} else {
|
||||
Log.e("ReceiveFragment", "Error obtaining the uri");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CryptoNetInfoRequests.getInstance().addRequest(uriRequest);
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap textToImageEncode(String Value) throws WriterException {
|
||||
//TODO: do this in another thread
|
||||
|
||||
BitMatrix bitMatrix;
|
||||
Bitmap bitmap = null;
|
||||
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
|
||||
try {
|
||||
bitMatrix = new MultiFormatWriter().encode(
|
||||
Value,
|
||||
BarcodeFormat.DATA_MATRIX.QR_CODE,
|
||||
ivQrCode.getWidth(), ivQrCode.getHeight(), null
|
||||
);
|
||||
|
||||
} catch (IllegalArgumentException Illegalargumentexception) {
|
||||
return null;
|
||||
}
|
||||
int bitMatrixWidth = bitMatrix.getWidth();
|
||||
int bitMatrixHeight = bitMatrix.getHeight();
|
||||
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
|
||||
|
||||
for (int y = 0; y < bitMatrixHeight; y++) {
|
||||
int offset = y * bitMatrixWidth;
|
||||
|
||||
for (int x = 0; x < bitMatrixWidth; x++) {
|
||||
pixels[offset + x] = bitMatrix.get(x, y) ?
|
||||
getResources().getColor(R.color.QRCodeBlackColor):getResources().getColor(R.color.QRCodeWhiteColor);
|
||||
}
|
||||
BitMatrix bitMatrix = multiFormatWriter.encode(Value, BarcodeFormat.QR_CODE, ivQrCode.getWidth(), ivQrCode.getHeight());
|
||||
BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
|
||||
bitmap = barcodeEncoder.createBitmap(bitMatrix);
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight, Bitmap.Config.ARGB_4444);
|
||||
bitmap.setPixels(pixels, 0, ivQrCode.getWidth(), 0, 0, bitMatrixWidth, bitMatrixHeight);
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,10 +83,15 @@ 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);
|
||||
|
||||
switch(CrystalSecurityMonitor.getInstance(null).actualSecurity()) {
|
||||
switch(CrystalSecurityMonitor.getInstance(getActivity()).actualSecurity()) {
|
||||
case GeneralSetting.SETTING_PASSWORD:
|
||||
mPager.setCurrentItem(1);
|
||||
break;
|
||||
|
@ -96,7 +101,6 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
default:
|
||||
mPager.setCurrentItem(0);
|
||||
}
|
||||
mPager.setSwipeLocked(true);
|
||||
|
||||
TabLayout tabLayout = v.findViewById(R.id.tabs);
|
||||
|
||||
|
@ -117,7 +121,7 @@ public class SecuritySettingsFragment extends Fragment {
|
|||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
CrystalSecurityMonitor.getInstance(null).callPasswordRequest(this.getActivity());
|
||||
//CrystalSecurityMonitor.getInstance(null).callPasswordRequest(this.getActivity());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -8,11 +8,11 @@ import android.arch.lifecycle.Observer;
|
|||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -22,25 +22,21 @@ import android.support.v4.app.ActivityCompat;
|
|||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.Result;
|
||||
import com.jaredrummler.materialspinner.MaterialSpinner;
|
||||
import com.vincent.filepicker.ToastUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.RoundingMode;
|
||||
|
@ -56,6 +52,14 @@ import butterknife.OnClick;
|
|||
import butterknife.OnItemSelected;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.CrystalDialog;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.interfaces.OnResponse;
|
||||
import cy.agorise.crystalwallet.requestmanagers.BitcoinSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.BitcoinUriParseRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitsharesSendRequest;
|
||||
|
@ -81,10 +85,12 @@ import static butterknife.internal.Utils.listOf;
|
|||
|
||||
public class SendTransactionFragment extends DialogFragment implements UIValidatorListener, ZXingScannerView.ResultHandler {
|
||||
|
||||
private final String TAG = getClass().getName();
|
||||
|
||||
SendTransactionValidator sendTransactionValidator;
|
||||
|
||||
@BindView(R.id.spFrom)
|
||||
MaterialSpinner spFrom;
|
||||
Spinner spFrom;
|
||||
@BindView(R.id.tvFromError)
|
||||
TextView tvFromError;
|
||||
@BindView(R.id.etTo)
|
||||
|
@ -93,12 +99,14 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
View viewSend;
|
||||
@BindView(R.id.tvToError)
|
||||
TextView tvToError;
|
||||
@BindView(R.id.fabCloseCamera)
|
||||
FloatingActionButton btnCloseCamera;
|
||||
@BindView(R.id.spAsset)
|
||||
Spinner spAsset;
|
||||
@BindView(R.id.tvAssetError)
|
||||
TextView tvAssetError;
|
||||
@BindView(R.id.scrollMain)
|
||||
ScrollView scrollMain;
|
||||
//@BindView(R.id.scrollMain)
|
||||
//ScrollView scrollMain;
|
||||
@BindView(R.id.etAmount)
|
||||
EditText etAmount;
|
||||
@BindView(R.id.tvAmountError)
|
||||
|
@ -109,11 +117,8 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
TextView tvMemoError;
|
||||
@BindView(R.id.btnSend)
|
||||
FloatingActionButton btnSend;
|
||||
@BindView(R.id.btnCancel)
|
||||
TextView btnCancel;
|
||||
@BindView(R.id.ivPeople)
|
||||
ImageView ivPeople;
|
||||
|
||||
@BindView(R.id.ivCamera)
|
||||
ZXingScannerView mScannerView;
|
||||
|
||||
|
@ -122,7 +127,8 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
@BindView(R.id.gravatar)
|
||||
CircularImageView userImg;
|
||||
|
||||
Button btnScanQrCode;
|
||||
/* Flag to control when the camera is visible and when is hidden */
|
||||
private boolean cameraVisible = false;
|
||||
|
||||
private long cryptoNetAccountId;
|
||||
private CryptoNetAccount cryptoNetAccount;
|
||||
|
@ -131,7 +137,8 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
private FloatingActionButton fabSend;
|
||||
private AlertDialog.Builder builder;
|
||||
|
||||
|
||||
/* Dialog for loading */
|
||||
private CrystalDialog crystalDialog;
|
||||
|
||||
public static SendTransactionFragment newInstance(long cryptoNetAccountId) {
|
||||
SendTransactionFragment f = new SendTransactionFragment();
|
||||
|
@ -157,72 +164,45 @@ 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);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
|
||||
/*
|
||||
* Detet scroll changes
|
||||
* */
|
||||
scrollMain.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
|
||||
@Override
|
||||
public void onScrollChanged() {
|
||||
|
||||
View view = scrollMain.getChildAt(scrollMain.getChildCount() - 1);
|
||||
|
||||
int diff = (view.getBottom() - (scrollMain.getHeight() + scrollMain.getScrollY()));
|
||||
|
||||
float traslationY = btnSend.getTranslationY();
|
||||
|
||||
if(diff<=266 && diff>128){
|
||||
//btnSend.setTranslationY(0);
|
||||
//viewSend.setTranslationY(0);
|
||||
|
||||
btnSend.animate().y(880);
|
||||
viewSend.animate().y(800);
|
||||
}
|
||||
else if(diff<=128 && diff>10){
|
||||
//btnSend.setTranslationY(-130);
|
||||
//viewSend.setTranslationY(-130);
|
||||
|
||||
btnSend.animate().y(880);
|
||||
viewSend.animate().y(800);
|
||||
}
|
||||
else if(diff<=10 && diff>0){
|
||||
//btnSend.setTranslationY(-170);
|
||||
//viewSend.setTranslationY(-170);
|
||||
|
||||
btnSend.animate().y(680);
|
||||
viewSend.animate().y(600);
|
||||
}
|
||||
else if(diff==0){
|
||||
//btnSend.setTranslationY(-190);
|
||||
//viewSend.setTranslationY(-190);
|
||||
|
||||
btnSend.animate().y(680);
|
||||
viewSend.animate().y(600);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.cryptoNetAccountId = getArguments().getLong("CRYPTO_NET_ACCOUNT_ID",-1);
|
||||
|
||||
/*
|
||||
* Add style to the spinner android
|
||||
* */
|
||||
/* Add style to the spinner android */
|
||||
spFrom.setBackground(getContext().getDrawable(R.drawable.square_color));
|
||||
|
||||
if (this.cryptoNetAccountId != -1) {
|
||||
db = CrystalDatabase.getAppDatabase(this.getContext());
|
||||
this.cryptoNetAccount = db.cryptoNetAccountDao().getById(this.cryptoNetAccountId);
|
||||
|
||||
CryptoNetAccountListViewModel cryptoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
|
||||
List<CryptoNetAccount> cryptoNetAccounts = cryptoNetAccountListViewModel.getCryptoNetAccountList();
|
||||
CryptoNetAccountAdapter fromSpinnerAdapter = new CryptoNetAccountAdapter(this.getContext(), android.R.layout.simple_spinner_item, cryptoNetAccounts);
|
||||
|
||||
spFrom.setAdapter(fromSpinnerAdapter);
|
||||
spFrom.setSelection(0);
|
||||
|
||||
setAccountUI();
|
||||
}
|
||||
|
||||
loadUserImage();
|
||||
|
||||
/* Check for CAMERA permission */
|
||||
if (Build.VERSION.SDK_INT >= 23 && !checkCameraPermission())
|
||||
requestCameraPermission();
|
||||
|
||||
return builder.setView(view).create();
|
||||
}
|
||||
|
||||
public void setAccountUI(){
|
||||
if (this.cryptoNetAccount.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
this.grapheneAccount = new GrapheneAccount(this.cryptoNetAccount);
|
||||
this.grapheneAccount.loadInfo(db.grapheneAccountInfoDao().getByAccountId(this.cryptoNetAccountId));
|
||||
|
||||
|
@ -236,70 +216,102 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
}
|
||||
List<CryptoCurrency> cryptoCurrencyList = db.cryptoCurrencyDao().getByIds(assetIds);
|
||||
|
||||
/*
|
||||
* Test
|
||||
* */
|
||||
//CryptoCurrency crypto1 = new CryptoCurrency();
|
||||
//crypto1.setId(1);
|
||||
//crypto1.setName("BITCOIN");
|
||||
//crypto1.setPrecision(1);
|
||||
//cryptoCurrencyList.add(crypto1);
|
||||
|
||||
|
||||
assetAdapter = new CryptoCurrencyAdapter(getContext(), android.R.layout.simple_spinner_item, cryptoCurrencyList);
|
||||
spAsset.setAdapter(assetAdapter);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO SendTransactionValidator to accept spFrom
|
||||
sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, spFrom, etTo, spAsset, etAmount, etMemo);
|
||||
sendTransactionValidator.setListener(this);
|
||||
|
||||
CryptoNetAccountListViewModel cryptoNetAccountListViewModel = ViewModelProviders.of(this).get(CryptoNetAccountListViewModel.class);
|
||||
List<CryptoNetAccount> cryptoNetAccounts = cryptoNetAccountListViewModel.getCryptoNetAccountList();
|
||||
CryptoNetAccountAdapter fromSpinnerAdapter = new CryptoNetAccountAdapter(this.getContext(), android.R.layout.simple_spinner_item, cryptoNetAccounts);
|
||||
} else {
|
||||
CryptoCoin cryptoCoin = CryptoCoin.getByCryptoNet(this.cryptoNetAccount.getCryptoNet()).get(0);
|
||||
|
||||
spFrom.setAdapter(fromSpinnerAdapter);
|
||||
//spFrom.setSelection(0);
|
||||
List<String> currencyList = new ArrayList<>();
|
||||
currencyList.add(cryptoCoin.getLabel());
|
||||
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this.getContext(),android.R.layout.simple_list_item_1,currencyList);
|
||||
spAsset.setAdapter(arrayAdapter);
|
||||
|
||||
/*
|
||||
* 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() {
|
||||
// TODO SendTransactionValidator to accept spFrom
|
||||
sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, spFrom, etTo, spAsset, etAmount, etMemo);
|
||||
sendTransactionValidator.setListener(this);
|
||||
|
||||
@Override public void onNothingSelected(MaterialSpinner spinner) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// etFrom.setText(this.grapheneAccount.getName());
|
||||
}
|
||||
}
|
||||
|
||||
loadUserImage();
|
||||
try {
|
||||
verifyCameraPermissions(getActivity());
|
||||
beginScanQrCode();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
private boolean checkCameraPermission() {
|
||||
int result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA);
|
||||
return result == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA)) {
|
||||
Toast.makeText(getActivity(), getActivity().getString(R.string.permission_denied_camera), Toast.LENGTH_LONG).show();
|
||||
|
||||
/* Disable the button of the camera visibility */
|
||||
btnCloseCamera.setVisibility(View.INVISIBLE);
|
||||
|
||||
} else {
|
||||
requestPermissions(new String[] {android.Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.setView(view).create();
|
||||
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_CAMERA_PERMISSION:
|
||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
Log.e("value", "Permission Granted, Now you can use camera .");
|
||||
|
||||
getActivity().runOnUiThread(new Runnable(){
|
||||
public void run() {
|
||||
Toast.makeText(getActivity(), getActivity().getString(R.string.permission_granted_camera), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
Log.e("value", "Permission Denied, You cannot use the camera.");
|
||||
|
||||
getActivity().runOnUiThread(new Runnable(){
|
||||
public void run() {
|
||||
Toast.makeText(getActivity(), getActivity().getString(R.string.permission_denied_camera), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
/*builder.setNeutralButton("Scan QR Code", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
beginScanQrCode();
|
||||
}
|
||||
});*/
|
||||
mScannerView.setResultHandler(this);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mScannerView.stopCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
@ -328,10 +340,12 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
}
|
||||
}
|
||||
|
||||
/*@OnItemSelected(R.id.spFrom)
|
||||
@OnItemSelected(R.id.spFrom)
|
||||
public void afterFromSelected(Spinner spinner, int position) {
|
||||
this.cryptoNetAccount = (CryptoNetAccount)spinner.getSelectedItem();
|
||||
setAccountUI();
|
||||
this.sendTransactionValidator.validate();
|
||||
}*/
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.etTo,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
|
@ -351,6 +365,46 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
}
|
||||
|
||||
|
||||
@OnClick(R.id.fabCloseCamera)
|
||||
public void onClickCloseCamera(){
|
||||
if(cameraVisible)
|
||||
hideCamera();
|
||||
else
|
||||
showCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the camera and hide the black background
|
||||
* */
|
||||
private void showCamera(){
|
||||
/* Change visibilities of views */
|
||||
mScannerView.setVisibility(View.VISIBLE);
|
||||
|
||||
/* Change icon */
|
||||
btnCloseCamera.setImageDrawable(getResources().getDrawable(R.drawable.ic_close));
|
||||
|
||||
/* Reset variable */
|
||||
cameraVisible = true;
|
||||
|
||||
/* Star the camera again */
|
||||
beginScanQrCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hides the camera and show the black background
|
||||
* */
|
||||
private void hideCamera(){
|
||||
/* Change visibilities of views */
|
||||
mScannerView.setVisibility(View.INVISIBLE);
|
||||
|
||||
/* Change icon */
|
||||
btnCloseCamera.setImageDrawable(getResources().getDrawable(R.drawable.ok));
|
||||
|
||||
/* Reset variable */
|
||||
cameraVisible = false;
|
||||
}
|
||||
|
||||
@OnTextChanged(value = R.id.etMemo,
|
||||
callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED)
|
||||
void afterMemoChanged(Editable editable) {
|
||||
|
@ -408,51 +462,113 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
|
||||
@OnClick(R.id.btnSend)
|
||||
public void sendTransaction(){
|
||||
final SendTransactionFragment thisFragment = this;
|
||||
final CryptoNetInfoRequest sendRequest;
|
||||
|
||||
if (this.sendTransactionValidator.isValid()) {
|
||||
CryptoNetAccount fromAccountSelected = (CryptoNetAccount) spFrom.getItems().get(spFrom.getSelectedIndex());
|
||||
//CryptoNetAccount fromAccountSelected = (CryptoNetAccount) spFrom.getItems().get(spFrom.getSelectedIndex());
|
||||
CryptoNetAccount fromAccountSelected = (CryptoNetAccount) spFrom.getSelectedItem();
|
||||
|
||||
|
||||
/*
|
||||
* this is only for graphene accounts.
|
||||
*
|
||||
**/
|
||||
GrapheneAccount grapheneAccountSelected = new GrapheneAccount(fromAccountSelected);
|
||||
grapheneAccountSelected.loadInfo(db.grapheneAccountInfoDao().getByAccountId(fromAccountSelected.getId()));
|
||||
if (fromAccountSelected.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
/* This is only for graphene accounts. */
|
||||
GrapheneAccount grapheneAccountSelected = new GrapheneAccount(fromAccountSelected);
|
||||
grapheneAccountSelected.loadInfo(db.grapheneAccountInfoDao().getByAccountId(fromAccountSelected.getId()));
|
||||
|
||||
|
||||
//TODO convert the amount to long type using the precision of the currency
|
||||
Double amountFromEditText = Double.parseDouble(this.etAmount.getText().toString());
|
||||
Long amount = (long) Math.floor(amountFromEditText * Math.round(Math.pow(10, ((CryptoCurrency) spAsset.getSelectedItem()).getPrecision())));
|
||||
|
||||
//TODO convert the amount to long type using the precision of the currency
|
||||
Double amountFromEditText = Double.parseDouble(this.etAmount.getText().toString());
|
||||
Long amount = (long)Math.floor(amountFromEditText*Math.round(Math.pow(10,((CryptoCurrency)spAsset.getSelectedItem()).getPrecision())));
|
||||
/*final ValidateBitsharesSendRequest*/
|
||||
sendRequest = new ValidateBitsharesSendRequest(
|
||||
this.getContext(),
|
||||
grapheneAccountSelected,
|
||||
this.etTo.getText().toString(),
|
||||
amount,
|
||||
((CryptoCurrency) spAsset.getSelectedItem()).getName(),
|
||||
etMemo.getText().toString()
|
||||
);
|
||||
|
||||
final ValidateBitsharesSendRequest sendRequest = new ValidateBitsharesSendRequest(
|
||||
this.getContext(),
|
||||
grapheneAccountSelected,
|
||||
this.etTo.getText().toString(),
|
||||
amount,
|
||||
((CryptoCurrency)spAsset.getSelectedItem()).getName(),
|
||||
etMemo.getText().toString()
|
||||
);
|
||||
|
||||
sendRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (sendRequest.getStatus().equals(ValidateBitsharesSendRequest.StatusCode.SUCCEEDED)){
|
||||
try {
|
||||
this.finalize();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
sendRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (((ValidateBitsharesSendRequest)sendRequest).getStatus().equals(ValidateBitsharesSendRequest.StatusCode.SUCCEEDED)) {
|
||||
try {
|
||||
crystalDialog.dismiss();
|
||||
thisFragment.dismiss();
|
||||
//thisFragment.finalize();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
crystalDialog.dismiss();
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
CryptoCoin cryptoCoin = CryptoCoin.getByCryptoNet(this.cryptoNetAccount.getCryptoNet()).get(0);
|
||||
|
||||
//TODO convert the amount to long type using the precision of the currency
|
||||
Double amountFromEditText = Double.parseDouble(this.etAmount.getText().toString());
|
||||
Long amount = (long) Math.floor(amountFromEditText * (Math.pow(10, cryptoCoin.getPrecision())));
|
||||
|
||||
sendRequest = new BitcoinSendRequest(
|
||||
this.getContext(),
|
||||
this.cryptoNetAccount,
|
||||
this.etTo.getText().toString(),
|
||||
amount,
|
||||
cryptoCoin,
|
||||
etMemo.getText().toString()
|
||||
);
|
||||
|
||||
sendRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (((BitcoinSendRequest)sendRequest).getStatus().equals(ValidateBitsharesSendRequest.StatusCode.SUCCEEDED)) {
|
||||
try {
|
||||
crystalDialog.dismiss();
|
||||
thisFragment.dismiss();
|
||||
//thisFragment.finalize();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
crystalDialog.dismiss();
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
crystalDialog = new CrystalDialog((Activity) getContext());
|
||||
crystalDialog.setText("Sending");
|
||||
crystalDialog.progress();
|
||||
crystalDialog.show();
|
||||
|
||||
CryptoNetInfoRequests.getInstance().addRequest(sendRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed() {
|
||||
|
||||
}
|
||||
});
|
||||
CryptoNetInfoRequests.getInstance().addRequest(sendRequest);
|
||||
//CryptoNetInfoRequests.getInstance().addRequest(sendRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public void beginScanQrCode(){
|
||||
//mScannerView = new ZXingScannerView(getContext());
|
||||
mScannerView.setFormats(listOf(BarcodeFormat.QR_CODE));
|
||||
mScannerView.setAspectTolerance(0.5f);
|
||||
mScannerView.setAutoFocus(true);
|
||||
mScannerView.setLaserColor(R.color.colorAccent);
|
||||
mScannerView.setMaskColor(R.color.colorAccent);
|
||||
|
@ -462,24 +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
|
||||
};
|
||||
|
||||
|
||||
public static void verifyCameraPermissions(Activity activity) {
|
||||
// Check if we have write permission
|
||||
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
|
||||
|
||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
||||
// We don't have permission so prompt the user
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
PERMISSIONS_CAMERA,
|
||||
REQUEST_CAMERA_PERMISSION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValidationSucceeded(final ValidationField field) {
|
||||
|
@ -534,13 +632,14 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
@Override
|
||||
public void handleResult(Result result) {
|
||||
try {
|
||||
System.out.println("CAMERA result " + result.getText() );
|
||||
Invoice invoice = Invoice.fromQrCode(result.getText());
|
||||
|
||||
Log.d(TAG, "QR Code read: " + invoice.toJsonString());
|
||||
|
||||
etTo.setText(invoice.getTo());
|
||||
|
||||
for (int i = 0; i < assetAdapter.getCount(); i++) {
|
||||
if (assetAdapter.getItem(i).getName().equals(invoice.getCurrency())) {
|
||||
if (assetAdapter.getItem(i).getName().equals(invoice.getCurrency().toUpperCase())) {
|
||||
spAsset.setSelection(i);
|
||||
break;
|
||||
}
|
||||
|
@ -557,8 +656,34 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ENGLISH));
|
||||
etAmount.setText(df.format(amount));
|
||||
Log.i("SendFragment", result.getText());
|
||||
return;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//Is not a bitshares QR
|
||||
//CryptoCoin cryptoCoin = CryptoCoin.getByCryptoNet(this.cryptoNetAccount.getCryptoNet()).get(0);
|
||||
final BitcoinUriParseRequest bitcoinUriParseRequest = new BitcoinUriParseRequest(result.getText(), CryptoCoin.BITCOIN);
|
||||
|
||||
bitcoinUriParseRequest.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (bitcoinUriParseRequest.getAddress() != null) {
|
||||
if (!bitcoinUriParseRequest.getAddress().equals("")) {
|
||||
etTo.setText(bitcoinUriParseRequest.getAddress());
|
||||
}
|
||||
if (bitcoinUriParseRequest.getAmount() > 0) {
|
||||
etAmount.setText(bitcoinUriParseRequest.getAmount().toString());
|
||||
}
|
||||
if (!bitcoinUriParseRequest.getMemo().equals("")) {
|
||||
etMemo.setText(bitcoinUriParseRequest.getMemo());
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Not a valid QR info", Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CryptoNetInfoRequests.getInstance().addRequest(bitcoinUriParseRequest);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,18 +5,20 @@ import android.arch.lifecycle.Observer;
|
|||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.arch.paging.PagedList;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Editable;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -25,27 +27,30 @@ import butterknife.BindView;
|
|||
import butterknife.ButterKnife;
|
||||
import butterknife.OnTextChanged;
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransactionExtended;
|
||||
import cy.agorise.crystalwallet.viewmodels.TransactionListViewModel;
|
||||
import cy.agorise.crystalwallet.views.TransactionListView;
|
||||
import cy.agorise.crystalwallet.views.TransactionListAdapter;
|
||||
import cy.agorise.crystalwallet.views.TransactionOrderSpinnerAdapter;
|
||||
|
||||
public class TransactionsFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.vTransactionListView)
|
||||
TransactionListView transactionListView;
|
||||
|
||||
@BindView(R.id.spTransactionsOrder)
|
||||
Spinner spTransactionsOrder;
|
||||
|
||||
@BindView(R.id.etTransactionSearch)
|
||||
EditText etTransactionSearch;
|
||||
|
||||
RecyclerView balanceRecyclerView;
|
||||
@BindView(R.id.tvNoTransactions)
|
||||
TextView tvNoTransactions;
|
||||
|
||||
@BindView(R.id.rvTransactions)
|
||||
RecyclerView rvTransactions;
|
||||
|
||||
FloatingActionButton fabSend;
|
||||
FloatingActionButton fabReceive;
|
||||
|
||||
|
||||
TransactionListAdapter transactionListAdapter;
|
||||
TransactionListViewModel transactionListViewModel;
|
||||
LiveData<PagedList<CryptoCoinTransactionExtended>> transactionsLiveData;
|
||||
|
||||
|
@ -66,20 +71,22 @@ public class TransactionsFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View view = inflater.inflate(R.layout.fragment_transactions, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
// Gets the Balance RecyclerView
|
||||
balanceRecyclerView = view.findViewById(R.id.transactionListView);
|
||||
rvTransactions.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
transactionListAdapter = new TransactionListAdapter(this);
|
||||
rvTransactions.setAdapter(transactionListAdapter);
|
||||
|
||||
fabSend = getActivity().findViewById(R.id.fabSend);
|
||||
fabReceive = getActivity().findViewById(R.id.fabReceive);
|
||||
|
||||
// TODO move this listener to the activity, to make this fragment reusable
|
||||
// Adds listener to the RecyclerView to show and hide buttons at the bottom of the screen
|
||||
balanceRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
rvTransactions.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx,int dy){
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
|
@ -119,12 +126,17 @@ public class TransactionsFragment extends Fragment {
|
|||
transactionListViewModel.initTransactionList(orderSelected.getField(),etTransactionSearch.getText().toString());
|
||||
transactionsLiveData = transactionListViewModel.getTransactionList();
|
||||
|
||||
final Fragment fragment = this;
|
||||
transactionsLiveData.observe(this, new Observer<PagedList<CryptoCoinTransactionExtended>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable PagedList<CryptoCoinTransactionExtended> cryptoCoinTransactions) {
|
||||
Log.i("Transactions","Transactions have change! Count:"+cryptoCoinTransactions.size());
|
||||
transactionListView.setData(cryptoCoinTransactions, fragment);
|
||||
public void onChanged(@Nullable PagedList<CryptoCoinTransactionExtended> transactions) {
|
||||
transactionListAdapter.submitList(transactions);
|
||||
|
||||
if(transactions != null && transactions.size() > 0){
|
||||
tvNoTransactions.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
else{
|
||||
tvNoTransactions.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -136,7 +148,7 @@ public class TransactionsFragment extends Fragment {
|
|||
}
|
||||
|
||||
public void initTransactionsOrderSpinner(){
|
||||
List<TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem> spinnerValues = new ArrayList<TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem>();
|
||||
List<TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem> spinnerValues = new ArrayList<>();
|
||||
spinnerValues.add(new TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem("date","Date",0,false));
|
||||
spinnerValues.add(new TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem("amount","Amount",0,false));
|
||||
spinnerValues.add(new TransactionOrderSpinnerAdapter.TransactionOrderSpinnerItem("is_input","In/Out",0,false));
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package cy.agorise.crystalwallet.interfaces;
|
||||
|
||||
public interface OnResponse {
|
||||
void onSuccess();
|
||||
void onFailed();
|
||||
}
|
|
@ -2,11 +2,13 @@ package cy.agorise.crystalwallet.manager;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
|
@ -20,12 +22,14 @@ import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
|||
import cy.agorise.crystalwallet.apigenerator.grapheneoperation.AccountUpgradeOperationBuilder;
|
||||
import cy.agorise.crystalwallet.application.constant.BitsharesConstant;
|
||||
import cy.agorise.crystalwallet.dao.AccountSeedDao;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAccountNameCache;
|
||||
import cy.agorise.crystalwallet.models.seed.BIP39;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetEquivalentRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.GetBitsharesAccountNameCacheRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitsharesLTMUpgradeRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitsharesSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateCreateBitsharesAccountRequest;
|
||||
|
@ -55,6 +59,7 @@ import cy.agorise.graphenej.UserAccount;
|
|||
import cy.agorise.graphenej.models.AccountProperties;
|
||||
import cy.agorise.graphenej.models.BlockHeader;
|
||||
import cy.agorise.graphenej.models.HistoricalTransfer;
|
||||
import cy.agorise.graphenej.objects.Memo;
|
||||
import cy.agorise.graphenej.operations.TransferOperationBuilder;
|
||||
|
||||
/**
|
||||
|
@ -64,8 +69,6 @@ import cy.agorise.graphenej.operations.TransferOperationBuilder;
|
|||
*/
|
||||
public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||
|
||||
//private final static String BITSHARES_TESTNET_CHAIN_ID= "9cf6f255a208100d2bb275a3c52f4b1589b7ec9c9bfc2cb2a5fe6411295106d8";
|
||||
|
||||
private final static String SIMPLE_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
private final static String DEFAULT_TIME_ZONE = "GMT";
|
||||
|
||||
|
@ -89,6 +92,11 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(fetch)[0];
|
||||
fetch.setId(idAccount);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(fetch));
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(fetch.getId(),fetch.getAccountId(),context);
|
||||
request.success(fetch);
|
||||
}
|
||||
|
@ -129,6 +137,11 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
long[] idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
grapheneAccount.setId(idAccount[0]);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
|
@ -145,8 +158,14 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
GrapheneAccount fetch = (GrapheneAccount) answer;
|
||||
grapheneAccount.setName(fetch.getName());
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount)[0];
|
||||
grapheneAccount.setId(idAccount);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
|
@ -157,8 +176,14 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
});
|
||||
}else {
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount)[0];
|
||||
grapheneAccount.setId(idAccount);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(), grapheneAccount.getAccountId(), context);
|
||||
}
|
||||
}
|
||||
|
@ -179,6 +204,11 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
info.setAccountId(fetch.getAccountId());
|
||||
grapheneAccount.setAccountId(fetch.getAccountId());
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(info);
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
|
@ -195,6 +225,11 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
info.setName(fetch.getName());
|
||||
grapheneAccount.setName(fetch.getName());
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(info);
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
|
@ -204,6 +239,11 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
}
|
||||
});
|
||||
}else{
|
||||
AccountSeed seed = db.accountSeedDao().findById(grapheneAccount.getSeedId());
|
||||
if(seed.getName() == null || seed.getName().isEmpty()){
|
||||
seed.setName(grapheneAccount.getName());
|
||||
db.accountSeedDao().insertAccountSeed(seed);
|
||||
}
|
||||
subscribeBitsharesAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +252,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
private void subscribeBitsharesAccount(long accountId, String accountBitsharesID, Context context){
|
||||
GrapheneApiGenerator.subscribeBitsharesAccount(accountId,accountBitsharesID,context);
|
||||
BitsharesAccountManager.refreshAccountTransactions(accountId,context);
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountBitsharesID,context);
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountBitsharesID,CryptoNet.BITSHARES,context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,27 +261,103 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
*/
|
||||
@Override
|
||||
public void onNewRequest(CryptoNetInfoRequest request) {
|
||||
if (request instanceof ValidateImportBitsharesAccountRequest){
|
||||
this.validateImportAccount((ValidateImportBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateExistBitsharesAccountRequest){
|
||||
this.validateExistAcccount((ValidateExistBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateBitsharesSendRequest){
|
||||
this.validateSendRequest((ValidateBitsharesSendRequest) request);
|
||||
}else if (request instanceof CryptoNetEquivalentRequest){
|
||||
this.getEquivalentValue((CryptoNetEquivalentRequest) request);
|
||||
}else if (request instanceof ValidateCreateBitsharesAccountRequest){
|
||||
this.validateCreateAccount((ValidateCreateBitsharesAccountRequest) request);
|
||||
}else if (request instanceof ValidateBitsharesLTMUpgradeRequest){
|
||||
this.validateLTMAccountUpgrade((ValidateBitsharesLTMUpgradeRequest) request);
|
||||
}else if (request instanceof GetBitsharesAccountNameCacheRequest){
|
||||
this.getBitsharesAccountNameCacheRequest((GetBitsharesAccountNameCacheRequest) request);
|
||||
}else{
|
||||
if(request.getCoin().equals(CryptoCoin.BITSHARES)) {
|
||||
if (request instanceof ImportBitsharesAccountRequest) {
|
||||
this.importAccount((ImportBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateImportBitsharesAccountRequest) {
|
||||
this.validateImportAccount((ValidateImportBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateExistBitsharesAccountRequest) {
|
||||
this.validateExistAcccount((ValidateExistBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateBitsharesSendRequest) {
|
||||
this.validateSendRequest((ValidateBitsharesSendRequest) request);
|
||||
} else if (request instanceof CryptoNetEquivalentRequest) {
|
||||
this.getEquivalentValue((CryptoNetEquivalentRequest) request);
|
||||
} else if (request instanceof ValidateCreateBitsharesAccountRequest) {
|
||||
this.validateCreateAccount((ValidateCreateBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateBitsharesLTMUpgradeRequest) {
|
||||
this.validateLTMAccountUpgrade((ValidateBitsharesLTMUpgradeRequest) request);
|
||||
} else if (request instanceof GetBitsharesAccountNameCacheRequest) {
|
||||
this.getBitsharesAccountNameCacheRequest((GetBitsharesAccountNameCacheRequest) request);
|
||||
} else {
|
||||
|
||||
//TODO not implemented
|
||||
System.out.println("Error request not implemented " + request.getClass().getName());
|
||||
//TODO not implemented
|
||||
System.out.println("Error request not implemented " + request.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void importAccount(final ImportBitsharesAccountRequest importRequest){
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(importRequest.getContext());
|
||||
final AccountSeedDao accountSeedDao = db.accountSeedDao();
|
||||
ApiRequest getAccountNamesBK = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer != null && importRequest.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.NOT_STARTED)) {
|
||||
UserAccount userAccount = (UserAccount) answer;
|
||||
importRequest.setSeedType(SeedType.BRAINKEY);
|
||||
importRequest.setStatus(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
AccountSeed seed = new AccountSeed();
|
||||
seed.setName(userAccount.getName());
|
||||
seed.setType(importRequest.getSeedType());
|
||||
seed.setMasterSeed(importRequest.getMnemonic());
|
||||
long idSeed = accountSeedDao.insertAccountSeed(seed);
|
||||
if (idSeed >= 0) {
|
||||
GrapheneAccount account = new GrapheneAccount();
|
||||
account.setCryptoNet(CryptoNet.BITSHARES);
|
||||
account.setAccountIndex(0);
|
||||
account.setSeedId(idSeed);
|
||||
account.setAccountId(userAccount.getObjectId());
|
||||
importAccountFromSeed(account, importRequest.getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
BIP39 bip39 = new BIP39(-1, importRequest.getMnemonic());
|
||||
ApiRequest getAccountNamesBP39 = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer != null && importRequest.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.NOT_STARTED)) {
|
||||
UserAccount userAccount = (UserAccount) answer;
|
||||
importRequest.setSeedType(SeedType.BIP39);
|
||||
importRequest.setStatus(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
AccountSeed seed = new AccountSeed();
|
||||
seed.setName(userAccount.getName());
|
||||
seed.setType(importRequest.getSeedType());
|
||||
seed.setMasterSeed(importRequest.getMnemonic());
|
||||
long idSeed = accountSeedDao.insertAccountSeed(seed);
|
||||
if (idSeed >= 0) {
|
||||
GrapheneAccount account = new GrapheneAccount();
|
||||
account.setCryptoNet(CryptoNet.BITSHARES);
|
||||
account.setAccountIndex(0);
|
||||
account.setSeedId(idSeed);
|
||||
account.setAccountId(userAccount.getObjectId());
|
||||
importAccountFromSeed(account, importRequest.getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
importRequest.setStatus(ImportBitsharesAccountRequest.StatusCode.BAD_SEED);
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getAccountByOwnerOrActiveAddress(new Address(ECKey.fromPublicOnly(bip39.getBitsharesActiveKey(0).getPubKey())),CryptoNet.BITSHARES,getAccountNamesBP39);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0);
|
||||
|
||||
GrapheneApiGenerator.getAccountByOwnerOrActiveAddress(bk.getPublicAddress("BTS"),CryptoNet.BITSHARES,getAccountNamesBK);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the import account request
|
||||
*/
|
||||
|
@ -307,7 +423,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.NO_ACCOUNT_DATA);
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getAccountById((String)answer,getAccountInfo);
|
||||
GrapheneApiGenerator.getAccountById((String)answer,CryptoNet.BITSHARES,getAccountInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -317,7 +433,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
}
|
||||
});
|
||||
|
||||
GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),checkAccountName);
|
||||
GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),CryptoNet.BITSHARES,checkAccountName);
|
||||
}
|
||||
|
||||
private void validateCreateAccount(final ValidateCreateBitsharesAccountRequest createRequest){
|
||||
|
@ -372,7 +488,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
validateRequest.setAccountExists(false);
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getAccountIdByName(validateRequest.getAccountName(),checkAccountName);
|
||||
GrapheneApiGenerator.getAccountIdByName(validateRequest.getAccountName(),CryptoNet.BITSHARES,checkAccountName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -471,9 +587,16 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
.setTransferAmount(new AssetAmount(UnsignedLong.valueOf(sendRequest.getAmount()), new Asset(idAsset)))
|
||||
.setFee(new AssetAmount(UnsignedLong.valueOf(0), feeAsset));
|
||||
if (sendRequest.getMemo() != null) {
|
||||
//builder.setMemo(new Memo(fromUserAccount,toUserAccount,0,sendRequest.getMemo().getBytes()));
|
||||
//TODO memo
|
||||
System.out.println("transaction has memo");
|
||||
try {
|
||||
//TODO change authority for memo
|
||||
Address fromAddress = new Address(fromUserAccount.getActive().getKeyAuthList().get(0).getKey(), "BTS");
|
||||
Address toAddress = new Address(toUserAccount.getActive().getKeyAuthList().get(0).getKey(), "BTS");
|
||||
builder.setMemo(new Memo(fromAddress,toAddress,BigInteger.ZERO,sendRequest.getMemo().getBytes()));
|
||||
//TODO add random nonce
|
||||
}catch ( Exception e){
|
||||
e.printStackTrace();
|
||||
//TODO error
|
||||
}
|
||||
}
|
||||
ArrayList<BaseOperation> operationList = new ArrayList<>();
|
||||
operationList.add(builder.build());
|
||||
|
@ -570,7 +693,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
AccountIdOrNameListener listener = new AccountIdOrNameListener(request);
|
||||
|
||||
ApiRequest accountRequest = new ApiRequest(0, listener);
|
||||
GrapheneApiGenerator.getAccountById(grapheneId,accountRequest);
|
||||
GrapheneApiGenerator.getAccountById(grapheneId,CryptoNet.BITSHARES,accountRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -582,7 +705,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
AccountIdOrNameListener listener = new AccountIdOrNameListener(request);
|
||||
|
||||
ApiRequest accountRequest = new ApiRequest(0, listener);
|
||||
GrapheneApiGenerator.getAccountByName(grapheneName,accountRequest);
|
||||
GrapheneApiGenerator.getAccountByName(grapheneName,CryptoNet.BITSHARES,accountRequest);
|
||||
|
||||
}
|
||||
|
||||
|
@ -593,7 +716,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
ApiRequest assetRequest = new ApiRequest(0, nameListener);
|
||||
ArrayList<String> assetNames = new ArrayList<>();
|
||||
assetNames.add(assetName);
|
||||
GrapheneApiGenerator.getAssetByName(assetNames, assetRequest);
|
||||
GrapheneApiGenerator.getAssetByName(assetNames, CryptoNet.BITSHARES,assetRequest);
|
||||
|
||||
}
|
||||
|
||||
|
@ -616,7 +739,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
int stop = start + limit;
|
||||
|
||||
ApiRequest transactionRequest = new ApiRequest(0, new TransactionRequestListener(start, stop, limit, grapheneAccount, db));
|
||||
GrapheneApiGenerator.getAccountTransaction(grapheneAccount.getAccountId(), start, stop, limit, transactionRequest);
|
||||
GrapheneApiGenerator.getAccountTransaction(grapheneAccount.getAccountId(), start, stop, limit, CryptoNet.BITSHARES,transactionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +829,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
});
|
||||
ArrayList<String> assets = new ArrayList<>();
|
||||
assets.add(transfer.getOperation().getAssetAmount().getAsset().getObjectId());
|
||||
GrapheneApiGenerator.getAssetById(assets,assetRequest);
|
||||
GrapheneApiGenerator.getAssetById(assets,CryptoNet.BITSHARES,assetRequest);
|
||||
|
||||
}else{
|
||||
saveTransaction(transaction,info,transfer);
|
||||
|
@ -719,7 +842,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
int newStart= start + limit;
|
||||
int newStop= stop + limit;
|
||||
ApiRequest transactionRequest = new ApiRequest(newStart/limit, new TransactionRequestListener(newStart,newStop,limit,account,db));
|
||||
GrapheneApiGenerator.getAccountTransaction(account.getAccountId(),newStart,newStop,limit,transactionRequest);
|
||||
GrapheneApiGenerator.getAccountTransaction(account.getAccountId(),newStart,newStop,limit,CryptoNet.BITSHARES,transactionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -735,7 +858,7 @@ public class BitsharesAccountManager implements CryptoAccountManager, CryptoNetI
|
|||
transaction.setInput(!transfer.getOperation().getFrom().getObjectId().equals(account.getAccountId()));
|
||||
transaction.setTo(transfer.getOperation().getTo().getObjectId());
|
||||
|
||||
GrapheneApiGenerator.getBlockHeaderTime(transfer.getBlockNum(), new ApiRequest(0, new GetTransactionDate(transaction, db.transactionDao())));
|
||||
GrapheneApiGenerator.getBlockHeaderTime(transfer.getBlockNum(),CryptoNet.BITSHARES, new ApiRequest(0, new GetTransactionDate(transaction, db.transactionDao())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -327,7 +327,6 @@ public class FileBackupManager implements FileServiceRequestsListener {
|
|||
public static byte[] decompress(byte[] inputBytes, int which) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
System.out.println("Bytes: "+Util.bytesToHex(inputBytes));
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(inputBytes);
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream(16*2048);
|
||||
if(which == Util.XZ) {
|
||||
|
|
|
@ -3,32 +3,74 @@ package cy.agorise.crystalwallet.manager;
|
|||
import android.content.Context;
|
||||
|
||||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutPoint;
|
||||
import org.bitcoinj.crypto.ChildNumber;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.crypto.HDKeyDerivation;
|
||||
import org.bitcoinj.script.Script;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.ApiRequest;
|
||||
import cy.agorise.crystalwallet.apigenerator.ApiRequestListener;
|
||||
import cy.agorise.crystalwallet.apigenerator.InsightApiGenerator;
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.BroadcastTransaction;
|
||||
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.dao.BitcoinAddressDao;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.BitcoinAddress;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.BitcoinTransactionGTxIO;
|
||||
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.models.GeneralTransaction;
|
||||
import cy.agorise.crystalwallet.requestmanagers.BitcoinSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.BitcoinUriParseRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CalculateBitcoinUriRequest;
|
||||
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.crystalwallet.requestmanagers.ValidateBitcoinAddressRequest;
|
||||
import cy.agorise.graphenej.Util;
|
||||
|
||||
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||
|
||||
static HashMap<CryptoCoin, GeneralAccountManager> generalAccountManagers = new HashMap();
|
||||
|
||||
private static CryptoCoin[] SUPPORTED_COINS = new CryptoCoin[]{
|
||||
CryptoCoin.BITCOIN,
|
||||
CryptoCoin.BITCOIN_TEST,
|
||||
CryptoCoin.DASH,
|
||||
CryptoCoin.LITECOIN
|
||||
} ;
|
||||
|
||||
final CryptoCoin cryptoCoin;
|
||||
final Context context;
|
||||
|
||||
public static GeneralAccountManager getAccountManager(CryptoCoin coin){
|
||||
return generalAccountManagers.get(coin);
|
||||
}
|
||||
|
||||
public GeneralAccountManager(CryptoCoin cryptoCoin, Context context) {
|
||||
this.cryptoCoin = cryptoCoin;
|
||||
this.context = context;
|
||||
generalAccountManagers.put(cryptoCoin,this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccountFromSeed(CryptoNetAccount account, ManagerRequest request, Context context) {
|
||||
|
||||
|
@ -40,55 +82,347 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
}
|
||||
|
||||
@Override
|
||||
public void loadAccountFromDB(CryptoNetAccount account, Context context) {
|
||||
public void loadAccountFromDB(final CryptoNetAccount account, Context context) {
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
|
||||
AccountSeed seed = db.accountSeedDao().findById(account.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(account.getAccountIndex(), true));
|
||||
final DeterministicKey externalKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||
new ChildNumber(0, false));
|
||||
final DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||
new ChildNumber(1, false));
|
||||
|
||||
CryptoCoinBalance balance = new CryptoCoinBalance();
|
||||
long amount = 0;
|
||||
List<CryptoCoinTransaction> trransactions = db.transactionDao().getByIdAccount(account.getId());
|
||||
for(CryptoCoinTransaction transaction : trransactions){
|
||||
if(transaction.isConfirmed()){
|
||||
if(transaction.getInput()){
|
||||
amount += transaction.getAmount();
|
||||
}else{
|
||||
amount -= transaction.getAmount();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
balance.setBalance(amount);
|
||||
balance.setCryptoCurrencyId(db.cryptoCurrencyDao().getByName(cryptoCoin.getLabel(),cryptoCoin.name()).getId());
|
||||
balance.setAccountId(account.getId());
|
||||
db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance);
|
||||
|
||||
long indexExternal = db.bitcoinAddressDao().getLastExternalAddress(account.getId());
|
||||
if(indexExternal > 0){
|
||||
for(int i = 0; i < indexExternal;i++){
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getExternalByIndex(i);
|
||||
InsightApiGenerator.getTransactionFromAddress(cryptoCoin,address.getAddress(),true,null);
|
||||
}
|
||||
}else {
|
||||
ECKey externalAddrKey = HDKeyDerivation.deriveChildKey(externalKey, new ChildNumber((int) 0, true));
|
||||
BitcoinAddress address = new BitcoinAddress();
|
||||
address.setChange(false);
|
||||
address.setAccountId(account.getId());
|
||||
address.setIndex(0);
|
||||
String addressString = externalAddrKey.toAddress(this.cryptoCoin.getParameters()).toString();
|
||||
address.setAddress(addressString);
|
||||
db.bitcoinAddressDao().insertBitcoinAddresses(address);
|
||||
InsightApiGenerator.getTransactionFromAddress(cryptoCoin,addressString,true,
|
||||
new CheckAddressForTransaction(db.bitcoinAddressDao(),account.getId(),externalKey,false,0));
|
||||
}
|
||||
|
||||
long indexChange = db.bitcoinAddressDao().getLastChangeAddress(account.getId());
|
||||
if(indexChange > 0){
|
||||
for(int i = 0; i < indexChange;i++){
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getChangeByIndex(i);
|
||||
InsightApiGenerator.getTransactionFromAddress(cryptoCoin,address.getAddress(),true,null);
|
||||
}
|
||||
}else {
|
||||
ECKey changeAddrKey = HDKeyDerivation.deriveChildKey(changeKey, new ChildNumber((int) 0, true));
|
||||
BitcoinAddress address = new BitcoinAddress();
|
||||
address.setChange(true);
|
||||
address.setAccountId(account.getId());
|
||||
address.setIndex(0);
|
||||
String addressString =changeAddrKey.toAddress(this.cryptoCoin.getParameters()).toString();
|
||||
address.setAddress(addressString);
|
||||
db.bitcoinAddressDao().insertBitcoinAddresses(address);
|
||||
InsightApiGenerator.getTransactionFromAddress(cryptoCoin,addressString,true,
|
||||
new CheckAddressForTransaction(db.bitcoinAddressDao(),account.getId(),externalKey,true,0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onNewRequest(CryptoNetInfoRequest 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){
|
||||
this.createGeneralAccount((CreateBitcoinAccountRequest) request);
|
||||
}else if(request instanceof NextBitcoinAccountAddressRequest){
|
||||
this.getNextAddress((NextBitcoinAccountAddressRequest) request);
|
||||
}else if(request instanceof ValidateBitcoinAddressRequest){
|
||||
this.validateAddress((ValidateBitcoinAddressRequest) request);
|
||||
}else if(request instanceof CalculateBitcoinUriRequest){
|
||||
this.calculateUri((CalculateBitcoinUriRequest) request);
|
||||
}else if(request instanceof BitcoinUriParseRequest){
|
||||
this.parseUri((BitcoinUriParseRequest) request);
|
||||
}else{
|
||||
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that process each transaction fetched by the insight api
|
||||
* @param txi
|
||||
*/
|
||||
public void processTxi(Txi txi){
|
||||
try {
|
||||
System.out.println("GeneralAccountManager processingTxi " + txi.txid);
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(this.context);
|
||||
List<BitcoinTransaction> btTransactions = db.bitcoinTransactionDao().getTransactionsByTxid(txi.txid);
|
||||
if (!btTransactions.isEmpty()) {
|
||||
System.out.println("GeneralAccountManager Transaction not null " + txi.txid);
|
||||
for (BitcoinTransaction btTransaction : btTransactions) {
|
||||
btTransaction.setConfirmations(txi.confirmations);
|
||||
CryptoCoinTransaction ccTransaction = db.transactionDao().getById(btTransaction.getCryptoCoinTransactionId());
|
||||
if (!ccTransaction.isConfirmed() && btTransaction.getConfirmations() >= cryptoCoin.getCryptoNet().getConfirmationsNeeded()) {
|
||||
ccTransaction.setConfirmed(true);
|
||||
db.transactionDao().insertTransaction(ccTransaction);
|
||||
updateBalance(ccTransaction, (ccTransaction.getInput() ? 1 : -1) * ccTransaction.getAmount(), db);
|
||||
}
|
||||
|
||||
db.bitcoinTransactionDao().insertBitcoinTransaction(btTransaction);
|
||||
}
|
||||
} else {
|
||||
/*List<CryptoCoinTransaction> ccTransactions = new ArrayList();
|
||||
btTransactions = new ArrayList();*/ //TODO transactions involving multiples accounts
|
||||
CryptoCoinTransaction ccTransaction = new CryptoCoinTransaction();
|
||||
BitcoinTransaction btTransaction = new BitcoinTransaction();
|
||||
btTransaction.setTxId(txi.txid);
|
||||
btTransaction.setBlock(txi.blockheight);
|
||||
btTransaction.setFee((long) (txi.fee * Math.pow(10, cryptoCoin.getPrecision())));
|
||||
btTransaction.setConfirmations(txi.confirmations);
|
||||
ccTransaction.setDate(new Date(txi.time * 1000));
|
||||
if (txi.txlock || txi.confirmations >= cryptoCoin.getCryptoNet().getConfirmationsNeeded()) {
|
||||
ccTransaction.setConfirmed(true);
|
||||
} else {
|
||||
ccTransaction.setConfirmed(false);
|
||||
}
|
||||
|
||||
ccTransaction.setInput(false);
|
||||
|
||||
long amount = 0;
|
||||
|
||||
|
||||
//transaction.setAccount(this.mAccount);
|
||||
//transaction.setType(cryptoCoin);
|
||||
List<BitcoinTransactionGTxIO> gtxios = new ArrayList();
|
||||
for (Vin vin : txi.vin) {
|
||||
BitcoinTransactionGTxIO input = new BitcoinTransactionGTxIO();
|
||||
String addr = vin.addr;
|
||||
input.setAddress(addr);
|
||||
input.setIndex(vin.n);
|
||||
input.setOutput(true);
|
||||
input.setAmount((long) (vin.value * Math.pow(10, cryptoCoin.getPrecision())));
|
||||
input.setOriginalTxId(vin.txid);
|
||||
input.setScriptHex(vin.scriptSig.hex);
|
||||
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getdadress(addr);
|
||||
if (address != null) {
|
||||
if (ccTransaction.getAccountId() < 0) {
|
||||
ccTransaction.setAccountId(address.getAccountId());
|
||||
ccTransaction.setFrom(addr);
|
||||
ccTransaction.setInput(false);
|
||||
amount -= (long) (txi.fee * Math.pow(10, cryptoCoin.getPrecision()));
|
||||
}
|
||||
|
||||
//if (ccTransaction.getAccountId() == address.getAccountId()) {
|
||||
amount -= (long) (vin.value * Math.pow(10, cryptoCoin.getPrecision()));
|
||||
//}
|
||||
}
|
||||
|
||||
if (ccTransaction.getFrom() == null || ccTransaction.getFrom().isEmpty()) {
|
||||
ccTransaction.setFrom(addr);
|
||||
}
|
||||
|
||||
gtxios.add(input);
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (Vout vout : txi.vout) {
|
||||
if (vout.scriptPubKey.addresses == null || vout.scriptPubKey.addresses.length <= 0) {
|
||||
|
||||
} else {
|
||||
BitcoinTransactionGTxIO output = new BitcoinTransactionGTxIO();
|
||||
String addr = vout.scriptPubKey.addresses[0];
|
||||
output.setAddress(addr);
|
||||
output.setIndex(vout.n);
|
||||
output.setOutput(false);
|
||||
output.setAmount((long) (vout.value * Math.pow(10, cryptoCoin.getPrecision())));
|
||||
output.setScriptHex(vout.scriptPubKey.hex);
|
||||
output.setOriginalTxId(txi.txid);
|
||||
|
||||
gtxios.add(output);
|
||||
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getdadress(addr);
|
||||
if (address != null) {
|
||||
if (ccTransaction.getAccountId() < 0) {
|
||||
ccTransaction.setAccountId(address.getAccountId());
|
||||
ccTransaction.setInput(true);
|
||||
ccTransaction.setTo(addr);
|
||||
}
|
||||
|
||||
//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()) {
|
||||
ccTransaction.setTo(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccTransaction.setAmount(amount);
|
||||
CryptoCurrency currency = db.cryptoCurrencyDao().getByNameAndCryptoNet(this.cryptoCoin.getLabel(), this.cryptoCoin.getCryptoNet().name());
|
||||
if (currency == null) {
|
||||
currency = new CryptoCurrency();
|
||||
currency.setCryptoNet(this.cryptoCoin.getCryptoNet());
|
||||
currency.setName(this.cryptoCoin.getLabel());
|
||||
currency.setPrecision(this.cryptoCoin.getPrecision());
|
||||
long idCurrency = db.cryptoCurrencyDao().insertCryptoCurrency(currency)[0];
|
||||
currency.setId(idCurrency);
|
||||
}
|
||||
|
||||
ccTransaction.setIdCurrency((int) currency.getId());
|
||||
|
||||
long ccId = db.transactionDao().insertTransaction(ccTransaction)[0];
|
||||
btTransaction.setCryptoCoinTransactionId(ccId);
|
||||
long btId = db.bitcoinTransactionDao().insertBitcoinTransaction(btTransaction)[0];
|
||||
for (BitcoinTransactionGTxIO gtxio : gtxios) {
|
||||
gtxio.setBitcoinTransactionId(ccId);
|
||||
db.bitcoinTransactionDao().insertBitcoinTransactionGTxIO(gtxio);
|
||||
}
|
||||
|
||||
if (ccTransaction.isConfirmed()) {
|
||||
updateBalance(ccTransaction, amount, db);
|
||||
}
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void createGeneralAccount(CreateBitcoinAccountRequest request){
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(this.context);
|
||||
CryptoNetAccount account = new CryptoNetAccount();
|
||||
account.setAccountIndex(0);
|
||||
account.setCryptoNet(this.cryptoCoin.getCryptoNet());
|
||||
account.setName(request.getAccountSeed().getName());
|
||||
account.setSeedId(request.getAccountSeed().getId());
|
||||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(account)[0];
|
||||
account.setId(idAccount);
|
||||
|
||||
loadAccountFromDB(account,request.getContext());
|
||||
request.setStatus(CreateBitcoinAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
}
|
||||
|
||||
public void send(final GeneralAccountSendRequest request){
|
||||
private void updateBalance(CryptoCoinTransaction ccTransaction, long amount, CrystalDatabase db){
|
||||
CryptoCurrency currency = db.cryptoCurrencyDao().getByNameAndCryptoNet(this.cryptoCoin.getLabel(), this.cryptoCoin.getCryptoNet().name());
|
||||
if (currency == null) {
|
||||
currency = new CryptoCurrency();
|
||||
currency.setCryptoNet(this.cryptoCoin.getCryptoNet());
|
||||
currency.setName(this.cryptoCoin.getLabel());
|
||||
currency.setPrecision(this.cryptoCoin.getPrecision());
|
||||
long idCurrency = db.cryptoCurrencyDao().insertCryptoCurrency(currency)[0];
|
||||
currency.setId(idCurrency);
|
||||
}
|
||||
|
||||
CryptoCoinBalance balance = db.cryptoCoinBalanceDao().getBalanceFromAccount(ccTransaction.getAccountId(), currency.getId());
|
||||
if (balance == null) {
|
||||
balance = new CryptoCoinBalance();
|
||||
balance.setAccountId(ccTransaction.getAccountId());
|
||||
balance.setCryptoCurrencyId(currency.getId());
|
||||
long idBalance = db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance)[0];
|
||||
balance.setId(idBalance);
|
||||
}
|
||||
balance.setBalance(balance.getBalance()+amount);
|
||||
db.cryptoCoinBalanceDao().insertCryptoCoinBalance(balance);
|
||||
}
|
||||
|
||||
private void validateAddress(ValidateBitcoinAddressRequest request){
|
||||
try{
|
||||
Address address = Address.fromBase58(this.cryptoCoin.getParameters(), request.getAddress());
|
||||
request.setAddressValid(true);
|
||||
}catch(AddressFormatException ex){
|
||||
request.setAddressValid(false);
|
||||
}
|
||||
request.validate();
|
||||
}
|
||||
|
||||
public void send(final BitcoinSendRequest request){
|
||||
//TODO check server connection
|
||||
//TODO validate to address
|
||||
|
||||
InsightApiGenerator.getEstimateFee(request.getAccount().getCryptoNet(),new ApiRequest(1, new ApiRequestListener() {
|
||||
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(request.getAccount().getNetworkParam());
|
||||
long currentAmount = 0;
|
||||
long fee = -1;
|
||||
long feeRate = (Long) answer;
|
||||
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;
|
||||
|
||||
List<GeneralCoinAddress> addresses = request.getAccount().getAddresses();
|
||||
List<GTxIO> utxos = new ArrayList();
|
||||
for(GeneralCoinAddress address : addresses){
|
||||
List<GTxIO> addrUtxos = address.getUTXos();
|
||||
for(GTxIO addrUtxo : addrUtxos){
|
||||
utxos.add(addrUtxo);
|
||||
currentAmount += addrUtxo.getAmount();
|
||||
if(currentAmount >= request.getAmount()+ fee){
|
||||
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);
|
||||
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){
|
||||
break;
|
||||
|
||||
if (currentAmount < request.getAmount() + fee) {
|
||||
System.out.println("GeneralAccount Manager Send request no balance" );
|
||||
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){
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.NO_BALANCE);
|
||||
return;
|
||||
}
|
||||
//String to an address
|
||||
Address toAddr = Address.fromBase58(cryptoCoin.getParameters(), request.getToAccount());
|
||||
tx.addOutput(Coin.valueOf(request.getAmount()), toAddr);
|
||||
|
||||
//String to an address
|
||||
Address toAddr = Address.fromBase58(request.getAccount().getNetworkParam(), 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();
|
||||
if(request.getMemo().length()>40){
|
||||
memo = memo.substring(0,40);
|
||||
|
@ -99,47 +433,282 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
System.arraycopy(memo.getBytes(),0,scriptByte,2,memo.length());
|
||||
Script memoScript = new Script(scriptByte);
|
||||
tx.addOutput(Coin.valueOf(0),memoScript);
|
||||
}
|
||||
}*/
|
||||
|
||||
//Change address
|
||||
long remain = currentAmount - request.getAmount() - fee;
|
||||
if( remain > 0 ) {
|
||||
Address changeAddr = Address.fromBase58(request.getAccount().getNetworkParam(), request.getAccount().getNextChangeAddress());
|
||||
tx.addOutput(Coin.valueOf(remain), changeAddr);
|
||||
}
|
||||
//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());
|
||||
|
||||
for(GTxIO utxo: utxos) {
|
||||
Sha256Hash txHash = Sha256Hash.wrap(utxo.getTransaction().getTxid());
|
||||
Script script = new Script(Util.hexToBytes(utxo.getScriptHex()));
|
||||
TransactionOutPoint outPoint = new TransactionOutPoint(request.getAccount().getNetworkParam(), utxo.getIndex(), txHash);
|
||||
if(utxo.getAddress().getKey().isPubKeyOnly()){
|
||||
if(utxo.getAddress().isIsChange()){
|
||||
utxo.getAddress().setKey(HDKeyDerivation.deriveChildKey(request.getAccount().getChangeKey(), new ChildNumber(utxo.getAddress().getIndex(), false)));
|
||||
}else{
|
||||
utxo.getAddress().setKey(HDKeyDerivation.deriveChildKey(request.getAccount().getExternalKey(), new ChildNumber(utxo.getAddress().getIndex(), false)));
|
||||
} 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());
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
tx.addSignedInput(outPoint, script, utxo.getAddress().getKey(), Transaction.SigHash.ALL, true);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
InsightApiGenerator.broadcastTransaction(request.getAccount().getCryptoNet(),Util.bytesToHex(tx.bitcoinSerialize()),new ApiRequest(1, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.SUCCEEDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.PETITION_FAILED);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
request.setStatus(GeneralAccountSendRequest.StatusCode.NO_FEE);
|
||||
System.out.println("GeneralAccount Manager Send request fee fail" );
|
||||
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());
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getExternalByIndex(index);
|
||||
if(address != null && db.bitcoinTransactionDao().getGtxIOByAddress(address.getAddress()).size()<=0){
|
||||
request.setAddress(address.getAddress());
|
||||
request.setStatus(NextBitcoinAccountAddressRequest.StatusCode.SUCCEEDED);
|
||||
}else {
|
||||
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));
|
||||
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, null);
|
||||
|
||||
request.setAddress(addressString);
|
||||
request.setStatus(NextBitcoinAccountAddressRequest.StatusCode.SUCCEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateUri(CalculateBitcoinUriRequest request) {
|
||||
StringBuilder uri = new StringBuilder(this.cryptoCoin.name().toLowerCase()+":");
|
||||
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||
long index = db.bitcoinAddressDao().getLastExternalAddress(request.getAccount().getId());
|
||||
BitcoinAddress address = db.bitcoinAddressDao().getExternalByIndex(index);
|
||||
if(address != null && db.bitcoinTransactionDao().getGtxIOByAddress(address.getAddress()).size()<=0){
|
||||
uri.append(address.getAddress());
|
||||
}else {
|
||||
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));
|
||||
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, null);
|
||||
|
||||
uri.append(address.getAddress());
|
||||
}
|
||||
if(request.getAmount() > 0 ){
|
||||
uri.append("?amount=");
|
||||
uri.append(Double.toString(request.getAmount()));
|
||||
}
|
||||
|
||||
System.out.println("GeneralAccountMAnager uri calculated : " + uri.toString());
|
||||
|
||||
request.setUri(uri.toString());
|
||||
//request.validate();
|
||||
}
|
||||
|
||||
private void parseUri(BitcoinUriParseRequest request){
|
||||
String uri = request.getUri();
|
||||
if(uri.indexOf(":")>0){
|
||||
String cryptoNet = uri.substring(0,uri.indexOf(":"));
|
||||
if(cryptoNet.equalsIgnoreCase(this.cryptoCoin.name().toLowerCase())){
|
||||
try{
|
||||
int parameterIndex =uri.indexOf("?");
|
||||
Address address = Address.fromBase58(this.cryptoCoin.getParameters(), uri.substring(uri.indexOf(":")+1,parameterIndex>0?parameterIndex:uri.length()));
|
||||
request.setAddress(address.toString());
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.VALID);
|
||||
if(parameterIndex>0){
|
||||
try {
|
||||
String[] parameters = uri.substring(parameterIndex + 1).split("&");
|
||||
for (String parameter : parameters) {
|
||||
int idx = parameter.indexOf("=");
|
||||
if (idx > 0 && parameter.substring(0, idx).equalsIgnoreCase("amount")) {
|
||||
request.setAmount(Double.parseDouble(parameter.substring(idx + 1)));
|
||||
}
|
||||
}
|
||||
}catch(Exception ignored){}
|
||||
}
|
||||
}catch(AddressFormatException ex){
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.NOT_VALID);
|
||||
}
|
||||
|
||||
}else{
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.NOT_VALID);
|
||||
}
|
||||
}else{
|
||||
int parameterIndex =uri.indexOf("?");
|
||||
if(parameterIndex>0){
|
||||
try{
|
||||
Address address = Address.fromBase58(this.cryptoCoin.getParameters(), uri.substring(uri.indexOf(":")+1,parameterIndex>0?parameterIndex:uri.length()));
|
||||
request.setAddress(address.toString());
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.VALID);
|
||||
try{
|
||||
String[] parameters = uri.substring(parameterIndex+1).split("&");
|
||||
for(String parameter : parameters){
|
||||
int idx = parameter.indexOf("=");
|
||||
if(idx > 0 && parameter.substring(0,idx).equalsIgnoreCase("amount")){
|
||||
request.setAmount(Double.parseDouble(parameter.substring(idx+1)));
|
||||
}
|
||||
}
|
||||
}catch(Exception ignored){}
|
||||
|
||||
}catch(AddressFormatException ex){
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.NOT_VALID);
|
||||
}
|
||||
}else{
|
||||
try{
|
||||
Address address = Address.fromBase58(this.cryptoCoin.getParameters(), uri);
|
||||
request.setAddress(address.toString());
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.VALID);
|
||||
|
||||
}catch(AddressFormatException ex){
|
||||
request.setStatus(BitcoinUriParseRequest.StatusCode.NOT_VALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
request.validate();
|
||||
}
|
||||
|
||||
private List<BitcoinTransactionGTxIO> getUtxos(long accountId, CrystalDatabase db){
|
||||
List<BitcoinTransactionGTxIO> answer = new ArrayList<>();
|
||||
List<BitcoinTransactionGTxIO> bTGTxI = new ArrayList<>();
|
||||
List<BitcoinTransactionGTxIO> bTGTxO = new ArrayList<>();
|
||||
List<CryptoCoinTransaction> ccTransactions = db.transactionDao().getByIdAccount(accountId);
|
||||
for(CryptoCoinTransaction ccTransaction : ccTransactions) {
|
||||
List<BitcoinTransactionGTxIO> gtxios = db.bitcoinTransactionDao().getGtxIOByTransaction(ccTransaction.getId());
|
||||
for(BitcoinTransactionGTxIO gtxio : gtxios){
|
||||
if(db.bitcoinAddressDao().addressExists(gtxio.getAddress())){
|
||||
if(gtxio.isOutput()){
|
||||
bTGTxO.add(gtxio);
|
||||
}else{
|
||||
bTGTxI.add(gtxio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(BitcoinTransactionGTxIO gtxi : bTGTxI){
|
||||
boolean find = false;
|
||||
for(BitcoinTransactionGTxIO gtxo : bTGTxO){
|
||||
if(gtxo.getOriginalTxId().equals(gtxi.getOriginalTxId())){
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!find){
|
||||
answer.add(gtxi);
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
class CheckAddressForTransaction implements InsightApiGenerator.HasTransactionListener{
|
||||
BitcoinAddressDao bitcoinAddressDao;
|
||||
long idAccount;
|
||||
DeterministicKey addressKey;
|
||||
boolean isChange;
|
||||
int lastIndex;
|
||||
|
||||
public CheckAddressForTransaction(BitcoinAddressDao bitcoinAddressDao, long idAccount, DeterministicKey addressKey, boolean isChange, int lastIndex) {
|
||||
this.bitcoinAddressDao = bitcoinAddressDao;
|
||||
this.idAccount = idAccount;
|
||||
this.addressKey = addressKey;
|
||||
this.isChange = isChange;
|
||||
this.lastIndex = lastIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasTransaction(boolean value) {
|
||||
if(value){
|
||||
|
||||
ECKey externalAddrKey = HDKeyDerivation.deriveChildKey(addressKey, new ChildNumber(lastIndex+1, true));
|
||||
BitcoinAddress address = new BitcoinAddress();
|
||||
address.setChange(isChange);
|
||||
address.setAccountId(idAccount);
|
||||
address.setIndex(lastIndex+1);
|
||||
String addressString =externalAddrKey.toAddress(cryptoCoin.getParameters()).toString();
|
||||
address.setAddress(addressString);
|
||||
bitcoinAddressDao.insertBitcoinAddresses(address);
|
||||
InsightApiGenerator.getTransactionFromAddress(cryptoCoin,addressString,true,
|
||||
new CheckAddressForTransaction(bitcoinAddressDao,idAccount,addressKey,isChange,lastIndex+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,756 @@
|
|||
package cy.agorise.crystalwallet.manager;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.common.primitives.UnsignedLong;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.ApiRequest;
|
||||
import cy.agorise.crystalwallet.apigenerator.ApiRequestListener;
|
||||
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
||||
import cy.agorise.crystalwallet.dao.AccountSeedDao;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.dao.TransactionDao;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.enums.SeedType;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAccountNameCache;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAsset;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAssetInfo;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccountInfo;
|
||||
import cy.agorise.crystalwallet.models.seed.BIP39;
|
||||
import cy.agorise.crystalwallet.network.CryptoNetManager;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.GetBitsharesAccountNameCacheRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ImportBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitsharesSendRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateImportBitsharesAccountRequest;
|
||||
import cy.agorise.graphenej.Address;
|
||||
import cy.agorise.graphenej.Asset;
|
||||
import cy.agorise.graphenej.AssetAmount;
|
||||
import cy.agorise.graphenej.BaseOperation;
|
||||
import cy.agorise.graphenej.BrainKey;
|
||||
import cy.agorise.graphenej.PublicKey;
|
||||
import cy.agorise.graphenej.Transaction;
|
||||
import cy.agorise.graphenej.UserAccount;
|
||||
import cy.agorise.graphenej.models.AccountProperties;
|
||||
import cy.agorise.graphenej.models.BlockHeader;
|
||||
import cy.agorise.graphenej.models.HistoricalTransfer;
|
||||
import cy.agorise.graphenej.operations.TransferOperationBuilder;
|
||||
|
||||
/**
|
||||
* The manager for the Bitshare CryptoCoin
|
||||
*
|
||||
* Created by henry on 26/9/2017.
|
||||
*/
|
||||
public class SteemAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||
|
||||
private final static String SIMPLE_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
private final static String DEFAULT_TIME_ZONE = "GMT";
|
||||
|
||||
@Override
|
||||
public void createAccountFromSeed(CryptoNetAccount account, final ManagerRequest request, final Context context) {
|
||||
//TODO error, can't create steem accounts
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importAccountFromSeed(CryptoNetAccount account, final Context context) {
|
||||
if(account instanceof GrapheneAccount) {
|
||||
final GrapheneAccount grapheneAccount = (GrapheneAccount) account;
|
||||
|
||||
if(grapheneAccount.getAccountId() == null){
|
||||
this.getAccountInfoByName(grapheneAccount.getName(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount fetch = (GrapheneAccount) answer;
|
||||
grapheneAccount.setAccountId(fetch.getAccountId());
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
long[] idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
grapheneAccount.setId(idAccount[0]);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
subscribeSteemAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO get account data fail
|
||||
}
|
||||
});
|
||||
|
||||
}else if(grapheneAccount.getName() == null){
|
||||
this.getAccountInfoById(grapheneAccount.getAccountId(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount fetch = (GrapheneAccount) answer;
|
||||
grapheneAccount.setName(fetch.getName());
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount)[0];
|
||||
grapheneAccount.setId(idAccount);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
subscribeSteemAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO get account data fail
|
||||
}
|
||||
});
|
||||
}else {
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
long idAccount = db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount)[0];
|
||||
grapheneAccount.setId(idAccount);
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(new GrapheneAccountInfo(grapheneAccount));
|
||||
subscribeSteemAccount(grapheneAccount.getId(), grapheneAccount.getAccountId(), context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAccountFromDB(CryptoNetAccount account, final Context context) {
|
||||
if(account instanceof GrapheneAccount){
|
||||
final GrapheneAccount grapheneAccount = (GrapheneAccount) account;
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
final GrapheneAccountInfo info = db.grapheneAccountInfoDao().getByAccountId(account.getId());
|
||||
grapheneAccount.loadInfo(info);
|
||||
if(grapheneAccount.getAccountId() == null){
|
||||
this.getAccountInfoByName(grapheneAccount.getName(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount fetch = (GrapheneAccount) answer;
|
||||
info.setAccountId(fetch.getAccountId());
|
||||
grapheneAccount.setAccountId(fetch.getAccountId());
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(info);
|
||||
subscribeSteemAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO account data retrieve failed
|
||||
}
|
||||
});
|
||||
}else if(grapheneAccount.getName() == null){
|
||||
this.getAccountInfoById(grapheneAccount.getAccountId(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount fetch = (GrapheneAccount) answer;
|
||||
info.setName(fetch.getName());
|
||||
grapheneAccount.setName(fetch.getName());
|
||||
db.grapheneAccountInfoDao().insertGrapheneAccountInfo(info);
|
||||
subscribeSteemAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO account data retrieve failed
|
||||
}
|
||||
});
|
||||
}else{
|
||||
subscribeSteemAccount(grapheneAccount.getId(),grapheneAccount.getAccountId(),context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void subscribeSteemAccount(long accountId, String accountSteemID, Context context){
|
||||
GrapheneApiGenerator.subscribeSteemAccount(accountId,accountSteemID,context);
|
||||
SteemAccountManager.refreshAccountTransactions(accountId,context);
|
||||
GrapheneApiGenerator.getAccountBalance(accountId,accountSteemID,CryptoNet.STEEM,context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the bitshares manager request
|
||||
* @param request The request Object
|
||||
*/
|
||||
@Override
|
||||
public void onNewRequest(CryptoNetInfoRequest request) {
|
||||
if(request.getCoin().equals(CryptoCoin.STEEM)) {
|
||||
if (request instanceof ImportBitsharesAccountRequest) {
|
||||
this.importAccount((ImportBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateImportBitsharesAccountRequest) {
|
||||
this.validateImportAccount((ValidateImportBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateExistBitsharesAccountRequest) {
|
||||
this.validateExistAcccount((ValidateExistBitsharesAccountRequest) request);
|
||||
} else if (request instanceof ValidateBitsharesSendRequest) {
|
||||
this.validateSendRequest((ValidateBitsharesSendRequest) request);
|
||||
} else if (request instanceof GetBitsharesAccountNameCacheRequest) {
|
||||
this.getBitsharesAccountNameCacheRequest((GetBitsharesAccountNameCacheRequest) request);
|
||||
} else {
|
||||
|
||||
//TODO not implemented
|
||||
System.out.println("Error request not implemented " + request.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void importAccount(final ImportBitsharesAccountRequest importRequest){
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(importRequest.getContext());
|
||||
final AccountSeedDao accountSeedDao = db.accountSeedDao();
|
||||
ApiRequest getAccountNamesBK = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer != null && importRequest.getStatus().equals(ImportBitsharesAccountRequest.StatusCode.NOT_STARTED)) {
|
||||
UserAccount userAccount = (UserAccount) answer;
|
||||
importRequest.setSeedType(SeedType.BRAINKEY);
|
||||
importRequest.setStatus(ImportBitsharesAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
AccountSeed seed = new AccountSeed();
|
||||
seed.setName(userAccount.getName());
|
||||
seed.setType(importRequest.getSeedType());
|
||||
seed.setMasterSeed(importRequest.getMnemonic());
|
||||
long idSeed = accountSeedDao.insertAccountSeed(seed);
|
||||
if (idSeed >= 0) {
|
||||
GrapheneAccount account = new GrapheneAccount();
|
||||
account.setCryptoNet(CryptoNet.STEEM);
|
||||
account.setAccountIndex(0);
|
||||
account.setSeedId(idSeed);
|
||||
account.setAccountId(userAccount.getObjectId());
|
||||
importAccountFromSeed(account, importRequest.getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
importRequest.setStatus(ImportBitsharesAccountRequest.StatusCode.BAD_SEED);
|
||||
}
|
||||
});
|
||||
|
||||
BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0);
|
||||
GrapheneApiGenerator.getAccountByOwnerOrActiveAddress(bk.getPublicAddress("STM"),CryptoNet.STEEM,getAccountNamesBK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the import account request
|
||||
*/
|
||||
private void validateImportAccount(final ValidateImportBitsharesAccountRequest importRequest){
|
||||
//TODO check internet and server status
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(importRequest.getContext());
|
||||
final AccountSeedDao accountSeedDao = db.accountSeedDao();
|
||||
|
||||
ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
ApiRequest getAccountInfo = new ApiRequest(1,new ApiRequestListener(){
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer != null && answer instanceof AccountProperties) {
|
||||
AccountProperties prop = (AccountProperties) answer;
|
||||
BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0);
|
||||
for(PublicKey activeKey : prop.owner.getKeyAuthList()){
|
||||
if((new Address(activeKey.getKey(),"STM")).toString().equals(bk.getPublicAddress("STM").toString())){
|
||||
importRequest.setSeedType(SeedType.BRAINKEY);
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((importRequest.getStatus() == ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED)){
|
||||
if (importRequest.addAccountIfValid()) {
|
||||
AccountSeed seed = new AccountSeed();
|
||||
seed.setName(importRequest.getAccountName());
|
||||
seed.setType(importRequest.getSeedType());
|
||||
seed.setMasterSeed(importRequest.getMnemonic());
|
||||
long idSeed = accountSeedDao.insertAccountSeed(seed);
|
||||
if (idSeed >= 0) {
|
||||
GrapheneAccount account = new GrapheneAccount();
|
||||
account.setCryptoNet(CryptoNet.STEEM);
|
||||
account.setAccountIndex(0);
|
||||
account.setSeedId(idSeed);
|
||||
account.setName(importRequest.getAccountName());
|
||||
importAccountFromSeed(account, importRequest.getContext());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.BAD_SEED);
|
||||
}
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.PETITION_FAILED);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.NO_ACCOUNT_DATA);
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getAccountById((String)answer,CryptoNet.STEEM,getAccountInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.ACCOUNT_DOESNT_EXIST);
|
||||
}
|
||||
});
|
||||
|
||||
GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),CryptoNet.STEEM,checkAccountName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the account exist request, it consults the bitshares api for the account name.
|
||||
*
|
||||
* This can be used to know if the name is avaible, or the account to be send fund exists
|
||||
*/
|
||||
private void validateExistAcccount(final ValidateExistBitsharesAccountRequest validateRequest){
|
||||
ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if (answer != null) {
|
||||
validateRequest.setAccountExists(true);
|
||||
} else {
|
||||
validateRequest.setAccountExists(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//TODO verified
|
||||
validateRequest.setAccountExists(false);
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getAccountIdByName(validateRequest.getAccountName(),CryptoNet.STEEM,checkAccountName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast a transaction request
|
||||
*/
|
||||
private void validateSendRequest(final ValidateBitsharesSendRequest sendRequest) {
|
||||
//TODO check internet, server connection
|
||||
//TODO feeAsset
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(sendRequest.getContext());
|
||||
CryptoCurrency currency = db.cryptoCurrencyDao().getByNameAndCryptoNet(sendRequest.getAsset(), CryptoNet.STEEM.name());
|
||||
if (currency == null){
|
||||
getAssetInfoByName(sendRequest.getAsset(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
validateSendRequest(sendRequest, ((BitsharesAsset) answer).getBitsharesId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
sendRequest.setStatus(ValidateBitsharesSendRequest.StatusCode.NO_ASSET_INFO_DB);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
BitsharesAssetInfo info = db.bitsharesAssetDao().getBitsharesAssetInfo(currency.getId());
|
||||
if (info == null || info.getBitsharesId() == null || info.getBitsharesId().isEmpty()){
|
||||
getAssetInfoByName(sendRequest.getAsset(), new ManagerRequest() {
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
validateSendRequest(sendRequest, ((BitsharesAsset) answer).getBitsharesId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
sendRequest.setStatus(ValidateBitsharesSendRequest.StatusCode.NO_ASSET_INFO);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
this.validateSendRequest(sendRequest, info.getBitsharesId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast a send asset request, the idAsset is already fetched
|
||||
* @param sendRequest The petition for transfer
|
||||
* @param idAsset The Bitshares Asset's id
|
||||
*/
|
||||
private void validateSendRequest(final ValidateBitsharesSendRequest sendRequest , final String idAsset){
|
||||
final Asset feeAsset = new Asset(idAsset);
|
||||
final UserAccount fromUserAccount =new UserAccount(sendRequest.getSourceAccount().getAccountId());
|
||||
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(sendRequest.getContext());
|
||||
BitsharesAccountNameCache cacheAccount = db.bitsharesAccountNameCacheDao().getByAccountName(sendRequest.getToAccount());
|
||||
if(cacheAccount == null) {
|
||||
this.getAccountInfoByName(sendRequest.getToAccount(), new ManagerRequest() {
|
||||
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount toUserGrapheneAccount = (GrapheneAccount) answer;
|
||||
UserAccount toUserAccount = new UserAccount(toUserGrapheneAccount.getAccountId());
|
||||
try {
|
||||
BitsharesAccountNameCache cacheAccount = new BitsharesAccountNameCache();
|
||||
cacheAccount.setName(sendRequest.getToAccount());
|
||||
cacheAccount.setAccountId(toUserAccount.getObjectId());
|
||||
db.bitsharesAccountNameCacheDao().insertBitsharesAccountNameCache(cacheAccount);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
validateSendRequest(sendRequest,fromUserAccount,toUserAccount,feeAsset,idAsset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
sendRequest.setStatus(ValidateBitsharesSendRequest.StatusCode.NO_TO_USER_INFO);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
UserAccount toUserAccount = new UserAccount(cacheAccount.getAccountId());
|
||||
this.validateSendRequest(sendRequest,fromUserAccount,toUserAccount,feeAsset,idAsset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast a transaction request
|
||||
* @param sendRequest The petition for transfer operation
|
||||
* @param fromUserAccount The source account
|
||||
* @param toUserAccount The receiver account
|
||||
* @param feeAsset The Fee Asset
|
||||
* @param idAsset The id of the asset to be used on the operation
|
||||
*/
|
||||
private void validateSendRequest(final ValidateBitsharesSendRequest sendRequest, UserAccount fromUserAccount,
|
||||
UserAccount toUserAccount, Asset feeAsset, String idAsset){
|
||||
TransferOperationBuilder builder = new TransferOperationBuilder()
|
||||
.setSource(fromUserAccount)
|
||||
.setDestination(toUserAccount)
|
||||
.setTransferAmount(new AssetAmount(UnsignedLong.valueOf(sendRequest.getAmount()), new Asset(idAsset)))
|
||||
.setFee(new AssetAmount(UnsignedLong.valueOf(0), feeAsset));
|
||||
if (sendRequest.getMemo() != null) {
|
||||
//builder.setMemo(new Memo(fromUserAccount,toUserAccount,0,sendRequest.getMemo().getBytes()));
|
||||
//TODO memo
|
||||
System.out.println("transaction has memo");
|
||||
}
|
||||
ArrayList<BaseOperation> operationList = new ArrayList<>();
|
||||
operationList.add(builder.build());
|
||||
|
||||
ECKey privateKey = sendRequest.getSourceAccount().getActiveKey(sendRequest.getContext());
|
||||
|
||||
Transaction transaction = new Transaction(privateKey, null, operationList);
|
||||
transaction.setChainId(CryptoNetManager.getChaindId(CryptoNet.STEEM));
|
||||
|
||||
ApiRequest transactionRequest = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
sendRequest.setStatus(ValidateBitsharesSendRequest.StatusCode.SUCCEEDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
sendRequest.setStatus(ValidateBitsharesSendRequest.StatusCode.PETITION_FAILED);
|
||||
}
|
||||
});
|
||||
|
||||
GrapheneApiGenerator.broadcastTransaction(transaction, feeAsset, transactionRequest);
|
||||
}
|
||||
|
||||
private void getBitsharesAccountNameCacheRequest(final GetBitsharesAccountNameCacheRequest request){
|
||||
final CrystalDatabase db = CrystalDatabase.getAppDatabase(request.getContext());
|
||||
BitsharesAccountNameCache cacheAccount = db.bitsharesAccountNameCacheDao().getByAccountId(request.getAccountId());
|
||||
if(cacheAccount == null) {
|
||||
this.getAccountInfoById(request.getAccountId(), new ManagerRequest() {
|
||||
|
||||
@Override
|
||||
public void success(Object answer) {
|
||||
GrapheneAccount userGrapheneAccount = (GrapheneAccount) answer;
|
||||
BitsharesAccountNameCache cacheAccount = new BitsharesAccountNameCache();
|
||||
cacheAccount.setName(userGrapheneAccount.getName());
|
||||
cacheAccount.setAccountId(request.getAccountId());
|
||||
db.bitsharesAccountNameCacheDao().insertBitsharesAccountNameCache(cacheAccount);
|
||||
request.setAccountName(userGrapheneAccount.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO error
|
||||
}
|
||||
});
|
||||
}else {
|
||||
request.setAccountName(cacheAccount.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the account info from a graphene id
|
||||
* @param grapheneId The graphene id of the account
|
||||
*/
|
||||
private void getAccountInfoById(String grapheneId, ManagerRequest request){
|
||||
|
||||
AccountIdOrNameListener listener = new AccountIdOrNameListener(request);
|
||||
|
||||
ApiRequest accountRequest = new ApiRequest(0, listener);
|
||||
GrapheneApiGenerator.getAccountById(grapheneId,CryptoNet.STEEM,accountRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets account info by its name
|
||||
* @param grapheneName The name of the account to retrieve
|
||||
*/
|
||||
private void getAccountInfoByName(String grapheneName, ManagerRequest request){
|
||||
|
||||
AccountIdOrNameListener listener = new AccountIdOrNameListener(request);
|
||||
|
||||
ApiRequest accountRequest = new ApiRequest(0, listener);
|
||||
GrapheneApiGenerator.getAccountByName(grapheneName,CryptoNet.STEEM,accountRequest);
|
||||
|
||||
}
|
||||
|
||||
//TODO expand function to be more generic
|
||||
private void getAssetInfoByName(String assetName, ManagerRequest request){
|
||||
|
||||
AssetIdOrNameListener nameListener = new AssetIdOrNameListener(request);
|
||||
ApiRequest assetRequest = new ApiRequest(0, nameListener);
|
||||
ArrayList<String> assetNames = new ArrayList<>();
|
||||
assetNames.add(assetName);
|
||||
GrapheneApiGenerator.getAssetByName(assetNames, CryptoNet.STEEM, assetRequest);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the transactions of an account, important to notice, it return nothing, to get the changes tuse the LiveData
|
||||
* @param idAccount database id of the account
|
||||
* @param context The android context of this application
|
||||
*/
|
||||
private static void refreshAccountTransactions(long idAccount, Context context){
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
List<CryptoCoinTransaction> transactions = db.transactionDao().getByIdAccount(idAccount);
|
||||
CryptoNetAccount account = db.cryptoNetAccountDao().getById(idAccount);
|
||||
if(account.getCryptoNet() == CryptoNet.STEEM) {
|
||||
|
||||
GrapheneAccount grapheneAccount = new GrapheneAccount(account);
|
||||
grapheneAccount.loadInfo(db.grapheneAccountInfoDao().getByAccountId(idAccount));
|
||||
|
||||
int start = transactions.size();
|
||||
int limit = 50;
|
||||
int stop = start + limit;
|
||||
|
||||
ApiRequest transactionRequest = new ApiRequest(0, new TransactionRequestListener(start, stop, limit, grapheneAccount, db));
|
||||
GrapheneApiGenerator.getAccountTransaction(grapheneAccount.getAccountId(), start, stop, limit, CryptoNet.STEEM,transactionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that handles the transactions request
|
||||
*/
|
||||
private static class TransactionRequestListener implements ApiRequestListener{
|
||||
|
||||
/**
|
||||
* Start index
|
||||
*/
|
||||
int start;
|
||||
/**
|
||||
* End index
|
||||
*/
|
||||
int stop;
|
||||
/**
|
||||
* Limit of transasction to fetch
|
||||
*/
|
||||
int limit;
|
||||
/**
|
||||
* The grapheneaccount with all data CryptoCurrnecy + info
|
||||
*/
|
||||
GrapheneAccount account;
|
||||
/**
|
||||
* The database
|
||||
*/
|
||||
CrystalDatabase db;
|
||||
|
||||
/**
|
||||
* Basic consturctor
|
||||
*/
|
||||
TransactionRequestListener(int start, int stop, int limit, GrapheneAccount account, CrystalDatabase db) {
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
this.limit = limit;
|
||||
this.account = account;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the success request of the transaction, if the amount of transaction is equal to the limit, ask for more transaction
|
||||
* @param answer The answer, this object depends on the kind of request is made to the api
|
||||
* @param idPetition the id of the ApiRequest petition
|
||||
*/
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
List<HistoricalTransfer> transfers = (List<HistoricalTransfer>) answer ;
|
||||
for(final HistoricalTransfer transfer : transfers) {
|
||||
if (transfer.getOperation() != null){
|
||||
final CryptoCoinTransaction transaction = new CryptoCoinTransaction();
|
||||
transaction.setAccountId(account.getId());
|
||||
transaction.setAmount(transfer.getOperation().getAssetAmount().getAmount().longValue());
|
||||
BitsharesAssetInfo info = db.bitsharesAssetDao().getBitsharesAssetInfoById(transfer.getOperation().getAssetAmount().getAsset().getObjectId());
|
||||
|
||||
if (info == null) {
|
||||
//The cryptoCurrency is not in the database, queringfor its data
|
||||
ApiRequest assetRequest = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
ArrayList<BitsharesAsset> assets = (ArrayList<BitsharesAsset>) answer;
|
||||
for(BitsharesAsset asset : assets){
|
||||
long currencyId = -1;
|
||||
CryptoCurrency cryptoCurrencyDb = db.cryptoCurrencyDao().getByNameAndCryptoNet(asset.getName(),asset.getCryptoNet().name());
|
||||
|
||||
if (cryptoCurrencyDb != null){
|
||||
currencyId = cryptoCurrencyDb.getId();
|
||||
} else {
|
||||
long idCryptoCurrency = db.cryptoCurrencyDao().insertCryptoCurrency(asset)[0];
|
||||
currencyId = idCryptoCurrency;
|
||||
}
|
||||
|
||||
|
||||
BitsharesAssetInfo info = new BitsharesAssetInfo(asset);
|
||||
info.setCryptoCurrencyId(currencyId);
|
||||
asset.setId((int)currencyId);
|
||||
db.bitsharesAssetDao().insertBitsharesAssetInfo(info);
|
||||
saveTransaction(transaction,info,transfer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//TODO Error
|
||||
}
|
||||
});
|
||||
ArrayList<String> assets = new ArrayList<>();
|
||||
assets.add(transfer.getOperation().getAssetAmount().getAsset().getObjectId());
|
||||
GrapheneApiGenerator.getAssetById(assets,CryptoNet.STEEM,assetRequest);
|
||||
|
||||
}else{
|
||||
saveTransaction(transaction,info,transfer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(transfers.size()>= limit){
|
||||
// The amount of transaction in the answer is equal to the limit, we need to query to see if there is more transactions
|
||||
int newStart= start + limit;
|
||||
int newStop= stop + limit;
|
||||
ApiRequest transactionRequest = new ApiRequest(newStart/limit, new TransactionRequestListener(newStart,newStop,limit,account,db));
|
||||
GrapheneApiGenerator.getAccountTransaction(account.getAccountId(),newStart,newStop,limit,CryptoNet.STEEM,transactionRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
|
||||
}
|
||||
|
||||
private void saveTransaction(CryptoCoinTransaction transaction, BitsharesAssetInfo info, HistoricalTransfer transfer){
|
||||
transaction.setIdCurrency((int)info.getCryptoCurrencyId());
|
||||
transaction.setConfirmed(true); //graphene transaction are always confirmed
|
||||
transaction.setFrom(transfer.getOperation().getFrom().getObjectId());
|
||||
transaction.setInput(!transfer.getOperation().getFrom().getObjectId().equals(account.getAccountId()));
|
||||
transaction.setTo(transfer.getOperation().getTo().getObjectId());
|
||||
|
||||
GrapheneApiGenerator.getBlockHeaderTime(transfer.getBlockNum(), CryptoNet.STEEM,new ApiRequest(0, new GetTransactionDate(transaction, db.transactionDao())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to retrieve the account id or the account name, if one of those is missing
|
||||
*/
|
||||
private class AccountIdOrNameListener implements ApiRequestListener{
|
||||
final ManagerRequest request;
|
||||
|
||||
GrapheneAccount account;
|
||||
|
||||
AccountIdOrNameListener(ManagerRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer instanceof AccountProperties){
|
||||
AccountProperties props = (AccountProperties) answer;
|
||||
account = new GrapheneAccount();
|
||||
account.setAccountId(props.id);
|
||||
account.setName(props.name);
|
||||
}
|
||||
|
||||
request.success(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
request.fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to retrieve the asset id or the asset name, if one of those is missing
|
||||
*/
|
||||
private class AssetIdOrNameListener implements ApiRequestListener{
|
||||
final ManagerRequest request;
|
||||
|
||||
BitsharesAsset asset;
|
||||
|
||||
AssetIdOrNameListener(ManagerRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer instanceof ArrayList) {
|
||||
if (((ArrayList) answer).get(0) instanceof BitsharesAsset) {
|
||||
asset = (BitsharesAsset) ((ArrayList) answer).get(0);
|
||||
request.success(asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//TODO fail asset retrieve
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to retrieve the transaction date
|
||||
*/
|
||||
public static class GetTransactionDate implements ApiRequestListener{
|
||||
/**
|
||||
* The transaction to retrieve
|
||||
*/
|
||||
private CryptoCoinTransaction transaction;
|
||||
/**
|
||||
* The DAO to insert or update the transaction
|
||||
*/
|
||||
TransactionDao transactionDao;
|
||||
|
||||
GetTransactionDate(CryptoCoinTransaction transaction, TransactionDao transactionDao) {
|
||||
this.transaction = transaction;
|
||||
this.transactionDao = transactionDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
if(answer instanceof BlockHeader){
|
||||
@SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat = new SimpleDateFormat(SIMPLE_DATE_FORMAT);
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(DEFAULT_TIME_ZONE));
|
||||
try {
|
||||
transaction.setDate(dateFormat.parse(((BlockHeader) answer).timestamp));
|
||||
if (transactionDao.getByTransaction(transaction.getDate(),transaction.getFrom(),transaction.getTo(),transaction.getAmount()) == null) {
|
||||
transactionDao.insertTransaction(transaction);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,12 +9,14 @@ import android.content.Context;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.util.DiffUtil;
|
||||
|
||||
import org.bitcoinj.core.Base58;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.crypto.HDKeyDerivation;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Arrays;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.SeedType;
|
||||
import cy.agorise.crystalwallet.models.seed.BIP39;
|
||||
|
@ -115,8 +117,6 @@ public class AccountSeed {
|
|||
BufferedReader reader = null;
|
||||
switch (type) {
|
||||
case BRAINKEY:
|
||||
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(context.getAssets().open("brainkeydict.txt"), "UTF-8"));
|
||||
|
||||
|
@ -130,6 +130,7 @@ public class AccountSeed {
|
|||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case BIP39:
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(context.getAssets().open("bip39dict.txt"), "UTF-8"));
|
||||
|
@ -139,6 +140,7 @@ public class AccountSeed {
|
|||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -149,6 +151,15 @@ public class AccountSeed {
|
|||
return new BrainKey(this.mMasterSeed,0).getPrivateKey();
|
||||
case BIP39:
|
||||
return HDKeyDerivation.createMasterPrivateKey(new BIP39(mId, mMasterSeed).getSeed());
|
||||
case WIF:
|
||||
byte[] decoded = Base58.decode(this.mMasterSeed);
|
||||
byte[] privKey = Arrays.copyOfRange(decoded, 1, decoded.length - 4);
|
||||
byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length);
|
||||
//TODO calculate chekcsum
|
||||
while(privKey.length>32){
|
||||
privKey = Arrays.copyOfRange(privKey,0,privKey.length-1);
|
||||
}
|
||||
return ECKey.fromPrivate(privKey);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package cy.agorise.crystalwallet.models;
|
||||
|
||||
import android.arch.persistence.room.ColumnInfo;
|
||||
import android.arch.persistence.room.Entity;
|
||||
import android.arch.persistence.room.ForeignKey;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Represents a Bitcoin derivated address
|
||||
*
|
||||
* Created by Henry Varona on 10/17/2018.
|
||||
*/
|
||||
@Entity(
|
||||
tableName="bitcoin_address",
|
||||
primaryKeys = {"account_id","address_index","is_change"},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = CryptoNetAccount.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "account_id",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class BitcoinAddress {
|
||||
|
||||
/**
|
||||
* The id of the account associated
|
||||
*/
|
||||
@ColumnInfo(name="account_id")
|
||||
protected long accountId;
|
||||
|
||||
/**
|
||||
* The index of this address
|
||||
*/
|
||||
@ColumnInfo(name="address_index")
|
||||
@NonNull protected long index;
|
||||
|
||||
/**
|
||||
* Whether or not this address is a change one
|
||||
*/
|
||||
@ColumnInfo(name="is_change")
|
||||
@NonNull protected boolean isChange;
|
||||
|
||||
/**
|
||||
* Address
|
||||
*/
|
||||
@ColumnInfo(name="address")
|
||||
@NonNull protected String address;
|
||||
|
||||
public BitcoinAddress(long accountId, @NonNull long index, boolean isChange, String address) {
|
||||
this.accountId = accountId;
|
||||
this.index = index;
|
||||
this.isChange = isChange;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public BitcoinAddress() {
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public long getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(@NonNull long index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public boolean isChange() {
|
||||
return isChange;
|
||||
}
|
||||
|
||||
public void setChange(boolean change) {
|
||||
isChange = change;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package cy.agorise.crystalwallet.models;
|
||||
|
||||
import android.arch.persistence.room.ColumnInfo;
|
||||
import android.arch.persistence.room.Entity;
|
||||
import android.arch.persistence.room.ForeignKey;
|
||||
import android.arch.persistence.room.Ignore;
|
||||
import android.arch.persistence.room.Index;
|
||||
import android.arch.persistence.room.PrimaryKey;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.util.DiffUtil;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Represents a Bitcoin alike Transaction
|
||||
*
|
||||
* Created by Henry Varona on 10/2/2018.
|
||||
*/
|
||||
@Entity(
|
||||
tableName="bitcoin_transaction",
|
||||
primaryKeys = {"crypto_coin_transaction_id"},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = CryptoCoinTransaction.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "crypto_coin_transaction_id",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class BitcoinTransaction {
|
||||
|
||||
/**
|
||||
* The id of the base transaction
|
||||
*/
|
||||
@ColumnInfo(name="crypto_coin_transaction_id")
|
||||
protected long cryptoCoinTransactionId;
|
||||
|
||||
|
||||
/**
|
||||
* The transaction id in the blockchain
|
||||
*/
|
||||
@ColumnInfo(name="tx_id")
|
||||
@NonNull protected String txId;
|
||||
|
||||
/**
|
||||
* The block id in the blockchain
|
||||
*/
|
||||
@ColumnInfo(name="block")
|
||||
protected long block;
|
||||
|
||||
/**
|
||||
* The fee of the transaction
|
||||
*/
|
||||
@ColumnInfo(name="fee")
|
||||
protected long fee;
|
||||
/**
|
||||
* The confirmations of the transaction in the blockchain
|
||||
*/
|
||||
@ColumnInfo(name="confirmations")
|
||||
protected int confirmations;
|
||||
|
||||
public BitcoinTransaction() {
|
||||
}
|
||||
|
||||
public BitcoinTransaction(long cryptoCoinTransactionId, String txId, long block, long fee, int confirmations) {
|
||||
this.cryptoCoinTransactionId = cryptoCoinTransactionId;
|
||||
this.txId = txId;
|
||||
this.block = block;
|
||||
this.fee = fee;
|
||||
this.confirmations = confirmations;
|
||||
}
|
||||
|
||||
public long getCryptoCoinTransactionId() {
|
||||
return cryptoCoinTransactionId;
|
||||
}
|
||||
|
||||
public void setCryptoCoinTransactionId(long cryptoCoinTransactionId) {
|
||||
this.cryptoCoinTransactionId = cryptoCoinTransactionId;
|
||||
}
|
||||
|
||||
public String getTxId() {
|
||||
return txId;
|
||||
}
|
||||
|
||||
public void setTxId(String txId) {
|
||||
this.txId = txId;
|
||||
}
|
||||
|
||||
public long getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public void setBlock(long block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public long getFee() {
|
||||
return fee;
|
||||
}
|
||||
|
||||
public void setFee(long fee) {
|
||||
this.fee = fee;
|
||||
}
|
||||
|
||||
public int getConfirmations() {
|
||||
return confirmations;
|
||||
}
|
||||
|
||||
public void setConfirmations(int confirmations) {
|
||||
this.confirmations = confirmations;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package cy.agorise.crystalwallet.models;
|
||||
|
||||
import android.arch.persistence.room.ColumnInfo;
|
||||
import android.arch.persistence.room.Embedded;
|
||||
import android.arch.persistence.room.Entity;
|
||||
import android.arch.persistence.room.ForeignKey;
|
||||
import android.arch.persistence.room.Relation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a Bitcoin alike Transaction
|
||||
*
|
||||
* Created by Henry Varona on 10/2/2018.
|
||||
*/
|
||||
public class BitcoinTransactionExtended {
|
||||
|
||||
@Embedded
|
||||
public CryptoCoinTransaction cryptoCoinTransaction;
|
||||
|
||||
@Embedded
|
||||
public BitcoinTransaction bitcoinTransaction;
|
||||
|
||||
@Relation(parentColumn = "id", entityColumn = "bitcoin_transaction_id", entity = BitcoinTransactionGTxIO.class)
|
||||
public List<BitcoinTransactionGTxIO> bitcoinTransactionGTxIOList;
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package cy.agorise.crystalwallet.models;
|
||||
|
||||
import android.arch.persistence.room.ColumnInfo;
|
||||
import android.arch.persistence.room.Entity;
|
||||
import android.arch.persistence.room.ForeignKey;
|
||||
|
||||
/**
|
||||
* Represents a Bitcoin alike Transaction Inputs and Outputs
|
||||
*
|
||||
* Created by Henry Varona on 10/2/2018.
|
||||
*/
|
||||
@Entity(
|
||||
tableName="bitcoin_transaction_gt_io",
|
||||
primaryKeys = {"bitcoin_transaction_id", "io_index", "is_output"},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = CryptoCoinTransaction.class,
|
||||
parentColumns = "id",
|
||||
childColumns = "bitcoin_transaction_id",
|
||||
onDelete = ForeignKey.CASCADE
|
||||
)
|
||||
}
|
||||
)
|
||||
public class BitcoinTransactionGTxIO {
|
||||
|
||||
/**
|
||||
* The id of the bitcoin transaction
|
||||
*/
|
||||
@ColumnInfo(name="bitcoin_transaction_id")
|
||||
protected long bitcoinTransactionId;
|
||||
|
||||
/**
|
||||
* The index in the transaction
|
||||
*/
|
||||
@ColumnInfo(name="io_index")
|
||||
protected int index;
|
||||
|
||||
/**
|
||||
* The address of the input or output
|
||||
*/
|
||||
@ColumnInfo(name="address")
|
||||
protected String address;
|
||||
|
||||
/**
|
||||
* determines if this is an input or output
|
||||
*/
|
||||
@ColumnInfo(name="is_output")
|
||||
protected boolean isOutput;
|
||||
|
||||
@ColumnInfo(name="amount")
|
||||
protected long amount;
|
||||
|
||||
@ColumnInfo(name="script_hex")
|
||||
protected String scriptHex;
|
||||
|
||||
@ColumnInfo(name="original_txid")
|
||||
protected String originalTxId;
|
||||
|
||||
public BitcoinTransactionGTxIO() {
|
||||
}
|
||||
|
||||
public BitcoinTransactionGTxIO(long bitcoinTransactionId, int index, String address, boolean isOutput) {
|
||||
this.bitcoinTransactionId = bitcoinTransactionId;
|
||||
this.index = index;
|
||||
this.address = address;
|
||||
this.isOutput = isOutput;
|
||||
}
|
||||
|
||||
public long getBitcoinTransactionId() {
|
||||
return bitcoinTransactionId;
|
||||
}
|
||||
|
||||
public void setBitcoinTransactionId(long bitcoinTransactionId) {
|
||||
this.bitcoinTransactionId = bitcoinTransactionId;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public boolean isOutput() {
|
||||
return isOutput;
|
||||
}
|
||||
|
||||
public void setOutput(boolean output) {
|
||||
isOutput = output;
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(long amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getScriptHex() {
|
||||
return scriptHex;
|
||||
}
|
||||
|
||||
public void setScriptHex(String scriptHex) {
|
||||
this.scriptHex = scriptHex;
|
||||
}
|
||||
|
||||
public String getOriginalTxId() {
|
||||
return originalTxId;
|
||||
}
|
||||
|
||||
public void setOriginalTxId(String originalTxId) {
|
||||
this.originalTxId = originalTxId;
|
||||
}
|
||||
}
|
|
@ -20,9 +20,13 @@ import cy.agorise.crystalwallet.enums.CryptoCoin;
|
|||
*/
|
||||
@Entity(
|
||||
tableName="crypto_coin_transaction",
|
||||
primaryKeys = {
|
||||
|
||||
},
|
||||
indices={
|
||||
@Index(value={"account_id"}),
|
||||
@Index(value={"id_currency"})
|
||||
@Index(value={"id_currency"}),
|
||||
@Index(value={"date", "account_id", "id_currency", "from", "to"},unique=true)
|
||||
},
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
|
@ -66,7 +70,7 @@ public class CryptoCoinTransaction {
|
|||
* The id of the account assoiciated, this is used for the foreign key definition
|
||||
*/
|
||||
@ColumnInfo(name="account_id")
|
||||
protected long accountId;
|
||||
protected long accountId = -1;
|
||||
/**
|
||||
* The amount of asset is moved in this transaction
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,15 @@ public class CryptoCurrency {
|
|||
@ColumnInfo(name = "precision")
|
||||
private int mPrecision;
|
||||
|
||||
public CryptoCurrency() {
|
||||
}
|
||||
|
||||
public CryptoCurrency(String name, CryptoNet cryptoNet, int precision) {
|
||||
this.mName = name;
|
||||
this.mCryptoNet = cryptoNet;
|
||||
this.mPrecision = precision;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return mId;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package cy.agorise.crystalwallet.models;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.util.DiffUtil;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
|
||||
public class CryptoNetSelection {
|
||||
CryptoNet cryptoNet;
|
||||
Boolean selected;
|
||||
|
||||
public CryptoNetSelection(CryptoNet cryptoNet, Boolean selected) {
|
||||
this.cryptoNet = cryptoNet;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public CryptoNet getCryptoNet() {
|
||||
return cryptoNet;
|
||||
}
|
||||
|
||||
public void setCryptoNet(CryptoNet cryptoNet) {
|
||||
this.cryptoNet = cryptoNet;
|
||||
}
|
||||
|
||||
public Boolean getSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void setSelected(Boolean selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public static final DiffUtil.ItemCallback<CryptoNetSelection> DIFF_CALLBACK = new DiffUtil.ItemCallback<CryptoNetSelection>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(
|
||||
@NonNull CryptoNetSelection oldCryptoNetSelection, @NonNull CryptoNetSelection newCryptoNetSelection) {
|
||||
return oldCryptoNetSelection.getCryptoNet() == newCryptoNetSelection.getCryptoNet();
|
||||
}
|
||||
@Override
|
||||
public boolean areContentsTheSame(
|
||||
@NonNull CryptoNetSelection oldCryptoNetSelection, @NonNull CryptoNetSelection newCryptoNetSelection) {
|
||||
return oldCryptoNetSelection.equals(newCryptoNetSelection);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -31,9 +31,16 @@ public class GrapheneAccount extends CryptoNetAccount {
|
|||
}
|
||||
|
||||
public void loadInfo(GrapheneAccountInfo info){
|
||||
this.name = info.getName();
|
||||
this.accountId = info.getAccountId();
|
||||
this.upgradedToLtm = info.getUpgradedToLtm();
|
||||
if(info != null){
|
||||
this.name = info.getName();
|
||||
this.accountId = info.getAccountId();
|
||||
this.upgradedToLtm = info.getUpgradedToLtm();
|
||||
}
|
||||
else{
|
||||
this.name = "";
|
||||
this.accountId = "-1";
|
||||
this.upgradedToLtm = false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.insightapi.GetGenesisBlock;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
|
||||
public class BitcoinCryptoNetVerifier extends CryptoNetVerifier{
|
||||
|
||||
final CryptoCoin cryptoCoin;
|
||||
|
||||
public BitcoinCryptoNetVerifier(CryptoCoin cryptoCoin) {
|
||||
this.cryptoCoin = cryptoCoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkURL(final String url) {
|
||||
|
||||
final long startTime = System.currentTimeMillis();
|
||||
GetGenesisBlock genesisBloc = new GetGenesisBlock(url, new GetGenesisBlock.genesisBlockListener() {
|
||||
@Override
|
||||
public void genesisBlock(String value) {
|
||||
if(cryptoCoin.getParameters()!= null){
|
||||
if(value.equals(cryptoCoin.getParameters().getGenesisBlock().getHashAsString())){
|
||||
|
||||
CryptoNetManager.verifiedCryptoNetURL(cryptoCoin.getCryptoNet(), url, System.currentTimeMillis() - startTime);
|
||||
}else{
|
||||
System.out.println("BitcoinCryptoNetVerifier bad genesis block " + value + " " + url);
|
||||
}
|
||||
//TODO bad genesis block
|
||||
}else{
|
||||
CryptoNetManager.verifiedCryptoNetURL(cryptoCoin.getCryptoNet(), url, System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail() {
|
||||
//TODO failed
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChainId() {
|
||||
if(cryptoCoin == null || cryptoCoin.getParameters()== null) {
|
||||
return null;
|
||||
}
|
||||
return cryptoCoin.getParameters().getGenesisBlock().getHashAsString();
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ public abstract class CryptoNetManager {
|
|||
|
||||
public static String getURL(CryptoNet crypto, int index){
|
||||
if(TestedURLs.containsKey(crypto) && TestedURLs.get(crypto).size()>index){
|
||||
System.out.println("Servers url list " + Arrays.toString(TestedURLs.get(crypto).toArray()));
|
||||
return TestedURLs.get(crypto).get(index).getUrl();
|
||||
}
|
||||
System.out.println("Servers " + crypto.getLabel()+" dioesn't have testedurl");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
|
||||
/**
|
||||
|
@ -15,6 +16,10 @@ public abstract class CryptoNetVerifier {
|
|||
static CryptoNetVerifier getNetworkVerify(CryptoNet cryptoNet){
|
||||
if(cryptoNet.getLabel().equals(CryptoNet.BITSHARES.getLabel())){
|
||||
return new BitsharesCryptoNetVerifier();
|
||||
}else if(cryptoNet.getLabel().equals(CryptoNet.BITCOIN.getLabel())){
|
||||
return new BitcoinCryptoNetVerifier(CryptoCoin.BITCOIN);
|
||||
}else if(cryptoNet.getLabel().equals(CryptoNet.STEEM.getLabel())){
|
||||
return new SteemCryptoNetVerifier();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ public class GetChainId extends BaseGrapheneHandler {
|
|||
|
||||
@Override
|
||||
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||
System.out.println("<<< "+frame.getPayloadText());
|
||||
String response = frame.getPayloadText();
|
||||
|
||||
Type GetChainIdResponse = new TypeToken<WitnessResponse<String>>(){}.getType();
|
||||
|
@ -55,7 +54,5 @@ public class GetChainId extends BaseGrapheneHandler {
|
|||
|
||||
@Override
|
||||
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||
if(frame.isTextFrame())
|
||||
System.out.println(">>> "+frame.getPayloadText());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.neovisionaries.ws.client.WebSocket;
|
||||
import com.neovisionaries.ws.client.WebSocketFrame;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cy.agorise.graphenej.RPC;
|
||||
import cy.agorise.graphenej.api.BaseGrapheneHandler;
|
||||
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
|
||||
import cy.agorise.graphenej.models.ApiCall;
|
||||
import cy.agorise.graphenej.models.WitnessResponse;
|
||||
|
||||
/**
|
||||
* Created by henry on 28/2/2018.
|
||||
*/
|
||||
|
||||
public class GetDatabaseVersion extends BaseGrapheneHandler {
|
||||
|
||||
private final WitnessResponseListener mListener;
|
||||
|
||||
public GetDatabaseVersion(WitnessResponseListener listener) {
|
||||
super(listener);
|
||||
this.mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
|
||||
ApiCall getAccountByName = new ApiCall(0, "database_api.get_version", new ArrayList<Serializable>(), RPC.VERSION, 1);
|
||||
websocket.sendText(getAccountByName.toJsonString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||
String response = frame.getPayloadText();
|
||||
|
||||
Type GetChainIdResponse = new TypeToken<WitnessResponse<String>>(){}.getType();
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
WitnessResponse<VersionResponse> witnessResponse = builder.create().fromJson(response, GetChainIdResponse);
|
||||
if(witnessResponse.error != null){
|
||||
this.mListener.onError(witnessResponse.error);
|
||||
}else{
|
||||
this.mListener.onSuccess(witnessResponse);
|
||||
}
|
||||
|
||||
websocket.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
|
||||
}
|
||||
|
||||
public class VersionResponse{
|
||||
public String blockchain_version;
|
||||
public String steem_revision;
|
||||
public String fc_revision;
|
||||
public String chain_id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package cy.agorise.crystalwallet.network;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.graphenej.interfaces.WitnessResponseListener;
|
||||
import cy.agorise.graphenej.models.BaseResponse;
|
||||
import cy.agorise.graphenej.models.WitnessResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* Created by henry on 28/2/2018.
|
||||
*/
|
||||
|
||||
public class SteemCryptoNetVerifier extends CryptoNetVerifier {
|
||||
private final CryptoNet cryptoNet = CryptoNet.STEEM;
|
||||
private final String CHAIN_ID = "0000000000000000000000000000000000000000000000000000000000000000";//mainnet
|
||||
|
||||
@Override
|
||||
public void checkURL(final String url) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
WebSocketThread thread = new WebSocketThread(new GetChainId(new WitnessResponseListener() {
|
||||
@Override
|
||||
public void onSuccess(WitnessResponse response) {
|
||||
if(response.result instanceof GetDatabaseVersion.VersionResponse) {
|
||||
GetDatabaseVersion.VersionResponse result = (GetDatabaseVersion.VersionResponse) response.result;
|
||||
if(result.chain_id.equals(CHAIN_ID)) {
|
||||
CryptoNetManager.verifiedCryptoNetURL(cryptoNet, url, System.currentTimeMillis() - startTime);
|
||||
}else{
|
||||
System.out.println(" BitsharesCryptoNetVerifier Error we are not in the net current chain id " + result.chain_id + " excepted " + CHAIN_ID);
|
||||
//TODO handle error bad chain
|
||||
}
|
||||
}else{
|
||||
//TODO handle error bad answer
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(BaseResponse.Error error) {
|
||||
//TODO handle error
|
||||
System.out.println("Bad server response " + url);
|
||||
}
|
||||
}),url);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChainId() {
|
||||
return CHAIN_ID;
|
||||
}
|
||||
}
|
|
@ -3,9 +3,16 @@ package cy.agorise.crystalwallet.requestmanagers;
|
|||
import android.content.Context;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.GeneralCoinAccount;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
|
||||
public class GeneralAccountSendRequest extends CryptoNetInfoRequest {
|
||||
/**
|
||||
* Class used to make a send amount request.
|
||||
*
|
||||
* Created by henry on 8/10/2017.
|
||||
*/
|
||||
|
||||
public class BitcoinSendRequest extends CryptoNetInfoRequest {
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
|
@ -14,45 +21,48 @@ public class GeneralAccountSendRequest extends CryptoNetInfoRequest {
|
|||
SUCCEEDED,
|
||||
NO_INTERNET,
|
||||
NO_SERVER_CONNECTION,
|
||||
BAD_TO_ADDRESS,
|
||||
NO_FEE,
|
||||
NO_BALANCE,
|
||||
NO_FEE,
|
||||
PETITION_FAILED
|
||||
}
|
||||
|
||||
// The app context
|
||||
private Context mContext;
|
||||
//The soruce Account
|
||||
private GeneralCoinAccount mAccount;
|
||||
// The destination account address
|
||||
// The source account used to transfer fund from
|
||||
private CryptoNetAccount mSourceAccount;
|
||||
// The destination account id
|
||||
private String mToAccount;
|
||||
// The amount of the transaction
|
||||
private long mAmount;
|
||||
// The asset id of the transaction
|
||||
private CryptoCoin mCryptoCoin;
|
||||
// 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, GeneralCoinAccount account, String toAccount, long amount, String memo) {
|
||||
super(coin);
|
||||
public BitcoinSendRequest(Context context, CryptoNetAccount sourceAccount,
|
||||
String toAccount, long amount, CryptoCoin cryptoCoin, String memo) {
|
||||
super(cryptoCoin);
|
||||
this.mContext = context;
|
||||
this.mAccount = account;
|
||||
this.mSourceAccount = sourceAccount;
|
||||
this.mToAccount = toAccount;
|
||||
this.mAmount = amount;
|
||||
this.mCryptoCoin = cryptoCoin;
|
||||
this.mMemo = memo;
|
||||
}
|
||||
|
||||
public GeneralAccountSendRequest(CryptoCoin coin, Context context, GeneralCoinAccount account, String toAccount, long amount) {
|
||||
this(coin,context,account,toAccount,amount,null);
|
||||
|
||||
public BitcoinSendRequest(Context context, GrapheneAccount sourceAccount,
|
||||
String toAccount, long amount, CryptoCoin cryptoCoin) {
|
||||
this(context, sourceAccount,toAccount,amount,cryptoCoin,null);
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public GeneralCoinAccount getAccount() {
|
||||
return mAccount;
|
||||
public CryptoNetAccount getSourceAccount() {
|
||||
return mSourceAccount;
|
||||
}
|
||||
|
||||
public String getToAccount() {
|
||||
|
@ -63,6 +73,10 @@ public class GeneralAccountSendRequest extends CryptoNetInfoRequest {
|
|||
return mAmount;
|
||||
}
|
||||
|
||||
public CryptoCoin getCryptoCoin() {
|
||||
return mCryptoCoin;
|
||||
}
|
||||
|
||||
public String getMemo() {
|
||||
return mMemo;
|
||||
}
|
||||
|
@ -75,11 +89,10 @@ public class GeneralAccountSendRequest extends CryptoNetInfoRequest {
|
|||
|
||||
public void setStatus(StatusCode code){
|
||||
this.status = code;
|
||||
this._fireOnCarryOutEvent();
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public StatusCode getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
|
||||
/**
|
||||
* Class used to make a bitcoin uri parse request.
|
||||
*
|
||||
* Created by henry on 11/13/2018.
|
||||
*/
|
||||
|
||||
public class BitcoinUriParseRequest extends CryptoNetInfoRequest {
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
public enum StatusCode{
|
||||
NOT_STARTED,
|
||||
VALID,
|
||||
NOT_VALID
|
||||
}
|
||||
|
||||
private String uri;
|
||||
|
||||
private String address;
|
||||
private Double amount;
|
||||
private String memo;
|
||||
|
||||
|
||||
|
||||
private StatusCode status = StatusCode.NOT_STARTED;
|
||||
|
||||
public BitcoinUriParseRequest(String uri, CryptoCoin cryptoCoin) {
|
||||
super(cryptoCoin);
|
||||
this.address = "";
|
||||
this.amount = -1.0;
|
||||
this.memo = "";
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public Double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(Double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getMemo() {
|
||||
return memo;
|
||||
}
|
||||
|
||||
public void setMemo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
|
||||
/**
|
||||
* This class validates that an account name exist, this can be used to verified the existing accounts
|
||||
* or to verified if the name is available to create an Account
|
||||
*
|
||||
* Created by henry on 8/10/2017.
|
||||
*/
|
||||
|
||||
public class CalculateBitcoinUriRequest extends CryptoNetInfoRequest {
|
||||
private CryptoNetAccount account;
|
||||
private CryptoCurrency currency;
|
||||
private double amount;
|
||||
private Context context;
|
||||
|
||||
private String uri;
|
||||
|
||||
public CalculateBitcoinUriRequest(CryptoCoin coin, CryptoNetAccount account, Context context) {
|
||||
super(coin);
|
||||
this.account = account;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public CalculateBitcoinUriRequest(CryptoCoin coin, CryptoNetAccount account, Context context, double amount) {
|
||||
super(coin);
|
||||
this.account = account;
|
||||
this.context = context;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public CalculateBitcoinUriRequest(CryptoCoin coin, CryptoNetAccount account, CryptoCurrency currency, double amount, Context context) {
|
||||
super(coin);
|
||||
this.account = account;
|
||||
this.currency = currency;
|
||||
this.amount = amount;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public CryptoNetAccount getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public CryptoCurrency getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
if ((this.uri != null)){
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.GrapheneAccount;
|
||||
|
||||
/**
|
||||
* Creates bitcoin accounts using a seed,
|
||||
*
|
||||
* Created by Henry Varona on 10/22/2018.
|
||||
*/
|
||||
|
||||
public class CreateBitcoinAccountRequest extends CryptoNetInfoRequest {
|
||||
|
||||
private AccountSeed accountSeed;
|
||||
private CryptoNet accountCryptoNet;
|
||||
|
||||
private Context context;
|
||||
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
public enum StatusCode{
|
||||
NOT_STARTED,
|
||||
SUCCEEDED,
|
||||
ACCOUNT_EXIST
|
||||
}
|
||||
|
||||
// The state of this request
|
||||
private StatusCode status = StatusCode.NOT_STARTED;
|
||||
|
||||
public CreateBitcoinAccountRequest(AccountSeed accountSeed, Context context, CryptoCoin cryptoCoin){
|
||||
super(cryptoCoin);
|
||||
this.accountSeed = accountSeed;
|
||||
this.accountCryptoNet = cryptoCoin.getCryptoNet();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public AccountSeed getAccountSeed() {
|
||||
return this.accountSeed;
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
if(!status.equals(StatusCode.NOT_STARTED))
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
|
||||
public CryptoNet getAccountCryptoNet() {
|
||||
return this.accountCryptoNet;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setStatus(StatusCode code){
|
||||
this.status = code;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public StatusCode getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
|
@ -21,13 +21,6 @@ public abstract class CryptoNetInfoRequest {
|
|||
*/
|
||||
protected CryptoNetInfoRequestListener listener;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected CryptoNetInfoRequest(CryptoCoin coin){
|
||||
this.coin = coin;
|
||||
}
|
||||
|
@ -43,4 +36,7 @@ public abstract class CryptoNetInfoRequest {
|
|||
CryptoNetInfoRequests.getInstance().removeRequest(this);
|
||||
}
|
||||
|
||||
public CryptoCoin getCoin() {
|
||||
return coin;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.SeedType;
|
||||
|
||||
/**
|
||||
* Imports a bitshares accounts,
|
||||
*
|
||||
* return true if the account exist, and the mnemonic (brainkey provide is for that account
|
||||
* Created by Henry Varona on 10/24/2018.
|
||||
*/
|
||||
|
||||
public class ImportBitsharesAccountRequest extends CryptoNetInfoRequest {
|
||||
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
public enum StatusCode{
|
||||
NOT_STARTED,
|
||||
SUCCEEDED,
|
||||
NO_INTERNET,
|
||||
NO_SERVER_CONNECTION,
|
||||
ACCOUNT_DOESNT_EXIST,
|
||||
BAD_SEED,
|
||||
NO_ACCOUNT_DATA,
|
||||
PETITION_FAILED
|
||||
}
|
||||
|
||||
/**
|
||||
* The mnemonic words
|
||||
*/
|
||||
private final String mnemonic;
|
||||
|
||||
/**
|
||||
* If this seed is BIP39 or Brainkey
|
||||
*/
|
||||
private SeedType seedType;
|
||||
|
||||
/**
|
||||
* The status of this request
|
||||
*/
|
||||
private StatusCode status = StatusCode.NOT_STARTED;
|
||||
|
||||
private Context context;
|
||||
|
||||
public ImportBitsharesAccountRequest(String mnemonic, Context context){
|
||||
super(CryptoCoin.BITSHARES);
|
||||
this.mnemonic = mnemonic;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public ImportBitsharesAccountRequest(String mnemonic, Context context, boolean addAccountIfValid){
|
||||
super(CryptoCoin.BITSHARES);
|
||||
this.mnemonic = mnemonic;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
if (!(this.status.equals(StatusCode.NOT_STARTED))){
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public String getMnemonic() {
|
||||
return mnemonic;
|
||||
}
|
||||
|
||||
public SeedType getSeedType() {
|
||||
return seedType;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setSeedType(SeedType seedType) {
|
||||
this.seedType = seedType;
|
||||
}
|
||||
|
||||
public void setStatus(StatusCode status) {
|
||||
this.status = status;
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
|
||||
public StatusCode getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.AccountSeed;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
|
||||
/**
|
||||
* Ask for the next address of a bitcoin alike account
|
||||
*
|
||||
* Created by Henry Varona on 10/22/2018.
|
||||
*/
|
||||
|
||||
public class NextBitcoinAccountAddressRequest extends CryptoNetInfoRequest {
|
||||
|
||||
private CryptoNetAccount account;
|
||||
private CryptoCoin cryptoCoin;
|
||||
private Context context;
|
||||
|
||||
private String address = null;
|
||||
|
||||
/**
|
||||
* The status code of this request
|
||||
*/
|
||||
public enum StatusCode{
|
||||
NOT_STARTED,
|
||||
SUCCEEDED
|
||||
}
|
||||
|
||||
// The state of this request
|
||||
private StatusCode status = StatusCode.NOT_STARTED;
|
||||
|
||||
public NextBitcoinAccountAddressRequest(CryptoNetAccount account, CryptoCoin cryptoCoin, Context context){
|
||||
super(cryptoCoin);
|
||||
this.account = account;
|
||||
this.cryptoCoin = cryptoCoin;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public CryptoNetAccount getAccount() {
|
||||
return this.account;
|
||||
}
|
||||
|
||||
public CryptoCoin getCryptoCoin() {
|
||||
return this.cryptoCoin;
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
if(!status.equals(StatusCode.NOT_STARTED))
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setStatus(StatusCode code){
|
||||
this.status = code;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public StatusCode getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package cy.agorise.crystalwallet.requestmanagers;
|
||||
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
|
||||
/**
|
||||
* This class validates that an account name exist, this can be used to verified the existing accounts
|
||||
* or to verified if the name is available to create an Account
|
||||
*
|
||||
* Created by henry on 8/10/2017.
|
||||
*/
|
||||
|
||||
public class ValidateBitcoinAddressRequest extends CryptoNetInfoRequest {
|
||||
// The account name to validate
|
||||
private String address;
|
||||
// The result of the validation, or null if there isn't a response
|
||||
private Boolean addressValid;
|
||||
|
||||
public ValidateBitcoinAddressRequest(CryptoCoin cryptoCoin, String address) {
|
||||
super(cryptoCoin);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public boolean getAddressValid(){
|
||||
return this.addressValid;
|
||||
}
|
||||
|
||||
public void setAddressValid(boolean value){
|
||||
this.addressValid = value;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
if ((this.addressValid != null)){
|
||||
this._fireOnCarryOutEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,9 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.manager.FileBackupManager;
|
||||
import cy.agorise.crystalwallet.manager.GeneralAccountManager;
|
||||
import cy.agorise.crystalwallet.models.BitsharesAccountNameCache;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
|
@ -43,6 +45,7 @@ public class CrystalWalletService extends LifecycleService {
|
|||
private Looper mServiceLooper;
|
||||
private ServiceHandler mServiceHandler;
|
||||
private BitsharesAccountManager bitsharesAccountManager;
|
||||
private GeneralAccountManager generalAccountManager;
|
||||
private Thread LoadAccountTransactionsThread;
|
||||
private Thread LoadBitsharesAccountNamesThread;
|
||||
private EquivalencesThread LoadEquivalencesThread;
|
||||
|
@ -167,7 +170,15 @@ public class CrystalWalletService extends LifecycleService {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
final LiveData<List<CryptoNetAccount>> cryptoNetAccountList = db.cryptoNetAccountDao().getAllBitcoins();
|
||||
cryptoNetAccountList.observe(this, new Observer<List<CryptoNetAccount>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<CryptoNetAccount> cryptoNetAccounts) {
|
||||
for(CryptoNetAccount nextCryptoNetAccount : cryptoNetAccounts) {
|
||||
generalAccountManager.loadAccountFromDB(nextCryptoNetAccount,thisService);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*while(this.keepLoadingAccountTransactions){
|
||||
try{
|
||||
|
@ -188,11 +199,13 @@ public class CrystalWalletService extends LifecycleService {
|
|||
this.cryptoNetInfoRequests = CryptoNetInfoRequests.getInstance();
|
||||
this.fileServiceRequests = FileServiceRequests.getInstance();
|
||||
this.bitsharesAccountManager = new BitsharesAccountManager();
|
||||
this.generalAccountManager = new GeneralAccountManager(CryptoCoin.BITCOIN,this.getApplicationContext());
|
||||
this.fileBackupManager = new FileBackupManager();
|
||||
|
||||
//Add the managers as listeners of the CryptoNetInfoRequest so
|
||||
//they can carry out the info requests from the ui
|
||||
this.cryptoNetInfoRequests.addListener(this.bitsharesAccountManager);
|
||||
this.cryptoNetInfoRequests.addListener(this.generalAccountManager);
|
||||
|
||||
this.fileServiceRequests.addListener(this.fileBackupManager);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canScrollHorizontally(int direction) {
|
||||
return !swipeLocked && super.canScrollHorizontally(direction);
|
||||
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 void startScroll(int startX, int startY, int dx, int dy, int duration) {
|
||||
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package cy.agorise.crystalwallet.util;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 25/2/2018.
|
||||
*/
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import com.squareup.picasso.Transformation;
|
||||
|
||||
public class CircleTransformation implements Transformation {
|
||||
@Override
|
||||
public Bitmap transform(Bitmap source) {
|
||||
int size = Math.min(source.getWidth(), source.getHeight());
|
||||
|
||||
int x = (source.getWidth() - size) / 2;
|
||||
int y = (source.getHeight() - size) / 2;
|
||||
|
||||
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
|
||||
if (squaredBitmap != source) {
|
||||
source.recycle();
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint();
|
||||
BitmapShader shader = new BitmapShader(squaredBitmap,
|
||||
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
|
||||
paint.setShader(shader);
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
float r = size / 2f;
|
||||
canvas.drawCircle(r, r, r, paint);
|
||||
|
||||
squaredBitmap.recycle();
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return "CircleTransformation";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package cy.agorise.crystalwallet.util;
|
||||
|
||||
import com.bumptech.glide.annotation.GlideModule;
|
||||
import com.bumptech.glide.module.AppGlideModule;
|
||||
|
||||
|
||||
/**
|
||||
* This function is used to generate a local Glide API accessible by a GlideApp call
|
||||
* which makes it easier to use more advanced Glide methods.
|
||||
* {more information - https://bumptech.github.io/glide/doc/generatedapi.html}
|
||||
*/
|
||||
@GlideModule
|
||||
public class MyAppGlideModule extends AppGlideModule {}
|
|
@ -1,33 +0,0 @@
|
|||
package cy.agorise.crystalwallet.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.AppCompatImageView;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* Created by xd on 1/24/18.
|
||||
* ImageView which adjusts its size to always create a square
|
||||
*/
|
||||
|
||||
public class SquaredImageView extends AppCompatImageView {
|
||||
public SquaredImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SquaredImageView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SquaredImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
|
||||
setMeasuredDimension(size, size);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ import android.arch.paging.PagedList;
|
|||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.Contact;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 1/17/2018.
|
||||
|
|
|
@ -3,19 +3,12 @@ package cy.agorise.crystalwallet.viewmodels;
|
|||
import android.app.Application;
|
||||
import android.arch.lifecycle.AndroidViewModel;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.ViewModel;
|
||||
import android.arch.paging.DataSource;
|
||||
import android.arch.paging.LivePagedListBuilder;
|
||||
import android.arch.paging.LivePagedListProvider;
|
||||
import android.arch.paging.PagedList;
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransaction;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinTransactionExtended;
|
||||
import cy.agorise.crystalwallet.views.TransactionListView;
|
||||
|
||||
/**
|
||||
* Created by Henry Varona on 12/9/2017.
|
||||
|
|
|
@ -18,7 +18,7 @@ public class ImportSeedValidator extends UIValidator {
|
|||
super(context);
|
||||
this.addField(new PinValidationField(pinEdit));
|
||||
this.addField(new PinConfirmationValidationField(pinEdit,pinConfirmationEdit));
|
||||
this.addField(new BitsharesAccountNameValidationField(bitsharesAccountNameEdit));
|
||||
this.addField(new BitsharesAccountMnemonicValidationField(mnemonicEdit,bitsharesAccountNameEdit));
|
||||
//this.addField(new BitsharesAccountNameValidationField(bitsharesAccountNameEdit));
|
||||
//this.addField(new BitsharesAccountMnemonicValidationField(mnemonicEdit,bitsharesAccountNameEdit));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public class SendTransactionValidator extends UIValidator {
|
|||
private CryptoNetAccount account;
|
||||
|
||||
|
||||
public SendTransactionValidator(Context context, CryptoNetAccount account, MaterialSpinner fromEdit, EditText toEdit, Spinner assetSpinner, EditText amountEdit, EditText memoEdit){
|
||||
public SendTransactionValidator(Context context, CryptoNetAccount account, Spinner fromEdit, EditText toEdit, Spinner assetSpinner, EditText amountEdit, EditText memoEdit){
|
||||
super(context);
|
||||
this.account = account;
|
||||
this.addField(new FromValidationField(fromEdit));
|
||||
|
|
|
@ -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 {
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,6 +5,8 @@ import android.widget.Spinner;
|
|||
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.dao.CrystalDatabase;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.CryptoCoinBalance;
|
||||
import cy.agorise.crystalwallet.models.CryptoCurrency;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
|
@ -29,7 +31,12 @@ public class AmountValidationField extends ValidationField {
|
|||
public void validate(){
|
||||
try {
|
||||
final float newAmountValue = Float.parseFloat(amountField.getText().toString());
|
||||
final CryptoCurrency cryptoCurrency = (CryptoCurrency)assetSpinner.getSelectedItem();
|
||||
final CryptoCurrency cryptoCurrency;
|
||||
if(this.account.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
cryptoCurrency = (CryptoCurrency) assetSpinner.getSelectedItem();
|
||||
}else{
|
||||
cryptoCurrency = CrystalDatabase.getAppDatabase(amountField.getContext()).cryptoCurrencyDao().getByNameAndCryptoNet(CryptoCoin.getByCryptoNet(this.account.getCryptoNet()).get(0).getLabel(),this.account.getCryptoNet().name());
|
||||
}
|
||||
|
||||
/*
|
||||
* Validation for the money
|
||||
|
@ -48,7 +55,12 @@ public class AmountValidationField extends ValidationField {
|
|||
|
||||
CryptoCoinBalance balance = CrystalDatabase.getAppDatabase(amountField.getContext()).cryptoCoinBalanceDao().getBalanceFromAccount(this.account.getId(),cryptoCurrency.getId());
|
||||
|
||||
if (newAmountValue > balance.getBalance()){
|
||||
double balanceDouble = 0;
|
||||
if(balance != null){
|
||||
balanceDouble = balance.getBalance();
|
||||
}
|
||||
|
||||
if (newAmountValue > balanceDouble){
|
||||
setMessageForValue(mixedValues, validator.getContext().getResources().getString(R.string.insufficient_amount));
|
||||
setValidForValue(mixedValues, false);
|
||||
} else if (newAmountValue == 0){
|
||||
|
@ -61,6 +73,8 @@ public class AmountValidationField extends ValidationField {
|
|||
setLastValue("");
|
||||
setMessageForValue("",validator.getContext().getResources().getString(R.string.please_enter_valid_amount));
|
||||
setValidForValue("", false);
|
||||
} catch (Exception e ){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,16 +18,22 @@ public class AssetValidationField extends ValidationField {
|
|||
}
|
||||
|
||||
public void validate(){
|
||||
final CryptoCurrency cryptoCurrencySelected = (CryptoCurrency) this.assetField.getSelectedItem();
|
||||
if (cryptoCurrencySelected != null) {
|
||||
final String newValue = "" + cryptoCurrencySelected.getId();
|
||||
if (this.assetField.getSelectedItem() instanceof CryptoCurrency) {
|
||||
final CryptoCurrency cryptoCurrencySelected = (CryptoCurrency) this.assetField.getSelectedItem();
|
||||
if (cryptoCurrencySelected != null) {
|
||||
final String newValue = "" + cryptoCurrencySelected.getId();
|
||||
this.setLastValue(newValue);
|
||||
setValidForValue(newValue, true);
|
||||
} else {
|
||||
final String newValue = "" + -1;
|
||||
setMessageForValue(newValue, "Select a currency");
|
||||
this.setLastValue(newValue);
|
||||
setValidForValue(newValue, false);
|
||||
}
|
||||
} else {
|
||||
final String newValue = "" + -1;
|
||||
this.setLastValue(newValue);
|
||||
setValidForValue(newValue, true);
|
||||
} else {
|
||||
final String newValue = ""+-1;
|
||||
setMessageForValue(newValue,"Select a currency");
|
||||
this.setLastValue(newValue);
|
||||
setValidForValue(newValue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue