diff --git a/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java b/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java index cecaca0..79867b9 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java +++ b/app/src/main/java/cy/agorise/crystalwallet/apigenerator/GrapheneApiGenerator.java @@ -8,13 +8,19 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import cy.agorise.crystalwallet.models.BitsharesAsset; import cy.agorise.crystalwallet.network.WebSocketThread; import cy.agorise.graphenej.Address; +import cy.agorise.graphenej.Asset; +import cy.agorise.graphenej.Transaction; import cy.agorise.graphenej.UserAccount; import cy.agorise.graphenej.api.GetAccountByName; import cy.agorise.graphenej.api.GetAccounts; import cy.agorise.graphenej.api.GetKeyReferences; import cy.agorise.graphenej.api.GetRelativeAccountHistory; +import cy.agorise.graphenej.api.ListAssets; +import cy.agorise.graphenej.api.LookupAssetSymbols; +import cy.agorise.graphenej.api.TransactionBroadcastSequence; import cy.agorise.graphenej.interfaces.WitnessResponseListener; import cy.agorise.graphenej.models.AccountProperties; import cy.agorise.graphenej.models.BaseResponse; @@ -31,7 +37,6 @@ public class GrapheneApiGenerator { //TODO network connections //TODO make to work with all Graphene stype, not only bitshares - private static int connectionTimeout = 5000; private static String url = "http://128.0.69.157:8090"; /** @@ -143,4 +148,105 @@ public class GrapheneApiGenerator { }),url); thread.start(); } + + public static void broadcastTransaction(Transaction transaction, Asset feeAsset, final ApiRequest request){ + WebSocketThread thread = new WebSocketThread(new TransactionBroadcastSequence(transaction, feeAsset, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + request.getListener().success(true,request.getId()); + } + + @Override + public void onError(BaseResponse.Error error) { + request.getListener().fail(request.getId()); + } + }),url); + thread.start(); + } + + public static void getAssetByName(ArrayList assetNames, final ApiRequest request){ + //TODO the graphenej library needs a way to creates the Asset object only with the symbol + ArrayList assets = new ArrayList<>(); + for(String assetName : assetNames){ + Asset asset = new Asset("",assetName,-1); + assets.add(asset); + } + //TODO the graphenj library needs to add the lookupAssetSymbols to be able to search the asset by symbol + // this can be done with the same lookupassetsymbol, but passing only the symbol not the objetcid + WebSocketThread thread = new WebSocketThread(new LookupAssetSymbols(assets, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + List assets = (List) response.result; + if(assets.size() <= 0){ + request.getListener().fail(request.getId()); + }else{ + ArrayList responseAssets = new ArrayList<>(); + for(Asset asset: assets){ + BitsharesAsset.Type assetType = null; + if(asset.getAssetType().equals(Asset.AssetType.CORE_ASSET)){ + assetType = BitsharesAsset.Type.CORE; + }else if(asset.getAssetType().equals(Asset.AssetType.SMART_COIN)){ + assetType = BitsharesAsset.Type.SMART_COIN; + }else if(asset.getAssetType().equals(Asset.AssetType.UIA)){ + assetType = BitsharesAsset.Type.UIA; + }else if(asset.getAssetType().equals(Asset.AssetType.PREDICTION_MARKET)){ + assetType = BitsharesAsset.Type.PREDICTION_MARKET; + } + BitsharesAsset responseAsset = new BitsharesAsset(asset.getSymbol(),asset.getPrecision(),asset.getObjectId(),assetType); + responseAssets.add(responseAsset); + } + request.getListener().success(responseAssets,request.getId()); + } + } + + @Override + public void onError(BaseResponse.Error error) { + request.getListener().fail(request.getId()); + } + }),url); + thread.start(); + } + + public static void getAssetById(ArrayList assetIds, final ApiRequest request){ + //TODO the graphenej library needs a way to creates the Asset object only with the symbol + ArrayList assets = new ArrayList<>(); + for(String assetId : assetIds){ + Asset asset = new Asset(assetId); + assets.add(asset); + } + //TODO the graphenj library needs to add the lookupAssetSymbols to be able to search the asset by symbol + // this can be done with the same lookupassetsymbol, but passing only the symbol not the objetcid + WebSocketThread thread = new WebSocketThread(new LookupAssetSymbols(assets, new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + List assets = (List) response.result; + if(assets.size() <= 0){ + request.getListener().fail(request.getId()); + }else{ + ArrayList responseAssets = new ArrayList<>(); + for(Asset asset: assets){ + BitsharesAsset.Type assetType = null; + if(asset.getAssetType().equals(Asset.AssetType.CORE_ASSET)){ + assetType = BitsharesAsset.Type.CORE; + }else if(asset.getAssetType().equals(Asset.AssetType.SMART_COIN)){ + assetType = BitsharesAsset.Type.SMART_COIN; + }else if(asset.getAssetType().equals(Asset.AssetType.UIA)){ + assetType = BitsharesAsset.Type.UIA; + }else if(asset.getAssetType().equals(Asset.AssetType.PREDICTION_MARKET)){ + assetType = BitsharesAsset.Type.PREDICTION_MARKET; + } + BitsharesAsset responseAsset = new BitsharesAsset(asset.getSymbol(),asset.getPrecision(),asset.getObjectId(),assetType); + responseAssets.add(responseAsset); + } + request.getListener().success(responseAssets,request.getId()); + } + } + + @Override + public void onError(BaseResponse.Error error) { + request.getListener().fail(request.getId()); + } + }),url); + thread.start(); + } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/cryptonetinforequests/ValidateBitsharesSendRequest.java b/app/src/main/java/cy/agorise/crystalwallet/cryptonetinforequests/ValidateBitsharesSendRequest.java new file mode 100644 index 0000000..3a985f5 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/cryptonetinforequests/ValidateBitsharesSendRequest.java @@ -0,0 +1,82 @@ +package cy.agorise.crystalwallet.cryptonetinforequests; + +import cy.agorise.crystalwallet.enums.CryptoCoin; + +/** + * Created by henry on 8/10/2017. + */ + +public class ValidateBitsharesSendRequest extends CryptoNetInfoRequest { + private String mSourceAccount; + private String mToAccount; + private long mBaseAmount; + private String mBaseAsset; + private long mFeeAmount; + private String mFeeAsset; + private String mMemo; + + + private Boolean isSend; + + public ValidateBitsharesSendRequest(CryptoCoin coin, String sourceAccount, String toAccount, + long baseAmount, String baseAsset, long feeAmount, + String feeAsset, String memo) { + super(coin); + this.mSourceAccount = sourceAccount; + this.mToAccount = toAccount; + this.mBaseAmount = baseAmount; + this.mBaseAsset = baseAsset; + this.mFeeAmount = feeAmount; + this.mFeeAsset = feeAsset; + this.mMemo = memo; + } + + public ValidateBitsharesSendRequest(CryptoCoin coin, String sourceAccount, String toAccount, + long baseAmount, String baseAsset, long feeAmount, + String feeAsset) { + this(coin,sourceAccount,toAccount,baseAmount,baseAsset,feeAmount,feeAsset,null); + } + + public String getSourceAccount() { + return mSourceAccount; + } + + public String getToAccount() { + return mToAccount; + } + + public long getBaseAmount() { + return mBaseAmount; + } + + public String getBaseAsset() { + return mBaseAsset; + } + + public long getFeeAmount() { + return mFeeAmount; + } + + public String getFeeAsset() { + return mFeeAsset; + } + + public String getMemo() { + return mMemo; + } + + public boolean isSend() { + return isSend; + } + + public void setSend(boolean send) { + isSend = send; + this.validate(); + } + + public void validate(){ + if ((this.isSend != null)){ + this._fireOnCarryOutEvent(); + } + } +} diff --git a/app/src/main/java/cy/agorise/crystalwallet/manager/BitsharesAccountManager.java b/app/src/main/java/cy/agorise/crystalwallet/manager/BitsharesAccountManager.java index a5ba668..a2f8e7a 100644 --- a/app/src/main/java/cy/agorise/crystalwallet/manager/BitsharesAccountManager.java +++ b/app/src/main/java/cy/agorise/crystalwallet/manager/BitsharesAccountManager.java @@ -1,17 +1,32 @@ package cy.agorise.crystalwallet.manager; +import com.google.common.primitives.UnsignedLong; + +import org.bitcoinj.core.ECKey; + +import java.util.ArrayList; + import cy.agorise.crystalwallet.apigenerator.ApiRequest; import cy.agorise.crystalwallet.apigenerator.ApiRequestListener; import cy.agorise.crystalwallet.apigenerator.GrapheneApiGenerator; import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequest; import cy.agorise.crystalwallet.cryptonetinforequests.CryptoNetInfoRequestsListener; +import cy.agorise.crystalwallet.cryptonetinforequests.ValidateBitsharesSendRequest; import cy.agorise.crystalwallet.cryptonetinforequests.ValidateExistBitsharesAccountRequest; import cy.agorise.crystalwallet.cryptonetinforequests.ValidateImportBitsharesAccountRequest; import cy.agorise.crystalwallet.models.CryptoNetAccount; import cy.agorise.graphenej.Address; +import cy.agorise.graphenej.Asset; +import cy.agorise.graphenej.AssetAmount; +import cy.agorise.graphenej.BaseOperation; +import cy.agorise.graphenej.BlockData; 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.operations.TransferOperation; +import cy.agorise.graphenej.operations.TransferOperationBuilder; /** * Created by henry on 26/9/2017. @@ -36,61 +51,98 @@ 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); + } + } - final ValidateImportBitsharesAccountRequest importRequest = (ValidateImportBitsharesAccountRequest) request; - ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() { - @Override - public void success(Object answer, int idPetition) { - importRequest.setAccountExists(true); - 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; - //TODO change the way to compare keys + private void validateImportAccount(final ValidateImportBitsharesAccountRequest importRequest){ + ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() { + @Override + public void success(Object answer, int idPetition) { + importRequest.setAccountExists(true); + 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; + //TODO change the way to compare keys - BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0); - for(PublicKey activeKey : prop.active.getKeyAuthList()){ + BrainKey bk = new BrainKey(importRequest.getMnemonic(), 0); + for(PublicKey activeKey : prop.active.getKeyAuthList()){ if((new Address(activeKey.getKey(),"BTS")).toString().equals(bk.getPublicAddress("BTS").toString())){ importRequest.setMnemonicIsCorrect(true); return; } - } - importRequest.setMnemonicIsCorrect(false); } - + importRequest.setMnemonicIsCorrect(false); } - @Override - public void fail(int idPetition) { - // - } - }); - GrapheneApiGenerator.getAccountById((String)answer,getAccountInfo); - } + } - @Override - public void fail(int idPetition) { - // - } - }); + @Override + public void fail(int idPetition) { + // + } + }); + GrapheneApiGenerator.getAccountById((String)answer,getAccountInfo); + } - GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),checkAccountName); - } else if (request instanceof ValidateExistBitsharesAccountRequest){ - final ValidateExistBitsharesAccountRequest importRequest = (ValidateExistBitsharesAccountRequest) request; - ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() { - @Override - public void success(Object answer, int idPetition) { - importRequest.setAccountExists(true); - } + @Override + public void fail(int idPetition) { + // + } + }); - @Override - public void fail(int idPetition) { - //TODO verified - importRequest.setAccountExists(false); - } - }); - GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),checkAccountName); - } + GrapheneApiGenerator.getAccountIdByName(importRequest.getAccountName(),checkAccountName); + } + + private void validateExistAcccount(final ValidateExistBitsharesAccountRequest validateRequest){ + ApiRequest checkAccountName = new ApiRequest(0, new ApiRequestListener() { + @Override + public void success(Object answer, int idPetition) { + validateRequest.setAccountExists(true); + } + + @Override + public void fail(int idPetition) { + //TODO verified + validateRequest.setAccountExists(false); + } + }); + GrapheneApiGenerator.getAccountIdByName(validateRequest.getAccountName(),checkAccountName); + } + + private void validateSendRequest(final ValidateBitsharesSendRequest sendRequest){ + Asset feeAsset = new Asset(sendRequest.getFeeAsset()); + TransferOperationBuilder builder = new TransferOperationBuilder() + .setSource(new UserAccount(sendRequest.getSourceAccount())) + .setDestination(new UserAccount(sendRequest.getToAccount())) + .setTransferAmount(new AssetAmount(UnsignedLong.valueOf(sendRequest.getBaseAmount()), new Asset(sendRequest.getBaseAsset()))) + .setFee(new AssetAmount(UnsignedLong.valueOf(sendRequest.getFeeAmount()), feeAsset)); + //TODO memo + ArrayList operationList = new ArrayList(); + operationList.add(builder.build()); + + //TODO blockdata + BlockData blockData = null; + //TODO privateKey + ECKey privateKey = null; + Transaction transaction = new Transaction(privateKey, blockData, operationList); + + ApiRequest transactionRequest = new ApiRequest(0, new ApiRequestListener() { + @Override + public void success(Object answer, int idPetition) { + sendRequest.setSend(true); + } + + @Override + public void fail(int idPetition) { + sendRequest.setSend(false); + } + }); + + GrapheneApiGenerator.broadcastTransaction(transaction,feeAsset, transactionRequest); } } diff --git a/app/src/main/java/cy/agorise/crystalwallet/models/BitsharesAsset.java b/app/src/main/java/cy/agorise/crystalwallet/models/BitsharesAsset.java new file mode 100644 index 0000000..fbff981 --- /dev/null +++ b/app/src/main/java/cy/agorise/crystalwallet/models/BitsharesAsset.java @@ -0,0 +1,63 @@ +package cy.agorise.crystalwallet.models; + +import cy.agorise.crystalwallet.enums.CryptoNet; + +/** + * Created by henry on 8/10/2017. + */ + +public class BitsharesAsset extends CryptoCurrency { + + // The bitshares internal id + private String bitsharesId; + // The bitshares type see the enum below + private Type assetType; + + /** + * For representing each type of asset in the bitshares network + */ + public enum Type{ + // The core asset aka BTS + CORE(0), + // the smartcoin assets, like bitEUR, bitUSD + SMART_COIN(1), + // The UIA assets type + UIA(2), + //THe prediction market type + PREDICTION_MARKET(3); + + private int code; + + /** + * The code is used for be stored in the database + */ + Type(int code) { + this.code = code; + } + + } + + public BitsharesAsset(String symbol, int precision, String bitsharesId, Type assetType) { + this.bitsharesId = bitsharesId; + this.assetType = assetType; + this.setCryptoNet(CryptoNet.BITSHARES); + this.setName(symbol); + this.setPrecision(precision); + } + + public String getBitsharesId() { + return bitsharesId; + } + + public void setBitsharesId(String bitsharesId) { + this.bitsharesId = bitsharesId; + } + + public Type getAssetType() { + return assetType; + } + + public void setAssetType(Type assetType) { + this.assetType = assetType; + } +}