diff --git a/app/src/main/java/com/flashwifi/wifip2p/Constants.java b/app/src/main/java/com/flashwifi/wifip2p/Constants.java new file mode 100644 index 0000000..07b2e53 --- /dev/null +++ b/app/src/main/java/com/flashwifi/wifip2p/Constants.java @@ -0,0 +1,20 @@ +package com.flashwifi.wifip2p; + +/** + * Created by daniel on 23.01.18. + */ + +public class Constants { + public interface ACTION { + public static String MAIN_ACTION = "com.flashwifi.wifip2p.service.main"; + public static String PREV_ACTION = "com.flashwifi.wifip2p.service.prev"; + public static String PLAY_ACTION = "com.flashwifi.wifip2p.service.play"; + public static String NEXT_ACTION = "com.flashwifi.wifip2p.service.next"; + public static String STARTFOREGROUND_ACTION = "com.flashwifi.wifip2p.start_foreground_service"; + public static String STOPFOREGROUND_ACTION = "com.flashwifi.wifip2p.sop_foreground_service"; + } + + public interface NOTIFICATION_ID { + public static int FOREGROUND_SERVICE = 101; + } +} diff --git a/app/src/main/java/com/flashwifi/wifip2p/FundWalletFragment.java b/app/src/main/java/com/flashwifi/wifip2p/FundWalletFragment.java index e45b83a..54ef4fc 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/FundWalletFragment.java +++ b/app/src/main/java/com/flashwifi/wifip2p/FundWalletFragment.java @@ -85,7 +85,7 @@ public class FundWalletFragment extends Fragment { transactionInProgress = false; if(returnStatus.equals("noError")){ - balanceTextView.setText(balance + " i"); + balanceTextView.setText(balance); addressTextView.setText(depositAddress); createAddressQRCode(depositAddress); makeToastFundWalletFragment("Balance and address updated"); diff --git a/app/src/main/java/com/flashwifi/wifip2p/HomeActivity.java b/app/src/main/java/com/flashwifi/wifip2p/HomeActivity.java index bb98373..78b48ed 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/HomeActivity.java +++ b/app/src/main/java/com/flashwifi/wifip2p/HomeActivity.java @@ -23,10 +23,8 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import com.flashwifi.wifip2p.iotaFlashWrapper.Example; import com.flashwifi.wifip2p.iotaFlashWrapper.IotaFlashBridge; -import com.flashwifi.wifip2p.iotaFlashWrapper.Main; -import com.google.common.base.Charsets; -import com.google.common.io.CharStreams; import com.pddstudio.preferences.encrypted.EncryptedPreferences; import java.io.BufferedReader; @@ -102,14 +100,16 @@ public class HomeActivity extends AppCompatActivity { String iotaflash = readFile("iotaflash"); String iotaflashhelper = readFile("iotaflashhelper"); - /*try { + try { IotaFlashBridge.boot(iotaflash, iotaflashhelper); - Main.runExample(); + Example.setup(); + Example.transaction(Example.one, Example.two); + Example.close(Example.one, Example.two); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); - }*/ + } } @Override diff --git a/app/src/main/java/com/flashwifi/wifip2p/HotspotFragment.java b/app/src/main/java/com/flashwifi/wifip2p/HotspotFragment.java index 0e5ad17..2fe6000 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/HotspotFragment.java +++ b/app/src/main/java/com/flashwifi/wifip2p/HotspotFragment.java @@ -34,8 +34,6 @@ public class HotspotFragment extends Fragment { private int numberConnectedPeers = 0; - WiFiDirectBroadcastService mService; - boolean mBound = false; BroadcastReceiver updateUIReceiver; public HotspotFragment() { @@ -73,7 +71,7 @@ public class HotspotFragment extends Fragment { private void updateUi(Intent intent) { Log.d(TAG, "updateUi: Got some network data into the hotspot fragment"); - String numberAvailableDevices = Integer.toString(mService.getArrayList().size()); + String numberAvailableDevices = Integer.toString(getmService().getArrayList().size()); TextView text = (TextView) getActivity().findViewById(R.id.numberPeers); text.setVisibility(View.VISIBLE); text.setText(String.format("%s peers", numberAvailableDevices)); @@ -81,9 +79,9 @@ public class HotspotFragment extends Fragment { //if (intent.hasExtra("what") && intent.getExtras().getString("what", "").equals("connectivity_changed")) { - NetworkInfo network_info = mService.getNetwork_info(); - WifiP2pInfo p2p_info = mService.getP2p_info(); - WifiP2pGroup wifiP2pGroup = mService.getP2p_group(); + NetworkInfo network_info = getmService().getNetwork_info(); + WifiP2pInfo p2p_info = getmService().getP2p_info(); + WifiP2pGroup wifiP2pGroup = getmService().getP2p_group(); if (intent.hasExtra("currentDeviceConnected")) { //String macAddress = intent.getExtras().getString("currentDeviceConnected"); @@ -92,11 +90,11 @@ public class HotspotFragment extends Fragment { if (p2p_info.isGroupOwner) { Snackbar.make(activity_view, "You are the group owner", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - mService.startNegotiationServer(false, null); + getmService().startNegotiationServer(false, null); } else { InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress; Snackbar.make(activity_view, "You are only a member of the group", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - mService.startNegotiationClient(groupOwnerAddress, false, null); + getmService().startNegotiationClient(groupOwnerAddress, false, null); } } @@ -111,9 +109,7 @@ public class HotspotFragment extends Fragment { @Override public void onStop() { super.onStop(); - getActivity().unbindService(mConnection); getActivity().unregisterReceiver(updateUIReceiver); - mBound = false; } @Override @@ -129,6 +125,11 @@ public class HotspotFragment extends Fragment { initFragment(); } + public WiFiDirectBroadcastService getmService() { + MainActivity act = (MainActivity) getActivity(); + return act.getmService(); + } + private void initFragment(){ IntentFilter filter = new IntentFilter(); filter.addAction("com.flashwifi.wifip2p.update_ui"); @@ -138,6 +139,10 @@ public class HotspotFragment extends Fragment { updateUIReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (getActivity() == null) { + Log.d(TAG, "onReceive: getActivity is null"); + return; + } if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) { String mac = intent.getStringExtra("peer_mac_address"); ToggleButton toggle = (ToggleButton) getActivity().findViewById(R.id.startAPButton); @@ -157,10 +162,6 @@ public class HotspotFragment extends Fragment { getActivity().registerReceiver(updateUIReceiver, filter); - // Bind to Service - Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class); - getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - initUI(); testInternetConnection(); @@ -185,29 +186,13 @@ public class HotspotFragment extends Fragment { // ToDo: Move this to a async task //boolean status = (isNetworkConnected() && isInternetAvailable()); } - - private boolean isNetworkConnected() { - ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); - - return cm.getActiveNetworkInfo() != null; - } - - public boolean isInternetAvailable() { - try { - InetAddress ipAddr = InetAddress.getByName("google.com"); - return !ipAddr.getHostAddress().equals(""); - - } catch (Exception e) { - return false; - } - } private void startDiscovery() { final View activity_view = getActivity().findViewById(R.id.drawer_layout); - if (mBound) { - mService.setInRoleConsumer(false); - mService.setInRoleHotspot(true); - mService.getPeerList(new WifiP2pManager.ActionListener() { + if (getmService() != null) { + getmService().setInRoleConsumer(false); + getmService().setInRoleHotspot(true); + getmService().getPeerList(new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // show progress wheel @@ -228,12 +213,12 @@ public class HotspotFragment extends Fragment { private void stopDiscovery() { final View activity_view = getActivity().findViewById(R.id.drawer_layout); - if (mBound) { - mService.stopDiscovery(new WifiP2pManager.ActionListener() { + if (getmService() != null) { + getmService().stopDiscovery(new WifiP2pManager.ActionListener() { @Override public void onSuccess() { - mService.setInRoleConsumer(false); - mService.setInRoleHotspot(false); + getmService().setInRoleConsumer(false); + getmService().setInRoleHotspot(false); Snackbar.make(activity_view, "Stopped Hotspot mode", Snackbar.LENGTH_LONG).setAction("Action", null).show(); ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP); progressBar.setVisibility(View.INVISIBLE); @@ -241,8 +226,8 @@ public class HotspotFragment extends Fragment { @Override public void onFailure(int reasonCode) { - mService.setInRoleConsumer(false); - mService.setInRoleHotspot(false); + getmService().setInRoleConsumer(false); + getmService().setInRoleHotspot(false); Snackbar.make(activity_view, "Aaaargh :( Problem stopping discovery", Snackbar.LENGTH_LONG).setAction("Action", null).show(); ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP); progressBar.setVisibility(View.INVISIBLE); @@ -255,12 +240,11 @@ public class HotspotFragment extends Fragment { private void initUI() { final View activity_view = getActivity().findViewById(R.id.drawer_layout); final ToggleButton button = (ToggleButton) getActivity().findViewById(R.id.startAPButton); - //button.setChecked(mService.isInRoleHotspot()); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (mBound) { - if (!mService.isSetup()) { + if (getmService() != null) { + if (!getmService().isSetup()) { Snackbar.make(activity_view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show(); button.setChecked(false); return; @@ -276,23 +260,4 @@ public class HotspotFragment extends Fragment { } }); } - - /** Defines callbacks for service binding, passed to bindService() */ - private ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - // We've bound to LocalService, cast the IBinder and get LocalService instance - WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service; - mService = binder.getService(); - mBound = true; - - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mBound = false; - } - }; } \ No newline at end of file diff --git a/app/src/main/java/com/flashwifi/wifip2p/MainActivity.java b/app/src/main/java/com/flashwifi/wifip2p/MainActivity.java index 926c866..83b1c05 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/MainActivity.java +++ b/app/src/main/java/com/flashwifi/wifip2p/MainActivity.java @@ -1,5 +1,6 @@ package com.flashwifi.wifip2p; +import android.app.ActivityManager; import android.app.Fragment; import android.app.FragmentManager; import android.content.BroadcastReceiver; @@ -13,6 +14,8 @@ import android.net.wifi.p2p.WifiP2pManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; import android.preference.PreferenceManager; import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; @@ -24,14 +27,13 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.widget.CompoundButton; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.Switch; import android.widget.Toast; import com.flashwifi.wifip2p.billing.Accountant; import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService; +import com.flashwifi.wifip2p.iotaAPI.Requests.WalletBalanceChecker; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener @@ -40,6 +42,9 @@ public class MainActivity extends AppCompatActivity private static final String TAG = "MainAct"; private String password; private String seed; + private static final int PREF_UPDATE = 2; + private static final int BALANCE_RETRIEVE_TASK_COMPLETE = 1; + private Handler balanceHandler; private DrawerLayout mDrawerLayout; private ListView mDrawerList; @@ -71,15 +76,27 @@ public class MainActivity extends AppCompatActivity intent.getStringExtra("key")); } else if (intent.getAction().equals("com.flashwifi.wifip2p.stop_roaming")) { Log.d(TAG, "onReceive: Reset billing state"); - mService.resetBillingState(); - mService.setInRoleConsumer(false); - mService.setInRoleHotspot(false); + } } }; registerReceiver(updateUIReceiver, filter); } + public boolean isTheServiceRunning() { + return isMyServiceRunning(WiFiDirectBroadcastService.class); + } + + private boolean isMyServiceRunning(Class serviceClass) { + ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + if (serviceClass.getName().equals(service.service.getClassName())) { + return true; + } + } + return false; + } + @Override protected void onPause() { super.onPause(); @@ -110,7 +127,7 @@ public class MainActivity extends AppCompatActivity } private void initUi() { - final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch); + /*final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch); switch_.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { @@ -124,7 +141,7 @@ public class MainActivity extends AppCompatActivity mService.disableService(); } } - }); + });*/ } @Override @@ -140,6 +157,9 @@ public class MainActivity extends AppCompatActivity password = intent.getStringExtra("password"); seed = intent.getStringExtra("seed"); + setBalanceHandler(); + updateBalance(); + Accountant.getInstance().setSeed(seed); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -153,10 +173,29 @@ public class MainActivity extends AppCompatActivity PreferenceManager.setDefaultValues(this, R.xml.preferences, false); + beginForegroundService(); + Intent intent2 = new Intent(this, WiFiDirectBroadcastService.class); bindService(intent2, mConnection, Context.BIND_AUTO_CREATE); } + public WiFiDirectBroadcastService getmService() { + if (mBound) { + return mService; + } + return null; + } + + private void beginForegroundService() { + if (!isTheServiceRunning()) { + Intent startIntent = new Intent(MainActivity.this, WiFiDirectBroadcastService.class); + startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION); + startService(startIntent); + } else { + Log.d(TAG, "beginForegroundService: Service is already running"); + } + } + private void initEverything() { subscribeToBroadcasts(); initUi(); @@ -245,6 +284,11 @@ public class MainActivity extends AppCompatActivity return true; } + private void updateBalance() { + WalletBalanceChecker balanceChecker = new WalletBalanceChecker(this,this.getString(R.string.preference_file_key),seed, balanceHandler,PREF_UPDATE,true); + balanceChecker.execute(); + } + public void startSearchFragment() { if (mBound && mService.isInRoleHotspot()) { Toast.makeText(this, "Can't start search because you are hotspot", Toast.LENGTH_SHORT).show(); @@ -381,6 +425,7 @@ public class MainActivity extends AppCompatActivity WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service; mService = binder.getService(); mBound = true; + mService.enableService(); } @Override @@ -388,4 +433,34 @@ public class MainActivity extends AppCompatActivity mBound = false; } }; + + private void setBalanceHandler() { + //Handle post-asynctask activities + balanceHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message inputMessage) { + switch (inputMessage.what) { + case BALANCE_RETRIEVE_TASK_COMPLETE: + AddressBalanceTransfer addressBalanceTransfer = (AddressBalanceTransfer) inputMessage.obj; + String returnStatus = addressBalanceTransfer.getMessage(); + if (returnStatus.equals("noError")) { + makeToastBalance("Balance updated"); + } else if (returnStatus.equals("hostError")) { + makeToastBalance("Unable to reach host (node)"); + } else if (returnStatus.equals("addressError")) { + makeToastBalance("Error getting address"); + } else if (returnStatus.equals("balanceError")) { + makeToastBalance("Error getting balance. May not be able to resolve host/node"); + } else { + makeToastBalance("Unknown error"); + } + } + } + }; + } + + private void makeToastBalance(String message) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/flashwifi/wifip2p/RoamingActivity.java b/app/src/main/java/com/flashwifi/wifip2p/RoamingActivity.java index 78e2bc2..954ee06 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/RoamingActivity.java +++ b/app/src/main/java/com/flashwifi/wifip2p/RoamingActivity.java @@ -232,50 +232,7 @@ public class RoamingActivity extends AppCompatActivity { } private void cancelNotification() { - NotificationManager mNotificationManager = - (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationManager.cancel(1); - } - - - private void showNotification() { - // The id of the channel. - String CHANNEL_ID = "com.flashwifi.wifip2p.roaming_1"; - - String contentText = mService.isInRoleHotspot() ? "You are providing" : "You are consuming"; - - // ToDo: make this work on high API version - NotificationCompat.Builder mBuilder = - new NotificationCompat.Builder(this) - .setSmallIcon(R.drawable.icon_tethering_on) - .setContentTitle("IOTA HOTSPOT") - .setContentText(contentText); - // Creates an explicit intent for an Activity in your app - Intent resultIntent = new Intent(this, RoamingActivity.class); - - // The stack builder object will contain an artificial back stack for the - // started Activity. - // This ensures that navigating backward from the Activity leads out of - // your app to the Home screen. - TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); - // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(RoamingActivity.class); - // Adds the Intent that starts the Activity to the top of the stack - stackBuilder.addNextIntent(resultIntent); - PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - mBuilder.setContentIntent(resultPendingIntent); - NotificationManager mNotificationManager = - (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - - // mNotificationId is a unique integer your app uses to identify the - // notification. For example, to cancel the notification, you can pass its ID - // number to NotificationManager.cancel(). - mNotificationManager.notify(1, mBuilder.build()); } @@ -326,7 +283,8 @@ public class RoamingActivity extends AppCompatActivity { updateBillingCard(); - showNotification(); + // ToDo: update notification + //showNotification(); } private void endRoaming() { @@ -350,6 +308,12 @@ public class RoamingActivity extends AppCompatActivity { mService.disconnectAP(); } mService.setRoaming(false); + mService.resetBillingState(); + mService.setInRoleConsumer(false); + mService.setInRoleHotspot(false); + + PeerStore.getInstance().clear(); + // hide the spinner and the stop button ProgressBar stopProgressBar = (ProgressBar) findViewById(R.id.stopProgressBar); stopProgressBar.setVisibility(View.GONE); diff --git a/app/src/main/java/com/flashwifi/wifip2p/SearchFragment.java b/app/src/main/java/com/flashwifi/wifip2p/SearchFragment.java index 83fde43..2a45300 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/SearchFragment.java +++ b/app/src/main/java/com/flashwifi/wifip2p/SearchFragment.java @@ -33,6 +33,7 @@ import java.net.InetAddress; import java.util.ArrayList; import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService; +import com.flashwifi.wifip2p.iotaFlashWrapper.Main; /** * Fragment that appears in the "content_frame", shows a planet @@ -41,8 +42,6 @@ public class SearchFragment extends Fragment { public final static String TAG = "SearchActivity"; - WiFiDirectBroadcastService mService; - boolean mBound = false; BroadcastReceiver updateUIReceiver = null; ArrayList arrayList; @@ -64,6 +63,14 @@ public class SearchFragment extends Fragment { return rootView; } + public WiFiDirectBroadcastService getmService() { + MainActivity act = (MainActivity) getActivity(); + if (act != null) { + return act.getmService(); + } + return null; + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -112,7 +119,7 @@ public class SearchFragment extends Fragment { } private void startNegotiationProtocol(String macAddress){ - WifiP2pInfo p2p_info = mService.getP2p_info(); + WifiP2pInfo p2p_info = getmService().getP2p_info(); if (p2p_info.isGroupOwner) { startNegotiationProtocolServer(macAddress); @@ -123,13 +130,13 @@ public class SearchFragment extends Fragment { private void startNegotiationProtocolServer(String macAddress) { // starts the server if necessary - WifiP2pInfo p2p_info = mService.getP2p_info(); - NetworkInfo network_info = mService.getNetwork_info(); + WifiP2pInfo p2p_info = getmService().getP2p_info(); + NetworkInfo network_info = getmService().getNetwork_info(); if (network_info.getState() == NetworkInfo.State.CONNECTED) { if (p2p_info.isGroupOwner) { Log.d(TAG, "You are the group owner"); - mService.startNegotiationServer(true, macAddress); + getmService().startNegotiationServer(true, macAddress); Log.d(TAG, "SocketServer started"); } } @@ -137,8 +144,8 @@ public class SearchFragment extends Fragment { private void startNegotiationProtocolClient(String macAddress){ // starts the server if necessary - WifiP2pInfo p2p_info = mService.getP2p_info(); - NetworkInfo network_info = mService.getNetwork_info(); + WifiP2pInfo p2p_info = getmService().getP2p_info(); + NetworkInfo network_info = getmService().getNetwork_info(); if (network_info.getState() == NetworkInfo.State.CONNECTED) { if (!p2p_info.isGroupOwner) { @@ -146,7 +153,7 @@ public class SearchFragment extends Fragment { // groupOwnerAddress = p2p_info.groupOwnerAddress; InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress; Log.d(TAG, "Group owner address: " + p2p_info.groupOwnerAddress.getHostAddress()); - mService.startNegotiationClient(groupOwnerAddress, true, macAddress); + getmService().startNegotiationClient(groupOwnerAddress, true, macAddress); Log.d(TAG, "Client Socket started"); } } @@ -155,10 +162,6 @@ public class SearchFragment extends Fragment { @Override public void onPause() { super.onPause(); - if (mBound) { - getActivity().unbindService(mConnection); - mBound = false; - } if (updateUIReceiver != null) { getActivity().unregisterReceiver(updateUIReceiver); updateUIReceiver = null; @@ -168,10 +171,6 @@ public class SearchFragment extends Fragment { @Override public void onStop() { super.onStop(); - if (mBound) { - getActivity().unbindService(mConnection); - mBound = false; - } if (updateUIReceiver != null) { getActivity().unregisterReceiver(updateUIReceiver); updateUIReceiver = null; @@ -200,6 +199,10 @@ public class SearchFragment extends Fragment { updateUIReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (getActivity() == null) { + Log.d(TAG, "onReceive: getActivity is null"); + return; + } Log.d("", "onReceive: FRAGMENT HAT WAS"); if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) { String mac = intent.getStringExtra("peer_mac_address"); @@ -217,10 +220,6 @@ public class SearchFragment extends Fragment { }; getActivity().registerReceiver(updateUIReceiver, filter); - // Bind to Service - Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class); - getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - view = getActivity().findViewById(R.id.fragment_view); initUI(); @@ -235,26 +234,20 @@ public class SearchFragment extends Fragment { toggle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { - if (mBound) { - if (!mService.isSetup()) { - Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - toggle.setChecked(false); - return; - } + if (!getmService().isSetup()) { + Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show(); + toggle.setChecked(false); + return; } updateList(); if (toggle.isChecked()) { - if (mBound) { - mService.setInRoleHotspot(false); - mService.setInRoleConsumer(true); - startSearching(); - } + getmService().setInRoleHotspot(false); + getmService().setInRoleConsumer(true); + startSearching(); } else { - if (mBound) { - mService.setInRoleHotspot(false); - mService.setInRoleConsumer(false); - stopSearching(); - } + getmService().setInRoleHotspot(false); + getmService().setInRoleConsumer(false); + stopSearching(); } } }); @@ -298,7 +291,7 @@ public class SearchFragment extends Fragment { public void startChat(final String address, String name) { - mService.connect(address, new WifiP2pManager.ActionListener() { + getmService().connect(address, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { Toast.makeText(view.getContext(), "Connected to peer", Toast.LENGTH_SHORT).show(); @@ -315,53 +308,31 @@ public class SearchFragment extends Fragment { } private void stopSearching() { - if (mBound) { - mService.stopDiscovery(new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - } + getmService().stopDiscovery(new WifiP2pManager.ActionListener() { + @Override + public void onSuccess() { + Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show(); + } - @Override - public void onFailure(int reasonCode) { - Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - } - }); - } + @Override + public void onFailure(int reasonCode) { + Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show(); + } + }); } public void startSearching() { + getmService().getPeerList(new WifiP2pManager.ActionListener() { + @Override + public void onSuccess() { + Snackbar.make(view, "Successfully searched for peers", Snackbar.LENGTH_LONG).setAction("Action", null).show(); + } - if (mBound) { - mService.getPeerList(new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - Snackbar.make(view, "Successfully searched for peers", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - } + @Override + public void onFailure(int reasonCode) { + Snackbar.make(view, "Aaaargh :( Peering problem!", Snackbar.LENGTH_LONG).setAction("Action", null).show(); + } + }); - @Override - public void onFailure(int reasonCode) { - Snackbar.make(view, "Aaaargh :( Peering problem!", Snackbar.LENGTH_LONG).setAction("Action", null).show(); - } - }); - } } - - /** Defines callbacks for service binding, passed to bindService() */ - private ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, - IBinder service) { - // We've bound to LocalService, cast the IBinder and get LocalService instance - WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service; - mService = binder.getService(); - mBound = true; - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - mBound = false; - } - }; } \ No newline at end of file diff --git a/app/src/main/java/com/flashwifi/wifip2p/SettingsFragment.java b/app/src/main/java/com/flashwifi/wifip2p/SettingsFragment.java index 1528867..89029de 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/SettingsFragment.java +++ b/app/src/main/java/com/flashwifi/wifip2p/SettingsFragment.java @@ -103,13 +103,14 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { switch(key){ case "pref_key_security": - makeToastSettingsFragment("Security Changed"); + //makeToastSettingsFragment("Security Changed"); break; case "pref_key_network_timeout": - makeToastSettingsFragment("Network Timeout Changed"); + //makeToastSettingsFragment("Network Timeout Changed"); break; case "pref_key_units": makeToastSettingsFragment("Units Changed"); + //makeToastSettingsFragment("Units Changed"); break; case "pref_key_switch_testnet": makeToastSettingsFragment("Testnet on/off Changed"); diff --git a/app/src/main/java/com/flashwifi/wifip2p/WithdrawWalletFragment.java b/app/src/main/java/com/flashwifi/wifip2p/WithdrawWalletFragment.java index 9fe3da6..5a18fe3 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/WithdrawWalletFragment.java +++ b/app/src/main/java/com/flashwifi/wifip2p/WithdrawWalletFragment.java @@ -95,11 +95,11 @@ public class WithdrawWalletFragment extends Fragment { transactionInProgress = false; if(returnStatus.equals("noError")){ - balanceTextView.setText(appWalletBalance + " i"); + balanceTextView.setText(appWalletBalance); makeToastFundWalletFragment("Balance updated"); } else if (returnStatus.equals("noErrorNoUpdateMessage")){ - balanceTextView.setText(appWalletBalance + " i"); + balanceTextView.setText(appWalletBalance); clearAllTransferValues(); makeFieldsEditable(); } diff --git a/app/src/main/java/com/flashwifi/wifip2p/billing/BillingClient.java b/app/src/main/java/com/flashwifi/wifip2p/billing/BillingClient.java index 221531d..8431659 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/billing/BillingClient.java +++ b/app/src/main/java/com/flashwifi/wifip2p/billing/BillingClient.java @@ -197,6 +197,7 @@ public class BillingClient { if (error_count >= maxErrorCount) { // stop trying to connect + Log.d(TAG, "start: error count too high"); state = State.ERROR; sendUpdateUIBroadcastWithMessage("Exit"); } diff --git a/app/src/main/java/com/flashwifi/wifip2p/billing/BillingServer.java b/app/src/main/java/com/flashwifi/wifip2p/billing/BillingServer.java index e63b01f..1e85d1d 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/billing/BillingServer.java +++ b/app/src/main/java/com/flashwifi/wifip2p/billing/BillingServer.java @@ -244,13 +244,17 @@ public class BillingServer { e.printStackTrace(); } finally { try { - socketWrapper.close(); - } catch (IOException e) { + if (socketWrapper != null) { + socketWrapper.close(); + } + } catch (Exception e) { } try { - serverSocket.close(); - } catch (IOException e) { + if (serverSocket != null) { + serverSocket.close(); + } + } catch (Exception e) { } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/broadcast/WiFiDirectBroadcastService.java b/app/src/main/java/com/flashwifi/wifip2p/broadcast/WiFiDirectBroadcastService.java index 9c5dd63..a75792e 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/broadcast/WiFiDirectBroadcastService.java +++ b/app/src/main/java/com/flashwifi/wifip2p/broadcast/WiFiDirectBroadcastService.java @@ -1,11 +1,16 @@ package com.flashwifi.wifip2p.broadcast; import android.app.Activity; +import android.app.Notification; +import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.DhcpInfo; import android.net.NetworkInfo; import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pConfig; @@ -20,9 +25,14 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.text.format.Formatter; import android.util.Log; import com.flashwifi.wifip2p.AddressBalanceTransfer; +import com.flashwifi.wifip2p.Constants; +import com.flashwifi.wifip2p.MainActivity; +import com.flashwifi.wifip2p.R; import com.flashwifi.wifip2p.accesspoint.AccessPointTask; import com.flashwifi.wifip2p.accesspoint.ConnectTask; import com.flashwifi.wifip2p.accesspoint.StopAccessPointTask; @@ -38,10 +48,14 @@ import com.flashwifi.wifip2p.protocol.NegotiationFinalization; import com.flashwifi.wifip2p.protocol.NegotiationOffer; import com.flashwifi.wifip2p.protocol.NegotiationOfferAnswer; +import org.apache.commons.lang3.ArrayUtils; + import java.io.IOException; import java.lang.reflect.Method; +import java.math.BigInteger; import java.net.InetAddress; import java.net.NetworkInterface; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -96,6 +110,57 @@ public class WiFiDirectBroadcastService extends Service { ConnectTask connectTask; private boolean negotiatorRunning = false; + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) { + Log.i(TAG, "Received Start Foreground Intent "); + Intent notificationIntent = new Intent(this, MainActivity.class); + notificationIntent.setAction(Constants.ACTION.MAIN_ACTION); + notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_CLEAR_TASK); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, + notificationIntent, 0); +/* + Intent previousIntent = new Intent(this, WiFiDirectBroadcastService.class); + previousIntent.setAction(Constants.ACTION.PREV_ACTION); + PendingIntent ppreviousIntent = PendingIntent.getService(this, 0, + previousIntent, 0); + + Intent playIntent = new Intent(this, WiFiDirectBroadcastService.class); + playIntent.setAction(Constants.ACTION.PLAY_ACTION); + PendingIntent pplayIntent = PendingIntent.getService(this, 0, + playIntent, 0);*/ + + Intent stopIntent = new Intent(this, WiFiDirectBroadcastService.class); + stopIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION); + PendingIntent pstopIntent = PendingIntent.getService(this, 0, + stopIntent, 0); + + Bitmap icon = BitmapFactory.decodeResource(getResources(), + R.drawable.icon_tethering_on); + + Notification notification = new NotificationCompat.Builder(this) + .setContentTitle(getString(R.string.app_name)) + .setTicker(getString(R.string.app_name)) + .setContentText(getString(R.string.notification_doing_nothing)) + .setSmallIcon(R.drawable.icon_tethering_on) + .setLargeIcon( + Bitmap.createScaledBitmap(icon, 128, 128, false)) + .setContentIntent(pendingIntent) + .setOngoing(true) + .addAction(R.drawable.icon_tethering_off, "Stop", + pstopIntent).build(); + startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, + notification); + } else if (intent.getAction().equals( + Constants.ACTION.STOPFOREGROUND_ACTION)) { + Log.i(TAG, "Received Stop Foreground Intent"); + stopForeground(true); + stopSelf(); + } + return START_STICKY; + } + public boolean isSetup() { return setup; } @@ -165,9 +230,23 @@ public class WiFiDirectBroadcastService extends Service { @Override public void run() { BillingClient billingClient = new BillingClient(mac, getApplicationContext()); - // ToDo: get the AP gateway ip address + // Gget the AP gateway ip address // https://stackoverflow.com/questions/9035784/how-to-know-ip-address-of-the-router-from-code-in-android - billingClient.start("192.168.43.1"); + final WifiManager manager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); + final DhcpInfo dhcp = manager.getDhcpInfo(); + byte[] myIPAddress = BigInteger.valueOf(dhcp.gateway).toByteArray(); + ArrayUtils.reverse(myIPAddress); + InetAddress myInetIP = null; + String routerIP = null; + try { + myInetIP = InetAddress.getByAddress(myIPAddress); + routerIP = myInetIP.getHostAddress(); + } catch (UnknownHostException e) { + e.printStackTrace(); + routerIP = "192.168.43.1"; + } + Log.d(TAG, "DHCP gateway: " + routerIP); + billingClient.start(routerIP); // ToDo: handle billingServer EXIT CODES // -> close the roaming etc. } @@ -379,7 +458,7 @@ public class WiFiDirectBroadcastService extends Service { stopAllTasks(); thread.start(); } else { - Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state"); + Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state or negotiator running"); } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletAddressChecker.java b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletAddressChecker.java index 6c4e7ee..617d633 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletAddressChecker.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletAddressChecker.java @@ -76,14 +76,13 @@ public class WalletAddressChecker { SharedPreferences prefManager = PreferenceManager.getDefaultSharedPreferences(context); String security = prefManager.getString("pref_key_security","2"); int securityInt = Integer.parseInt(security); - System.out.println("securityInt: "+securityInt); addressResponse = api.getNewAddress(seed, securityInt, keyIndex, true, 1, false); } catch (ArgumentException e) { e.printStackTrace(); + return addressList; } if(addressResponse != null) { - System.out.println("WalletAddressChecker - Address: "+addressResponse.getAddresses().get(0)); addressList.add(addressResponse.getAddresses().get(0)); String[] addressesCheckArray = new String[1]; @@ -101,7 +100,7 @@ public class WalletAddressChecker { } } - if(transactionsForAddress.isEmpty() || (transactionsForAddress.size() == 0 || transactionsForAddress.equals(null))){ + if(transactionsForAddress == null || transactionsForAddress.isEmpty() || (transactionsForAddress.size() == 0)){ //Transactions not found, use this address foundAddress = true; } @@ -110,11 +109,6 @@ public class WalletAddressChecker { String curHash = transactionsForAddress.get(0).getHash(); hashStringList.add(curHash); - - System.out.println("WalletAddressChecker value: "+transactionsForAddress.get(0).getValue()); - System.out.println("WalletAddressChecker time: "+transactionsForAddress.get(0).getAttachmentTimestamp()); - System.out.println("WalletAddressChecker address: "+transactionsForAddress.get(0).getAddress()); - keyIndex = keyIndex + 1; } } @@ -130,34 +124,27 @@ public class WalletAddressChecker { //Check whether pending transactions exist containsPendingTransaction = false; keyIndexChanged = false; + GetInclusionStateResponse inclusionResponse; try { - GetInclusionStateResponse inclusionResponse = api.getLatestInclusion(hashStringArray); - boolean[] states = inclusionResponse.getStates(); - - for (boolean state : states) { - if(!state){ - containsPendingTransaction = true; - } - } - } catch (ArgumentException e) { + inclusionResponse = api.getLatestInclusion(hashStringArray); + } catch (ArgumentException | IllegalStateException e) { e.printStackTrace(); + return addressList; } - System.out.println("containsPendingTransaction: "+containsPendingTransaction); + boolean[] states = inclusionResponse.getStates(); + + for (boolean state : states) { + if(!state){ + containsPendingTransaction = true; + } + } if(!containsPendingTransaction){ //all confirmed transactions, ok to change keyIndex - if(keyIndex != getKeyIndex()){ keyIndexChanged = true; - if(keyIndex == 0){ - //Put the initial address to search. No transactions for the seed yet. - putKeyIndex(keyIndex); - } - else{ - //Put the second last address to search - putKeyIndex(keyIndex-1); - } + putKeyIndex(keyIndex); } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletBalanceChecker.java b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletBalanceChecker.java index e7519a5..c64d856 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletBalanceChecker.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletBalanceChecker.java @@ -10,6 +10,8 @@ import android.preference.PreferenceManager; import com.flashwifi.wifip2p.AddressBalanceTransfer; import com.flashwifi.wifip2p.R; +import java.text.DateFormat; +import java.util.Date; import java.util.List; import jota.IotaAPI; @@ -24,6 +26,7 @@ public class WalletBalanceChecker extends AsyncTask { private static final int FUND_WALLET = 0; private static final int WITHDRAW_WALLET = 1; + private static final int PREF_UPDATE = 2; private static IotaAPI api; private static Context context; @@ -76,6 +79,7 @@ public class WalletBalanceChecker extends AsyncTask { @Override protected Void doInBackground(Void... voids) { + if(context != null){ WalletAddressChecker addressChecker = new WalletAddressChecker(context,prefFile); @@ -83,8 +87,6 @@ public class WalletBalanceChecker extends AsyncTask { boolean containsPendingTransactions = addressChecker.getContainsPendingTransaction(); boolean keyIndexChanged = addressChecker.getkeyIndexChanged(); - System.out.println("seed: "+seed); - if(addressList != null && addressList.get(0).equals("Unable to resolve host")){ AddressBalanceTransfer addressBalanceTransfer = new AddressBalanceTransfer(null,null,"hostError"); Message completeMessage = mHandler.obtainMessage(BALANCE_RETRIEVE_TASK_COMPLETE, addressBalanceTransfer); @@ -126,10 +128,6 @@ public class WalletBalanceChecker extends AsyncTask { public String getBalance(List inAddresses, boolean containsPendingTransactions, boolean keyIndexChanged){ - for (String inAddress : inAddresses) { - System.out.println("addressGetBalance: "+inAddress); - } - String updatedBalanceString; try { StopWatch stopWatch = new StopWatch(); @@ -140,11 +138,7 @@ public class WalletBalanceChecker extends AsyncTask { GetBalancesAndFormatResponse balanceResponse = api.getBalanceAndFormat(inAddresses, 0, 0, stopWatch, securityInt); long total = balanceResponse.getTotalBalance(); - System.out.println("getTotalBalance: "+total); - long storedBaseBalance = Long.parseLong(getBaseSharedPrefKeyBalance()); - System.out.println("getBaseSharedPreKeyBalance: "+storedBaseBalance); - long updatedBaseBalance = storedBaseBalance + total; updatedBalanceString = Long.toString(updatedBaseBalance); @@ -163,26 +157,35 @@ public class WalletBalanceChecker extends AsyncTask { //No Pending Transactions, new confirmed transactions else if(!containsPendingTransactions && keyIndexChanged){ putBaseSharedPrefBalance(updatedBalanceString); - - System.out.println("Store new base balance"); - System.out.println("updated balance: "+updatedBaseBalance); - updatedBalanceString = Long.toString(updatedBaseBalance); putSharedPrefBalance(updatedBalanceString); } } catch (ArgumentException | IllegalStateException e) { e.printStackTrace(); - return null; + return getSharedPrefKeyBalance()+"i (cached: "+getSharedPrefKeyBalanceDateUpdate()+")"; } - return updatedBalanceString; + String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date()); + putSharedPrefBalanceDateUpdate(currentDateTimeString); + return updatedBalanceString+"i"; + } + + private void putSharedPrefBalanceDateUpdate(String currentDateTimeString) { + SharedPreferences sharedPref = context.getSharedPreferences( + prefFile, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString("balanceDateUpdate", currentDateTimeString); + editor.apply(); + } + + private String getSharedPrefKeyBalanceDateUpdate() { + SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE); + String defaultValue = "0"; + String storedBalance = sharedPref.getString("balanceDateUpdate",defaultValue); + return storedBalance; } private String getSharedPrefKeyBalance() { SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE); - int keyIndex = sharedPref.getInt("keyIndex",0); - - System.out.println("KeyIndex: "+keyIndex); - String defaultValue = "0"; String storedBalance = sharedPref.getString("balance",defaultValue); return storedBalance; @@ -198,10 +201,6 @@ public class WalletBalanceChecker extends AsyncTask { private String getBaseSharedPrefKeyBalance() { SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE); - int keyIndex = sharedPref.getInt("keyIndex",0); - - System.out.println("KeyIndex: "+keyIndex); - String defaultValue = "0"; String storedBalance = sharedPref.getString("baseBalance",defaultValue); return storedBalance; diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTestnetTokenGen.java b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTestnetTokenGen.java index f905aa8..727268f 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTestnetTokenGen.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTestnetTokenGen.java @@ -148,8 +148,6 @@ public class WalletTestnetTokenGen extends AsyncTask { private void transferToWallet(List destAddressses, TokenGenJSONResponse token) { - System.out.println("2000 seed: "+token.getSeed()); - if(destAddressses != null && destAddressses.get(0).equals("Unable to resolve host")){ //Host Error Message completeMessage = settingsFragmentHandler.obtainMessage(TOKEN_TESTNET_RETRIEVE_TASK_COMPLETE, "hostError"); @@ -161,9 +159,6 @@ public class WalletTestnetTokenGen extends AsyncTask { completeMessage.sendToTarget(); String destAddress = destAddressses.get(destAddressses.size()-1); - System.out.println("DestAddress: "+destAddress); - System.out.println("TokenAmt: "+token.getAmount().toString()); - WalletTransferRequest transferRequest = new WalletTransferRequest(destAddress,token.getSeed(),token.getAmount().toString(),"","",context,testnetTokenGenHandler); transferRequest.execute(); } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTransferRequest.java b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTransferRequest.java index e5d00dd..0720dd5 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTransferRequest.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaAPI/Requests/WalletTransferRequest.java @@ -107,7 +107,6 @@ public class WalletTransferRequest extends AsyncTask { try { if(testnet) { //Testnet - System.out.println("WalletTransferRequest: Testnet"); if(testnetPrivate){ sendTransferResponse = api.sendTransfer(appWalletSeed, securityInt, 4, 3, transfers, null, null, false); } @@ -155,7 +154,6 @@ public class WalletTransferRequest extends AsyncTask { else{ transferResult = "Transfer error: Send Response not received"; } - System.out.println("WalletTransferRequest - result: "+transferResult); return transferResult; } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Example.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Example.java new file mode 100644 index 0000000..8d06d4c --- /dev/null +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Example.java @@ -0,0 +1,198 @@ +package com.flashwifi.wifip2p.iotaFlashWrapper; + +import android.util.Log; + +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Bundle; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.CreateTransactionHelperObject; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Digest; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Multisig; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Signature; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Transfer; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wlad on 24.01.18. + */ + +public class Example { + public static FlashChannelHelper one; + public static FlashChannelHelper two; + + public static void setup() { + + double[] deposits = new double[]{100,100}; + int depth = 4; + + + // Example of a user setup. + one = FlashChannelHelper.getInstance(); + one.setupUser(0, "RDNUSLPNOQUGDIZVOINTYRIRRIJMLODOC9ZTQU9KQSCDXPVSBILXUE9AHEOA9MNYZWNSECAVPQ9QSAHCN", 0, 1); + one.setupFlash(deposits, depth); + + // Create a second user + // Here i needed a second instance so I left the public in the constructor of FlashChannelHelper + two = new FlashChannelHelper(); + two.setupUser(0, "IUQDBHFDXK9EHKC9VUHCUXDLICLRANNDHYRMDYFCGSZMROWCZBLBNRKXWBSWZYDMLLHIHMP9ZPOPIFUSW", 0, 1); + two.setupFlash(deposits, depth); + + // The addresses must be exchanged over the network. + // When done setup the settlementAddresses. + ArrayList settlementAddresses = new ArrayList<>(); + settlementAddresses.add("EYUSQTMUVAFUGXMJEJYRHVMSCUBDXXKOEPFWPKVJJIY9DDTQJGJRZJTMPZAVBAICZBRGSTBOGCQR9Y9P9"); + settlementAddresses.add("EYUSQTMUVAFUGXMJEJYRHVMSCUBDXXKOEPFWPKVJJIY9DDTQJGJRZJTMPZAVBAICZBRGSTBOGCQR9Y9P9"); + + // Set the addresses + one.setupSettlementAddresses(settlementAddresses); + two.setupSettlementAddresses(settlementAddresses); + + // Now generate the digests for each user. + List initialDigestsOne = one.initialChannelDigests(); + List initialDigestsTwo = two.initialChannelDigests(); + + // Now the users should exchange the digests over the network + // When the both have the digests create a array with them. make sure the order is kept. + List> digestPairs = new ArrayList<>(); + digestPairs.add(initialDigestsOne); + digestPairs.add(initialDigestsTwo); + + // This will create the initial multisig addresses and the root address. + one.setupChannelWithDigests(digestPairs); + two.setupChannelWithDigests(digestPairs); + + // After this the root must be set. You can check for it using this call. + Log.d("[ROOT ADDR]", one.getRootAddressWithChecksum()); + + // Now the setup is ready + } + + public static void transaction(FlashChannelHelper sender, FlashChannelHelper reciever) { + // Check if we need to expand the tree + CreateTransactionHelperObject helper = sender.getTransactionHelper(); + + // If the generate value is larget 0 we need to generate some new addresses + if (helper.getGenerate() > 0) { + // Get digests from the sender + ArrayList senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate()); + + // Send senderDigests to user two and wait for his digests. + + // User two makes digests. + ArrayList recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate()); + + // When you have both you can create a digest array + List> digestPairs = new ArrayList<>(); + digestPairs.add(senderDigests); + digestPairs.add(recieverDigests); + + // Now each party must generate the digests. + Multisig updatedAddress = one.updateTreeWithDigests(digestPairs, helper.getAddress()); + + // Since the other user does not have the address to use (the object reference). We search for it. + Multisig extansionMultisigTwo = two.getMultisigByAddress(helper.getAddress().getAddress()); + if (extansionMultisigTwo == null) { + Log.d("[ERROR]", "Could not find attachment address for tree expansion."); + } + + two.updateTreeWithDigests(digestPairs, extansionMultisigTwo); + + // Now the sender just has to update the helper objects multisig address. I will optimize this in the future. + helper.setAddress(updatedAddress); + } + + // Now you can perform a transaction + + // Create transfers. + ArrayList transfers = new ArrayList<>(); + transfers.add(new Transfer(reciever.getSettlementAddress(), 10)); + + // Create a transaction from a transfer. + ArrayList senderBundles = Helpers.createTransaction(transfers, helper, sender.getUser()); + + // Now send the senderBundles to the receiver and wait for the response signatures. + + // USER2: check if bundle content is okay. Only the first transaction of the last bundle is interesting. + // But if we want to be sure we need to check both bundles and all transactions. + + // User two generates signatures if all is okay. + ArrayList receiverSignatures = two.createSignaturesForBundles(senderBundles); + + // Now both just have to apply the signatures and check if all is good. + ArrayList senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures); + ArrayList receiverSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures); + + // Now if all is good just apply. In future I will throw a error on invalid signing. + one.applyTransfers(senderSignedBundles); + two.applyTransfers(receiverSignedBundles); + } + + /** + * + * @param sender + * @param reciever + */ + public static void close(FlashChannelHelper sender, FlashChannelHelper reciever) { + // Close is more or a less just a transaction. + // So the start is exactly the same. + + // Check if we need to expand the tree + CreateTransactionHelperObject helper = sender.getTransactionHelper(); + + // If the generate value is larget 0 we need to generate some new addresses + if (helper.getGenerate() > 0) { + // Get digests from the sender + ArrayList senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate()); + + // Send senderDigests to user two and wait for his digests. + + // User two makes digests. + ArrayList recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate()); + + // When you have both you can create a digest array + List> digestPairs = new ArrayList<>(); + digestPairs.add(senderDigests); + digestPairs.add(recieverDigests); + + // Now each party must generate the digests. + Multisig updatedAddress = one.updateTreeWithDigests(digestPairs, helper.getAddress()); + + // Since the other user does not have the address to use (the object reference). We search for it. + Multisig extansionMultisigTwo = two.getMultisigByAddress(helper.getAddress().getAddress()); + if (extansionMultisigTwo == null) { + Log.d("[ERROR]", "Could not find attachment address for tree expansion."); + } + + two.updateTreeWithDigests(digestPairs, extansionMultisigTwo); + + // Now the sender just has to update the helper objects multisig address. I will optimize this in the future. + helper.setAddress(updatedAddress); + } + + // Now we create is closing transaction. + ArrayList senderBundles = sender.createCloseTransactions(); + + // Here the same game as before with the signatures... + + + // Now send the senderBundles to the receiver and wait for the response signatures. + + // USER2: check if bundle content is okay. Only the first transaction of the last bundle is interesting. + // But if we want to be sure we need to check both bundles and all transactions. + + // User two generates signatures if all is okay. + ArrayList receiverSignatures = two.createSignaturesForBundles(senderBundles); + + // Now both just have to apply the signatures and check if all is good. + ArrayList senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures); + ArrayList receiverSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures); + + // Now if all is good just apply. In future I will throw a error on invalid signing. + one.applyTransfers(senderSignedBundles); + two.applyTransfers(receiverSignedBundles); + + // And here we attach the bundle to the tangle. We can check the response bundles since we may need to rebroadcast them. + // As far as I understand only one needs to send them. + List attachedBundles = Helpers.POWClosedBundle(senderSignedBundles, 4, 13); + } +} diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/FlashChannelHelper.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/FlashChannelHelper.java new file mode 100644 index 0000000..e121033 --- /dev/null +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/FlashChannelHelper.java @@ -0,0 +1,171 @@ +package com.flashwifi.wifip2p.iotaFlashWrapper; + +import android.util.Log; + +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Bundle; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.CreateTransactionHelperObject; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Digest; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.FlashObject; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Multisig; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Signature; +import com.flashwifi.wifip2p.iotaFlashWrapper.Model.UserObject; + +import java.util.ArrayList; +import java.util.List; + +import jota.utils.Checksum; + +/** + * Created by wlad on 24.01.18. + */ + +public class FlashChannelHelper { + public static FlashChannelHelper getInstance() { + if (instance == null) { + instance = new FlashChannelHelper(); + } + return instance; + } + private static FlashChannelHelper instance; + + + private UserObject user; + + /** + * When ready change public to private and only use a singleton. + */ + public FlashChannelHelper() {} + + /** + * + * @param userIndex + * @param seed + * @param seedIndex + * @param security + */ + public void setupUser(int userIndex, String seed, int seedIndex, int security) { + this.user = new UserObject(userIndex, seed, seedIndex, security); + } + + /** + * + * @param deposits + * @param depth + */ + public void setupFlash(double[] deposits, int depth) { + if (user == null) { + Log.d("[ERROR]", "setupUser must be called before calling setupFlash"); + return; + } + this.user.setFlash(new FlashObject(deposits, depth, user.getSecurity())); + } + + /** + * Create digests for the depth of the flash channel. Branches will be added when needed. + * @return + */ + public List initialChannelDigests() { + return Helpers.getDigestsForUser(this.user, this.user.getFlash().getDepth()); + } + + /** + * Sets settlement addresses in the flash object, the addresses must be ordered according to the userIndex. + * @param addresses + */ + public void setupSettlementAddresses(ArrayList addresses) { + if (addresses.size() != user.getFlash().getSignersCount()) { + Log.d("[ERROR]", "Not enough addresses found..."); + return; + } + user.getFlash().setSettlementAddresses(addresses); + } + + /** + * Combine all user digests pairs, create multisig addresses and setup tree structure. + * @param digestPairs + */ + public void setupChannelWithDigests(List> digestPairs) { + if (digestPairs.size() != user.getFlash().getSignersCount()) { + Log.d("[ERROR]", " Not enough digest pairs found..."); + return; + } + + // Create multisigs. + List mulitisigs = Helpers.getMultisigsForUser(digestPairs, user); + + // Set renainder address. + Multisig oneRemainderAddr = mulitisigs.remove(0); //shiftCopyArray(); + user.getFlash().setRemainderAddress(oneRemainderAddr); + + // Build flash trees + for (int i = 1; i < mulitisigs.size(); i++) { + System.out.println(mulitisigs.get(i - 1).toString() + " -> " + mulitisigs.get(i).toString()); + mulitisigs.get(i - 1).push(mulitisigs.get(i)); + } + user.getFlash().setRoot(mulitisigs.remove(0)); + } + + public String getRootAddressWithChecksum() { + try { + return Checksum.addChecksum(user.getFlash().getRoot().getAddress()); + } catch (Exception e) { + Log.d("[ERROR]", "Failed to get root address"); + return ""; + } + } + + + /** + * Transfer utils + */ + + /** + * Create new multisig and insert it into the flash channel tree of the user. + * @param digestPairs + * @param address address to which the new address will be attached. + */ + public Multisig updateTreeWithDigests(List> digestPairs, Multisig address) { + Multisig multisig = Helpers.getNewBranch(digestPairs, user, address); + + // Find the multisig with the address and append new address to children + return Helpers.updateMultisigChildrenForUser(user, multisig); + } + + public Multisig getMultisigByAddress(String address) { + return user.getFlash().getRoot().find(address); + } + + public ArrayList createSignaturesForBundles(ArrayList bundles) { + return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles); + } + + public void applyTransfers(ArrayList signedBundles) { + Helpers.applyTransfers(signedBundles, user); + } + + + /** + * Closing utils + */ + + public ArrayList createCloseTransactions() { + return Helpers.closeChannel(user); + } + + /** + * Returns a helper with the address to use and the number of new addresses to generate. + * Please create the new addresses before making the transaction. + * @return + */ + public CreateTransactionHelperObject getTransactionHelper() { + return Helpers.getTransactionHelper(user.getFlash().getRoot()); + } + + public UserObject getUser() { + return user; + } + + public String getSettlementAddress() { + return user.getFlash().getSettlementAddresses().get(user.getUserIndex()); + } +} diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Helpers.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Helpers.java index 1af0efb..6461639 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Helpers.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Helpers.java @@ -1,95 +1,467 @@ package com.flashwifi.wifip2p.iotaFlashWrapper; - - +import com.google.gson.Gson; import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; +import jota.IotaAPI; +import jota.dto.response.GetBalancesResponse; +import jota.model.Transaction; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class Helpers { - public static ArrayList createTransaction(UserObject user, ArrayList transfers, boolean shouldClose) { - CreateTransactionHelperObject toUse = IotaFlashBridge.updateLeafToRoot(user.getFlash().getRoot()); - if (toUse.getGenerate() != 0) { - // TODO: tell the server to gen new address. - System.out.println("No more addresses in channel."); - } + private static boolean useTestnet = true; + private static String seedGeneratorURL = "http://87.118.96.200:3000"; //"https://seeedy.tangle.works"; + private static String testNetNodeURL = "https://testnet140.tangle.works:443"; + private static String netNodeURL = "http://node.iotawallet.info:14265"; // "http://87.118.96.200:14700";// + private static IotaAPI iotaAPI = null; - ArrayList newTransfers; + /** + * Get a transaction object. The object contains the address to use and if required the number of new addresses to generate + * @param root multisig address at the top of the tree + * @return Transaction object with address and number of addresses to create. + */ + public static CreateTransactionHelperObject getTransactionHelper(Multisig root) { + return IotaFlashBridge.updateLeafToRoot(root); + } - if (shouldClose) { - newTransfers = IotaFlashBridge.close(user.getFlash().getSettlementAddresses(), user.getFlash().getDeposits()); - } else { - newTransfers = IotaFlashBridge.prepare( - user.getFlash().getSettlementAddresses(), - user.getFlash().getDeposits(), - user.getUserIndex(), - transfers - ); - } + /** + * + * @param transfers + * @param toUse Transaction helper object + * @param user + * @return + */ + public static ArrayList createTransaction(ArrayList transfers, CreateTransactionHelperObject toUse, UserObject user) { + // System.out.println("Creating a transaction of" + transfers.getValue() + " to " + transfers.getAddress()); + System.out.println("[INFO]: using address " + toUse.getAddress().getAddress() + ", with boundle count" + toUse.getAddress().getBundles().size()); - ArrayList bundles = IotaFlashBridge.compose( - user.getFlash().getBalance(), - user.getFlash().getDeposits(), - user.getFlash().getOutputs(), - toUse.getAddress(), - user.getFlash().getRemainderAddress(), - user.getFlash().getTransfers(), - newTransfers, - shouldClose + + FlashObject flash = user.getFlash(); + ArrayList bundles; + // Prepare a new transaction. + ArrayList newTransfers = IotaFlashBridge.prepare( + flash.getSettlementAddresses(), + flash.getDeposits(), + user.getUserIndex(), + transfers ); - return bundles; - } - public static ArrayList signTransaction(UserObject user, ArrayList bundles) { - return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles); - } -// -// public static ArrayList appliedSignatures(ArrayList bundles, ArrayList signatures) { -// ArrayList clonedBundles = clone(bundles); -// bundles.clone(); -// -// for (int i = 0; i < bundles.size(); i++) { -// Signature sig = signatures.get(i); -// Bundle b = bundles.get(i); -// if (sig == null) { -// continue; -// } -// -// ArrayList transactions = b.getBundles(); -// String addy = transactions.stream().filter(tx -> tx.getValue() < 0).findFirst().get().getAddress(); -// List tmp = transactions.stream() -// .filter(tx -> tx.getAddress().equals(addy)) -// .collect(Collectors.toList()); -// -// tmp = tmp.subList(sig.getIndex(), sig.getIndex() + sig.getSignatureFragments().size()); -// -// for (int j = 0; j < tmp.size(); j++) { -// tmp.get(j).setSignatureFragments(sig.getSignatureFragments().get(j)); -// } -// } -// -// return clonedBundles; -// } - - public static void applyTransfers(UserObject user, ArrayList bundles) { - FlashObject flash = IotaFlashBridge.applyTransfersToUser(user, bundles); - user.setFlash(flash); - // IotaFlashBridge.applyTransfers( -// user.getFlash().getRoot(), -// user.getFlash().getDeposits(), -// user.getFlash().getOutputs(), -// user.getFlash().getRemainderAddress(), -// user.getFlash().getTransfers(), -// bundles -// ); - } - - public static ArrayList clone(ArrayList bundles) { - ArrayList clonedBundles = new ArrayList<>(); - for (Bundle b : bundles) { - clonedBundles.add(b.clone()); + if (newTransfers == null) { + return new ArrayList<>(); } - return clonedBundles; + + // Compose the transaction. This may also add some management transactions (moving remainder tokens.) + bundles = IotaFlashBridge.compose( + flash.getBalance(), + flash.getDeposits(), + flash.getOutputs(), + toUse.getAddress(), + flash.getRemainderAddress(), + flash.getTransfers(), + newTransfers, + false + ); + + System.out.println("[SUCCESS] Created signatures for user" + user.getUserIndex()); + // Apply the signature of the transaction creater to the current transactions bundle. + ArrayList signatures = IotaFlashBridge.sign(toUse.getAddress(), user.getSeed(), bundles); + + System.out.println("[SUCCESS] Parial applied Signature for user" + user.getUserIndex() + " on transfer bundle"); + // Sign bundle with your USER ONE'S signatures + return IotaFlashBridge.appliedSignatures(bundles, signatures); + } + + public static ArrayList closeChannel(UserObject user) { + FlashObject flash = user.getFlash(); + ArrayList closeTransfers = IotaFlashBridge.close(flash.getSettlementAddresses(), flash.getDeposits()); + // Compose the transaction. This may also add some management transactions (moving remainder tokens.) + ArrayList bundles = IotaFlashBridge.compose( + flash.getBalance(), + flash.getDeposits(), + flash.getOutputs(), + flash.getRoot(), + flash.getRemainderAddress(), + flash.getTransfers(), + closeTransfers, + true + ); + + System.out.println("[SUCCESS] Created signatures for user" + user.getUserIndex()); + // Apply the signature of the transaction creater to the current transactions bundle. + ArrayList signatures = IotaFlashBridge.sign(flash.getRoot(), user.getSeed(), bundles); + + System.out.println("[SUCCESS] Parial applied Signature for user" + user.getUserIndex() + " on transfer bundle"); + // Sign bundle with your USER ONE'S signatures + return IotaFlashBridge.appliedSignatures(bundles, signatures); + } + + /** + * + * Tree management. + * + */ + + /** + * + * @param user + * @param toGenerate + * @return + */ + public static ArrayList getNewBranchDigests(UserObject user, int toGenerate) { + ArrayList digests = new ArrayList<>(); + for (int i = 0; i < toGenerate; i++) { + Digest digest = IotaFlashBridge.getDigest(user.getSeed(), user.getSeedIndex(), user.getSecurity()); + System.out.println("USING index for digest: " + user.getSeedIndex() ); + user.incrementSeedIndex(); + digests.add(digest); + } + return digests; + } + + + /** + * + * @param oneDigests + * @param twoDigests + * @param user + * @param address + * @return + */ + public static Multisig getNewBranch(ArrayList oneDigests, ArrayList twoDigests, UserObject user, Multisig address) { + List> userDigestList = new ArrayList<>(); + userDigestList.add(oneDigests); + userDigestList.add(twoDigests); + return getNewBranch(userDigestList, user, address); + } + + public static Multisig getNewBranch(List> digestPairs, UserObject user, Multisig address) { + List multisigs = getMultisigsForUser(digestPairs, user); + + System.out.println("[INFO]: Adding to address " + address.getAddress()); + + // Build flash trees + for (int i = 1; i < multisigs.size(); i++) { + multisigs.get(i - 1).push(multisigs.get(i)); + } + + // Clone the address to avoid overwriting params. + Multisig output = address.clone(); + + // Add new multisigs to address. + output.push(multisigs.get(0)); + + return output; + } + + + /** + * + * Digests and Multisig creation + * + */ + + /** + * Creates initial digests for a user. This will only create digests for a given TREE_DEPTH -> Digests.size == TREE_DEPTH + 1 + * Other transactions will be generated when required. + * @param user user for which the digests should be generated + * @param TREE_DEPTH number of initial digests to generate + * @return digests for provided user. + */ + public static ArrayList getDigestsForUser(UserObject user, int TREE_DEPTH) { + ArrayList digests = new ArrayList<>(); + // Create digests for the start of the channel + for (int i = 0; i < TREE_DEPTH + 1; i++) { + // Create new digest + Digest digest = IotaFlashBridge.getDigest( + user.getSeed(), + user.getSeedIndex(), + user.getSecurity() + ); + user.incrementSeedIndex(); + System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex()); + // Increment key index + + digests.add(digest); + } + return digests; + } + + + /** + * + * @param allDigests + * @param currentUser + * @return + */ + public static List getMultisigsForUser(List> allDigests, UserObject currentUser) { + + // Generate the first addresses + ArrayList multisigs = new ArrayList(); + + // Loop for all digests. + for (int index = 0; index < allDigests.get(0).size(); index++) { + ArrayList alignedDigests = new ArrayList<>(); + + int securitySum = 0; + + // Loop for all users. + for (int userIndex = 0; userIndex < allDigests.size(); userIndex++) { + Digest digest = allDigests.get(userIndex).get(index); + // Get array of digests for all users. + alignedDigests.add(digest); + securitySum += digest.getSecurity(); + } + + // Create multisgAddr from digests. + Multisig multisig = IotaFlashBridge.composeAddress(alignedDigests); + + // Get digests data for current user. + Digest digest = allDigests.get(currentUser.getUserIndex()).get(index); + + multisig.setIndex(digest.getIndex()); + multisig.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity()); + multisig.setSecuritySum(securitySum); + multisig.setSecurity(digest.getSecurity()); + + System.out.println("Creating address " + multisig.getAddress() + " index" + multisig.getIndex() + " signingIndex: " + multisig.getSigningIndex()); + + multisigs.add(multisig); + } + + return multisigs; + } + + + /** + * + * @param user + * @param multisig + * @return + */ + public static Multisig updateMultisigChildrenForUser(UserObject user, Multisig multisig) { + FlashObject flash = user.getFlash(); + Multisig originAddress = flash.getRoot().find(multisig.getAddress()); + if (originAddress != null) { + + System.out.println("[INFO]: found address in user" + user.getUserIndex() + " data"); + originAddress.setChildren(multisig.getChildren()); + originAddress.setBundles(multisig.getBundles()); + originAddress.setSecurity(multisig.getSecurity()); + return originAddress; + } + return null; + } + + /** + * Apply transfers to a user flash state. + * @param signedBundles + * @param user + */ + public static void applyTransfers(ArrayList signedBundles, UserObject user) { + // Apply transfers to User ONE + FlashObject newFlash = IotaFlashBridge.applyTransfersToUser(user, signedBundles); + + // Set new flash object to user + user.setFlash(newFlash); + } + + /** + * Send trytes array to the node specified in the IotaAPI setup. + * @param trytes + * @param api + * @return returns the transactions applied to the node tangle. + */ + public static List sendTrytes(String[] trytes, IotaAPI api, int depth, int minWeightMagnitude) { + + try { + System.out.println("[INFO] Sinding close bundle... This can take some time"); + List txs = api.sendTrytes(trytes, depth, minWeightMagnitude); + return txs; + } catch (IllegalAccessError error) { + System.out.println("[ERROR] " + error.getLocalizedMessage()); + } catch (Exception exception) { + System.out.println("[ERROR]: could not send trytes " + exception.getLocalizedMessage()); + } + + return new ArrayList(); + } + + + public static List POWClosedBundle(List bundles, int depth, int minWeightMagnitude) { + List attachedBundles = new ArrayList<>(); + for (Bundle b : bundles) { + String[] trytes = b.toTrytesArray(); + List txs = sendTrytes(trytes, getIotaAPI(), depth, minWeightMagnitude); + if (txs != null && txs.size() > 0) { + Bundle bundle = new Bundle(txs); + attachedBundles.add(bundle); + } + } + + return attachedBundles; + } + + /** + * creates a new iota instace with the defined url and mode (testnet or not) + * if api instance available the just return it + * @return IotaAPI instance with setup url + */ + public static IotaAPI getIotaAPI() { + if (iotaAPI == null) { + return getNewIotaAPI(); + } + return iotaAPI; + } + + /** + * Creates a new instance of iota api and override the currently set one. + * Can be used to change url settings. + * @return IotaAPI instance with setup url + */ + public static IotaAPI getNewIotaAPI() { + URL nodeURL; + + try { + if (useTestnet) { + nodeURL = new URL(testNetNodeURL); + } else { + nodeURL = new URL(netNodeURL); + } + iotaAPI = new IotaAPI.Builder() + .protocol(nodeURL.getProtocol()) + .host(nodeURL.getHost()) + .port(String.valueOf(nodeURL.getPort())) + .build(); + } catch (Exception e) { + System.out.println("[ERROR] Failed to create IotaAPI instance." + e.getLocalizedMessage()); + return null; + } + + return iotaAPI; + } + + + /** + * + * Utilities + */ + + /** + * gives a new funded seed from a seedGeneratorURL + * @return + */ + public static GeneratedSeed getNewSeed() { + try { + String seedData = readUrl(seedGeneratorURL); + Gson gson = new Gson(); + GeneratedSeed genSeed = gson.fromJson(seedData, GeneratedSeed.class); + return genSeed; + } catch (Exception e) { + System.out.println("[ERROR]: Failed to get new testned seed" + e.getLocalizedMessage()); + return null; + } + } + + /** + * Get the total left in the flash channel. + * @param user + * @return + */ + public static double getFlashDeposits(UserObject user) { + double sum = 0; + for (double deposit : user.getFlash().getDeposits()) { + sum += deposit; + } + return sum; + } + + /** + * get current output of the flash channel. All transactions and remainder. + * @param user UserObject for which to compute amount + * @return amount of IOTA + */ + public static double getBalanceOfUser(UserObject user) { + FlashObject flash = user.getFlash(); + double balance = flash.getDeposits().get(user.getUserIndex()); + Map transfers = flash.getOutputs(); + for (Map.Entry transfer : transfers.entrySet()) { + String userSettlementAddr = flash.getSettlementAddresses().get(user.getUserIndex()); + if (transfer.getKey().equals(userSettlementAddr)) { + balance += transfer.getValue(); + } + } + + return balance; + } + + /** + * Returns the amount of iota deposited in a selected address + * @param address + * @return + */ + public static long getBalance(String address) { + ArrayList addreses = new ArrayList<>(); + addreses.add(address); + IotaAPI api = getIotaAPI(); + try { + GetBalancesResponse resp = api.getBalances(100, addreses); + return Long.parseLong(resp.getBalances()[0]); + } catch (Exception e) { + System.out.println("[ERROR]: could not read balance for account " + address + " with error " + e.getLocalizedMessage()); + return -1; + } + } + + /** + * Utility for reading date from a provided url string. + * @param urlString + * @return + * @throws Exception + */ + private static String readUrl(String urlString) throws Exception { + BufferedReader reader = null; + try { + URL url = new URL(urlString); + reader = new BufferedReader(new InputStreamReader(url.openStream())); + StringBuffer buffer = new StringBuffer(); + int read; + char[] chars = new char[1024]; + while ((read = reader.read(chars)) != -1) + buffer.append(chars, 0, read); + + return buffer.toString(); + } finally { + if (reader != null) + reader.close(); + } + } + + public static Transaction cloneTransaction(jota.model.Transaction transaction) { + return new Transaction( + transaction.getSignatureFragments(), + transaction.getCurrentIndex(), + transaction.getLastIndex(), + transaction.getNonce(), + transaction.getHash(), + transaction.getObsoleteTag(), + transaction.getTimestamp(), + transaction.getTrunkTransaction(), + transaction.getBranchTransaction(), + transaction.getAddress(), + transaction.getValue(), + transaction.getBundle(), + transaction.getTag(), + transaction.getAttachmentTimestamp(), + transaction.getAttachmentTimestampLowerBound(), + transaction.getAttachmentTimestampUpperBound() + ); } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/IotaFlashBridge.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/IotaFlashBridge.java index 0cea8b4..60254bc 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/IotaFlashBridge.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/IotaFlashBridge.java @@ -1,21 +1,17 @@ package com.flashwifi.wifip2p.iotaFlashWrapper; import com.eclipsesource.v8.*; import com.eclipsesource.v8.utils.V8ObjectUtils; - import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Map; - public class IotaFlashBridge { private static V8 engine; private static V8Object transfer; @@ -45,7 +41,7 @@ public class IotaFlashBridge { * @param digests * @return */ - public static MultisigAddress composeAddress(ArrayList digests) { + public static Multisig composeAddress(ArrayList digests) { // Create js object for digest List list = new ArrayList(); for (Digest digest: digests) { @@ -58,17 +54,12 @@ public class IotaFlashBridge { V8Array params = V8ObjectUtils.toV8Array(engine, paramsList); V8Object retV8 = multisig.executeObjectFunction("composeAddress", params); - - // Parse return values from JS into Java world. - Map resultMap = V8ObjectUtils.toMap(retV8); - // Parse result into Java Obj. - String addr = (String) resultMap.get("address"); - int secSum = (Integer) resultMap.get("securitySum"); - MultisigAddress ret = new MultisigAddress(addr, secSum); + // Create multisig. + Multisig multisig = V8Converter.multisigAddressFromV8Object(retV8); params.release(); retV8.release(); - return ret; + return multisig; } /** @@ -99,7 +90,7 @@ public class IotaFlashBridge { * * @param root */ - public static CreateTransactionHelperObject updateLeafToRoot(MultisigAddress root) { + public static CreateTransactionHelperObject updateLeafToRoot(Multisig root) { Map map = root.toMap(); // Create param list List paramsObj = new ArrayList(); @@ -109,7 +100,7 @@ public class IotaFlashBridge { V8Object ret = multisig.executeObjectFunction("updateLeafToRoot", params); int generate = ret.getInteger("generate"); V8Object multisigObject = (V8Object) ret.getObject("multisig"); - MultisigAddress multisig = V8Converter.multisigAddressFromV8Object(multisigObject); + Multisig multisig = V8Converter.multisigAddressFromV8Object(multisigObject); return new CreateTransactionHelperObject(generate, multisig); } @@ -122,7 +113,7 @@ public class IotaFlashBridge { * @param transfers array of all transfers (value, address) pairs * @return */ - public static ArrayList prepare(ArrayList settlementAddresses, ArrayList deposits, int index, ArrayList transfers) { + public static ArrayList prepare(List settlementAddresses, List deposits, int index, List transfers) { // Now put all params into JS ready array. List params = new ArrayList<>(); @@ -132,8 +123,14 @@ public class IotaFlashBridge { params.add(V8Converter.transferListToV8Array(engine, transfers)); // Call js function. - V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params)); - return V8Converter.transferListFromV8Array(ret); + try { + V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params)); + return V8Converter.transferListFromV8Array(ret); + } catch (V8ScriptExecutionException exception) { + + return null; + } + } @@ -143,7 +140,7 @@ public class IotaFlashBridge { * @param deposits * @return */ - public static ArrayList close(ArrayList settlementAddresses, ArrayList deposits) { + public static ArrayList close(List settlementAddresses, List deposits) { V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses); // Deposits V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits); @@ -170,27 +167,24 @@ public class IotaFlashBridge { * @return */ public static ArrayList compose(int balance, - List deposits, - ArrayList outputs, - MultisigAddress root, - MultisigAddress remainderAddress, - ArrayList history, - ArrayList transfers, + List deposits, + Map outputs, + Multisig root, + Multisig remainderAddress, + List history, + List transfers, boolean close) { - - - // Create params. // Now put all params into JS ready array. List params = new ArrayList(); params.add(balance); params.add(V8ObjectUtils.toV8Array(engine, deposits)); - params.add(V8Converter.bundleListToV8Array(engine, outputs)); + params.add(V8ObjectUtils.toV8Object(engine, outputs)); params.add(V8Converter.multisigToV8Object(engine, root)); params.add(V8Converter.multisigToV8Object(engine, remainderAddress)); params.add(V8Converter.bundleListToV8Array(engine, history)); params.add(V8Converter.transferListToV8Array(engine, transfers)); - + params.add(close); // Call js function. V8Array ret = transfer.executeArrayFunction("compose", V8ObjectUtils.toV8Array(engine, params)); @@ -204,7 +198,7 @@ public class IotaFlashBridge { * @param bundles * @return */ - public static ArrayList sign(MultisigAddress root, String seed, ArrayList bundles) { + public static ArrayList sign(Multisig root, String seed, ArrayList bundles) { // Create params. // Now put all params into JS ready array. @@ -257,10 +251,10 @@ public class IotaFlashBridge { * @param signedBundles * @return */ - public static void applyTransfers(MultisigAddress root, + public static void applyTransfers(Multisig root, ArrayList deposits, ArrayList outputs, - MultisigAddress remainderAddress, + Multisig remainderAddress, ArrayList transfers, ArrayList signedBundles) { // Construct Java params @@ -288,4 +282,25 @@ public class IotaFlashBridge { ret.release(); return flash; } + + /// Utils + + /** + * + * @param path + * @param encoding + * @return + * @throws IOException + */ + static String readFile(String path, Charset encoding) + throws IOException + { + File file = new File(IotaFlashBridge.class.getClassLoader().getResource(path).getFile()); + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + fis.read(data); + fis.close(); + + return new String(data, "UTF-8"); + } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Main.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Main.java deleted file mode 100644 index d95e5e5..0000000 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Main.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.flashwifi.wifip2p.iotaFlashWrapper; - -import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.stream.Collectors; - - -public class Main { - - public static void runExample() throws Exception { - - // Run a test based on the flash example - // Link: https://github.com/iotaledger/iota.flash.js/blob/master/examples/flash.js - - String oneSeed = "USERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER"; - String oneSettlement = "USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9U"; - String twoSeed = "USERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSER"; - String twoSettlement = "USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9U"; - - ////////////////////////////////// - // INITIAL CHANNEL CONDITIONS - - // Security level - int SECURITY = 2; - // Number of parties taking signing part in the channel - int SIGNERS_COUNT = 2; - // Flash tree depth - int TREE_DEPTH = 4; - // Total channel Balance - int CHANNEL_BALANCE = 2000; - // Users deposits - ArrayList DEPOSITS = new ArrayList<>(); - DEPOSITS.add(1000); - DEPOSITS.add(1000); - // Setup users. - FlashObject oneFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS); - UserObject oneFlash = new UserObject(0, oneSeed, TREE_DEPTH, oneFlashObj); - - FlashObject twoFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS); - UserObject twoFlash = new UserObject(1, twoSeed, TREE_DEPTH, twoFlashObj); - - // USER ONE - setupUser(oneFlash, TREE_DEPTH); - - // USER TWO - setupUser(twoFlash, TREE_DEPTH); - - ////////////////////////////////// - // INITAL MULTISIG - - // Make an array of digests - ArrayList allUsers = new ArrayList(); - allUsers.add(oneFlash); - allUsers.add(twoFlash); - - // Create partial digests for users. - createInitialPartialDigests(allUsers, oneFlash); - createInitialPartialDigests(allUsers, twoFlash); - - ArrayList oneMultisigs = oneFlash.getMultisigDigests(); - ArrayList twoMultisigs = twoFlash.getMultisigDigests(); - - // Set renainder address. - MultisigAddress oneRemainderAddr = oneMultisigs.remove(0); //shiftCopyArray(); - oneFlash.getFlash().setRemainderAddress(oneRemainderAddr); - - MultisigAddress twoRemainderAddr = twoMultisigs.remove(0); - twoFlash.getFlash().setRemainderAddress(twoRemainderAddr); - - // Build flash trees - for (int i = 1; i < oneMultisigs.size(); i++) { - System.out.println(oneMultisigs.get(i - 1).toString() + " -> " + oneMultisigs.get(i).toString()); - oneMultisigs.get(i - 1).push(oneMultisigs.get(i)); - } - - // Build flash trees - for (int i = 1; i < twoMultisigs.size(); i++) { - twoMultisigs.get(i - 1).push(twoMultisigs.get(i)); - } - - oneFlash.getFlash().setRoot(oneMultisigs.remove(0)); - twoFlash.getFlash().setRoot(twoMultisigs.remove(0)); - - ArrayList settlementAddresses = new ArrayList<>(); - settlementAddresses.add(oneSettlement); - settlementAddresses.add(twoSettlement); - oneFlash.getFlash().setSettlementAddresses(settlementAddresses); - twoFlash.getFlash().setSettlementAddresses(settlementAddresses); - - // Set digest/key index - oneFlash.setIndex(oneFlash.getPartialDigests().size()); - twoFlash.setIndex(twoFlash.getPartialDigests().size()); - - System.out.println("Channel Setup!"); - - ArrayList transfers = new ArrayList<>(); - transfers.add(new Transfer(twoSettlement, 1)); - transfers.add(new Transfer(twoSettlement, 400)); - - System.out.println(oneFlash); - - System.out.println("Creating a transaction: 200 to " + twoSettlement); - ArrayList bundles = Helpers.createTransaction(oneFlash, transfers, false); - - ArrayList partialSignedBundles = signTransfer(bundles, oneFlash); - ArrayList signedBundles = signTransfer(partialSignedBundles, twoFlash); - ///////////////////////////////// - /// APPLY SIGNED BUNDLES - - // Apply transfers to User ONE - Helpers.applyTransfers(oneFlash, signedBundles); - - // Save latest channel bundles - oneFlash.setBundles(signedBundles); - - // Apply transfers to User TWO - Helpers.applyTransfers(twoFlash, signedBundles); - // Save latest channel bundles - twoFlash.setBundles(signedBundles); - System.out.println("[SUCCESS] Apply Transfer to flash channel."); - - - System.out.println("Transaction Applied!"); -// System.out.println( -// "Transactable tokens: " + -// oneFlash.getFlash().getDeposits().stream().mapToInt(v -> v.intValue()).sum() -// ); - - System.out.println("Closing channel... not yet working..."); - } - - private static ArrayList signTransfer(ArrayList bundles, UserObject user) { - System.out.println("[SUCCESS] Created signatures for users."); - ArrayList oneSignatures = Helpers.signTransaction(user, bundles); - - System.out.println("[SUCCESS] Parial applied Signature for User one on transfer bundle"); - // Sign bundle with your USER ONE'S signatures - ArrayList signedBundles = IotaFlashBridge.appliedSignatures(bundles, oneSignatures); - - return signedBundles; - } - - private static void setupUser(UserObject user, int TREE_DEPTH) { - // Create digests for the start of the channel - for (int i = 0; i < TREE_DEPTH + 1; i++) { - // Create new digest - Digest digest = IotaFlashBridge.getDigest( - user.getSeed(), - user.getIndex(), - user.getSecurity() - ); - System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex()); - // Increment key index - user.incrementIndex(); - user.add(digest); - } - } - - private static void createInitialPartialDigests(ArrayList allUsers, UserObject currentUser) { - - // Generate the first addresses - ArrayList oneMultisigs = new ArrayList(); - - - System.out.println("_________________________________________________________________"); - System.out.println("Creating multisigs on user: " + currentUser.getUserIndex()); - int index = 0; - // Create address - for (Digest digest: allUsers.get(index).getPartialDigests()) { - int i = index; - - ArrayList currentDigests = new ArrayList<>(); - int securitySum = 0; - for (int j = 0; j < allUsers.size(); j++) { - Digest currentDigest = allUsers.get(j).getPartialDigests().get(i); - currentDigests.add(currentDigest); - securitySum += currentDigest.getSecurity(); - } - - MultisigAddress addy = IotaFlashBridge.composeAddress(currentDigests); - - System.out.println("Multisig: " + addy.toString()); - - // Add key index in - addy.setIndex(digest.getIndex()); - // Add the signing index to the object IMPORTANT - addy.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity()); - // Get the sum of all digest security to get address security sum - addy.setSecuritySum(securitySum); - addy.setSecurity(digest.getSecurity()); - oneMultisigs.add(addy); - index++; - } - currentUser.setMultisigDigests(oneMultisigs); - } - - private static ArrayList shiftCopyArray(ArrayList input) { - ArrayList output = new ArrayList<>(); - - for (int i = 1; i < input.size(); i++) { - output.add(input.get(i)); - } - - return output; - } - - private static void test() throws IOException { - - System.out.println("IOTA Flash channel tester"); - - String pathToLib = "res/iotaflash.js"; - - System.out.println("Loading lib into V8 engine"); - System.out.println("Lib imported"); - - - System.out.println("Testing getDigest(seed, index, security):"); - Digest digest1 = IotaFlashBridge.getDigest("USERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2); - Digest digest2 = IotaFlashBridge.getDigest("USERTWOUSERTWOUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2); - System.out.println("Digest1: " + digest1.toString()); - - - System.out.println("Testing composeAddress(digests):"); - ArrayList digests = new ArrayList(); - digests.add(digest1); - digests.add(digest2); - MultisigAddress composedAddr = IotaFlashBridge.composeAddress(digests); - System.out.println("Got multisig addr for digests: " + composedAddr.getAddress() + ", securitySum: " + composedAddr.getSecuritySum()); - - testPrepare(); - } - - private static void testPrepare() { - - System.out.println("Testing prepare()"); - ArrayList settlementAddr = new ArrayList(); - settlementAddr.add("RCZHCRDWMGJPHKROKEGVADVJXPGKEKNJRNLZZFPITUVEWNPGIWNUMKTYKMNB9DCNLWGMJZDNKYQDQKDLC"); - ArrayList depositsPrep = new ArrayList(); - ArrayList transfers = new ArrayList(); - - IotaFlashBridge.prepare(settlementAddr, depositsPrep, 0, transfers); - } -} diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Bundle.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Bundle.java index 349d70e..235a0ea 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Bundle.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Bundle.java @@ -1,50 +1,63 @@ package com.flashwifi.wifip2p.iotaFlashWrapper.Model; +import com.flashwifi.wifip2p.iotaFlashWrapper.V8Converter; +import com.flashwifi.wifip2p.iotaFlashWrapper.Helpers; +import jota.model.Transaction; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +public class Bundle extends jota.model.Bundle { -public class Bundle { - private ArrayList bundles; - - public Bundle(ArrayList bundles) { - this.bundles = bundles; + public Bundle(List transactions) { + super(transactions, transactions.size()); } public Bundle() { - this.bundles = new ArrayList<>(); + super(); } + @Override public String toString() { String out = ""; - for (Transaction t: bundles) { + for (Transaction t: getTransactions()) { out += t.toString(); out += "\n"; } return out; } + public String[] toTrytesArray() { + String[] bundleTrytes = new String[getTransactions().size()]; + List transactions = getTransactions(); + for (int i = 0; i < bundleTrytes.length; i++) { + bundleTrytes[(bundleTrytes.length - 1) - i] = transactions.get(i).toTrytes(); + } + + return bundleTrytes; + } + public Map toMap() { Map map = new HashMap(); - List bundleList = new ArrayList(); - for (Transaction b: bundles) { - bundleList.add(b.toMap()); - } - map.put("bundles", bundleList); + + map.put("bundles", toArrayList()); return map; } - public ArrayList getBundles() { - return bundles; + public List toArrayList() { + List bundleList = new ArrayList(); + for (Transaction tx: getTransactions()) { + bundleList.add(V8Converter.transactionToMap(tx)); + } + return bundleList; } - public Bundle clone() { + public Bundle clone() { ArrayList clonedTransactions = new ArrayList<>(); - for (Transaction t: bundles) { - clonedTransactions.add(t.clone()); + for (Transaction tx: getTransactions()) { + clonedTransactions.add(Helpers.cloneTransaction(tx)); } return new Bundle(clonedTransactions); } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/CreateTransactionHelperObject.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/CreateTransactionHelperObject.java index 80f1f06..87ae9ee 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/CreateTransactionHelperObject.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/CreateTransactionHelperObject.java @@ -1,11 +1,10 @@ package com.flashwifi.wifip2p.iotaFlashWrapper.Model; - public class CreateTransactionHelperObject { private int generate = 0; - private MultisigAddress address; + private Multisig address; - public CreateTransactionHelperObject(int gen, MultisigAddress addr) { + public CreateTransactionHelperObject(int gen, Multisig addr) { this.generate = gen; this.address = addr; } @@ -14,7 +13,11 @@ public class CreateTransactionHelperObject { return generate; } - public MultisigAddress getAddress() { + public Multisig getAddress() { return address; } + + public void setAddress(Multisig address) { + this.address = address; + } } \ No newline at end of file diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Digest.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Digest.java index 53cf530..c61ad18 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Digest.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Digest.java @@ -1,5 +1,4 @@ package com.flashwifi.wifip2p.iotaFlashWrapper.Model; - import java.util.HashMap; import java.util.Map; @@ -17,7 +16,6 @@ public class Digest { public int getIndex() { return index; } - public String getDigest() { return digest; } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashLibJSException.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashLibJSException.java new file mode 100644 index 0000000..df5594b --- /dev/null +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashLibJSException.java @@ -0,0 +1,21 @@ +package com.flashwifi.wifip2p.iotaFlashWrapper.Model; + +public class FlashLibJSException extends Exception { + + public enum FlashLibJSExceptionType { + INSUFFICIENT_FUNDS, UNKNOWN + } + + + private FlashLibJSExceptionType type = FlashLibJSExceptionType.UNKNOWN; + + public FlashLibJSException(String string) { + if (string.contains(FlashLibJSExceptionType.INSUFFICIENT_FUNDS.name())) { + this.type = FlashLibJSExceptionType.INSUFFICIENT_FUNDS; + } + } + + public FlashLibJSExceptionType getType() { + return type; + } +} diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashObject.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashObject.java index e6dde6e..33e1e40 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashObject.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/FlashObject.java @@ -1,28 +1,36 @@ package com.flashwifi.wifip2p.iotaFlashWrapper.Model; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; +import com.eclipsesource.v8.utils.V8ObjectUtils; + +import java.util.*; public class FlashObject { - int signersCount = 2; - int balance; - ArrayList settlementAddresses; - ArrayList deposits; // Clone correctly - ArrayList outputs = new ArrayList(); - ArrayList transfers = new ArrayList(); - MultisigAddress root; - MultisigAddress remainderAddress; + private int signersCount = 2; + private int balance; + private List settlementAddresses; + private List deposits; + private Map outputs = new HashMap<>(); + private List transfers = new ArrayList(); + private Multisig root; + private Multisig remainderAddress; + private int depth; + private int security; + public FlashObject(double[] deposits, int depth, int security) { - public FlashObject(int signersCount, int balance, ArrayList deposits) { - this.signersCount = signersCount; - this.balance = balance; - this.deposits = deposits; + this.signersCount = deposits.length; + for (double dep : deposits) { + this.balance += dep; + } + this.deposits = new ArrayList<>(); + for (double deposit : deposits){ + this.deposits.add(deposit); + } + this.depth = depth; + this.security = security; } - public FlashObject(int signersCount, int balance, ArrayList settlementAddresses, ArrayList deposits, ArrayList outputs, ArrayList transfers, MultisigAddress root, MultisigAddress remainderAddress) { + public FlashObject(int signersCount, int balance, List settlementAddresses, List deposits, Map outputs, List transfers, Multisig root, Multisig remainderAddress, int depth, int security) { this.signersCount = signersCount; this.balance = balance; this.settlementAddresses = settlementAddresses; @@ -31,35 +39,8 @@ public class FlashObject { this.transfers = transfers; this.root = root; this.remainderAddress = remainderAddress; - } - - @Override - public String toString() { - String out = ""; - out += "signersCount: " + signersCount + "\n"; - out += "balance: " + balance + "\n"; - out += "settlementAddresses: " + "\n"; - for (String b: settlementAddresses) { - out += "\t" + b + "\n"; - } - out += "deposits: " + "\n"; - for (Integer b: deposits) { - out += "\t" + b + "\n"; - } - - out += "outputs: " + "\n"; - for (Bundle b: outputs) { - out += "\t" + b.toString() + "\n"; - } - - out += "transfers: " + "\n"; - for (Bundle b: transfers) { - out += "\t" + b.toString() + "\n"; - } - out += "remainderAddress: " + remainderAddress.toString() + "\n"; - out += "root: " + root.toString() + "\n"; - - return out; + this.depth = depth; + this.security = security; } public Map toMap() { @@ -69,57 +50,62 @@ public class FlashObject { objectMap.put("root", root.toMap()); objectMap.put("remainderAddress", remainderAddress.toMap()); objectMap.put("settlementAddresses", getSettlementAddresses()); - - ArrayList outputMap = new ArrayList<>(); - for (Bundle b: outputs) { - outputMap.add(b.toMap()); - } - objectMap.put("outputs", outputMap); + objectMap.put("depth", getDepth()); + objectMap.put("security", getSecurity()); + // Wrap outputs inside an array. + objectMap.put("outputs", getOutputs()); objectMap.put("deposits", getDeposits()); ArrayList transfersMap = new ArrayList<>(); - for (Bundle b: transfers) { - outputMap.add(b.toMap()); + for (Bundle b: getTransfers()) { + transfersMap.add(b.toArrayList()); } objectMap.put("transfers", transfersMap); return objectMap; } - public int getSignersCount() { - return signersCount; - } - public int getBalance() { return balance; } - public MultisigAddress getRoot() { + public int getSignersCount() { + return signersCount; + } + + public int getDepth() { + return depth; + } + + public int getSecurity() { + return security; + } + + public Multisig getRoot() { return root; } - public ArrayList getDeposits() { + public List getDeposits() { return deposits; } - public ArrayList getOutputs() { + public Map getOutputs() { return outputs; } - - public ArrayList getTransfers() { + public List getTransfers() { return transfers; } - public void setRemainderAddress(MultisigAddress remainderAddress) { + public void setRemainderAddress(Multisig remainderAddress) { this.remainderAddress = remainderAddress; } - public MultisigAddress getRemainderAddress() { + public Multisig getRemainderAddress() { return remainderAddress; } - public void setRoot(MultisigAddress root) { + public void setRoot(Multisig root) { this.root = root; } @@ -127,7 +113,7 @@ public class FlashObject { this.settlementAddresses = settlementAddresses; } - public ArrayList getSettlementAddresses() { + public List getSettlementAddresses() { return settlementAddresses; } } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/GeneratedSeed.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/GeneratedSeed.java new file mode 100644 index 0000000..91be3e7 --- /dev/null +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/GeneratedSeed.java @@ -0,0 +1,37 @@ +package com.flashwifi.wifip2p.iotaFlashWrapper.Model; + +public class GeneratedSeed { + private String address; + private String seed; + private long amount; + + public GeneratedSeed(String address, String seed, long amount) { + this.address = address; + this.seed = seed; + this.amount = amount; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getSeed() { + return seed; + } + + public void setSeed(String seed) { + this.seed = seed; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } +} diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/MultisigAddress.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Multisig.java similarity index 56% rename from app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/MultisigAddress.java rename to app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Multisig.java index 5c81338..d2a678a 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/MultisigAddress.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Multisig.java @@ -9,35 +9,71 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class MultisigAddress { + +public class Multisig { private String address; private int securitySum; private int index; private int signingIndex; private int security = 2; - private ArrayList children; + private ArrayList children; private ArrayList bundles; - public MultisigAddress(String address, int securitySum) { + public Multisig(String address, int securitySum) { this.address = address; this.securitySum = securitySum; - this.children = new ArrayList(); + this.children = new ArrayList(); this.bundles = new ArrayList(); - } - public MultisigAddress(String address, int securitySum, ArrayList children) { + public Multisig(String address, int securitySum, ArrayList children) { this.address = address; this.securitySum = securitySum; this.children = children; this.bundles = new ArrayList(); } - public void push(MultisigAddress addr) { + public Multisig find(String address) { + if (getAddress().equals(address)) { + return this; + } else { + for (Multisig mult: getChildren()) { + Multisig result = mult.find(address); + if (result != null) { + return result; + } + } + } + return null; + } + + public Multisig clone() { + Multisig output = new Multisig(this.getAddress(), this.getSecuritySum()); + + output.setSecurity(this.getSecurity()); + output.setIndex(this.getIndex()); + output.setSigningIndex(this.getSigningIndex()); + // Copy all bundles + ArrayList bundleCopy = new ArrayList<>(); + for (Bundle b : this.getBundles()) { + bundleCopy.add(b.clone()); + } + output.setBundles(bundleCopy); + + // Copy all children + ArrayList childrenCopy = new ArrayList<>(); + for (Multisig child : this.getChildren()) { + childrenCopy.add(child.clone()); + } + output.setChildren(childrenCopy); + return output; + } + + public void push(Multisig addr) { children.add(addr); } - public ArrayList getChildren() { + public ArrayList getChildren() { return children; } @@ -52,6 +88,22 @@ public class MultisigAddress { return index; } + public void setAddress(String address) { + this.address = address; + } + + public void setChildren(ArrayList children) { + this.children = children; + } + + public ArrayList getBundles() { + return bundles; + } + + public void setBundles(ArrayList bundles) { + this.bundles = bundles; + } + public int getSigningIndex() { return signingIndex; } @@ -84,14 +136,14 @@ public class MultisigAddress { map.put("signingIndex", getSigningIndex()); map.put("security", security); List childrenList = new ArrayList(); - for (MultisigAddress ma: children) { + for (Multisig ma: children) { childrenList.add(ma.toMap()); } map.put("children", childrenList); List bundleList = new ArrayList(); for (Bundle b: bundles) { - bundleList.add(b.getBundles()); + bundleList.add(b.toArrayList()); } map.put("bundles", bundleList); @@ -105,7 +157,7 @@ public class MultisigAddress { @Override public String toString() { String out = "{ \n address':'" + address + "' \n, securitySum:" + securitySum + "\n, signingIndex: " + signingIndex + " \n"; - for (MultisigAddress addr: children) { + for (Multisig addr: children) { out += addr.toString(); } return out; diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Signature.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Signature.java index e149f69..286c11d 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Signature.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Signature.java @@ -8,56 +8,17 @@ import java.util.List; * * @author Adrian **/ -public class Signature { +public class Signature extends jota.model.Signature { private int index; private String bundle; - private String address; - private List signatureFragments; /** * Initializes a new instance of the Signature class. */ public Signature() { - this.signatureFragments = new ArrayList<>(); + super(); } - /** - * Get the address. - * - * @return The address. - */ - public String getAddress() { - return address; - } - - /** - * Set the address. - * - * @param address The address. - */ - public void setAddress(String address) { - this.address = address; - } - - /** - * Get the signatureFragments. - * - * @return The signatureFragments. - */ - public List getSignatureFragments() { - return signatureFragments; - } - - /** - * Set the signatureFragments. - * - * @param signatureFragments The signatureFragments. - */ - public void setSignatureFragments(List signatureFragments) { - this.signatureFragments = signatureFragments; - } - - public int getIndex() { return index; } @@ -79,10 +40,10 @@ public class Signature { String out = "{ \n" + " \tindex:" + index + ", " + " \n\tbundle: " + bundle + ", " + - " \n\taddress:" + address + ","; + " \n\taddress:" + getAddress() + ","; out += "\n\t[ \n"; - for (String sf : signatureFragments) { + for (String sf : getSignatureFragments()) { out += "\n\t" + sf + ","; } out += " ]"; diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Transaction.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Transaction.java deleted file mode 100644 index d4c96be..0000000 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/Transaction.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.flashwifi.wifip2p.iotaFlashWrapper.Model; - -import java.util.HashMap; -import java.util.Map; - -public class Transaction { - private String hash; - private String signatureFragments; - private String address; - private long value; - private String obsoleteTag; - private long timestamp; - private long currentIndex; - private long lastIndex; - private String bundle; - private String trunkTransaction; - private String branchTransaction; - private String nonce; - private Boolean persistence; - private long attachmentTimestamp; - private String tag; - private long attachmentTimestampLowerBound; - private long attachmentTimestampUpperBound; - - - // Unsigned constructor - public Transaction(String address, int value, String obsoleteTag, String tag, Integer timestamp) { - this.address = address; - this.value = value; - this.obsoleteTag = obsoleteTag; - this.tag = tag; - this.timestamp = timestamp; - } - - public Transaction(String signatureFragments, Long currentIndex, Long lastIndex, String nonce, - String hash, String obsoleteTag, Long timestamp, String trunkTransaction, - String branchTransaction, String address, Long value, String bundle, String tag, - Long attachmentTimestamp, Long attachmentTimestampLowerBound, Long attachmentTimestampUpperBound) { - - this.hash = hash; - this.obsoleteTag = obsoleteTag; - this.signatureFragments = signatureFragments; - this.address = address; - this.value = value; - this.timestamp = timestamp; - this.currentIndex = currentIndex; - this.lastIndex = lastIndex; - this.bundle = bundle; - this.trunkTransaction = trunkTransaction; - this.branchTransaction = branchTransaction; - this.tag = tag; - this.attachmentTimestamp = attachmentTimestamp; - this.attachmentTimestampLowerBound = attachmentTimestampLowerBound; - this.attachmentTimestampUpperBound = attachmentTimestampUpperBound; - this.nonce = nonce; - } - - - public String getSignatureFragments() { - return signatureFragments; - } - - public void setSignatureFragments(String signatureFragments) { - this.signatureFragments = signatureFragments; - } - - public long getValue() { - return value; - } - - public String getAddress() { - return address; - } - - public Map toMap() { - Map map = new HashMap(); - if (hash != null && !hash.equals("")) { - map.put("hash", hash); - } - map.put("signatureMessageFragment", signatureFragments); - map.put("address", address); - map.put("value", value); - map.put("obsoleteTag", obsoleteTag); - map.put("currentIndex", currentIndex); - map.put("timestamp", timestamp); - map.put("lastIndex", lastIndex); - map.put("bundle", bundle); - map.put("trunkTransaction", trunkTransaction); - map.put("branchTransaction", branchTransaction); - map.put("nonce", nonce); - map.put("attachmentTimestamp", String.valueOf(attachmentTimestamp)); - map.put("tag", tag); - map.put("attachmentTimestampLowerBound", String.valueOf(attachmentTimestampLowerBound)); - map.put("attachmentTimestampUpperBound", String.valueOf(attachmentTimestampUpperBound)); - return map; - } - - public Transaction clone() { - return new Transaction( - this.signatureFragments, - this.currentIndex, - this.lastIndex, - this.nonce, - this.hash, - this.obsoleteTag, - this.timestamp, - this.trunkTransaction, - this.branchTransaction, - this.address, - this.value, - this.bundle, - this.tag, - this.attachmentTimestamp, - this.attachmentTimestampLowerBound, - this.attachmentTimestampUpperBound - ); - } - - public String toString() { - Map mapObj = toMap(); - String value = "{"; - for (Map.Entry entry: mapObj.entrySet()) { - value += "'" + entry.getKey() + "':'" + entry.getValue().toString() + "', \n"; - } - value += "}"; - return value; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/UserObject.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/UserObject.java index fda6178..682f622 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/UserObject.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/Model/UserObject.java @@ -4,31 +4,24 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; - public class UserObject { - private int userIndex = 1; + private int userIndex; private String seed; - private int index = 0; - private int security = 2; - private int depth = 4; - private ArrayList bundles = new ArrayList(); - private ArrayList partialDigests = new ArrayList(); - private ArrayList multisigDigests = new ArrayList(); + private int seedIndex; + private int security; + private FlashObject flash; - public UserObject(int userID, String seed, int depth, FlashObject flash) { + public UserObject(int userID, String seed, int seedIndex, int security) { this.userIndex = userID; this.seed = seed; - this.depth = depth; - this.flash = flash; + this.seedIndex = seedIndex; + this.security = security; } - public void incrementIndex() { - index++; - } - - public void add(Digest digest) { - partialDigests.add(digest); + public int incrementSeedIndex() { + this.seedIndex = this.seedIndex + 1; + return seedIndex; } @Override @@ -36,21 +29,9 @@ public class UserObject { String out = ""; out += "userIndex: " + userIndex + "\n"; out += "seed: " + seed + "\n"; - out += "index: " + index + "\n"; + out += "seedIndex: " + seedIndex + "\n"; out += "security: " + getSecurity() + "\n"; - out += "depth: " + depth + "\n"; out += "bundles: " + "\n"; - for (Bundle b: bundles) { - out += "\t" + b.toString() + "\n"; - } - out += "partialDigests: " + "\n"; - for (Digest d: partialDigests) { - out += "\t" + d.toString() + "\n"; - } - out += "multisigDigests: " + "\n"; - for (MultisigAddress m: multisigDigests) { - out += "\t" + m.toString() + "\n"; - } out += "Flash: " + "\n"; out += flash.toString(); @@ -61,27 +42,8 @@ public class UserObject { Map objectMap = new HashMap<>(); objectMap.put("userIndex", getUserIndex()); objectMap.put("seed", getSeed()); - objectMap.put("index", getIndex()); + objectMap.put("seedIndex", getSeedIndex()); objectMap.put("security", getSecurity()); - objectMap.put("depth", depth); - - ArrayList bundleMaps = new ArrayList<>(); - for (Bundle b: bundles) { - bundleMaps.add(b.toMap()); - } - objectMap.put("bundles", bundleMaps); - - ArrayList partialDigestMaps = new ArrayList<>(); - for (Bundle b: bundles) { - partialDigestMaps.add(b.toMap()); - } - objectMap.put("partialDigests", partialDigestMaps); - - ArrayList multisigDigestsMaps = new ArrayList<>(); - for (Bundle b: bundles) { - partialDigestMaps.add(b.toMap()); - } - objectMap.put("multisigDigests", multisigDigestsMaps); objectMap.put("flash", flash.toMap()); return objectMap; } @@ -91,24 +53,12 @@ public class UserObject { * Getters and Setters */ - public void setMultisigDigests(ArrayList multisigDigests) { - this.multisigDigests = multisigDigests; - } - public void setFlash(FlashObject flash) { this.flash = flash; } - public void setIndex(int index) { - this.index = index; - } - - public void setBundles(ArrayList bundles) { - this.bundles = bundles; - } - - public ArrayList getMultisigDigests() { - return multisigDigests; + public void setSeedIndex(int index) { + this.seedIndex = index; } public int getSecurity() { @@ -119,22 +69,14 @@ public class UserObject { return seed; } - public int getIndex() { - return index; + public int getSeedIndex() { + return seedIndex; } public int getUserIndex() { return userIndex; } - public ArrayList getBundles() { - return bundles; - } - - public ArrayList getPartialDigests() { - return partialDigests; - } - public FlashObject getFlash() { return flash; } diff --git a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/V8Converter.java b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/V8Converter.java index 8e35be0..32bfe3f 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/V8Converter.java +++ b/app/src/main/java/com/flashwifi/wifip2p/iotaFlashWrapper/V8Converter.java @@ -5,7 +5,7 @@ import com.eclipsesource.v8.V8Array; import com.eclipsesource.v8.V8Object; import com.eclipsesource.v8.utils.V8ObjectUtils; import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; - +import jota.model.Transaction; import java.util.ArrayList; import java.util.HashMap; @@ -36,13 +36,14 @@ public class V8Converter { return signatures; } - public static V8Object multisigToV8Object(V8 engine, MultisigAddress multisig) { + public static V8Object multisigToV8Object(V8 engine, Multisig multisig) { Map sigMapg = multisig.toMap(); return V8ObjectUtils.toV8Object(engine, sigMapg); } public static V8Object flashObjectToV8Object(V8 engine, FlashObject flash) { - return V8ObjectUtils.toV8Object(engine, flash.toMap()); + Map flashMap = flash.toMap(); + return V8ObjectUtils.toV8Object(engine, flashMap); } public static FlashObject flashObjectFromV8Object(V8Object input) { @@ -51,22 +52,33 @@ public class V8Converter { Integer singersCount = (Integer) inputMap.get("signersCount"); Integer balance = (Integer) inputMap.get("balance"); ArrayList settlementAddresses = (ArrayList) inputMap.get("settlementAddresses"); - MultisigAddress root = multisigAddressFromPropertyMap((Map) inputMap.get("root")); - MultisigAddress remainderAddress = multisigAddressFromPropertyMap((Map) inputMap.get("remainderAddress")); - ArrayList deposits = (ArrayList) inputMap.get("deposits"); + Multisig root = multisigAddressFromPropertyMap((Map) inputMap.get("root")); + Multisig remainderAddress = multisigAddressFromPropertyMap((Map) inputMap.get("remainderAddress")); + ArrayList deposits = new ArrayList<>(); + if (inputMap.get("deposits") instanceof ArrayList) { + Object depositEntry = inputMap.get("deposits"); + if (((ArrayList) depositEntry).size() > 0 && ((ArrayList) depositEntry).get(0) instanceof Integer) { + for (int val: (ArrayList) depositEntry) { + deposits.add(new Double(val)); + } + } else { + deposits = (ArrayList) depositEntry; + } + } ArrayList transfers = bundleListFromArrayList((ArrayList) inputMap.get("transfers")); - ArrayList outputs = bundleListFromArrayList((ArrayList) inputMap.get("outputs")); - - return new FlashObject(singersCount, balance, settlementAddresses, deposits, outputs, transfers, root, remainderAddress); + Map outputs = (Map) inputMap.get("outputs"); + Integer depth = (Integer) inputMap.get("depth"); + Integer security = (Integer) inputMap.get("security"); + return new FlashObject(singersCount, balance, settlementAddresses, deposits, outputs, transfers, root, remainderAddress, depth ,security); } - public static V8Array bundleListToV8Array(V8 engine, ArrayList bundles) { + public static V8Array bundleListToV8Array(V8 engine, List bundles) { List bundleTmp = new ArrayList(); for (Bundle b: bundles) { List transactions = new ArrayList(); - for (Transaction t: b.getBundles()) { - transactions.add(t.toMap()); + for (jota.model.Transaction tx: b.getTransactions()) { + transactions.add(transactionToMap((Transaction) tx)); } bundleTmp.add(transactions); } @@ -85,32 +97,62 @@ public class V8Converter { ArrayList ret = new ArrayList<>(); for (Object o: input) { - ret.add(bundleFromArrayList((ArrayList) o)); + if (o instanceof Map) { + if (((Map) o).get("bundles") instanceof String) { + ArrayList bundles = (ArrayList) ((Map) o).get("bundles"); + ret.add(bundleFromArrayList(bundles)); + } else { + continue; + } + } + if (o instanceof ArrayList) { + ret.add(bundleFromArrayList((ArrayList) o)); + } } return ret; } - public static MultisigAddress multisigAddressFromV8Object(V8Object input) { + public static Multisig multisigAddressFromV8Object(V8Object input) { + if (input.isUndefined()) { + System.out.println("[ERROR]: could not parse object"); + return null; + } Map multiSigMap = V8ObjectUtils.toMap(input); return multisigAddressFromPropertyMap(multiSigMap); } - public static MultisigAddress multisigAddressFromPropertyMap(Map propMap) { + public static Multisig multisigAddressFromPropertyMap(Map propMap) { // Parse result into Java Obj. String addr = (String) propMap.get("address"); int secSum = (Integer) propMap.get("securitySum"); - - ArrayList children = new ArrayList<>(); + ArrayList children = new ArrayList<>(); for (Object child: (ArrayList) propMap.get("children")) { Map childPropMap = (Map) child; children.add(multisigAddressFromPropertyMap(childPropMap)); } - MultisigAddress multisig = new MultisigAddress(addr, secSum, children); + Multisig multisig = new Multisig(addr, secSum, children); + + if (propMap.get("bundles") instanceof ArrayList) { + ArrayList bundles = new ArrayList<>(); + for (Object bundle: (ArrayList) propMap.get("bundles")) { + Bundle b = new Bundle(); + if (!(bundle instanceof ArrayList)) { + continue; + } else { + for (Object transactionMap: (ArrayList) bundle) { + b.getTransactions().add(transactionFromObject(transactionMap)); + } + } + bundles.add(b); + } + + multisig.setBundles(bundles); + } if (propMap.get("index") != null) { multisig.setIndex((Integer) propMap.get("index")); @@ -119,6 +161,10 @@ public class V8Converter { multisig.setSigningIndex((Integer) propMap.get("signingIndex")); } + if (propMap.get("security") instanceof Integer) { + multisig.setSecurity((Integer) propMap.get("security")); + } + return multisig; } @@ -127,6 +173,10 @@ public class V8Converter { // Parse return as array of bundles ArrayList returnBundles = new ArrayList<>(); for (Object bundleItem: inputList) { + if (!(bundleItem instanceof ArrayList)) { + System.out.println("[ERROR]: got undefined for bunle"); + continue; + } ArrayList bundleContent = (ArrayList) bundleItem; ArrayList returnedTransactions = new ArrayList<>(); @@ -199,7 +249,7 @@ public class V8Converter { return null; } - public static V8Array transferListToV8Array(V8 engine, ArrayList transfers) { + public static V8Array transferListToV8Array(V8 engine, List transfers) { List transferObj = new ArrayList(); for (Transfer t: transfers) { transferObj.add(t.toMap()); @@ -209,12 +259,34 @@ public class V8Converter { public static V8Array transactionListToV8Array(V8 engine, ArrayList transactions) { List transfersObj = new ArrayList(); - for (Transaction t: transactions) { - transfersObj.add(t.toMap()); + for (Transaction tx: transactions) { + transfersObj.add(transactionToMap(tx)); } return V8ObjectUtils.toV8Array(engine, transfersObj); } + public static Map transactionToMap(jota.model.Transaction transaction) { + Map map = new HashMap(); + if (transaction.getHash() != null && !transaction.getHash().equals("")) { + map.put("hash", transaction.getHash()); + } + map.put("signatureMessageFragment", transaction.getSignatureFragments()); + map.put("address", transaction.getAddress()); + map.put("value", transaction.getValue()); + map.put("obsoleteTag", transaction.getObsoleteTag()); + map.put("currentIndex", transaction.getCurrentIndex()); + map.put("timestamp", transaction.getTimestamp()); + map.put("lastIndex", transaction.getLastIndex()); + map.put("bundle", transaction.getBundle()); + map.put("trunkTransaction", transaction.getTrunkTransaction()); + map.put("branchTransaction", transaction.getBranchTransaction()); + map.put("nonce", transaction.getNonce()); + map.put("attachmentTimestamp", String.valueOf(transaction.getAttachmentTimestamp())); + map.put("tag", transaction.getTag()); + map.put("attachmentTimestampLowerBound", String.valueOf(transaction.getAttachmentTimestampLowerBound())); + map.put("attachmentTimestampUpperBound", String.valueOf(transaction.getAttachmentTimestampUpperBound())); + return map; + } public static Transaction transactionFromObject(Object input) { Map bundleData = (Map) input; diff --git a/app/src/main/java/com/flashwifi/wifip2p/negotiation/Negotiator.java b/app/src/main/java/com/flashwifi/wifip2p/negotiation/Negotiator.java index ad9c096..537234b 100644 --- a/app/src/main/java/com/flashwifi/wifip2p/negotiation/Negotiator.java +++ b/app/src/main/java/com/flashwifi/wifip2p/negotiation/Negotiator.java @@ -301,11 +301,11 @@ public class Negotiator { if (iotaPerMegabyte < 0) { return error(R.string.err_sell_price_bad_setting, false); } - int minMinutes = Integer.valueOf(prefs.getString("edit_text_min_minutes", "-1")); + int minMinutes = Integer.valueOf(prefs.getString("edit_text_sell_min_minutes", "-1")); if (minMinutes < 0) { return error(R.string.err_min_minutes_bad_setting, false); } - int maxMinutes = Integer.valueOf(prefs.getString("edit_text_max_minutes", "-1")); + int maxMinutes = Integer.valueOf(prefs.getString("edit_text_sell_max_minutes", "-1")); if (maxMinutes < 0) { return error(R.string.err_max_minutes_bad_setting, false); } diff --git a/app/src/main/res/layout/activity_roaming.xml b/app/src/main/res/layout/activity_roaming.xml index b522c5d..39b9c52 100644 --- a/app/src/main/res/layout/activity_roaming.xml +++ b/app/src/main/res/layout/activity_roaming.xml @@ -102,10 +102,14 @@ + android:visibility="gone"/> + + diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml index f3dfb83..45e9934 100644 --- a/app/src/main/res/layout/app_bar_main.xml +++ b/app/src/main/res/layout/app_bar_main.xml @@ -19,7 +19,7 @@ android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay"> - + android:id="@+id/wifiSwitch"/>--> diff --git a/app/src/main/res/layout/fragment_hotspot.xml b/app/src/main/res/layout/fragment_hotspot.xml index 9d3d59a..c90c2bf 100644 --- a/app/src/main/res/layout/fragment_hotspot.xml +++ b/app/src/main/res/layout/fragment_hotspot.xml @@ -19,7 +19,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:text="@string/startAP" /> + android:textOn="@string/stopAP" + android:textOff="@string/startAPText" /> The payment channel was closed. Initializing retransfer Welcome to the Wifi Iota Hotspot App + Currently doing nothing + Stop Hotspot + Start Hotspot diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 7c861bd..a5f5ace 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -44,7 +44,7 @@ @@ -98,7 +98,7 @@ android:key="pref_key_payment_settings">