diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 1545559..e4528e8 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -14,7 +14,8 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
-
+
mResponseMap = new HashMap<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_htlc);
+
+ mHtlcMode = getIntent().getStringExtra(Constants.KEY_SELECTED_CALL);
+
+ FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
+ if(mHtlcMode.equals(CallsActivity.CREATE_HTLC)){
+ mCreateHtlcFragment = new CreateHtlcFragment();
+ mActiveBottomFragment = mCreateHtlcFragment;
+ }else{
+ mRedeemHtlcFragment = new RedeemHtlcFragment();
+ mActiveBottomFragment = mRedeemHtlcFragment;
+ }
+ fragmentTransaction.add(R.id.fragment_root, mActiveBottomFragment, "active-fragment").commit();
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ if(toolbar != null && mHtlcMode != null){
+ toolbar.setTitle(mHtlcMode.replace("_", " ").toUpperCase());
+ setSupportActionBar(toolbar);
+ }
+
+ // While for the real world is best to use a random pre-image, for testing purposes it is more
+ // convenient to make use of a fixed one.
+// SecureRandom secureRandom = new SecureRandom();
+// secureRandom.nextBytes(mPreimage);
+ mPreimage = Util.hexToBytes("efb79df9b0fd0d27b405e4decf9a2534efc1531f9e133915981fe27cd031ba32");
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.htlc_menu, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ this.switchHtlcMode();
+ return true;
+ }
+
+ @Override
+ public void onAttachFragment(Fragment fragment) {
+ super.onAttachFragment(fragment);
+ if(fragment instanceof CreateHtlcFragment){
+ mCreateHtlcFragment = (CreateHtlcFragment) fragment;
+ }
+ }
+
+ private void switchHtlcMode(){
+ if(mHtlcMode.equals(CallsActivity.CREATE_HTLC)){
+ mHtlcMode = CallsActivity.REDEEM_HTLC;
+ if(mRedeemHtlcFragment == null)
+ mRedeemHtlcFragment = new RedeemHtlcFragment();
+ mActiveBottomFragment = mRedeemHtlcFragment;
+ }else{
+ mHtlcMode = CallsActivity.CREATE_HTLC;
+ if(mCreateHtlcFragment == null)
+ mCreateHtlcFragment = new CreateHtlcFragment();
+ mActiveBottomFragment = mCreateHtlcFragment;
+ }
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.fragment_root, mActiveBottomFragment, "active-fragment")
+ .commit();
+
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ if(toolbar != null)
+ toolbar.setTitle(mHtlcMode.replace("_", " ").toUpperCase());
}
@Override
@@ -78,42 +163,55 @@ public class HtlcActivity extends ConnectedActivity implements CreateHtlcFragmen
@Override
public void onHtlcProposal(String from, String to, Double amount, Long timelock) {
- Log.d(TAG,"onHtlcProposal");
UserAccount sourceAccount = new UserAccount(from);
UserAccount destinationAccount = new UserAccount(to);
AssetAmount fee = new AssetAmount(UnsignedLong.valueOf("86726"), new Asset("1.3.0"));
AssetAmount operationAmount = new AssetAmount(UnsignedLong.valueOf(Double.valueOf(amount * 100000).longValue()), new Asset("1.3.0"));
- SecureRandom secureRandom = new SecureRandom();
- byte[] preimage = new byte[PREIMAGE_LENGTH];
- secureRandom.nextBytes(preimage);
try {
- byte[] hash = Util.htlcHash(preimage, HtlcHashType.RIPEMD160);
+ byte[] hash = Util.htlcHash(mPreimage, HtlcHashType.RIPEMD160);
HtlcHash htlcHash = new HtlcHash(HtlcHashType.RIPEMD160, hash);
// Creating a HTLC operation, used later.
createHtlcOperation = new CreateHtlcOperation(fee, sourceAccount, destinationAccount, operationAmount, htlcHash, PREIMAGE_LENGTH, timelock.intValue());
// Requesting dynamic network parameters
long id = mNetworkService.sendMessage(new GetDynamicGlobalProperties(), GetDynamicGlobalProperties.REQUIRED_API);
+ mResponseMap.put(id, CallsActivity.CREATE_HTLC);
Log.d(TAG,"sendMessage returned: " + id);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG,"NoSuchAlgorithmException while trying to create HTLC operation. Msg: " + e.getMessage());
}
}
+ @Override
+ public void onRedeemProposal(String userId, String htlcId) {
+ AssetAmount fee = new AssetAmount(UnsignedLong.valueOf("255128"), new Asset("1.3.0"));
+ UserAccount redeemer = new UserAccount(userId);
+ Htlc htlc = new Htlc(htlcId);
+ redeemHtlcOperation = new RedeemHtlcOperation(fee, redeemer, htlc, mPreimage);
+ long id = mNetworkService.sendMessage(new GetDynamicGlobalProperties(), GetDynamicGlobalProperties.REQUIRED_API);
+ mResponseMap.put(id, CallsActivity.REDEEM_HTLC);
+ Log.d(TAG,"sendMessage returned: " + id);
+ }
+
private void handleJsonRpcResponse(JsonRpcResponse jsonRpcResponse){
Log.d(TAG,"handleJsonRpcResponse");
if(jsonRpcResponse.error == null && jsonRpcResponse.result instanceof DynamicGlobalProperties){
DynamicGlobalProperties dynamicGlobalProperties = (DynamicGlobalProperties) jsonRpcResponse.result;
- Transaction tx = buildHltcTransaction(dynamicGlobalProperties);
+ Transaction tx = buildHltcTransaction(dynamicGlobalProperties, jsonRpcResponse.id);
long id = mNetworkService.sendMessage(new BroadcastTransaction(tx), BroadcastTransaction.REQUIRED_API);
Log.d(TAG,"sendMessage returned: " + id);
}
}
- private Transaction buildHltcTransaction(DynamicGlobalProperties dynamicProperties){
- // Deriving private key
- BrainKey brainKey = new BrainKey(">> Enter your own test Brainkey here <<", 0);
- ECKey privKey = brainKey.getPrivateKey();
- Address address = new Address(ECKey.fromPublicOnly(privKey.getPubKey()));
+ /**
+ * Private method used to build a transaction containing a specific HTLC operation.
+ *
+ * @param dynamicProperties The current dynamic properties.
+ * @param responseId The response id, used to decide whether to build a CREATE_HTLC or REDEEM_HTLC operation.
+ * @return A transaction that contains an HTLC operation.
+ */
+ private Transaction buildHltcTransaction(DynamicGlobalProperties dynamicProperties, long responseId){
+ // Private key, to be obtained differently below depending on which operation we'll be performing.
+ ECKey privKey = null;
// Use the valid BlockData just obtained from the blockchain
long expirationTime = (dynamicProperties.time.getTime() / 1000) + Transaction.DEFAULT_EXPIRATION_TIME;
@@ -123,7 +221,20 @@ public class HtlcActivity extends ConnectedActivity implements CreateHtlcFragmen
// Using the HTLC create operaton just obtained before
ArrayList operations = new ArrayList<>();
- operations.add(this.createHtlcOperation);
+
+ if(mResponseMap.get(responseId).equals(CallsActivity.CREATE_HTLC)){
+ // Deriving private key
+ BrainKey brainKey = new BrainKey(">> Place brainkey of HTLC creator here <<", 0);
+ privKey = brainKey.getPrivateKey();
+
+ operations.add(this.createHtlcOperation);
+ }else if(mResponseMap.get(responseId).equals(CallsActivity.REDEEM_HTLC)){
+ // Deriving private key
+ BrainKey brainKey = new BrainKey(">> Place brainkey of redeemer here <<", 0);
+ privKey = brainKey.getPrivateKey();
+
+ operations.add(this.redeemHtlcOperation);
+ }
// Return a newly built transaction
return new Transaction(privKey, blockData, operations);
diff --git a/sample/src/main/java/cy/agorise/labs/sample/fragments/CreateHtlcFragment.java b/sample/src/main/java/cy/agorise/labs/sample/fragments/CreateHtlcFragment.java
index f332365..b78573e 100644
--- a/sample/src/main/java/cy/agorise/labs/sample/fragments/CreateHtlcFragment.java
+++ b/sample/src/main/java/cy/agorise/labs/sample/fragments/CreateHtlcFragment.java
@@ -5,7 +5,6 @@ import android.content.Context;
import android.os.Bundle;
import android.support.design.widget.TextInputEditText;
import android.support.v4.app.Fragment;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -34,8 +33,8 @@ public class CreateHtlcFragment extends Fragment {
@BindView(R.id.timelock)
TextInputEditText timelockField;
- // Parent activity, which must implement the HtlcListener interface.
- private HtlcListener mListener;
+ // Parent activity, which must implement the CreateHtlcListener interface.
+ private CreateHtlcListener mListener;
public CreateHtlcFragment() {
// Required empty public constructor
@@ -52,7 +51,6 @@ public class CreateHtlcFragment extends Fragment {
@OnClick(R.id.button_create)
public void onSendClicked(View v){
- Log.d(TAG,"onSendClicked");
String from = fromField.getText().toString();
String to = toField.getText().toString();
Double amount = null;
@@ -67,7 +65,6 @@ public class CreateHtlcFragment extends Fragment {
}catch(NumberFormatException e){
timelockField.setError("Invalid value");
}
- Log.d(TAG,"amount: " + amount + ", timelock: " + timeLock);
if(amount != null && timeLock != null){
Toast.makeText(getContext(), "Should be sending message up", Toast.LENGTH_SHORT).show();
mListener.onHtlcProposal(from, to, amount, timeLock);
@@ -77,17 +74,17 @@ public class CreateHtlcFragment extends Fragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- if(context instanceof HtlcListener){
- mListener = (HtlcListener) context;
+ if(context instanceof CreateHtlcListener){
+ mListener = (CreateHtlcListener) context;
}else{
- throw new ClassCastException(context.toString() + " must implement the HtlcListener interface!");
+ throw new ClassCastException(context.toString() + " must implement the CreateHtlcListener interface!");
}
}
/**
* Interface to be implemented by the parent activity.
*/
- public interface HtlcListener {
+ public interface CreateHtlcListener {
/**
* Method used to notify the parent activity of the request to create an HTLC with the following parameters.
*
diff --git a/sample/src/main/java/cy/agorise/labs/sample/fragments/RedeemHtlcFragment.java b/sample/src/main/java/cy/agorise/labs/sample/fragments/RedeemHtlcFragment.java
new file mode 100644
index 0000000..621da5e
--- /dev/null
+++ b/sample/src/main/java/cy/agorise/labs/sample/fragments/RedeemHtlcFragment.java
@@ -0,0 +1,75 @@
+package cy.agorise.labs.sample.fragments;
+
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.design.widget.TextInputEditText;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+import cy.agorise.labs.sample.R;
+
+/**
+ * A simple {@link Fragment} subclass.
+ */
+public class RedeemHtlcFragment extends Fragment {
+
+ @BindView(R.id.redeemer)
+ TextInputEditText mRedeemer;
+
+ @BindView(R.id.htlc_id)
+ TextInputEditText mHtlcId;
+
+ // Parent activity, which must implement the RedeemHtlcListener interface.
+ private RedeemHtlcListener mListener;
+
+
+ public RedeemHtlcFragment() {
+ // Required empty public constructor
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_redeem_htlc, container, false);
+ ButterKnife.bind(this, view);
+ return view;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if(context instanceof RedeemHtlcListener){
+ mListener = (RedeemHtlcListener) context;
+ }else{
+ throw new ClassCastException(context.toString() + " must implement the RedeemHtlcListener interface!");
+ }
+ }
+
+ @OnClick(R.id.button_create)
+ public void onSendClicked(View v){
+ String redeemerId = mRedeemer.getText().toString();
+ String htlcId = mHtlcId.getText().toString();
+ Toast.makeText(getContext(), "Should be sending message up", Toast.LENGTH_SHORT).show();
+ mListener.onRedeemProposal(redeemerId, htlcId);
+ }
+
+ /**
+ * Interface to be implemented by the parent activity.
+ */
+ public interface RedeemHtlcListener {
+ /**
+ * Method used to notify the parent activity about the creation of an HTLC redeem operation.
+ *
+ * @param userId The id of the user that wishes to redeem an HTLC.
+ * @param htlcId The HTLC id.
+ */
+ void onRedeemProposal(String userId, String htlcId);
+ }
+}
diff --git a/sample/src/main/res/drawable/ic_switch_hltc_mode.xml b/sample/src/main/res/drawable/ic_switch_hltc_mode.xml
new file mode 100644
index 0000000..9908c1e
--- /dev/null
+++ b/sample/src/main/res/drawable/ic_switch_hltc_mode.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/sample/src/main/res/layout/activity_htlc.xml b/sample/src/main/res/layout/activity_htlc.xml
index 9269ed0..34e4bdd 100644
--- a/sample/src/main/res/layout/activity_htlc.xml
+++ b/sample/src/main/res/layout/activity_htlc.xml
@@ -3,16 +3,26 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".HtlcActivity">
+
-
+ android:layout_weight="0.6">
+
\ No newline at end of file
diff --git a/sample/src/main/res/layout/fragment_create_htlc.xml b/sample/src/main/res/layout/fragment_create_htlc.xml
index 493dab7..266ddc6 100644
--- a/sample/src/main/res/layout/fragment_create_htlc.xml
+++ b/sample/src/main/res/layout/fragment_create_htlc.xml
@@ -5,6 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
+ android:clickable="false"
tools:context=".fragments.CreateHtlcFragment">
+ android:text="1.2.143563" />
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/menu/htlc_menu.xml b/sample/src/main/res/menu/htlc_menu.xml
new file mode 100644
index 0000000..200aab7
--- /dev/null
+++ b/sample/src/main/res/menu/htlc_menu.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml
index 3ab3e9c..42288e1 100644
--- a/sample/src/main/res/values/colors.xml
+++ b/sample/src/main/res/values/colors.xml
@@ -3,4 +3,6 @@
#3F51B5
#303F9F
#FF4081
+
+ #FFFFFF
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
index f545f33..d8f51d0 100644
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -76,4 +76,8 @@
To account
Amount
Time to lock (in seconds)
+
+
+ Redeemer user id
+ HTLC id