commit
01e67ce258
28 changed files with 1445 additions and 171 deletions
|
@ -41,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)
|
||||
|
|
|
@ -82,6 +82,25 @@ 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
|
||||
*
|
||||
|
@ -164,7 +183,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
|
||||
|
@ -176,7 +195,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();
|
||||
}
|
||||
|
||||
|
@ -381,7 +400,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());
|
||||
|
@ -444,6 +463,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,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
|
||||
|
@ -482,7 +594,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){
|
||||
CryptoNet cryptoNet, final Context context){
|
||||
|
||||
CrystalDatabase db = CrystalDatabase.getAppDatabase(context);
|
||||
final CryptoCoinBalanceDao balanceDao = db.cryptoCoinBalanceDao();
|
||||
|
@ -542,7 +654,7 @@ public abstract class GrapheneApiGenerator {
|
|||
public void onError(BaseResponse.Error error) {
|
||||
|
||||
}
|
||||
}),CryptoNetManager.getURL(CryptoNet.BITSHARES));
|
||||
}),CryptoNetManager.getURL(cryptoNet));
|
||||
|
||||
thread.start();
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ public enum CryptoCoin implements Serializable {
|
|||
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);
|
||||
BITSHARES(CryptoNet.BITSHARES,"BTS",5,0,null),
|
||||
STEEM(CryptoNet.STEEM,"BTS",5,0,null);
|
||||
|
||||
protected CryptoNet cryptoNet;
|
||||
protected String label;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -10,11 +10,13 @@ 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;
|
||||
|
@ -98,7 +100,10 @@ public class GeneralAccountSeedCoinSettingsFragment extends Fragment implements
|
|||
@Override
|
||||
public void onCryptoNetSelectionChecked(CryptoNetSelection source) {
|
||||
//Toast.makeText(this.getContext(),"the coin "+source.getCryptoNet().name()+" was "+(source.getSelected()?"selected":"unselected"),Toast.LENGTH_LONG).show();
|
||||
final CreateBitcoinAccountRequest request = new CreateBitcoinAccountRequest(this.accountSeed,this.getContext(),source.getCryptoNet());
|
||||
List<CryptoCoin> cryptoCoins = CryptoCoin.getByCryptoNet(source.getCryptoNet());
|
||||
|
||||
|
||||
final CreateBitcoinAccountRequest request = new CreateBitcoinAccountRequest(this.accountSeed,this.getContext(),cryptoCoins.get(0));
|
||||
|
||||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@ 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;
|
||||
|
@ -35,6 +36,8 @@ import com.google.zxing.WriterException;
|
|||
import com.google.zxing.common.BitMatrix;
|
||||
|
||||
import butterknife.OnClick;
|
||||
import cy.agorise.crystalwallet.enums.CryptoCoin;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.util.CircularImageView;
|
||||
import cy.agorise.crystalwallet.viewmodels.CryptoNetAccountListViewModel;
|
||||
import cy.agorise.crystalwallet.views.CryptoNetAccountAdapter;
|
||||
|
@ -135,46 +138,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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
@ -247,8 +217,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();
|
||||
}
|
||||
|
||||
|
@ -260,7 +281,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();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ 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;
|
||||
|
@ -44,6 +45,8 @@ import com.google.zxing.Result;
|
|||
import com.jaredrummler.materialspinner.MaterialSpinner;
|
||||
import com.vincent.filepicker.ToastUtil;
|
||||
|
||||
import org.bitcoinj.wallet.SendRequest;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
|
@ -61,7 +64,11 @@ import cy.agorise.crystalwallet.R;
|
|||
import cy.agorise.crystalwallet.application.CrystalSecurityMonitor;
|
||||
import cy.agorise.crystalwallet.dialogs.material.CrystalDialog;
|
||||
import cy.agorise.crystalwallet.dialogs.material.ToastIt;
|
||||
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.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitsharesSendRequest;
|
||||
|
@ -90,7 +97,7 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
SendTransactionValidator sendTransactionValidator;
|
||||
|
||||
@BindView(R.id.spFrom)
|
||||
MaterialSpinner spFrom;
|
||||
Spinner spFrom;
|
||||
@BindView(R.id.tvFromError)
|
||||
TextView tvFromError;
|
||||
@BindView(R.id.etTo)
|
||||
|
@ -195,40 +202,6 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
@ -236,30 +209,31 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
/*
|
||||
* If only one account block the control
|
||||
* */
|
||||
if(cryptoNetAccounts.size()==1){
|
||||
spFrom.setEnabled(false);
|
||||
}
|
||||
//if(cryptoNetAccounts.size()==1){
|
||||
// spFrom.setEnabled(false);
|
||||
//}
|
||||
|
||||
spFrom.setAdapter(fromSpinnerAdapter);
|
||||
//spFrom.setSelection(0);
|
||||
spFrom.setSelection(0);
|
||||
|
||||
setAccountUI();
|
||||
/*
|
||||
* Custom material spinner implementation
|
||||
* */
|
||||
spFrom.setItems(cryptoNetAccounts);
|
||||
//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() {
|
||||
//spFrom.setOnItemSelectedListener(new MaterialSpinner.OnItemSelectedListener<CryptoNetAccount>() {
|
||||
// @Override
|
||||
// public void onItemSelected(MaterialSpinner view, int position, long id, CryptoNetAccount item) {
|
||||
// sendTransactionValidator.validate();
|
||||
// }
|
||||
//});
|
||||
//spFrom.setOnNothingSelectedListener(new MaterialSpinner.OnNothingSelectedListener() {
|
||||
|
||||
@Override public void onNothingSelected(MaterialSpinner spinner) {
|
||||
// @Override public void onNothingSelected(MaterialSpinner spinner) {
|
||||
|
||||
}
|
||||
});
|
||||
// }
|
||||
//});
|
||||
|
||||
// etFrom.setText(this.grapheneAccount.getName());
|
||||
}
|
||||
|
@ -305,6 +279,58 @@ public class SendTransactionFragment extends DialogFragment implements UIValidat
|
|||
return builder.setView(view).create();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO SendTransactionValidator to accept spFrom
|
||||
sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, spFrom, etTo, spAsset, etAmount, etMemo);
|
||||
sendTransactionValidator.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);
|
||||
|
||||
// TODO SendTransactionValidator to accept spFrom
|
||||
sendTransactionValidator = new SendTransactionValidator(this.getContext(), this.cryptoNetAccount, spFrom, etTo, spAsset, etAmount, etMemo);
|
||||
sendTransactionValidator.setListener(this);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void requestPermission() {
|
||||
|
||||
|
@ -430,10 +456,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)
|
||||
|
@ -576,49 +604,85 @@ 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 {
|
||||
crystalDialog.dismiss();
|
||||
thisFragment.dismiss();
|
||||
//thisFragment.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 {
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.unable_to_send_amount), Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* If exists mode scurity show it and valide events in case of success or fail
|
||||
|
|
|
@ -213,7 +213,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -693,7 +693,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,7 +796,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ 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;
|
||||
|
@ -41,6 +42,7 @@ import cy.agorise.crystalwallet.requestmanagers.CreateBitcoinAccountRequest;
|
|||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestsListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.NextBitcoinAccountAddressRequest;
|
||||
import cy.agorise.crystalwallet.requestmanagers.ValidateBitcoinAddressRequest;
|
||||
import cy.agorise.graphenej.Util;
|
||||
|
||||
public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInfoRequestsListener {
|
||||
|
@ -93,6 +95,12 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
final DeterministicKey changeKey = HDKeyDerivation.deriveChildKey(accountKey,
|
||||
new ChildNumber(1, false));
|
||||
|
||||
CryptoCoinBalance balance = new CryptoCoinBalance();
|
||||
balance.setBalance(0);
|
||||
balance.setCryptoCurrencyId(db.cryptoCurrencyDao().getByName(cryptoCoin.name(),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++){
|
||||
|
@ -143,6 +151,8 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
this.createGeneralAccount((CreateBitcoinAccountRequest) request);
|
||||
}else if(request instanceof NextBitcoinAccountAddressRequest){
|
||||
this.getNextAddress((NextBitcoinAccountAddressRequest) request);
|
||||
}else if(request instanceof ValidateBitcoinAddressRequest){
|
||||
this.validateAddress((ValidateBitcoinAddressRequest) request);
|
||||
}else{
|
||||
System.out.println("Invalid " +this.cryptoCoin.getLabel() + " request ");
|
||||
}
|
||||
|
@ -325,6 +335,16 @@ public class GeneralAccountManager implements CryptoAccountManager, CryptoNetInf
|
|||
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
|
||||
|
|
|
@ -0,0 +1,825 @@
|
|||
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.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.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);
|
||||
db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
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);
|
||||
db.cryptoNetAccountDao().insertCryptoNetAccount(grapheneAccount);
|
||||
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 CryptoNetEquivalentRequest) {
|
||||
this.getEquivalentValue((CryptoNetEquivalentRequest) 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.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())),getAccountNamesBP39);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0);
|
||||
|
||||
GrapheneApiGenerator.getAccountByOwnerOrActiveAddress(bk.getPublicAddress("BTS"),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(),"BTS")).toString().equals(bk.getPublicAddress("BTS").toString())){
|
||||
importRequest.setSeedType(SeedType.BRAINKEY);
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.SUCCEEDED);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
BIP39 bip39 = new BIP39(-1, importRequest.getMnemonic());
|
||||
for(PublicKey activeKey : prop.active.getKeyAuthList()){
|
||||
if((new Address(activeKey.getKey(),"BTS")).toString().equals(new Address(ECKey.fromPublicOnly(bip39.getBitsharesActiveKey(0).getPubKey())).toString())){
|
||||
importRequest.setSeedType(SeedType.BIP39);
|
||||
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.BITSHARES);
|
||||
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,getAccountInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//
|
||||
importRequest.setStatus(ValidateImportBitsharesAccountRequest.StatusCode.ACCOUNT_DOESNT_EXIST);
|
||||
}
|
||||
});
|
||||
|
||||
GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),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(),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.BITSHARES.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.BITSHARES));
|
||||
|
||||
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,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,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, 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,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(), new ApiRequest(0, new GetTransactionDate(transaction, db.transactionDao())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current change from two assets
|
||||
*/
|
||||
private void getEquivalentValue(final CryptoNetEquivalentRequest request){
|
||||
if(request.getFromCurrency() instanceof BitsharesAsset && request.getToCurrency() instanceof BitsharesAsset) {
|
||||
BitsharesAsset fromAsset = (BitsharesAsset) request.getFromCurrency();
|
||||
BitsharesAsset toAsset = (BitsharesAsset) request.getToCurrency();
|
||||
ApiRequest getEquivalentRequest = new ApiRequest(0, new ApiRequestListener() {
|
||||
@Override
|
||||
public void success(Object answer, int idPetition) {
|
||||
request.setPrice((Long)answer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(int idPetition) {
|
||||
//TODO error
|
||||
}
|
||||
});
|
||||
GrapheneApiGenerator.getEquivalentValue(fromAsset.getBitsharesId(),toAsset.getBitsharesId(), getEquivalentRequest);
|
||||
}else{
|
||||
//TODO error
|
||||
System.out.println("Equivalent Value error ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
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 {
|
||||
System.out.println("<<< "+frame.getPayloadText());
|
||||
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 {
|
||||
if(frame.isTextFrame())
|
||||
System.out.println(">>> "+frame.getPayloadText());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ 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;
|
||||
|
@ -32,10 +34,10 @@ public class CreateBitcoinAccountRequest extends CryptoNetInfoRequest {
|
|||
// The state of this request
|
||||
private StatusCode status = StatusCode.NOT_STARTED;
|
||||
|
||||
public CreateBitcoinAccountRequest(AccountSeed accountSeed, Context context, CryptoNet cryptoNet){
|
||||
super(CryptoCoin.BITSHARES);
|
||||
public CreateBitcoinAccountRequest(AccountSeed accountSeed, Context context, CryptoCoin cryptoCoin){
|
||||
super(cryptoCoin);
|
||||
this.accountSeed = accountSeed;
|
||||
this.accountCryptoNet = cryptoNet;
|
||||
this.accountCryptoNet = cryptoCoin.getCryptoNet();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -188,11 +191,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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountReq
|
|||
public class FromValidationField extends ValidationField {
|
||||
|
||||
//private EditText fromField;
|
||||
private MaterialSpinner fromField;
|
||||
private Spinner fromField;
|
||||
|
||||
public FromValidationField(MaterialSpinner fromField){
|
||||
public FromValidationField(Spinner fromField){
|
||||
super(fromField);
|
||||
this.fromField = fromField;
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ public class FromValidationField extends ValidationField {
|
|||
public void validate(){
|
||||
final String newValue;
|
||||
|
||||
if (fromField.getSelectedIndex() != -1) {
|
||||
final CryptoNetAccount cryptoNetAccount = (CryptoNetAccount) fromField.getItems().get(fromField.getSelectedIndex());
|
||||
if (fromField.getSelectedItem() instanceof CryptoNetAccount){
|
||||
final CryptoNetAccount cryptoNetAccount = (CryptoNetAccount) fromField.getSelectedItem();
|
||||
newValue = cryptoNetAccount.getName();
|
||||
} else {
|
||||
newValue = "";
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.widget.Spinner;
|
|||
import com.jaredrummler.materialspinner.MaterialSpinner;
|
||||
|
||||
import cy.agorise.crystalwallet.R;
|
||||
import cy.agorise.crystalwallet.enums.CryptoNet;
|
||||
import cy.agorise.crystalwallet.models.CryptoNetAccount;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequestListener;
|
||||
import cy.agorise.crystalwallet.requestmanagers.CryptoNetInfoRequests;
|
||||
|
@ -17,10 +18,10 @@ import cy.agorise.crystalwallet.requestmanagers.ValidateExistBitsharesAccountReq
|
|||
|
||||
public class ToValidationField extends ValidationField {
|
||||
|
||||
private MaterialSpinner fromField;
|
||||
private Spinner fromField;
|
||||
private EditText toField;
|
||||
|
||||
public ToValidationField(MaterialSpinner fromField, EditText toField){
|
||||
public ToValidationField(Spinner fromField, EditText toField){
|
||||
super(toField);
|
||||
this.fromField = fromField;
|
||||
this.toField = toField;
|
||||
|
@ -28,8 +29,9 @@ public class ToValidationField extends ValidationField {
|
|||
|
||||
public void validate(){
|
||||
final String fromNewValue;
|
||||
if (fromField.getSelectedIndex() != -1) {
|
||||
final CryptoNetAccount cryptoNetAccount = (CryptoNetAccount) fromField.getItems().get(fromField.getSelectedIndex());
|
||||
CryptoNetAccount cryptoNetAccount = null;
|
||||
if (fromField.getSelectedItem() instanceof CryptoNetAccount){
|
||||
cryptoNetAccount = (CryptoNetAccount) fromField.getSelectedItem();
|
||||
fromNewValue = cryptoNetAccount.getName();
|
||||
} else {
|
||||
fromNewValue = "";
|
||||
|
@ -45,19 +47,30 @@ public class ToValidationField extends ValidationField {
|
|||
setValidForValue(mixedValue, false);
|
||||
} else {
|
||||
|
||||
final ValidateExistBitsharesAccountRequest request = new ValidateExistBitsharesAccountRequest(toNewValue);
|
||||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (!request.getAccountExists()) {
|
||||
setMessageForValue(mixedValue, validator.getContext().getResources().getString(R.string.account_name_not_exist,"'"+toNewValue+"'"));
|
||||
setValidForValue(mixedValue, false);
|
||||
} else {
|
||||
if (cryptoNetAccount != null) {
|
||||
if (cryptoNetAccount.getCryptoNet() == CryptoNet.BITSHARES) {
|
||||
final ValidateExistBitsharesAccountRequest request = new ValidateExistBitsharesAccountRequest(toNewValue);
|
||||
request.setListener(new CryptoNetInfoRequestListener() {
|
||||
@Override
|
||||
public void onCarryOut() {
|
||||
if (!request.getAccountExists()) {
|
||||
setMessageForValue(mixedValue, validator.getContext().getResources().getString(R.string.account_name_not_exist, "'" + toNewValue + "'"));
|
||||
setValidForValue(mixedValue, false);
|
||||
} else {
|
||||
setValidForValue(mixedValue, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request);
|
||||
} else {
|
||||
//if (addressIsValid(toNewValue)) {
|
||||
setValidForValue(mixedValue, true);
|
||||
}
|
||||
//} else {
|
||||
// setMessageForValue(mixedValue, "Is not a valid address");
|
||||
// setValidForValue(mixedValue, false);
|
||||
//}
|
||||
}
|
||||
});
|
||||
CryptoNetInfoRequests.getInstance().addRequest(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -42,9 +43,11 @@ public class CryptoNetAccountAdapter extends ArrayAdapter<CryptoNetAccount> {
|
|||
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
View v = inflater.inflate(R.layout.crypto_net_account_adapter_item, parent, false);
|
||||
TextView tvCryptoNetAccountName = v.findViewById(R.id.tvCryptoNetAccountName);
|
||||
ImageView ivCryptoNetIcon = v.findViewById(R.id.ivCryptoNetIcon);
|
||||
|
||||
CryptoNetAccount cryptoNetAccount = getItem(position);
|
||||
tvCryptoNetAccountName.setText(cryptoNetAccount.getName());
|
||||
ivCryptoNetIcon.setImageResource(cryptoNetAccount.getCryptoNet().getIconImageResource());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ public class CryptoNetBalanceViewHolder extends RecyclerView.ViewHolder {
|
|||
} else {
|
||||
final CryptoNetBalanceViewHolder thisViewHolder = this;
|
||||
this.cryptoNetAccountId = balance.getAccountId();
|
||||
|
||||
this.cryptoNetIcon.setImageResource(balance.getCryptoNet().getIconImageResource());
|
||||
/*
|
||||
* The first letter should be in Uppercase
|
||||
* */
|
||||
|
|
BIN
app/src/main/res/drawable/coin_icon_bitcoin.png
Normal file
BIN
app/src/main/res/drawable/coin_icon_bitcoin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
app/src/main/res/drawable/coin_icon_dash.png
Normal file
BIN
app/src/main/res/drawable/coin_icon_dash.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
app/src/main/res/drawable/coin_icon_doge.png
Normal file
BIN
app/src/main/res/drawable/coin_icon_doge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
app/src/main/res/drawable/coin_icon_litecoin.png
Normal file
BIN
app/src/main/res/drawable/coin_icon_litecoin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
app/src/main/res/drawable/coin_icon_steem.png
Normal file
BIN
app/src/main/res/drawable/coin_icon_steem.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
|
@ -8,9 +8,27 @@
|
|||
android:paddingRight="10dp"
|
||||
android:paddingTop="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCryptoNetAccountName"
|
||||
android:layout_width="wrap_content"
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10" />
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true">
|
||||
<ImageView
|
||||
android:id="@+id/ivCryptoNetIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:maxHeight="28dp"
|
||||
android:maxWidth="28dp"
|
||||
app:srcCompat="@drawable/bts" />
|
||||
<TextView
|
||||
android:id="@+id/tvCryptoNetAccountName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_toRightOf="@id/ivCryptoNetIcon"
|
||||
android:ems="10"
|
||||
android:text="unknown coin" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
|
@ -46,7 +46,8 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.jaredrummler.materialspinner.MaterialSpinner
|
||||
<!--<com.jaredrummler.materialspinner.MaterialSpinner-->
|
||||
<Spinner
|
||||
android:id="@+id/spFrom"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
|
|
Loading…
Reference in a new issue