From 0cba6a9f8df574bea33b414245d0cc38846d0c4a Mon Sep 17 00:00:00 2001 From: "Nelson R. Perez" Date: Thu, 6 Dec 2018 19:17:32 -0500 Subject: [PATCH] Added support for the broadcast_transaction API call in the single connection mode --- .../api/calls/BroadcastTransaction.java | 27 +++++++++++ sample/build.gradle | 3 +- .../cy/agorise/labs/sample/CallsActivity.java | 1 + .../labs/sample/PerformCallActivity.java | 48 ++++++++++++++++++- 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 graphenej/src/main/java/cy/agorise/graphenej/api/calls/BroadcastTransaction.java diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/calls/BroadcastTransaction.java b/graphenej/src/main/java/cy/agorise/graphenej/api/calls/BroadcastTransaction.java new file mode 100644 index 0000000..8dc1ba5 --- /dev/null +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/calls/BroadcastTransaction.java @@ -0,0 +1,27 @@ +package cy.agorise.graphenej.api.calls; + +import java.io.Serializable; +import java.util.ArrayList; + +import cy.agorise.graphenej.RPC; +import cy.agorise.graphenej.Transaction; +import cy.agorise.graphenej.api.ApiAccess; +import cy.agorise.graphenej.models.ApiCall; + +public class BroadcastTransaction implements ApiCallable { + public static final int REQUIRED_API = ApiAccess.API_NETWORK_BROADCAST; + + private Transaction mTransaction; + + public BroadcastTransaction(Transaction transaction){ + if(!transaction.hasPrivateKey()) throw new IllegalStateException("The Transaction instance has to be provided with a private key in order to be broadcasted"); + mTransaction = transaction; + } + + @Override + public ApiCall toApiCall(int apiId, long sequenceId) { + ArrayList transactions = new ArrayList<>(); + transactions.add(mTransaction); + return new ApiCall(apiId, RPC.CALL_BROADCAST_TRANSACTION, transactions, RPC.VERSION, sequenceId); + } +} diff --git a/sample/build.gradle b/sample/build.gradle index de76e02..1ca3102 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -29,7 +29,8 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - api project(':graphenej') + implementation project(':graphenej') + implementation 'org.bitcoinj:bitcoinj-core:0.14.3' implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'com.android.support:design:27.1.1' diff --git a/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java b/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java index 28f2e0d..0066bfb 100644 --- a/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java +++ b/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java @@ -78,6 +78,7 @@ public class CallsActivity extends AppCompatActivity { RPC.CALL_GET_DYNAMIC_GLOBAL_PROPERTIES, RPC.CALL_GET_KEY_REFERENCES, RPC.CALL_GET_ACCOUNT_BALANCES, + RPC.CALL_BROADCAST_TRANSACTION, REMOVE_CURRENT_NODE }; diff --git a/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java b/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java index 052c653..651a4a0 100644 --- a/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java +++ b/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java @@ -17,6 +17,8 @@ import com.google.common.primitives.UnsignedLong; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import org.bitcoinj.core.ECKey; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -28,13 +30,17 @@ import butterknife.OnClick; 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.Memo; import cy.agorise.graphenej.OperationType; import cy.agorise.graphenej.RPC; +import cy.agorise.graphenej.Transaction; import cy.agorise.graphenej.UserAccount; import cy.agorise.graphenej.api.ConnectionStatusUpdate; import cy.agorise.graphenej.api.android.DeserializationMap; import cy.agorise.graphenej.api.android.RxBus; +import cy.agorise.graphenej.api.calls.BroadcastTransaction; import cy.agorise.graphenej.api.calls.GetAccountBalances; import cy.agorise.graphenej.api.calls.GetAccountByName; import cy.agorise.graphenej.api.calls.GetAccountHistoryByOperations; @@ -50,6 +56,7 @@ import cy.agorise.graphenej.api.calls.ListAssets; import cy.agorise.graphenej.errors.MalformedAddressException; import cy.agorise.graphenej.models.JsonRpcResponse; import cy.agorise.graphenej.operations.TransferOperation; +import cy.agorise.graphenej.operations.TransferOperationBuilder; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; @@ -155,6 +162,9 @@ public class PerformCallActivity extends ConnectedActivity { break; case RPC.CALL_GET_ACCOUNT_BALANCES: setupGetAccountBalances(); + break; + case RPC.CALL_BROADCAST_TRANSACTION: + setupBroadcastTransaction(); default: Log.d(TAG,"Default called"); } @@ -291,6 +301,12 @@ public class PerformCallActivity extends ConnectedActivity { param2.setHint(R.string.get_account_balances_arg2); } + private void setupBroadcastTransaction(){ + requiredInput(2); + param1.setText("1.2.116354"); + param2.setText("1"); + } + private void requiredInput(int inputCount){ if(inputCount == 0){ mParam1View.setVisibility(View.GONE); @@ -365,6 +381,9 @@ public class PerformCallActivity extends ConnectedActivity { break; case RPC.CALL_GET_ACCOUNT_BALANCES: getAccountBalances(); + break; + case RPC.CALL_BROADCAST_TRANSACTION: + broadcastTransaction(); default: Log.d(TAG,"Default called"); } @@ -486,6 +505,28 @@ public class PerformCallActivity extends ConnectedActivity { responseMap.put(id, mRPC); } + private void broadcastTransaction(){ + String destinationId = param1.getText().toString(); + String amount = param2.getText().toString(); + UnsignedLong transferAmount = UnsignedLong.valueOf(amount).times(UnsignedLong.valueOf(100000)); + TransferOperation operation = new TransferOperationBuilder() + .setSource(new UserAccount("1.2.1029856")) + .setDestination(new UserAccount(destinationId)) + .setTransferAmount(new AssetAmount( transferAmount, new Asset("1.3.0"))) + .setFee(new AssetAmount(UnsignedLong.valueOf("10420"), new Asset("1.3.0"))) + .build(); + ArrayList ops = new ArrayList<>(); + ops.add(operation); + // >> Replace with your brainkey << + BrainKey brainKey = new BrainKey(">> Place your brainkey here <<", 0); + ECKey privKey = brainKey.getPrivateKey(); + // Use valid BlockData + BlockData blockData = new BlockData(44542, 3342959171L, 1544917202L); + Transaction tx = new Transaction(privKey, blockData, ops); + long id = mNetworkService.sendMessage(new BroadcastTransaction(tx), BroadcastTransaction.REQUIRED_API); + responseMap.put(id, mRPC); + } + /** * Internal method that will decide what to do with each JSON-RPC response * @@ -521,7 +562,12 @@ public class PerformCallActivity extends ConnectedActivity { break; default: Log.w(TAG,"Case not handled"); - mResponseView.setText(mResponseView.getText() + response.result.toString()); + if(response.result != null) + mResponseView.setText(mResponseView.getText() + response.result.toString()); + else if(response.error != null) + mResponseView.setText(mResponseView.getText() + String.format("Error code: %d, Msg: %s", response.error.code, response.error.message)); + else + mResponseView.setText(mResponseView.getText() + "\nnull"); } // Remember to remove the used id entry from the map, as it would // otherwise just increase the app's memory usage