This commit is contained in:
Jennifer Muenk 2018-01-25 00:46:01 +01:00
commit 6cb3842798
38 changed files with 1536 additions and 1001 deletions

View File

@ -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;
}
}

View File

@ -85,7 +85,7 @@ public class FundWalletFragment extends Fragment {
transactionInProgress = false; transactionInProgress = false;
if(returnStatus.equals("noError")){ if(returnStatus.equals("noError")){
balanceTextView.setText(balance + " i"); balanceTextView.setText(balance);
addressTextView.setText(depositAddress); addressTextView.setText(depositAddress);
createAddressQRCode(depositAddress); createAddressQRCode(depositAddress);
makeToastFundWalletFragment("Balance and address updated"); makeToastFundWalletFragment("Balance and address updated");

View File

@ -23,10 +23,8 @@ import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.flashwifi.wifip2p.iotaFlashWrapper.Example;
import com.flashwifi.wifip2p.iotaFlashWrapper.IotaFlashBridge; 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 com.pddstudio.preferences.encrypted.EncryptedPreferences;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -102,14 +100,16 @@ public class HomeActivity extends AppCompatActivity {
String iotaflash = readFile("iotaflash"); String iotaflash = readFile("iotaflash");
String iotaflashhelper = readFile("iotaflashhelper"); String iotaflashhelper = readFile("iotaflashhelper");
/*try { try {
IotaFlashBridge.boot(iotaflash, iotaflashhelper); IotaFlashBridge.boot(iotaflash, iotaflashhelper);
Main.runExample(); Example.setup();
Example.transaction(Example.one, Example.two);
Example.close(Example.one, Example.two);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
}*/ }
} }
@Override @Override

View File

@ -34,8 +34,6 @@ public class HotspotFragment extends Fragment {
private int numberConnectedPeers = 0; private int numberConnectedPeers = 0;
WiFiDirectBroadcastService mService;
boolean mBound = false;
BroadcastReceiver updateUIReceiver; BroadcastReceiver updateUIReceiver;
public HotspotFragment() { public HotspotFragment() {
@ -73,7 +71,7 @@ public class HotspotFragment extends Fragment {
private void updateUi(Intent intent) { private void updateUi(Intent intent) {
Log.d(TAG, "updateUi: Got some network data into the hotspot fragment"); 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); TextView text = (TextView) getActivity().findViewById(R.id.numberPeers);
text.setVisibility(View.VISIBLE); text.setVisibility(View.VISIBLE);
text.setText(String.format("%s peers", numberAvailableDevices)); 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")) { //if (intent.hasExtra("what") && intent.getExtras().getString("what", "").equals("connectivity_changed")) {
NetworkInfo network_info = mService.getNetwork_info(); NetworkInfo network_info = getmService().getNetwork_info();
WifiP2pInfo p2p_info = mService.getP2p_info(); WifiP2pInfo p2p_info = getmService().getP2p_info();
WifiP2pGroup wifiP2pGroup = mService.getP2p_group(); WifiP2pGroup wifiP2pGroup = getmService().getP2p_group();
if (intent.hasExtra("currentDeviceConnected")) { if (intent.hasExtra("currentDeviceConnected")) {
//String macAddress = intent.getExtras().getString("currentDeviceConnected"); //String macAddress = intent.getExtras().getString("currentDeviceConnected");
@ -92,11 +90,11 @@ public class HotspotFragment extends Fragment {
if (p2p_info.isGroupOwner) { if (p2p_info.isGroupOwner) {
Snackbar.make(activity_view, "You are the group owner", Snackbar.LENGTH_LONG).setAction("Action", null).show(); 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 { } else {
InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress; InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress;
Snackbar.make(activity_view, "You are only a member of the group", Snackbar.LENGTH_LONG).setAction("Action", null).show(); 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 @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
getActivity().unbindService(mConnection);
getActivity().unregisterReceiver(updateUIReceiver); getActivity().unregisterReceiver(updateUIReceiver);
mBound = false;
} }
@Override @Override
@ -129,6 +125,11 @@ public class HotspotFragment extends Fragment {
initFragment(); initFragment();
} }
public WiFiDirectBroadcastService getmService() {
MainActivity act = (MainActivity) getActivity();
return act.getmService();
}
private void initFragment(){ private void initFragment(){
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction("com.flashwifi.wifip2p.update_ui"); filter.addAction("com.flashwifi.wifip2p.update_ui");
@ -138,6 +139,10 @@ public class HotspotFragment extends Fragment {
updateUIReceiver = new BroadcastReceiver() { updateUIReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { 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")) { if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) {
String mac = intent.getStringExtra("peer_mac_address"); String mac = intent.getStringExtra("peer_mac_address");
ToggleButton toggle = (ToggleButton) getActivity().findViewById(R.id.startAPButton); ToggleButton toggle = (ToggleButton) getActivity().findViewById(R.id.startAPButton);
@ -157,10 +162,6 @@ public class HotspotFragment extends Fragment {
getActivity().registerReceiver(updateUIReceiver, filter); getActivity().registerReceiver(updateUIReceiver, filter);
// Bind to Service
Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class);
getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
initUI(); initUI();
testInternetConnection(); testInternetConnection();
@ -185,29 +186,13 @@ public class HotspotFragment extends Fragment {
// ToDo: Move this to a async task // ToDo: Move this to a async task
//boolean status = (isNetworkConnected() && isInternetAvailable()); //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() { private void startDiscovery() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout); final View activity_view = getActivity().findViewById(R.id.drawer_layout);
if (mBound) { if (getmService() != null) {
mService.setInRoleConsumer(false); getmService().setInRoleConsumer(false);
mService.setInRoleHotspot(true); getmService().setInRoleHotspot(true);
mService.getPeerList(new WifiP2pManager.ActionListener() { getmService().getPeerList(new WifiP2pManager.ActionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
// show progress wheel // show progress wheel
@ -228,12 +213,12 @@ public class HotspotFragment extends Fragment {
private void stopDiscovery() { private void stopDiscovery() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout); final View activity_view = getActivity().findViewById(R.id.drawer_layout);
if (mBound) { if (getmService() != null) {
mService.stopDiscovery(new WifiP2pManager.ActionListener() { getmService().stopDiscovery(new WifiP2pManager.ActionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
mService.setInRoleConsumer(false); getmService().setInRoleConsumer(false);
mService.setInRoleHotspot(false); getmService().setInRoleHotspot(false);
Snackbar.make(activity_view, "Stopped Hotspot mode", Snackbar.LENGTH_LONG).setAction("Action", null).show(); Snackbar.make(activity_view, "Stopped Hotspot mode", Snackbar.LENGTH_LONG).setAction("Action", null).show();
ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP); ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP);
progressBar.setVisibility(View.INVISIBLE); progressBar.setVisibility(View.INVISIBLE);
@ -241,8 +226,8 @@ public class HotspotFragment extends Fragment {
@Override @Override
public void onFailure(int reasonCode) { public void onFailure(int reasonCode) {
mService.setInRoleConsumer(false); getmService().setInRoleConsumer(false);
mService.setInRoleHotspot(false); getmService().setInRoleHotspot(false);
Snackbar.make(activity_view, "Aaaargh :( Problem stopping discovery", Snackbar.LENGTH_LONG).setAction("Action", null).show(); Snackbar.make(activity_view, "Aaaargh :( Problem stopping discovery", Snackbar.LENGTH_LONG).setAction("Action", null).show();
ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP); ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP);
progressBar.setVisibility(View.INVISIBLE); progressBar.setVisibility(View.INVISIBLE);
@ -255,12 +240,11 @@ public class HotspotFragment extends Fragment {
private void initUI() { private void initUI() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout); final View activity_view = getActivity().findViewById(R.id.drawer_layout);
final ToggleButton button = (ToggleButton) getActivity().findViewById(R.id.startAPButton); final ToggleButton button = (ToggleButton) getActivity().findViewById(R.id.startAPButton);
//button.setChecked(mService.isInRoleHotspot());
button.setOnClickListener(new View.OnClickListener() { button.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (mBound) { if (getmService() != null) {
if (!mService.isSetup()) { if (!getmService().isSetup()) {
Snackbar.make(activity_view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show(); Snackbar.make(activity_view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show();
button.setChecked(false); button.setChecked(false);
return; 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;
}
};
} }

View File

@ -1,5 +1,6 @@
package com.flashwifi.wifip2p; package com.flashwifi.wifip2p;
import android.app.ActivityManager;
import android.app.Fragment; import android.app.Fragment;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -13,6 +14,8 @@ import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
@ -24,14 +27,13 @@ import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.CompoundButton;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.Toast; import android.widget.Toast;
import com.flashwifi.wifip2p.billing.Accountant; import com.flashwifi.wifip2p.billing.Accountant;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService; import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
import com.flashwifi.wifip2p.iotaAPI.Requests.WalletBalanceChecker;
public class MainActivity extends AppCompatActivity public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener implements NavigationView.OnNavigationItemSelectedListener
@ -40,6 +42,9 @@ public class MainActivity extends AppCompatActivity
private static final String TAG = "MainAct"; private static final String TAG = "MainAct";
private String password; private String password;
private String seed; 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 DrawerLayout mDrawerLayout;
private ListView mDrawerList; private ListView mDrawerList;
@ -71,15 +76,27 @@ public class MainActivity extends AppCompatActivity
intent.getStringExtra("key")); intent.getStringExtra("key"));
} else if (intent.getAction().equals("com.flashwifi.wifip2p.stop_roaming")) { } else if (intent.getAction().equals("com.flashwifi.wifip2p.stop_roaming")) {
Log.d(TAG, "onReceive: Reset billing state"); Log.d(TAG, "onReceive: Reset billing state");
mService.resetBillingState();
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
} }
} }
}; };
registerReceiver(updateUIReceiver, filter); 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 @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
@ -110,7 +127,7 @@ public class MainActivity extends AppCompatActivity
} }
private void initUi() { private void initUi() {
final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch); /*final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch);
switch_.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() { switch_.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) { if (isChecked) {
@ -124,7 +141,7 @@ public class MainActivity extends AppCompatActivity
mService.disableService(); mService.disableService();
} }
} }
}); });*/
} }
@Override @Override
@ -140,6 +157,9 @@ public class MainActivity extends AppCompatActivity
password = intent.getStringExtra("password"); password = intent.getStringExtra("password");
seed = intent.getStringExtra("seed"); seed = intent.getStringExtra("seed");
setBalanceHandler();
updateBalance();
Accountant.getInstance().setSeed(seed); Accountant.getInstance().setSeed(seed);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
@ -153,10 +173,29 @@ public class MainActivity extends AppCompatActivity
PreferenceManager.setDefaultValues(this, R.xml.preferences, false); PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
beginForegroundService();
Intent intent2 = new Intent(this, WiFiDirectBroadcastService.class); Intent intent2 = new Intent(this, WiFiDirectBroadcastService.class);
bindService(intent2, mConnection, Context.BIND_AUTO_CREATE); 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() { private void initEverything() {
subscribeToBroadcasts(); subscribeToBroadcasts();
initUi(); initUi();
@ -245,6 +284,11 @@ public class MainActivity extends AppCompatActivity
return true; 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() { public void startSearchFragment() {
if (mBound && mService.isInRoleHotspot()) { if (mBound && mService.isInRoleHotspot()) {
Toast.makeText(this, "Can't start search because you are hotspot", Toast.LENGTH_SHORT).show(); 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; WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service;
mService = binder.getService(); mService = binder.getService();
mBound = true; mBound = true;
mService.enableService();
} }
@Override @Override
@ -388,4 +433,34 @@ public class MainActivity extends AppCompatActivity
mBound = false; 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();
}
} }

View File

@ -232,50 +232,7 @@ public class RoamingActivity extends AppCompatActivity {
} }
private void cancelNotification() { 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(); updateBillingCard();
showNotification(); // ToDo: update notification
//showNotification();
} }
private void endRoaming() { private void endRoaming() {
@ -350,6 +308,12 @@ public class RoamingActivity extends AppCompatActivity {
mService.disconnectAP(); mService.disconnectAP();
} }
mService.setRoaming(false); mService.setRoaming(false);
mService.resetBillingState();
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
PeerStore.getInstance().clear();
// hide the spinner and the stop button // hide the spinner and the stop button
ProgressBar stopProgressBar = (ProgressBar) findViewById(R.id.stopProgressBar); ProgressBar stopProgressBar = (ProgressBar) findViewById(R.id.stopProgressBar);
stopProgressBar.setVisibility(View.GONE); stopProgressBar.setVisibility(View.GONE);

View File

@ -33,6 +33,7 @@ import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService; import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
import com.flashwifi.wifip2p.iotaFlashWrapper.Main;
/** /**
* Fragment that appears in the "content_frame", shows a planet * 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"; public final static String TAG = "SearchActivity";
WiFiDirectBroadcastService mService;
boolean mBound = false;
BroadcastReceiver updateUIReceiver = null; BroadcastReceiver updateUIReceiver = null;
ArrayList<String> arrayList; ArrayList<String> arrayList;
@ -64,6 +63,14 @@ public class SearchFragment extends Fragment {
return rootView; return rootView;
} }
public WiFiDirectBroadcastService getmService() {
MainActivity act = (MainActivity) getActivity();
if (act != null) {
return act.getmService();
}
return null;
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -112,7 +119,7 @@ public class SearchFragment extends Fragment {
} }
private void startNegotiationProtocol(String macAddress){ private void startNegotiationProtocol(String macAddress){
WifiP2pInfo p2p_info = mService.getP2p_info(); WifiP2pInfo p2p_info = getmService().getP2p_info();
if (p2p_info.isGroupOwner) { if (p2p_info.isGroupOwner) {
startNegotiationProtocolServer(macAddress); startNegotiationProtocolServer(macAddress);
@ -123,13 +130,13 @@ public class SearchFragment extends Fragment {
private void startNegotiationProtocolServer(String macAddress) { private void startNegotiationProtocolServer(String macAddress) {
// starts the server if necessary // starts the server if necessary
WifiP2pInfo p2p_info = mService.getP2p_info(); WifiP2pInfo p2p_info = getmService().getP2p_info();
NetworkInfo network_info = mService.getNetwork_info(); NetworkInfo network_info = getmService().getNetwork_info();
if (network_info.getState() == NetworkInfo.State.CONNECTED) { if (network_info.getState() == NetworkInfo.State.CONNECTED) {
if (p2p_info.isGroupOwner) { if (p2p_info.isGroupOwner) {
Log.d(TAG, "You are the group owner"); Log.d(TAG, "You are the group owner");
mService.startNegotiationServer(true, macAddress); getmService().startNegotiationServer(true, macAddress);
Log.d(TAG, "SocketServer started"); Log.d(TAG, "SocketServer started");
} }
} }
@ -137,8 +144,8 @@ public class SearchFragment extends Fragment {
private void startNegotiationProtocolClient(String macAddress){ private void startNegotiationProtocolClient(String macAddress){
// starts the server if necessary // starts the server if necessary
WifiP2pInfo p2p_info = mService.getP2p_info(); WifiP2pInfo p2p_info = getmService().getP2p_info();
NetworkInfo network_info = mService.getNetwork_info(); NetworkInfo network_info = getmService().getNetwork_info();
if (network_info.getState() == NetworkInfo.State.CONNECTED) { if (network_info.getState() == NetworkInfo.State.CONNECTED) {
if (!p2p_info.isGroupOwner) { if (!p2p_info.isGroupOwner) {
@ -146,7 +153,7 @@ public class SearchFragment extends Fragment {
// groupOwnerAddress = p2p_info.groupOwnerAddress; // groupOwnerAddress = p2p_info.groupOwnerAddress;
InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress; InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress;
Log.d(TAG, "Group owner address: " + p2p_info.groupOwnerAddress.getHostAddress()); 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"); Log.d(TAG, "Client Socket started");
} }
} }
@ -155,10 +162,6 @@ public class SearchFragment extends Fragment {
@Override @Override
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
if (mBound) {
getActivity().unbindService(mConnection);
mBound = false;
}
if (updateUIReceiver != null) { if (updateUIReceiver != null) {
getActivity().unregisterReceiver(updateUIReceiver); getActivity().unregisterReceiver(updateUIReceiver);
updateUIReceiver = null; updateUIReceiver = null;
@ -168,10 +171,6 @@ public class SearchFragment extends Fragment {
@Override @Override
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
if (mBound) {
getActivity().unbindService(mConnection);
mBound = false;
}
if (updateUIReceiver != null) { if (updateUIReceiver != null) {
getActivity().unregisterReceiver(updateUIReceiver); getActivity().unregisterReceiver(updateUIReceiver);
updateUIReceiver = null; updateUIReceiver = null;
@ -200,6 +199,10 @@ public class SearchFragment extends Fragment {
updateUIReceiver = new BroadcastReceiver() { updateUIReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (getActivity() == null) {
Log.d(TAG, "onReceive: getActivity is null");
return;
}
Log.d("", "onReceive: FRAGMENT HAT WAS"); Log.d("", "onReceive: FRAGMENT HAT WAS");
if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) { if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) {
String mac = intent.getStringExtra("peer_mac_address"); String mac = intent.getStringExtra("peer_mac_address");
@ -217,10 +220,6 @@ public class SearchFragment extends Fragment {
}; };
getActivity().registerReceiver(updateUIReceiver, filter); 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); view = getActivity().findViewById(R.id.fragment_view);
initUI(); initUI();
@ -235,26 +234,20 @@ public class SearchFragment extends Fragment {
toggle.setOnClickListener(new View.OnClickListener() { toggle.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(final View view) { public void onClick(final View view) {
if (mBound) { if (!getmService().isSetup()) {
if (!mService.isSetup()) { Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show();
Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show(); toggle.setChecked(false);
toggle.setChecked(false); return;
return;
}
} }
updateList(); updateList();
if (toggle.isChecked()) { if (toggle.isChecked()) {
if (mBound) { getmService().setInRoleHotspot(false);
mService.setInRoleHotspot(false); getmService().setInRoleConsumer(true);
mService.setInRoleConsumer(true); startSearching();
startSearching();
}
} else { } else {
if (mBound) { getmService().setInRoleHotspot(false);
mService.setInRoleHotspot(false); getmService().setInRoleConsumer(false);
mService.setInRoleConsumer(false); stopSearching();
stopSearching();
}
} }
} }
}); });
@ -298,7 +291,7 @@ public class SearchFragment extends Fragment {
public void startChat(final String address, String name) { public void startChat(final String address, String name) {
mService.connect(address, new WifiP2pManager.ActionListener() { getmService().connect(address, new WifiP2pManager.ActionListener() {
@Override @Override
public void onSuccess() { public void onSuccess() {
Toast.makeText(view.getContext(), "Connected to peer", Toast.LENGTH_SHORT).show(); Toast.makeText(view.getContext(), "Connected to peer", Toast.LENGTH_SHORT).show();
@ -315,53 +308,31 @@ public class SearchFragment extends Fragment {
} }
private void stopSearching() { private void stopSearching() {
if (mBound) { getmService().stopDiscovery(new WifiP2pManager.ActionListener() {
mService.stopDiscovery(new WifiP2pManager.ActionListener() { @Override
@Override public void onSuccess() {
public void onSuccess() { Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show();
Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show(); }
}
@Override @Override
public void onFailure(int reasonCode) { public void onFailure(int reasonCode) {
Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show(); Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
} }
}); });
}
} }
public void startSearching() { 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) { @Override
mService.getPeerList(new WifiP2pManager.ActionListener() { public void onFailure(int reasonCode) {
@Override Snackbar.make(view, "Aaaargh :( Peering problem!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
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();
}
});
}
} }
/** 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;
}
};
} }

View File

@ -103,13 +103,14 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch(key){ switch(key){
case "pref_key_security": case "pref_key_security":
makeToastSettingsFragment("Security Changed"); //makeToastSettingsFragment("Security Changed");
break; break;
case "pref_key_network_timeout": case "pref_key_network_timeout":
makeToastSettingsFragment("Network Timeout Changed"); //makeToastSettingsFragment("Network Timeout Changed");
break; break;
case "pref_key_units": case "pref_key_units":
makeToastSettingsFragment("Units Changed"); makeToastSettingsFragment("Units Changed");
//makeToastSettingsFragment("Units Changed");
break; break;
case "pref_key_switch_testnet": case "pref_key_switch_testnet":
makeToastSettingsFragment("Testnet on/off Changed"); makeToastSettingsFragment("Testnet on/off Changed");

View File

@ -95,11 +95,11 @@ public class WithdrawWalletFragment extends Fragment {
transactionInProgress = false; transactionInProgress = false;
if(returnStatus.equals("noError")){ if(returnStatus.equals("noError")){
balanceTextView.setText(appWalletBalance + " i"); balanceTextView.setText(appWalletBalance);
makeToastFundWalletFragment("Balance updated"); makeToastFundWalletFragment("Balance updated");
} }
else if (returnStatus.equals("noErrorNoUpdateMessage")){ else if (returnStatus.equals("noErrorNoUpdateMessage")){
balanceTextView.setText(appWalletBalance + " i"); balanceTextView.setText(appWalletBalance);
clearAllTransferValues(); clearAllTransferValues();
makeFieldsEditable(); makeFieldsEditable();
} }

View File

@ -197,6 +197,7 @@ public class BillingClient {
if (error_count >= maxErrorCount) { if (error_count >= maxErrorCount) {
// stop trying to connect // stop trying to connect
Log.d(TAG, "start: error count too high");
state = State.ERROR; state = State.ERROR;
sendUpdateUIBroadcastWithMessage("Exit"); sendUpdateUIBroadcastWithMessage("Exit");
} }

View File

@ -244,13 +244,17 @@ public class BillingServer {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
try { try {
socketWrapper.close(); if (socketWrapper != null) {
} catch (IOException e) { socketWrapper.close();
}
} catch (Exception e) {
} }
try { try {
serverSocket.close(); if (serverSocket != null) {
} catch (IOException e) { serverSocket.close();
}
} catch (Exception e) {
} }
} }

View File

@ -1,11 +1,16 @@
package com.flashwifi.wifip2p.broadcast; package com.flashwifi.wifip2p.broadcast;
import android.app.Activity; import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.DhcpInfo;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig; import android.net.wifi.p2p.WifiP2pConfig;
@ -20,9 +25,14 @@ import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.format.Formatter;
import android.util.Log; import android.util.Log;
import com.flashwifi.wifip2p.AddressBalanceTransfer; 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.AccessPointTask;
import com.flashwifi.wifip2p.accesspoint.ConnectTask; import com.flashwifi.wifip2p.accesspoint.ConnectTask;
import com.flashwifi.wifip2p.accesspoint.StopAccessPointTask; 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.NegotiationOffer;
import com.flashwifi.wifip2p.protocol.NegotiationOfferAnswer; import com.flashwifi.wifip2p.protocol.NegotiationOfferAnswer;
import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -96,6 +110,57 @@ public class WiFiDirectBroadcastService extends Service {
ConnectTask connectTask; ConnectTask connectTask;
private boolean negotiatorRunning = false; 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() { public boolean isSetup() {
return setup; return setup;
} }
@ -165,9 +230,23 @@ public class WiFiDirectBroadcastService extends Service {
@Override @Override
public void run() { public void run() {
BillingClient billingClient = new BillingClient(mac, getApplicationContext()); 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 // 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 // ToDo: handle billingServer EXIT CODES
// -> close the roaming etc. // -> close the roaming etc.
} }
@ -379,7 +458,7 @@ public class WiFiDirectBroadcastService extends Service {
stopAllTasks(); stopAllTasks();
thread.start(); thread.start();
} else { } else {
Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state"); Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state or negotiator running");
} }

View File

@ -76,14 +76,13 @@ public class WalletAddressChecker {
SharedPreferences prefManager = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefManager = PreferenceManager.getDefaultSharedPreferences(context);
String security = prefManager.getString("pref_key_security","2"); String security = prefManager.getString("pref_key_security","2");
int securityInt = Integer.parseInt(security); int securityInt = Integer.parseInt(security);
System.out.println("securityInt: "+securityInt);
addressResponse = api.getNewAddress(seed, securityInt, keyIndex, true, 1, false); addressResponse = api.getNewAddress(seed, securityInt, keyIndex, true, 1, false);
} catch (ArgumentException e) { } catch (ArgumentException e) {
e.printStackTrace(); e.printStackTrace();
return addressList;
} }
if(addressResponse != null) { if(addressResponse != null) {
System.out.println("WalletAddressChecker - Address: "+addressResponse.getAddresses().get(0));
addressList.add(addressResponse.getAddresses().get(0)); addressList.add(addressResponse.getAddresses().get(0));
String[] addressesCheckArray = new String[1]; 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 //Transactions not found, use this address
foundAddress = true; foundAddress = true;
} }
@ -110,11 +109,6 @@ public class WalletAddressChecker {
String curHash = transactionsForAddress.get(0).getHash(); String curHash = transactionsForAddress.get(0).getHash();
hashStringList.add(curHash); 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; keyIndex = keyIndex + 1;
} }
} }
@ -130,34 +124,27 @@ public class WalletAddressChecker {
//Check whether pending transactions exist //Check whether pending transactions exist
containsPendingTransaction = false; containsPendingTransaction = false;
keyIndexChanged = false; keyIndexChanged = false;
GetInclusionStateResponse inclusionResponse;
try { try {
GetInclusionStateResponse inclusionResponse = api.getLatestInclusion(hashStringArray); inclusionResponse = api.getLatestInclusion(hashStringArray);
boolean[] states = inclusionResponse.getStates(); } catch (ArgumentException | IllegalStateException e) {
for (boolean state : states) {
if(!state){
containsPendingTransaction = true;
}
}
} catch (ArgumentException e) {
e.printStackTrace(); e.printStackTrace();
return addressList;
} }
System.out.println("containsPendingTransaction: "+containsPendingTransaction); boolean[] states = inclusionResponse.getStates();
for (boolean state : states) {
if(!state){
containsPendingTransaction = true;
}
}
if(!containsPendingTransaction){ if(!containsPendingTransaction){
//all confirmed transactions, ok to change keyIndex //all confirmed transactions, ok to change keyIndex
if(keyIndex != getKeyIndex()){ if(keyIndex != getKeyIndex()){
keyIndexChanged = true; keyIndexChanged = true;
if(keyIndex == 0){ putKeyIndex(keyIndex);
//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);
}
} }
} }

View File

@ -10,6 +10,8 @@ import android.preference.PreferenceManager;
import com.flashwifi.wifip2p.AddressBalanceTransfer; import com.flashwifi.wifip2p.AddressBalanceTransfer;
import com.flashwifi.wifip2p.R; import com.flashwifi.wifip2p.R;
import java.text.DateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import jota.IotaAPI; import jota.IotaAPI;
@ -24,6 +26,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
private static final int FUND_WALLET = 0; private static final int FUND_WALLET = 0;
private static final int WITHDRAW_WALLET = 1; private static final int WITHDRAW_WALLET = 1;
private static final int PREF_UPDATE = 2;
private static IotaAPI api; private static IotaAPI api;
private static Context context; private static Context context;
@ -76,6 +79,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
if(context != null){ if(context != null){
WalletAddressChecker addressChecker = new WalletAddressChecker(context,prefFile); WalletAddressChecker addressChecker = new WalletAddressChecker(context,prefFile);
@ -83,8 +87,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
boolean containsPendingTransactions = addressChecker.getContainsPendingTransaction(); boolean containsPendingTransactions = addressChecker.getContainsPendingTransaction();
boolean keyIndexChanged = addressChecker.getkeyIndexChanged(); boolean keyIndexChanged = addressChecker.getkeyIndexChanged();
System.out.println("seed: "+seed);
if(addressList != null && addressList.get(0).equals("Unable to resolve host")){ if(addressList != null && addressList.get(0).equals("Unable to resolve host")){
AddressBalanceTransfer addressBalanceTransfer = new AddressBalanceTransfer(null,null,"hostError"); AddressBalanceTransfer addressBalanceTransfer = new AddressBalanceTransfer(null,null,"hostError");
Message completeMessage = mHandler.obtainMessage(BALANCE_RETRIEVE_TASK_COMPLETE, addressBalanceTransfer); Message completeMessage = mHandler.obtainMessage(BALANCE_RETRIEVE_TASK_COMPLETE, addressBalanceTransfer);
@ -126,10 +128,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
public String getBalance(List<String> inAddresses, boolean containsPendingTransactions, boolean keyIndexChanged){ public String getBalance(List<String> inAddresses, boolean containsPendingTransactions, boolean keyIndexChanged){
for (String inAddress : inAddresses) {
System.out.println("addressGetBalance: "+inAddress);
}
String updatedBalanceString; String updatedBalanceString;
try { try {
StopWatch stopWatch = new StopWatch(); StopWatch stopWatch = new StopWatch();
@ -140,11 +138,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
GetBalancesAndFormatResponse balanceResponse = api.getBalanceAndFormat(inAddresses, 0, 0, stopWatch, securityInt); GetBalancesAndFormatResponse balanceResponse = api.getBalanceAndFormat(inAddresses, 0, 0, stopWatch, securityInt);
long total = balanceResponse.getTotalBalance(); long total = balanceResponse.getTotalBalance();
System.out.println("getTotalBalance: "+total);
long storedBaseBalance = Long.parseLong(getBaseSharedPrefKeyBalance()); long storedBaseBalance = Long.parseLong(getBaseSharedPrefKeyBalance());
System.out.println("getBaseSharedPreKeyBalance: "+storedBaseBalance);
long updatedBaseBalance = storedBaseBalance + total; long updatedBaseBalance = storedBaseBalance + total;
updatedBalanceString = Long.toString(updatedBaseBalance); updatedBalanceString = Long.toString(updatedBaseBalance);
@ -163,26 +157,35 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
//No Pending Transactions, new confirmed transactions //No Pending Transactions, new confirmed transactions
else if(!containsPendingTransactions && keyIndexChanged){ else if(!containsPendingTransactions && keyIndexChanged){
putBaseSharedPrefBalance(updatedBalanceString); putBaseSharedPrefBalance(updatedBalanceString);
System.out.println("Store new base balance");
System.out.println("updated balance: "+updatedBaseBalance);
updatedBalanceString = Long.toString(updatedBaseBalance); updatedBalanceString = Long.toString(updatedBaseBalance);
putSharedPrefBalance(updatedBalanceString); putSharedPrefBalance(updatedBalanceString);
} }
} catch (ArgumentException | IllegalStateException e) { } catch (ArgumentException | IllegalStateException e) {
e.printStackTrace(); 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() { private String getSharedPrefKeyBalance() {
SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE); SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE);
int keyIndex = sharedPref.getInt("keyIndex",0);
System.out.println("KeyIndex: "+keyIndex);
String defaultValue = "0"; String defaultValue = "0";
String storedBalance = sharedPref.getString("balance",defaultValue); String storedBalance = sharedPref.getString("balance",defaultValue);
return storedBalance; return storedBalance;
@ -198,10 +201,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
private String getBaseSharedPrefKeyBalance() { private String getBaseSharedPrefKeyBalance() {
SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE); SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE);
int keyIndex = sharedPref.getInt("keyIndex",0);
System.out.println("KeyIndex: "+keyIndex);
String defaultValue = "0"; String defaultValue = "0";
String storedBalance = sharedPref.getString("baseBalance",defaultValue); String storedBalance = sharedPref.getString("baseBalance",defaultValue);
return storedBalance; return storedBalance;

View File

@ -148,8 +148,6 @@ public class WalletTestnetTokenGen extends AsyncTask<Void, Void, Void> {
private void transferToWallet(List<String> destAddressses, TokenGenJSONResponse token) { private void transferToWallet(List<String> destAddressses, TokenGenJSONResponse token) {
System.out.println("2000 seed: "+token.getSeed());
if(destAddressses != null && destAddressses.get(0).equals("Unable to resolve host")){ if(destAddressses != null && destAddressses.get(0).equals("Unable to resolve host")){
//Host Error //Host Error
Message completeMessage = settingsFragmentHandler.obtainMessage(TOKEN_TESTNET_RETRIEVE_TASK_COMPLETE, "hostError"); Message completeMessage = settingsFragmentHandler.obtainMessage(TOKEN_TESTNET_RETRIEVE_TASK_COMPLETE, "hostError");
@ -161,9 +159,6 @@ public class WalletTestnetTokenGen extends AsyncTask<Void, Void, Void> {
completeMessage.sendToTarget(); completeMessage.sendToTarget();
String destAddress = destAddressses.get(destAddressses.size()-1); 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); WalletTransferRequest transferRequest = new WalletTransferRequest(destAddress,token.getSeed(),token.getAmount().toString(),"","",context,testnetTokenGenHandler);
transferRequest.execute(); transferRequest.execute();
} }

View File

@ -107,7 +107,6 @@ public class WalletTransferRequest extends AsyncTask<Void, Void, Void> {
try { try {
if(testnet) { if(testnet) {
//Testnet //Testnet
System.out.println("WalletTransferRequest: Testnet");
if(testnetPrivate){ if(testnetPrivate){
sendTransferResponse = api.sendTransfer(appWalletSeed, securityInt, 4, 3, transfers, null, null, false); sendTransferResponse = api.sendTransfer(appWalletSeed, securityInt, 4, 3, transfers, null, null, false);
} }
@ -155,7 +154,6 @@ public class WalletTransferRequest extends AsyncTask<Void, Void, Void> {
else{ else{
transferResult = "Transfer error: Send Response not received"; transferResult = "Transfer error: Send Response not received";
} }
System.out.println("WalletTransferRequest - result: "+transferResult);
return transferResult; return transferResult;
} }
} }

View File

@ -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<String> 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<Digest> initialDigestsOne = one.initialChannelDigests();
List<Digest> 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<List<Digest>> 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<Digest> senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate());
// Send senderDigests to user two and wait for his digests.
// User two makes digests.
ArrayList<Digest> recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate());
// When you have both you can create a digest array
List<List<Digest>> 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<Transfer> transfers = new ArrayList<>();
transfers.add(new Transfer(reciever.getSettlementAddress(), 10));
// Create a transaction from a transfer.
ArrayList<Bundle> 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<Signature> receiverSignatures = two.createSignaturesForBundles(senderBundles);
// Now both just have to apply the signatures and check if all is good.
ArrayList<Bundle> senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
ArrayList<Bundle> 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<Digest> senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate());
// Send senderDigests to user two and wait for his digests.
// User two makes digests.
ArrayList<Digest> recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate());
// When you have both you can create a digest array
List<List<Digest>> 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<Bundle> 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<Signature> receiverSignatures = two.createSignaturesForBundles(senderBundles);
// Now both just have to apply the signatures and check if all is good.
ArrayList<Bundle> senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
ArrayList<Bundle> 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<Bundle> attachedBundles = Helpers.POWClosedBundle(senderSignedBundles, 4, 13);
}
}

View File

@ -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<Digest> 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<String> 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<List<Digest>> digestPairs) {
if (digestPairs.size() != user.getFlash().getSignersCount()) {
Log.d("[ERROR]", " Not enough digest pairs found...");
return;
}
// Create multisigs.
List<Multisig> 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<List<Digest>> 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<Signature> createSignaturesForBundles(ArrayList<Bundle> bundles) {
return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles);
}
public void applyTransfers(ArrayList<Bundle> signedBundles) {
Helpers.applyTransfers(signedBundles, user);
}
/**
* Closing utils
*/
public ArrayList<Bundle> 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());
}
}

View File

@ -1,95 +1,467 @@
package com.flashwifi.wifip2p.iotaFlashWrapper; package com.flashwifi.wifip2p.iotaFlashWrapper;
import com.google.gson.Gson;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Helpers { public class Helpers {
public static ArrayList<Bundle> createTransaction(UserObject user, ArrayList<Transfer> transfers, boolean shouldClose) { private static boolean useTestnet = true;
CreateTransactionHelperObject toUse = IotaFlashBridge.updateLeafToRoot(user.getFlash().getRoot()); private static String seedGeneratorURL = "http://87.118.96.200:3000"; //"https://seeedy.tangle.works";
if (toUse.getGenerate() != 0) { private static String testNetNodeURL = "https://testnet140.tangle.works:443";
// TODO: tell the server to gen new address. private static String netNodeURL = "http://node.iotawallet.info:14265"; // "http://87.118.96.200:14700";//
System.out.println("No more addresses in channel."); private static IotaAPI iotaAPI = null;
}
ArrayList<Transfer> 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<Bundle> createTransaction(ArrayList<Transfer> 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<Bundle> bundles = IotaFlashBridge.compose(
user.getFlash().getBalance(), FlashObject flash = user.getFlash();
user.getFlash().getDeposits(), ArrayList<Bundle> bundles;
user.getFlash().getOutputs(), // Prepare a new transaction.
toUse.getAddress(), ArrayList<Transfer> newTransfers = IotaFlashBridge.prepare(
user.getFlash().getRemainderAddress(), flash.getSettlementAddresses(),
user.getFlash().getTransfers(), flash.getDeposits(),
newTransfers, user.getUserIndex(),
shouldClose transfers
); );
return bundles;
}
public static ArrayList<Signature> signTransaction(UserObject user, ArrayList<Bundle> bundles) { if (newTransfers == null) {
return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles); return new ArrayList<>();
}
//
// public static ArrayList<Bundle> appliedSignatures(ArrayList<Bundle> bundles, ArrayList<Signature> signatures) {
// ArrayList<Bundle> 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<Transaction> transactions = b.getBundles();
// String addy = transactions.stream().filter(tx -> tx.getValue() < 0).findFirst().get().getAddress();
// List<Transaction> 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<Bundle> 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<Bundle> clone(ArrayList<Bundle> bundles) {
ArrayList<Bundle> clonedBundles = new ArrayList<>();
for (Bundle b : bundles) {
clonedBundles.add(b.clone());
} }
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<Signature> 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<Bundle> closeChannel(UserObject user) {
FlashObject flash = user.getFlash();
ArrayList<Transfer> closeTransfers = IotaFlashBridge.close(flash.getSettlementAddresses(), flash.getDeposits());
// Compose the transaction. This may also add some management transactions (moving remainder tokens.)
ArrayList<Bundle> 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<Signature> 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<Digest> getNewBranchDigests(UserObject user, int toGenerate) {
ArrayList<Digest> 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<Digest> oneDigests, ArrayList<Digest> twoDigests, UserObject user, Multisig address) {
List<List<Digest>> userDigestList = new ArrayList<>();
userDigestList.add(oneDigests);
userDigestList.add(twoDigests);
return getNewBranch(userDigestList, user, address);
}
public static Multisig getNewBranch(List<List<Digest>> digestPairs, UserObject user, Multisig address) {
List<Multisig> 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<Digest> getDigestsForUser(UserObject user, int TREE_DEPTH) {
ArrayList<Digest> 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<Multisig> getMultisigsForUser(List<List<Digest>> allDigests, UserObject currentUser) {
// Generate the first addresses
ArrayList<Multisig> multisigs = new ArrayList<Multisig>();
// Loop for all digests.
for (int index = 0; index < allDigests.get(0).size(); index++) {
ArrayList<Digest> 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<Bundle> 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<jota.model.Transaction> sendTrytes(String[] trytes, IotaAPI api, int depth, int minWeightMagnitude) {
try {
System.out.println("[INFO] Sinding close bundle... This can take some time");
List<jota.model.Transaction> 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<jota.model.Transaction>();
}
public static List<Bundle> POWClosedBundle(List<Bundle> bundles, int depth, int minWeightMagnitude) {
List<Bundle> attachedBundles = new ArrayList<>();
for (Bundle b : bundles) {
String[] trytes = b.toTrytesArray();
List<jota.model.Transaction> 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<String, Integer> transfers = flash.getOutputs();
for (Map.Entry<String, Integer> 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<String> 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()
);
} }
} }

View File

@ -1,21 +1,17 @@
package com.flashwifi.wifip2p.iotaFlashWrapper; package com.flashwifi.wifip2p.iotaFlashWrapper;
import com.eclipsesource.v8.*; import com.eclipsesource.v8.*;
import com.eclipsesource.v8.utils.V8ObjectUtils; import com.eclipsesource.v8.utils.V8ObjectUtils;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class IotaFlashBridge { public class IotaFlashBridge {
private static V8 engine; private static V8 engine;
private static V8Object transfer; private static V8Object transfer;
@ -45,7 +41,7 @@ public class IotaFlashBridge {
* @param digests * @param digests
* @return * @return
*/ */
public static MultisigAddress composeAddress(ArrayList<Digest> digests) { public static Multisig composeAddress(ArrayList<Digest> digests) {
// Create js object for digest // Create js object for digest
List<Object> list = new ArrayList<Object>(); List<Object> list = new ArrayList<Object>();
for (Digest digest: digests) { for (Digest digest: digests) {
@ -58,17 +54,12 @@ public class IotaFlashBridge {
V8Array params = V8ObjectUtils.toV8Array(engine, paramsList); V8Array params = V8ObjectUtils.toV8Array(engine, paramsList);
V8Object retV8 = multisig.executeObjectFunction("composeAddress", params); V8Object retV8 = multisig.executeObjectFunction("composeAddress", params);
// Create multisig.
// Parse return values from JS into Java world. Multisig multisig = V8Converter.multisigAddressFromV8Object(retV8);
Map<String, ? super Object> 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);
params.release(); params.release();
retV8.release(); retV8.release();
return ret; return multisig;
} }
/** /**
@ -99,7 +90,7 @@ public class IotaFlashBridge {
* *
* @param root * @param root
*/ */
public static CreateTransactionHelperObject updateLeafToRoot(MultisigAddress root) { public static CreateTransactionHelperObject updateLeafToRoot(Multisig root) {
Map<String, Object> map = root.toMap(); Map<String, Object> map = root.toMap();
// Create param list // Create param list
List<Object> paramsObj = new ArrayList<Object>(); List<Object> paramsObj = new ArrayList<Object>();
@ -109,7 +100,7 @@ public class IotaFlashBridge {
V8Object ret = multisig.executeObjectFunction("updateLeafToRoot", params); V8Object ret = multisig.executeObjectFunction("updateLeafToRoot", params);
int generate = ret.getInteger("generate"); int generate = ret.getInteger("generate");
V8Object multisigObject = (V8Object) ret.getObject("multisig"); V8Object multisigObject = (V8Object) ret.getObject("multisig");
MultisigAddress multisig = V8Converter.multisigAddressFromV8Object(multisigObject); Multisig multisig = V8Converter.multisigAddressFromV8Object(multisigObject);
return new CreateTransactionHelperObject(generate, multisig); return new CreateTransactionHelperObject(generate, multisig);
} }
@ -122,7 +113,7 @@ public class IotaFlashBridge {
* @param transfers array of all transfers (value, address) pairs * @param transfers array of all transfers (value, address) pairs
* @return * @return
*/ */
public static ArrayList<Transfer> prepare(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits, int index, ArrayList<Transfer> transfers) { public static ArrayList<Transfer> prepare(List<String> settlementAddresses, List<Double> deposits, int index, List<Transfer> transfers) {
// Now put all params into JS ready array. // Now put all params into JS ready array.
List<Object> params = new ArrayList<>(); List<Object> params = new ArrayList<>();
@ -132,8 +123,14 @@ public class IotaFlashBridge {
params.add(V8Converter.transferListToV8Array(engine, transfers)); params.add(V8Converter.transferListToV8Array(engine, transfers));
// Call js function. // Call js function.
V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params)); try {
return V8Converter.transferListFromV8Array(ret); 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 * @param deposits
* @return * @return
*/ */
public static ArrayList<Transfer> close(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits) { public static ArrayList<Transfer> close(List<String> settlementAddresses, List<Double> deposits) {
V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses); V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses);
// Deposits // Deposits
V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits); V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits);
@ -170,27 +167,24 @@ public class IotaFlashBridge {
* @return * @return
*/ */
public static ArrayList<Bundle> compose(int balance, public static ArrayList<Bundle> compose(int balance,
List<Integer> deposits, List<Double> deposits,
ArrayList<Bundle> outputs, Map<String, Integer> outputs,
MultisigAddress root, Multisig root,
MultisigAddress remainderAddress, Multisig remainderAddress,
ArrayList<Bundle> history, List<Bundle> history,
ArrayList<Transfer> transfers, List<Transfer> transfers,
boolean close) { boolean close) {
// Create params. // Create params.
// Now put all params into JS ready array. // Now put all params into JS ready array.
List<Object> params = new ArrayList<Object>(); List<Object> params = new ArrayList<Object>();
params.add(balance); params.add(balance);
params.add(V8ObjectUtils.toV8Array(engine, deposits)); 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, root));
params.add(V8Converter.multisigToV8Object(engine, remainderAddress)); params.add(V8Converter.multisigToV8Object(engine, remainderAddress));
params.add(V8Converter.bundleListToV8Array(engine, history)); params.add(V8Converter.bundleListToV8Array(engine, history));
params.add(V8Converter.transferListToV8Array(engine, transfers)); params.add(V8Converter.transferListToV8Array(engine, transfers));
params.add(close);
// Call js function. // Call js function.
V8Array ret = transfer.executeArrayFunction("compose", V8ObjectUtils.toV8Array(engine, params)); V8Array ret = transfer.executeArrayFunction("compose", V8ObjectUtils.toV8Array(engine, params));
@ -204,7 +198,7 @@ public class IotaFlashBridge {
* @param bundles * @param bundles
* @return * @return
*/ */
public static ArrayList<Signature> sign(MultisigAddress root, String seed, ArrayList<Bundle> bundles) { public static ArrayList<Signature> sign(Multisig root, String seed, ArrayList<Bundle> bundles) {
// Create params. // Create params.
// Now put all params into JS ready array. // Now put all params into JS ready array.
@ -257,10 +251,10 @@ public class IotaFlashBridge {
* @param signedBundles * @param signedBundles
* @return * @return
*/ */
public static void applyTransfers(MultisigAddress root, public static void applyTransfers(Multisig root,
ArrayList<Integer> deposits, ArrayList<Integer> deposits,
ArrayList<Bundle> outputs, ArrayList<Bundle> outputs,
MultisigAddress remainderAddress, Multisig remainderAddress,
ArrayList<Bundle> transfers, ArrayList<Bundle> transfers,
ArrayList<Bundle> signedBundles) { ArrayList<Bundle> signedBundles) {
// Construct Java params // Construct Java params
@ -288,4 +282,25 @@ public class IotaFlashBridge {
ret.release(); ret.release();
return flash; 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");
}
} }

View File

@ -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<Integer> 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<UserObject> allUsers = new ArrayList<UserObject>();
allUsers.add(oneFlash);
allUsers.add(twoFlash);
// Create partial digests for users.
createInitialPartialDigests(allUsers, oneFlash);
createInitialPartialDigests(allUsers, twoFlash);
ArrayList<MultisigAddress> oneMultisigs = oneFlash.getMultisigDigests();
ArrayList<MultisigAddress> 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<String> 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<Transfer> 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<Bundle> bundles = Helpers.createTransaction(oneFlash, transfers, false);
ArrayList<Bundle> partialSignedBundles = signTransfer(bundles, oneFlash);
ArrayList<Bundle> 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<Bundle> signTransfer(ArrayList<Bundle> bundles, UserObject user) {
System.out.println("[SUCCESS] Created signatures for users.");
ArrayList<Signature> 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<Bundle> 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<UserObject> allUsers, UserObject currentUser) {
// Generate the first addresses
ArrayList<MultisigAddress> oneMultisigs = new ArrayList<MultisigAddress>();
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<Digest> 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<MultisigAddress> shiftCopyArray(ArrayList<MultisigAddress> input) {
ArrayList<MultisigAddress> 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<Digest> digests = new ArrayList<Digest>();
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<String> settlementAddr = new ArrayList<String>();
settlementAddr.add("RCZHCRDWMGJPHKROKEGVADVJXPGKEKNJRNLZZFPITUVEWNPGIWNUMKTYKMNB9DCNLWGMJZDNKYQDQKDLC");
ArrayList<Integer> depositsPrep = new ArrayList<Integer>();
ArrayList<Transfer> transfers = new ArrayList<Transfer>();
IotaFlashBridge.prepare(settlementAddr, depositsPrep, 0, transfers);
}
}

View File

@ -1,50 +1,63 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model; 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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class Bundle extends jota.model.Bundle {
public class Bundle { public Bundle(List<Transaction> transactions) {
private ArrayList<Transaction> bundles; super(transactions, transactions.size());
public Bundle(ArrayList<Transaction> bundles) {
this.bundles = bundles;
} }
public Bundle() { public Bundle() {
this.bundles = new ArrayList<>(); super();
} }
@Override @Override
public String toString() { public String toString() {
String out = ""; String out = "";
for (Transaction t: bundles) { for (Transaction t: getTransactions()) {
out += t.toString(); out += t.toString();
out += "\n"; out += "\n";
} }
return out; return out;
} }
public String[] toTrytesArray() {
String[] bundleTrytes = new String[getTransactions().size()];
List<jota.model.Transaction> transactions = getTransactions();
for (int i = 0; i < bundleTrytes.length; i++) {
bundleTrytes[(bundleTrytes.length - 1) - i] = transactions.get(i).toTrytes();
}
return bundleTrytes;
}
public Map<String, Object> toMap() { public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
List<Object> bundleList = new ArrayList<Object>();
for (Transaction b: bundles) { map.put("bundles", toArrayList());
bundleList.add(b.toMap());
}
map.put("bundles", bundleList);
return map; return map;
} }
public ArrayList<Transaction> getBundles() { public List<Object> toArrayList() {
return bundles; List<Object> bundleList = new ArrayList<Object>();
for (Transaction tx: getTransactions()) {
bundleList.add(V8Converter.transactionToMap(tx));
}
return bundleList;
} }
public Bundle clone() { public Bundle clone() {
ArrayList<Transaction> clonedTransactions = new ArrayList<>(); ArrayList<Transaction> clonedTransactions = new ArrayList<>();
for (Transaction t: bundles) { for (Transaction tx: getTransactions()) {
clonedTransactions.add(t.clone()); clonedTransactions.add(Helpers.cloneTransaction(tx));
} }
return new Bundle(clonedTransactions); return new Bundle(clonedTransactions);
} }

View File

@ -1,11 +1,10 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model; package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
public class CreateTransactionHelperObject { public class CreateTransactionHelperObject {
private int generate = 0; 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.generate = gen;
this.address = addr; this.address = addr;
} }
@ -14,7 +13,11 @@ public class CreateTransactionHelperObject {
return generate; return generate;
} }
public MultisigAddress getAddress() { public Multisig getAddress() {
return address; return address;
} }
public void setAddress(Multisig address) {
this.address = address;
}
} }

View File

@ -1,5 +1,4 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model; package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -17,7 +16,6 @@ public class Digest {
public int getIndex() { public int getIndex() {
return index; return index;
} }
public String getDigest() { public String getDigest() {
return digest; return digest;
} }

View File

@ -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;
}
}

View File

@ -1,28 +1,36 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model; package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import java.util.ArrayList; import com.eclipsesource.v8.utils.V8ObjectUtils;
import java.util.HashMap;
import java.util.Map; import java.util.*;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
public class FlashObject { public class FlashObject {
int signersCount = 2; private int signersCount = 2;
int balance; private int balance;
ArrayList<String> settlementAddresses; private List<String> settlementAddresses;
ArrayList<Integer> deposits; // Clone correctly private List<Double> deposits;
ArrayList<Bundle> outputs = new ArrayList<Bundle>(); private Map<String, Integer> outputs = new HashMap<>();
ArrayList<Bundle> transfers = new ArrayList<Bundle>(); private List<Bundle> transfers = new ArrayList<Bundle>();
MultisigAddress root; private Multisig root;
MultisigAddress remainderAddress; private Multisig remainderAddress;
private int depth;
private int security;
public FlashObject(double[] deposits, int depth, int security) {
public FlashObject(int signersCount, int balance, ArrayList<Integer> deposits) { this.signersCount = deposits.length;
this.signersCount = signersCount; for (double dep : deposits) {
this.balance = balance; this.balance += dep;
this.deposits = deposits; }
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<String> settlementAddresses, ArrayList<Integer> deposits, ArrayList<Bundle> outputs, ArrayList<Bundle> transfers, MultisigAddress root, MultisigAddress remainderAddress) { public FlashObject(int signersCount, int balance, List<String> settlementAddresses, List<Double> deposits, Map<String, Integer> outputs, List<Bundle> transfers, Multisig root, Multisig remainderAddress, int depth, int security) {
this.signersCount = signersCount; this.signersCount = signersCount;
this.balance = balance; this.balance = balance;
this.settlementAddresses = settlementAddresses; this.settlementAddresses = settlementAddresses;
@ -31,35 +39,8 @@ public class FlashObject {
this.transfers = transfers; this.transfers = transfers;
this.root = root; this.root = root;
this.remainderAddress = remainderAddress; this.remainderAddress = remainderAddress;
} this.depth = depth;
this.security = security;
@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;
} }
public Map<String, Object> toMap() { public Map<String, Object> toMap() {
@ -69,57 +50,62 @@ public class FlashObject {
objectMap.put("root", root.toMap()); objectMap.put("root", root.toMap());
objectMap.put("remainderAddress", remainderAddress.toMap()); objectMap.put("remainderAddress", remainderAddress.toMap());
objectMap.put("settlementAddresses", getSettlementAddresses()); objectMap.put("settlementAddresses", getSettlementAddresses());
objectMap.put("depth", getDepth());
ArrayList<Object> outputMap = new ArrayList<>(); objectMap.put("security", getSecurity());
for (Bundle b: outputs) { // Wrap outputs inside an array.
outputMap.add(b.toMap()); objectMap.put("outputs", getOutputs());
}
objectMap.put("outputs", outputMap);
objectMap.put("deposits", getDeposits()); objectMap.put("deposits", getDeposits());
ArrayList<Object> transfersMap = new ArrayList<>(); ArrayList<Object> transfersMap = new ArrayList<>();
for (Bundle b: transfers) { for (Bundle b: getTransfers()) {
outputMap.add(b.toMap()); transfersMap.add(b.toArrayList());
} }
objectMap.put("transfers", transfersMap); objectMap.put("transfers", transfersMap);
return objectMap; return objectMap;
} }
public int getSignersCount() {
return signersCount;
}
public int getBalance() { public int getBalance() {
return balance; 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; return root;
} }
public ArrayList<Integer> getDeposits() { public List<Double> getDeposits() {
return deposits; return deposits;
} }
public ArrayList<Bundle> getOutputs() { public Map<String, Integer> getOutputs() {
return outputs; return outputs;
} }
public List<Bundle> getTransfers() {
public ArrayList<Bundle> getTransfers() {
return transfers; return transfers;
} }
public void setRemainderAddress(MultisigAddress remainderAddress) { public void setRemainderAddress(Multisig remainderAddress) {
this.remainderAddress = remainderAddress; this.remainderAddress = remainderAddress;
} }
public MultisigAddress getRemainderAddress() { public Multisig getRemainderAddress() {
return remainderAddress; return remainderAddress;
} }
public void setRoot(MultisigAddress root) { public void setRoot(Multisig root) {
this.root = root; this.root = root;
} }
@ -127,7 +113,7 @@ public class FlashObject {
this.settlementAddresses = settlementAddresses; this.settlementAddresses = settlementAddresses;
} }
public ArrayList<String> getSettlementAddresses() { public List<String> getSettlementAddresses() {
return settlementAddresses; return settlementAddresses;
} }
} }

View File

@ -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;
}
}

View File

@ -9,35 +9,71 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class MultisigAddress {
public class Multisig {
private String address; private String address;
private int securitySum; private int securitySum;
private int index; private int index;
private int signingIndex; private int signingIndex;
private int security = 2; private int security = 2;
private ArrayList<MultisigAddress> children; private ArrayList<Multisig> children;
private ArrayList<Bundle> bundles; private ArrayList<Bundle> bundles;
public MultisigAddress(String address, int securitySum) { public Multisig(String address, int securitySum) {
this.address = address; this.address = address;
this.securitySum = securitySum; this.securitySum = securitySum;
this.children = new ArrayList<MultisigAddress>(); this.children = new ArrayList<Multisig>();
this.bundles = new ArrayList<Bundle>(); this.bundles = new ArrayList<Bundle>();
} }
public MultisigAddress(String address, int securitySum, ArrayList<MultisigAddress> children) { public Multisig(String address, int securitySum, ArrayList<Multisig> children) {
this.address = address; this.address = address;
this.securitySum = securitySum; this.securitySum = securitySum;
this.children = children; this.children = children;
this.bundles = new ArrayList<Bundle>(); this.bundles = new ArrayList<Bundle>();
} }
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<Bundle> bundleCopy = new ArrayList<>();
for (Bundle b : this.getBundles()) {
bundleCopy.add(b.clone());
}
output.setBundles(bundleCopy);
// Copy all children
ArrayList<Multisig> 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); children.add(addr);
} }
public ArrayList<MultisigAddress> getChildren() { public ArrayList<Multisig> getChildren() {
return children; return children;
} }
@ -52,6 +88,22 @@ public class MultisigAddress {
return index; return index;
} }
public void setAddress(String address) {
this.address = address;
}
public void setChildren(ArrayList<Multisig> children) {
this.children = children;
}
public ArrayList<Bundle> getBundles() {
return bundles;
}
public void setBundles(ArrayList<Bundle> bundles) {
this.bundles = bundles;
}
public int getSigningIndex() { public int getSigningIndex() {
return signingIndex; return signingIndex;
} }
@ -84,14 +136,14 @@ public class MultisigAddress {
map.put("signingIndex", getSigningIndex()); map.put("signingIndex", getSigningIndex());
map.put("security", security); map.put("security", security);
List<Object> childrenList = new ArrayList<Object>(); List<Object> childrenList = new ArrayList<Object>();
for (MultisigAddress ma: children) { for (Multisig ma: children) {
childrenList.add(ma.toMap()); childrenList.add(ma.toMap());
} }
map.put("children", childrenList); map.put("children", childrenList);
List<Object> bundleList = new ArrayList<Object>(); List<Object> bundleList = new ArrayList<Object>();
for (Bundle b: bundles) { for (Bundle b: bundles) {
bundleList.add(b.getBundles()); bundleList.add(b.toArrayList());
} }
map.put("bundles", bundleList); map.put("bundles", bundleList);
@ -105,7 +157,7 @@ public class MultisigAddress {
@Override @Override
public String toString() { public String toString() {
String out = "{ \n address':'" + address + "' \n, securitySum:" + securitySum + "\n, signingIndex: " + signingIndex + " \n"; String out = "{ \n address':'" + address + "' \n, securitySum:" + securitySum + "\n, signingIndex: " + signingIndex + " \n";
for (MultisigAddress addr: children) { for (Multisig addr: children) {
out += addr.toString(); out += addr.toString();
} }
return out; return out;

View File

@ -8,56 +8,17 @@ import java.util.List;
* *
* @author Adrian * @author Adrian
**/ **/
public class Signature { public class Signature extends jota.model.Signature {
private int index; private int index;
private String bundle; private String bundle;
private String address;
private List<String> signatureFragments;
/** /**
* Initializes a new instance of the Signature class. * Initializes a new instance of the Signature class.
*/ */
public Signature() { 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<String> getSignatureFragments() {
return signatureFragments;
}
/**
* Set the signatureFragments.
*
* @param signatureFragments The signatureFragments.
*/
public void setSignatureFragments(List<String> signatureFragments) {
this.signatureFragments = signatureFragments;
}
public int getIndex() { public int getIndex() {
return index; return index;
} }
@ -79,10 +40,10 @@ public class Signature {
String out = "{ \n" + String out = "{ \n" +
" \tindex:" + index + ", " + " \tindex:" + index + ", " +
" \n\tbundle: " + bundle + ", " + " \n\tbundle: " + bundle + ", " +
" \n\taddress:" + address + ","; " \n\taddress:" + getAddress() + ",";
out += "\n\t[ \n"; out += "\n\t[ \n";
for (String sf : signatureFragments) { for (String sf : getSignatureFragments()) {
out += "\n\t" + sf + ","; out += "\n\t" + sf + ",";
} }
out += " ]"; out += " ]";

View File

@ -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<String, Object> toMap() {
Map<String, Object> map = new HashMap<String, Object>();
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<String, Object> mapObj = toMap();
String value = "{";
for (Map.Entry<String, Object> entry: mapObj.entrySet()) {
value += "'" + entry.getKey() + "':'" + entry.getValue().toString() + "', \n";
}
value += "}";
return value;
}
}

View File

@ -4,31 +4,24 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class UserObject { public class UserObject {
private int userIndex = 1; private int userIndex;
private String seed; private String seed;
private int index = 0; private int seedIndex;
private int security = 2; private int security;
private int depth = 4;
private ArrayList<Bundle> bundles = new ArrayList<Bundle>();
private ArrayList<Digest> partialDigests = new ArrayList<Digest>();
private ArrayList<MultisigAddress> multisigDigests = new ArrayList<MultisigAddress>();
private FlashObject flash; 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.userIndex = userID;
this.seed = seed; this.seed = seed;
this.depth = depth; this.seedIndex = seedIndex;
this.flash = flash; this.security = security;
} }
public void incrementIndex() { public int incrementSeedIndex() {
index++; this.seedIndex = this.seedIndex + 1;
} return seedIndex;
public void add(Digest digest) {
partialDigests.add(digest);
} }
@Override @Override
@ -36,21 +29,9 @@ public class UserObject {
String out = ""; String out = "";
out += "userIndex: " + userIndex + "\n"; out += "userIndex: " + userIndex + "\n";
out += "seed: " + seed + "\n"; out += "seed: " + seed + "\n";
out += "index: " + index + "\n"; out += "seedIndex: " + seedIndex + "\n";
out += "security: " + getSecurity() + "\n"; out += "security: " + getSecurity() + "\n";
out += "depth: " + depth + "\n";
out += "bundles: " + "\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: " + "\n";
out += flash.toString(); out += flash.toString();
@ -61,27 +42,8 @@ public class UserObject {
Map<String, Object> objectMap = new HashMap<>(); Map<String, Object> objectMap = new HashMap<>();
objectMap.put("userIndex", getUserIndex()); objectMap.put("userIndex", getUserIndex());
objectMap.put("seed", getSeed()); objectMap.put("seed", getSeed());
objectMap.put("index", getIndex()); objectMap.put("seedIndex", getSeedIndex());
objectMap.put("security", getSecurity()); objectMap.put("security", getSecurity());
objectMap.put("depth", depth);
ArrayList<Object> bundleMaps = new ArrayList<>();
for (Bundle b: bundles) {
bundleMaps.add(b.toMap());
}
objectMap.put("bundles", bundleMaps);
ArrayList<Object> partialDigestMaps = new ArrayList<>();
for (Bundle b: bundles) {
partialDigestMaps.add(b.toMap());
}
objectMap.put("partialDigests", partialDigestMaps);
ArrayList<Object> multisigDigestsMaps = new ArrayList<>();
for (Bundle b: bundles) {
partialDigestMaps.add(b.toMap());
}
objectMap.put("multisigDigests", multisigDigestsMaps);
objectMap.put("flash", flash.toMap()); objectMap.put("flash", flash.toMap());
return objectMap; return objectMap;
} }
@ -91,24 +53,12 @@ public class UserObject {
* Getters and Setters * Getters and Setters
*/ */
public void setMultisigDigests(ArrayList<MultisigAddress> multisigDigests) {
this.multisigDigests = multisigDigests;
}
public void setFlash(FlashObject flash) { public void setFlash(FlashObject flash) {
this.flash = flash; this.flash = flash;
} }
public void setIndex(int index) { public void setSeedIndex(int index) {
this.index = index; this.seedIndex = index;
}
public void setBundles(ArrayList<Bundle> bundles) {
this.bundles = bundles;
}
public ArrayList<MultisigAddress> getMultisigDigests() {
return multisigDigests;
} }
public int getSecurity() { public int getSecurity() {
@ -119,22 +69,14 @@ public class UserObject {
return seed; return seed;
} }
public int getIndex() { public int getSeedIndex() {
return index; return seedIndex;
} }
public int getUserIndex() { public int getUserIndex() {
return userIndex; return userIndex;
} }
public ArrayList<Bundle> getBundles() {
return bundles;
}
public ArrayList<Digest> getPartialDigests() {
return partialDigests;
}
public FlashObject getFlash() { public FlashObject getFlash() {
return flash; return flash;
} }

View File

@ -5,7 +5,7 @@ import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Object; import com.eclipsesource.v8.V8Object;
import com.eclipsesource.v8.utils.V8ObjectUtils; import com.eclipsesource.v8.utils.V8ObjectUtils;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*; import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import jota.model.Transaction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -36,13 +36,14 @@ public class V8Converter {
return signatures; return signatures;
} }
public static V8Object multisigToV8Object(V8 engine, MultisigAddress multisig) { public static V8Object multisigToV8Object(V8 engine, Multisig multisig) {
Map<String, Object> sigMapg = multisig.toMap(); Map<String, Object> sigMapg = multisig.toMap();
return V8ObjectUtils.toV8Object(engine, sigMapg); return V8ObjectUtils.toV8Object(engine, sigMapg);
} }
public static V8Object flashObjectToV8Object(V8 engine, FlashObject flash) { public static V8Object flashObjectToV8Object(V8 engine, FlashObject flash) {
return V8ObjectUtils.toV8Object(engine, flash.toMap()); Map <String, Object> flashMap = flash.toMap();
return V8ObjectUtils.toV8Object(engine, flashMap);
} }
public static FlashObject flashObjectFromV8Object(V8Object input) { public static FlashObject flashObjectFromV8Object(V8Object input) {
@ -51,22 +52,33 @@ public class V8Converter {
Integer singersCount = (Integer) inputMap.get("signersCount"); Integer singersCount = (Integer) inputMap.get("signersCount");
Integer balance = (Integer) inputMap.get("balance"); Integer balance = (Integer) inputMap.get("balance");
ArrayList<String> settlementAddresses = (ArrayList<String>) inputMap.get("settlementAddresses"); ArrayList<String> settlementAddresses = (ArrayList<String>) inputMap.get("settlementAddresses");
MultisigAddress root = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("root")); Multisig root = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("root"));
MultisigAddress remainderAddress = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("remainderAddress")); Multisig remainderAddress = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("remainderAddress"));
ArrayList<Integer> deposits = (ArrayList<Integer>) inputMap.get("deposits"); ArrayList<Double> deposits = new ArrayList<>();
if (inputMap.get("deposits") instanceof ArrayList) {
Object depositEntry = inputMap.get("deposits");
if (((ArrayList<Object>) depositEntry).size() > 0 && ((ArrayList<Object>) depositEntry).get(0) instanceof Integer) {
for (int val: (ArrayList<Integer>) depositEntry) {
deposits.add(new Double(val));
}
} else {
deposits = (ArrayList<Double>) depositEntry;
}
}
ArrayList<Bundle> transfers = bundleListFromArrayList((ArrayList<Object>) inputMap.get("transfers")); ArrayList<Bundle> transfers = bundleListFromArrayList((ArrayList<Object>) inputMap.get("transfers"));
ArrayList<Bundle> outputs = bundleListFromArrayList((ArrayList<Object>) inputMap.get("outputs")); Map<String, Integer> outputs = (Map<String, Integer>) inputMap.get("outputs");
Integer depth = (Integer) inputMap.get("depth");
return new FlashObject(singersCount, balance, settlementAddresses, deposits, outputs, transfers, root, remainderAddress); 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<Bundle> bundles) { public static V8Array bundleListToV8Array(V8 engine, List<Bundle> bundles) {
List<Object> bundleTmp = new ArrayList<Object>(); List<Object> bundleTmp = new ArrayList<Object>();
for (Bundle b: bundles) { for (Bundle b: bundles) {
List<Object> transactions = new ArrayList<Object>(); List<Object> transactions = new ArrayList<Object>();
for (Transaction t: b.getBundles()) { for (jota.model.Transaction tx: b.getTransactions()) {
transactions.add(t.toMap()); transactions.add(transactionToMap((Transaction) tx));
} }
bundleTmp.add(transactions); bundleTmp.add(transactions);
} }
@ -85,32 +97,62 @@ public class V8Converter {
ArrayList<Bundle> ret = new ArrayList<>(); ArrayList<Bundle> ret = new ArrayList<>();
for (Object o: input) { for (Object o: input) {
ret.add(bundleFromArrayList((ArrayList<Object>) o)); if (o instanceof Map) {
if (((Map) o).get("bundles") instanceof String) {
ArrayList<Object> bundles = (ArrayList<Object>) ((Map<String, Object>) o).get("bundles");
ret.add(bundleFromArrayList(bundles));
} else {
continue;
}
}
if (o instanceof ArrayList) {
ret.add(bundleFromArrayList((ArrayList<Object>) o));
}
} }
return ret; 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<String, ? super Object> multiSigMap = V8ObjectUtils.toMap(input); Map<String, ? super Object> multiSigMap = V8ObjectUtils.toMap(input);
return multisigAddressFromPropertyMap(multiSigMap); return multisigAddressFromPropertyMap(multiSigMap);
} }
public static MultisigAddress multisigAddressFromPropertyMap(Map<String, Object> propMap) { public static Multisig multisigAddressFromPropertyMap(Map<String, Object> propMap) {
// Parse result into Java Obj. // Parse result into Java Obj.
String addr = (String) propMap.get("address"); String addr = (String) propMap.get("address");
int secSum = (Integer) propMap.get("securitySum"); int secSum = (Integer) propMap.get("securitySum");
ArrayList<Multisig> children = new ArrayList<>();
ArrayList<MultisigAddress> children = new ArrayList<>();
for (Object child: (ArrayList<Object>) propMap.get("children")) { for (Object child: (ArrayList<Object>) propMap.get("children")) {
Map<String, ? super Object> childPropMap = (Map<String, ? super Object>) child; Map<String, ? super Object> childPropMap = (Map<String, ? super Object>) child;
children.add(multisigAddressFromPropertyMap(childPropMap)); 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<Bundle> bundles = new ArrayList<>();
for (Object bundle: (ArrayList<Object>) propMap.get("bundles")) {
Bundle b = new Bundle();
if (!(bundle instanceof ArrayList)) {
continue;
} else {
for (Object transactionMap: (ArrayList<Object>) bundle) {
b.getTransactions().add(transactionFromObject(transactionMap));
}
}
bundles.add(b);
}
multisig.setBundles(bundles);
}
if (propMap.get("index") != null) { if (propMap.get("index") != null) {
multisig.setIndex((Integer) propMap.get("index")); multisig.setIndex((Integer) propMap.get("index"));
@ -119,6 +161,10 @@ public class V8Converter {
multisig.setSigningIndex((Integer) propMap.get("signingIndex")); multisig.setSigningIndex((Integer) propMap.get("signingIndex"));
} }
if (propMap.get("security") instanceof Integer) {
multisig.setSecurity((Integer) propMap.get("security"));
}
return multisig; return multisig;
} }
@ -127,6 +173,10 @@ public class V8Converter {
// Parse return as array of bundles // Parse return as array of bundles
ArrayList<Bundle> returnBundles = new ArrayList<>(); ArrayList<Bundle> returnBundles = new ArrayList<>();
for (Object bundleItem: inputList) { for (Object bundleItem: inputList) {
if (!(bundleItem instanceof ArrayList)) {
System.out.println("[ERROR]: got undefined for bunle");
continue;
}
ArrayList<Object> bundleContent = (ArrayList<Object>) bundleItem; ArrayList<Object> bundleContent = (ArrayList<Object>) bundleItem;
ArrayList<Transaction> returnedTransactions = new ArrayList<>(); ArrayList<Transaction> returnedTransactions = new ArrayList<>();
@ -199,7 +249,7 @@ public class V8Converter {
return null; return null;
} }
public static V8Array transferListToV8Array(V8 engine, ArrayList<Transfer> transfers) { public static V8Array transferListToV8Array(V8 engine, List<Transfer> transfers) {
List<Object> transferObj = new ArrayList<Object>(); List<Object> transferObj = new ArrayList<Object>();
for (Transfer t: transfers) { for (Transfer t: transfers) {
transferObj.add(t.toMap()); transferObj.add(t.toMap());
@ -209,12 +259,34 @@ public class V8Converter {
public static V8Array transactionListToV8Array(V8 engine, ArrayList<Transaction> transactions) { public static V8Array transactionListToV8Array(V8 engine, ArrayList<Transaction> transactions) {
List<Object> transfersObj = new ArrayList<Object>(); List<Object> transfersObj = new ArrayList<Object>();
for (Transaction t: transactions) { for (Transaction tx: transactions) {
transfersObj.add(t.toMap()); transfersObj.add(transactionToMap(tx));
} }
return V8ObjectUtils.toV8Array(engine, transfersObj); return V8ObjectUtils.toV8Array(engine, transfersObj);
} }
public static Map<String, Object> transactionToMap(jota.model.Transaction transaction) {
Map<String, Object> map = new HashMap<String, Object>();
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) { public static Transaction transactionFromObject(Object input) {
Map<String, Object> bundleData = (Map<String, Object>) input; Map<String, Object> bundleData = (Map<String, Object>) input;

View File

@ -301,11 +301,11 @@ public class Negotiator {
if (iotaPerMegabyte < 0) { if (iotaPerMegabyte < 0) {
return error(R.string.err_sell_price_bad_setting, false); 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) { if (minMinutes < 0) {
return error(R.string.err_min_minutes_bad_setting, false); 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) { if (maxMinutes < 0) {
return error(R.string.err_max_minutes_bad_setting, false); return error(R.string.err_max_minutes_bad_setting, false);
} }

View File

@ -102,10 +102,14 @@
<TextView <TextView
android:id="@+id/stopText" android:id="@+id/stopText"
android:gravity="center"
android:layout_margin="5dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/channelClosed" android:text="@string/channelClosed"
android:visibility="invisible"/> android:visibility="gone"/>
</LinearLayout> </LinearLayout>

View File

@ -19,7 +19,7 @@
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay"> app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay">
<Switch <!--<Switch
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:layout_gravity="end" android:layout_gravity="end"
@ -27,7 +27,7 @@
android:checked="false" android:checked="false"
android:hint="@string/wifi_p2p_discovery" android:hint="@string/wifi_p2p_discovery"
android:width="120dp" android:width="120dp"
android:id="@+id/wifiSwitch"/> android:id="@+id/wifiSwitch"/>-->
</android.support.v7.widget.Toolbar> </android.support.v7.widget.Toolbar>

View File

@ -19,7 +19,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:text="@string/startAP" /> android:textOn="@string/stopAP"
android:textOff="@string/startAPText" />
<ProgressBar <ProgressBar
android:id="@+id/progressbarAP" android:id="@+id/progressbarAP"

View File

@ -68,6 +68,9 @@
<string name="channelClosed">The payment channel was closed.</string> <string name="channelClosed">The payment channel was closed.</string>
<string name="initRetransfer">Initializing retransfer</string> <string name="initRetransfer">Initializing retransfer</string>
<string name="welcome">Welcome to the Wifi Iota Hotspot App</string> <string name="welcome">Welcome to the Wifi Iota Hotspot App</string>
<string name="notification_doing_nothing">Currently doing nothing</string>
<string name="stopAP">Stop Hotspot</string>
<string name="startAPText">Start Hotspot</string>
<!-- Welcome Slideshow --> <!-- Welcome Slideshow -->

View File

@ -44,7 +44,7 @@
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="true"
android:key="pref_key_switch_testnet" android:key="pref_key_switch_testnet"
android:title="Testnet" /> android:title="Testnet" />
@ -98,7 +98,7 @@
android:key="pref_key_payment_settings"> android:key="pref_key_payment_settings">
<EditTextPreference <EditTextPreference
android:defaultValue="10" android:defaultValue="15"
android:key="edit_text_buy_price" android:key="edit_text_buy_price"
android:inputType="number" android:inputType="number"
android:selectAllOnFocus="true" android:selectAllOnFocus="true"