From 40da44222e75b5f50e0aa7992cdbeaea1b83ddea Mon Sep 17 00:00:00 2001 From: m2049r <30435443+m2049r@users.noreply.github.com> Date: Sat, 19 Aug 2017 13:27:26 +0200 Subject: [PATCH] sending done + added Transfers + tweaks --- app/src/main/cpp/monerujo.cpp | 122 +++++++++--------- .../com/m2049r/xmrwallet/LoginActivity.java | 5 +- .../com/m2049r/xmrwallet/SendFragment.java | 16 +-- .../com/m2049r/xmrwallet/WalletActivity.java | 51 +++++--- .../com/m2049r/xmrwallet/WalletFragment.java | 44 +++++-- .../layout/TransactionInfoAdapter.java | 12 +- .../xmrwallet/model/PendingTransaction.java | 2 +- .../xmrwallet/model/TransactionHistory.java | 20 ++- .../xmrwallet/model/TransactionInfo.java | 102 ++++++--------- .../com/m2049r/xmrwallet/model/Transfer.java | 31 +++++ .../com/m2049r/xmrwallet/model/Wallet.java | 4 +- .../service/MoneroHandlerThread.java | 2 +- .../xmrwallet/service/WalletService.java | 24 ++-- .../com/m2049r/xmrwallet/util/Helper.java | 4 +- app/src/main/res/layout/send_fragment.xml | 5 +- app/src/main/res/layout/wallet_fragment.xml | 1 + app/src/main/res/values/strings.xml | 3 +- 17 files changed, 256 insertions(+), 192 deletions(-) create mode 100644 app/src/main/java/com/m2049r/xmrwallet/model/Transfer.java diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index 57176b7..79c89df 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -37,7 +37,7 @@ static JavaVM *cachedJVM; static jclass class_ArrayList; static jclass class_WalletListener; static jclass class_TransactionInfo; -static jclass class_TransactionInfo$Transfer; +static jclass class_Transfer; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { cachedJVM = jvm; @@ -52,8 +52,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { jenv->FindClass("java/util/ArrayList"))); class_TransactionInfo = static_cast(jenv->NewGlobalRef( jenv->FindClass("com/m2049r/xmrwallet/model/TransactionInfo"))); - class_TransactionInfo$Transfer = static_cast(jenv->NewGlobalRef( - jenv->FindClass("com/m2049r/xmrwallet/model/TransactionInfo$Transfer"))); + class_Transfer = static_cast(jenv->NewGlobalRef( + jenv->FindClass("com/m2049r/xmrwallet/model/Transfer"))); class_WalletListener = static_cast(jenv->NewGlobalRef( jenv->FindClass("com/m2049r/xmrwallet/model/WalletListener"))); return JNI_VERSION_1_6; @@ -174,7 +174,6 @@ struct MyWalletListener : Bitmonero::WalletListener { detachJVM(jenv, envStat); } - /** * @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously */ @@ -189,7 +188,6 @@ struct MyWalletListener : Bitmonero::WalletListener { jmethodID listenerClass_refreshed = jenv->GetMethodID(class_WalletListener, "refreshed", "()V"); jenv->CallVoidMethod(jlistener, listenerClass_refreshed); - detachJVM(jenv, envStat); } }; @@ -767,9 +765,6 @@ Java_com_m2049r_xmrwallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject i const char *_payment_id = env->GetStringUTFChars(payment_id, JNI_FALSE); Bitmonero::PendingTransaction::Priority _priority = static_cast(priority); - - LOGD("Priority_Last is %i", static_cast(Bitmonero::PendingTransaction::Priority_Last)); - Bitmonero::Wallet *wallet = getHandle(env, instance); Bitmonero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id, @@ -883,9 +878,58 @@ Java_com_m2049r_xmrwallet_model_TransactionHistory_getTransactionByIdJ(JNIEnv *e return reinterpret_cast(info); } +jobject newTransferInstance(JNIEnv *env, uint64_t amount, const std::string &address) { + jmethodID c = env->GetMethodID(class_Transfer, "", + "(JLjava/lang/String;)V"); + jstring _address = env->NewStringUTF(address.c_str()); + jobject transfer = env->NewObject(class_Transfer, c, amount, _address); + env->DeleteLocalRef(_address); + return transfer; +} + +jobject newTransferList(JNIEnv *env, Bitmonero::TransactionInfo *info) { + const std::vector &transfers = info->transfers(); + // make new ArrayList + + jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "", "(I)V"); + jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add", + "(Ljava/lang/Object;)Z"); + jobject result = env->NewObject(class_ArrayList, java_util_ArrayList_, transfers.size()); + // create Transfer objects and stick them in the List + LOGD("size %i", transfers.size()); + for (const Bitmonero::TransactionInfo::Transfer &s: transfers) { + jobject element = newTransferInstance(env, s.amount, s.address); + env->CallBooleanMethod(result, java_util_ArrayList_add, element); + env->DeleteLocalRef(element); + } + return result; +} + jobject newTransactionInfo(JNIEnv *env, Bitmonero::TransactionInfo *info) { - jmethodID c = env->GetMethodID(class_TransactionInfo, "", "(J)V"); - return env->NewObject(class_TransactionInfo, c, reinterpret_cast(info)); + jmethodID c = env->GetMethodID(class_TransactionInfo, "", + "(IZZJJJLjava/lang/String;JLjava/lang/String;JLjava/util/List;)V"); + //"(IZZJJJLjava/lang/String;JLjava/lang/String;J)V"); + LOGD("newTransactionInfo %s", info->hash().c_str()); + jobject transfers = newTransferList(env, info); + jstring _hash = env->NewStringUTF(info->hash().c_str()); + jstring _paymentId = env->NewStringUTF(info->paymentId().c_str()); + jobject result = env->NewObject(class_TransactionInfo, c, + info->direction(), + info->isPending(), + info->isFailed(), + info->amount(), + info->fee(), + info->blockHeight(), + _hash, + static_cast (info->timestamp()), + _paymentId, + info->confirmations(), + transfers); + env->DeleteLocalRef(transfers); + env->DeleteLocalRef(_hash); + env->DeleteLocalRef(_paymentId); + LOGD("newTransactionInfo X"); + return result; } #include @@ -896,7 +940,7 @@ jobject cpp2java(JNIEnv *env, std::vector vector) jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add", "(Ljava/lang/Object;)Z"); - //LOGD(std::to_string(vector.size()).c_str()); + LOGD("%s", std::to_string(vector.size()).c_str()); jobject arrayList = env->NewObject(class_ArrayList, java_util_ArrayList_, vector.size()); for (Bitmonero::TransactionInfo *s: vector) { jobject info = newTransactionInfo(env, s); @@ -907,31 +951,15 @@ jobject cpp2java(JNIEnv *env, std::vector vector) } JNIEXPORT jobject JNICALL -Java_com_m2049r_xmrwallet_model_TransactionHistory_getAll(JNIEnv *env, jobject instance) { +Java_com_m2049r_xmrwallet_model_TransactionHistory_refreshJ(JNIEnv *env, jobject instance) { Bitmonero::TransactionHistory *history = getHandle(env, instance); + LOGD("history->refresh()"); + history->refresh(); + LOGD("history->refresh() done"); return cpp2java(env, history->getAll()); } -JNIEXPORT void JNICALL -Java_com_m2049r_xmrwallet_model_TransactionHistory_refresh(JNIEnv *env, jobject instance) { - Bitmonero::TransactionHistory *history = getHandle(env, - instance); - history->refresh(); -} - -/* this is wrong - history object belongs to wallet -JNIEXPORT void JNICALL -Java_com_m2049r_xmrwallet_model_TransactionHistory_dispose(JNIEnv *env, jobject instance) { - Bitmonero::TransactionHistory *history = getHandle(env, - instance); - if (history != nullptr) { - setHandle(env, instance, 0); - delete history; - } -} -*/ - // TransactionInfo JNIEXPORT jint JNICALL Java_com_m2049r_xmrwallet_model_TransactionInfo_getDirectionJ(JNIEnv *env, jobject instance) { @@ -974,7 +1002,7 @@ Java_com_m2049r_xmrwallet_model_TransactionInfo_getConfirmations(JNIEnv *env, jo Bitmonero::TransactionInfo *info = getHandle(env, instance); return info->confirmations(); } - +//TODO remove all these JNIEXPORT jstring JNICALL Java_com_m2049r_xmrwallet_model_TransactionInfo_getHash(JNIEnv *env, jobject instance) { Bitmonero::TransactionInfo *info = getHandle(env, instance); @@ -993,36 +1021,6 @@ Java_com_m2049r_xmrwallet_model_TransactionInfo_getPaymentId(JNIEnv *env, jobjec return env->NewStringUTF(info->paymentId().c_str()); } -jobject newTransferInstance(JNIEnv *env, jobject transactionInfo, long amount, - const std::string &address) { - - jmethodID methodID = env->GetMethodID(class_TransactionInfo$Transfer, "", - "(JL/java.lang/String;)V"); - jstring _address = env->NewStringUTF(address.c_str()); - jobject transfer = env->NewObject(class_TransactionInfo$Transfer, methodID, amount, _address); - env->DeleteLocalRef(_address); - return transfer; -} - -JNIEXPORT jobject JNICALL -Java_com_m2049r_xmrwallet_model_TransactionInfo_getTransfersJ(JNIEnv *env, jobject instance) { - Bitmonero::TransactionInfo *info = getHandle(env, instance); - const std::vector &transfers = info->transfers(); - // make new ArrayList - - jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "", "(I)V"); - jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add", - "(Ljava/lang/Object;)Z"); - jobject result = env->NewObject(class_ArrayList, java_util_ArrayList_, transfers.size()); - // create Transfer objects and stick them in the List - for (const Bitmonero::TransactionInfo::Transfer &s: transfers) { - jobject element = newTransferInstance(env, instance, s.amount, s.address); - env->CallBooleanMethod(result, java_util_ArrayList_add, element); - env->DeleteLocalRef(element); - } - return result; -} - JNIEXPORT jint JNICALL Java_com_m2049r_xmrwallet_model_TransactionInfo_getTransferCount(JNIEnv *env, jobject instance) { Bitmonero::TransactionInfo *info = getHandle(env, instance); diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java index 6448b0c..99caab6 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginActivity.java @@ -53,6 +53,7 @@ import java.nio.channels.FileChannel; public class LoginActivity extends AppCompatActivity implements LoginFragment.Listener, GenerateFragment.Listener, GenerateReviewFragment.Listener { static final String TAG = "LoginActivity"; + private static final String GENERATE_STACK = "gen"; static final int DAEMON_TIMEOUT = 500; // deamon must respond in 500ms @@ -264,7 +265,7 @@ public class LoginActivity extends AppCompatActivity } void startGenerateFragment() { - replaceFragment(new GenerateFragment(), "gen", null); + replaceFragment(new GenerateFragment(), GENERATE_STACK, null); Log.d(TAG, "GenerateFragment placed"); } @@ -397,7 +398,7 @@ public class LoginActivity extends AppCompatActivity && (testWallet(walletPath, password) == Wallet.Status.Status_Ok); if (rc) { - popFragmentStack("gen"); + popFragmentStack(GENERATE_STACK); Toast.makeText(LoginActivity.this, getString(R.string.generate_wallet_created), Toast.LENGTH_SHORT).show(); } else { diff --git a/app/src/main/java/com/m2049r/xmrwallet/SendFragment.java b/app/src/main/java/com/m2049r/xmrwallet/SendFragment.java index 422040e..2246482 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/SendFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/SendFragment.java @@ -41,8 +41,6 @@ import com.m2049r.xmrwallet.util.TxData; public class SendFragment extends Fragment { static final String TAG = "GenerateFragment"; - static final public String ARG_WALLETID = "walletId"; - EditText etAddress; EditText etPaymentId; EditText etAmount; @@ -56,11 +54,11 @@ public class SendFragment extends Fragment { TextView tvTxDust; Button bSend; - final static int Mixins[] = {4, 6, 8, 10, 13}; // must macth the layout + final static int Mixins[] = {4, 6, 8, 10, 13}; // must match the layout XML final static PendingTransaction.Priority Priorities[] = {PendingTransaction.Priority.Priority_Low, PendingTransaction.Priority.Priority_Medium, - PendingTransaction.Priority.Priority_High}; // must macth the layout + PendingTransaction.Priority.Priority_High}; // must match the layout XML @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -87,12 +85,12 @@ public class SendFragment extends Fragment { etAddress.setText("9tDC52GsMjTNt4dpnRCwAF7ekVBkbkgkXGaMKTcSTpBhGpqkPX56jCNRydLq9oGjbbAQBsZhLfgmTKsntmxRd3TaJFYM2f8"); boolean testnet = WalletManager.getInstance().isTestNet(); - // TODO die if NOT testnet + if (!testnet) throw new IllegalStateException("Sending TX only on testnet. sorry."); + Helper.showKeyboard(getActivity()); etAddress.requestFocus(); etAddress.setOnEditorActionListener(new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - Log.d(TAG, actionId + "/" + (event == null ? null : event.toString())); if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (actionId == EditorInfo.IME_ACTION_NEXT)) { if (addressOk()) { etPaymentId.requestFocus(); @@ -180,7 +178,7 @@ public class SendFragment extends Fragment { int mixin = Mixins[sMixin.getSelectedItemPosition()]; int priorityIndex = sPriority.getSelectedItemPosition(); PendingTransaction.Priority priority = Priorities[priorityIndex]; - Log.d(TAG, dst_addr + "/" + paymentId + "/" + amount + "/" + mixin + "/" + priority.toString()); + //Log.d(TAG, dst_addr + "/" + paymentId + "/" + amount + "/" + mixin + "/" + priority.toString()); TxData txData = new TxData( dst_addr, paymentId, @@ -198,6 +196,7 @@ public class SendFragment extends Fragment { activityCallback.onPrepareSend(txData); } + private void send() { activityCallback.onSend(); } @@ -227,11 +226,12 @@ public class SendFragment extends Fragment { if (status != PendingTransaction.Status.Status_Ok) { Log.d(TAG, "Wallet store failed: " + pendingTransaction.getErrorString()); } + /* Log.d(TAG, "transaction amount " + pendingTransaction.getAmount()); Log.d(TAG, "transaction fee " + pendingTransaction.getFee()); Log.d(TAG, "transaction dust " + pendingTransaction.getDust()); Log.d(TAG, "transactions " + pendingTransaction.getTxCount()); - + */ llConfirmSend.setVisibility(View.VISIBLE); tvTxAmount.setText(Wallet.getDisplayAmount(pendingTransaction.getAmount())); tvTxFee.setText(Wallet.getDisplayAmount(pendingTransaction.getFee())); diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index 9e6266b..e140aba 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -47,6 +47,10 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment. private boolean synced = false; + public boolean isSynced() { + return synced; + } + @Override protected void onStart() { super.onStart(); @@ -187,8 +191,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment. wl.acquire(); Log.d(TAG, "WakeLock acquired"); } catch (SecurityException ex) { - Log.d(TAG, "WakeLock NOT acquired"); - Log.d(TAG, ex.getLocalizedMessage()); + Log.d(TAG, "WakeLock NOT acquired: " + ex.getLocalizedMessage()); wl = null; } } @@ -252,25 +255,39 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment. /////////////////////////// // WalletService.Observer /////////////////////////// + + // refresh and return if successful @Override - public void onRefreshed(final Wallet wallet, final boolean full) { + public boolean onRefreshed(final Wallet wallet, final boolean full) { Log.d(TAG, "onRefreshed()"); - if (wallet.isSynchronized()) { - releaseWakeLock(); // the idea is to stay awake until synced - if (!synced) { - onProgress(null); - saveWallet(); // save on first sync - synced = true; - } - } // TODO check which fragment is loaded - final WalletFragment walletFragment = (WalletFragment) - getFragmentManager().findFragmentById(R.id.fragment_container); - runOnUiThread(new Runnable() { - public void run() { - walletFragment.onRefreshed(wallet, full); + try { + final WalletFragment walletFragment = (WalletFragment) + getFragmentManager().findFragmentById(R.id.fragment_container); + if (wallet.isSynchronized()) { + releaseWakeLock(); // the idea is to stay awake until synced + if (!synced) { + onProgress(null); + saveWallet(); // save on first sync + synced = true; + runOnUiThread(new Runnable() { + public void run() { + walletFragment.onSynced(); + } + }); + } } - }); + runOnUiThread(new Runnable() { + public void run() { + walletFragment.onRefreshed(wallet, full); + } + }); + return true; + } catch (ClassCastException ex) { + // not in wallet fragment (probably send monero) + // keep calm and carry on + } + return false; } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java index e116c74..c52bbff 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletFragment.java @@ -36,6 +36,7 @@ import android.widget.TextView; import com.m2049r.xmrwallet.layout.TransactionInfoAdapter; import com.m2049r.xmrwallet.model.TransactionInfo; +import com.m2049r.xmrwallet.model.Transfer; import com.m2049r.xmrwallet.model.Wallet; import java.text.NumberFormat; @@ -53,6 +54,7 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O LinearLayout llProgress; TextView tvProgress; ProgressBar pbProgress; + Button bSend; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -66,7 +68,8 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O tvUnlockedBalance = (TextView) view.findViewById(R.id.tvUnlockedBalance); tvBlockHeightProgress = (TextView) view.findViewById(R.id.tvBlockHeightProgress); tvConnectionStatus = (TextView) view.findViewById(R.id.tvConnectionStatus); - Button bSend = (Button) view.findViewById(R.id.bSend); + + bSend = (Button) view.findViewById(R.id.bSend); RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list); RecyclerView.ItemDecoration itemDecoration = new @@ -85,13 +88,18 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O } }); - activityCallback.setTitle(getString(R.string.status_wallet_loading)); + if (activityCallback.isSynced()) { + onSynced(); + } + +// activityCallback.setTitle(getString(R.string.status_wallet_loading)); activityCallback.forceUpdate(); return view; } + // Callbacks from TransactionInfoAdapter @Override public void onInteraction(final View view, final TransactionInfo infoItem) { @@ -103,7 +111,7 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O @Override public void onClick(DialogInterface dialog, int which) { ClipboardManager clipboardManager = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText("TX", infoItem.getHash()); + ClipData clip = ClipData.newPlainText("TX", infoItem.hash); clipboardManager.setPrimaryClip(clip); } }); @@ -113,11 +121,25 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O public void onClick(DialogInterface dialog, int which) { } }); - builder.setMessage("TX ID: " + infoItem.getHash() + - "\nPayment ID: " + infoItem.getPaymentId() + - "\nBlockHeight: " + infoItem.getBlockHeight() + - "\nAmount: " + Wallet.getDisplayAmount(infoItem.getAmount()) + - "\nFee: " + Wallet.getDisplayAmount(infoItem.getFee())); + // TODO use strings.xml + StringBuffer sb = new StringBuffer(); + sb.append("TX ID: ").append(infoItem.hash); + sb.append("\nPayment ID: ").append(infoItem.paymentId); + sb.append("\nBlockHeight: ").append(infoItem.blockheight); + sb.append("\nAmount: "); + sb.append(infoItem.direction == TransactionInfo.Direction.Direction_In ? "+" : "-"); + sb.append(Wallet.getDisplayAmount(infoItem.amount)); + sb.append("\nFee: ").append(Wallet.getDisplayAmount(infoItem.fee)); + sb.append("\nTransfers:"); + if (infoItem.transfers.size() > 0) { + for (Transfer transfer : infoItem.transfers) { + sb.append("\n[").append(transfer.address.substring(0, 6)).append("] "); + sb.append(Wallet.getDisplayAmount(transfer.amount)); + } + } else { + sb.append("-"); + } + builder.setMessage(sb.toString()); AlertDialog alert1 = builder.create(); alert1.show(); } @@ -133,6 +155,11 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O updateStatus(wallet); } + public void onSynced() { // TODO watchonly + bSend.setVisibility(View.VISIBLE); + bSend.setEnabled(true); + } + public void onProgress(final String text) { if (text != null) { tvProgress.setText(text); @@ -225,6 +252,7 @@ public class WalletFragment extends Fragment implements TransactionInfoAdapter.O void onSendRequest(); + boolean isSynced(); } @Override diff --git a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java index 88ab78e..57ef2f0 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java +++ b/app/src/main/java/com/m2049r/xmrwallet/layout/TransactionInfoAdapter.java @@ -88,8 +88,8 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter() { @Override public int compare(TransactionInfo o1, TransactionInfo o2) { - long b1 = o1.getBlockHeight(); - long b2 = o2.getBlockHeight(); + long b1 = o1.blockheight; + long b2 = o2.blockheight; return (b1 > b2) ? -1 : (b1 < b2) ? 1 : 0; } }); @@ -134,20 +134,20 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter getAll() { List handles = getAllJ(); @@ -51,12 +53,20 @@ public class TransactionHistory { */ public native int getCount(); - private native long getTransactionByIndexJ(int i); + //private native long getTransactionByIndexJ(int i); - private native long getTransactionByIdJ(String id); + //private native long getTransactionByIdJ(String id); - public native List getAll(); + public List getAll() { + return transactions; + } - public native void refresh(); + private List transactions = new ArrayList<>(); + + public void refresh() { + transactions = refreshJ(); + } + + private native List refreshJ(); } diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java b/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java index a32444d..fe986b6 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/TransactionInfo.java @@ -16,79 +16,57 @@ package com.m2049r.xmrwallet.model; +import java.util.List; + +// this is not the TransactionInfo from the API as that is owned by the TransactionHistory +// this is a POJO for the TransactionInfoAdapter public class TransactionInfo { - static { - System.loadLibrary("monerujo"); - } - - public long handle; - - TransactionInfo(long handle) { - this.handle = handle; - } + static final String TAG = "TransactionInfo"; public enum Direction { Direction_In, Direction_Out } - public class Transfer { - long amount; - String address; + public Direction direction; + public boolean isPending; + public boolean isFailed; + public long amount; + public long fee; + public long blockheight; + public String hash; + public long timestamp; + public String paymentId; + public long confirmations; + public List transfers; - public Transfer(long amount, String address) { - this.amount = amount; - this.address = address; - } - - public long getAmount() { - return amount; - } - - public String getAddress() { - return address; - } + public TransactionInfo( + int direction, + boolean isPending, + boolean isFailed, + long amount, + long fee, + long blockheight, + String hash, + long timestamp, + String paymentId, + long confirmations, + List transfers) { + this.direction = Direction.values()[direction]; + this.isPending = isPending; + this.isFailed = isFailed; + this.amount = amount; + this.fee = fee; + this.blockheight = blockheight; + this.hash = hash; + this.timestamp = timestamp; + this.paymentId = paymentId; + this.confirmations = confirmations; + this.transfers = transfers; } public String toString() { - return getDirection() + "@" + getBlockHeight() + " " + getAmount(); + return direction + "@" + blockheight + " " + amount; } - public Direction getDirection() { - return TransactionInfo.Direction.values()[getDirectionJ()]; - } - - public native int getDirectionJ(); - - public native boolean isPending(); - - public native boolean isFailed(); - - public native long getAmount(); - - public native long getFee(); - - public native long getBlockHeight(); - - public native long getConfirmations(); - - public native String getHash(); - - public native long getTimestamp(); - - public native String getPaymentId(); - -/* - private List transfers; - - public List getTransfers() { // not threadsafe - if (this.transfers == null) { - this.transfers = getTransfersJ(); - } - return this.transfers; - } - - private native List getTransfersJ(); -*/ - } diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/Transfer.java b/app/src/main/java/com/m2049r/xmrwallet/model/Transfer.java new file mode 100644 index 0000000..988fe16 --- /dev/null +++ b/app/src/main/java/com/m2049r/xmrwallet/model/Transfer.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 m2049r + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.m2049r.xmrwallet.model; + +import android.util.Log; + +public class Transfer { + public long amount; + public String address; + + public Transfer(long amount, String address) { + Log.d("Transfer", address + "/" + amount); + //Log.d("Transfer", "/" + amount); + this.amount = amount; + this.address = address; + } +} diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java index b7cf075..6c1a0a7 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java @@ -162,7 +162,6 @@ public class Wallet { //TODO virtual int autoRefreshInterval() const = 0; - // TODO - good place to keep this ? private PendingTransaction pendingTransaction = null; public PendingTransaction getPendingTransaction() { @@ -205,8 +204,11 @@ public class Wallet { private TransactionHistory history = null; public TransactionHistory getHistory() { + Log.d(TAG, "A"); if (history == null) { + Log.d(TAG, "B"); history = new TransactionHistory(getHistoryJ()); + Log.d(TAG, "C"); } return history; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/MoneroHandlerThread.java b/app/src/main/java/com/m2049r/xmrwallet/service/MoneroHandlerThread.java index a214ded..74b66ca 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/MoneroHandlerThread.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/MoneroHandlerThread.java @@ -26,7 +26,7 @@ import android.os.Process; /** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. - * The started Thread has a stck size of STACK_SIZE (=3MB) + * The started Thread has a stck size of STACK_SIZE (=5MB) */ public class MoneroHandlerThread extends Thread { // from src/cryptonote_config.h diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java index e454471..d913ab6 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java @@ -113,10 +113,12 @@ public class WalletService extends Service { updateDaemonState(wallet, wallet.isSynchronized() ? height : 0); if (!wallet.isSynchronized()) { // we want to see our transactions as they come in + Log.d(TAG, "newBlock() refresh history"); wallet.getHistory().refresh(); + Log.d(TAG, "newBlock() history refreshed"); int txCount = wallet.getHistory().getCount(); if (txCount > lastTxCount) { - lastTxCount = txCount; + lastTxCount = txCount; // TODO maybe do this later fullRefresh = true; } } @@ -138,10 +140,10 @@ public class WalletService extends Service { if (updated) { if (observer != null) { updateDaemonState(wallet, 0); - TransactionHistory history = wallet.getHistory(); - history.refresh(); - if (observer != null) observer.onRefreshed(wallet, true); - updated = false; + wallet.getHistory().refresh(); + if (observer != null) { + updated = !observer.onRefreshed(wallet, true); + } } } } @@ -196,7 +198,7 @@ public class WalletService extends Service { } public interface Observer { - void onRefreshed(Wallet wallet, boolean full); + boolean onRefreshed(Wallet wallet, boolean full); void onProgress(String text); @@ -262,7 +264,7 @@ public class WalletService extends Service { if (cmd.equals(REQUEST_CMD_LOAD)) { String walletId = extras.getString(REQUEST_WALLET, null); String walletPw = extras.getString(REQUEST_CMD_LOAD_PW, null); - Log.d(TAG, "LOAD wallet " + walletId);// + ":" + walletPw); + Log.d(TAG, "LOAD wallet " + walletId); if (walletId != null) { showProgress(getString(R.string.status_wallet_loading)); showProgress(10); @@ -270,7 +272,7 @@ public class WalletService extends Service { } } else if (cmd.equals(REQUEST_CMD_STORE)) { Wallet myWallet = getWallet(); - Log.d(TAG, "storing wallet: " + myWallet.getName()); + Log.d(TAG, "STORE wallet: " + myWallet.getName()); boolean rc = myWallet.store(); Log.d(TAG, "wallet stored: " + myWallet.getName() + " with rc=" + rc); if (!rc) { @@ -279,14 +281,12 @@ public class WalletService extends Service { if (observer != null) observer.onWalletStored(rc); } else if (cmd.equals(REQUEST_CMD_TX)) { Wallet myWallet = getWallet(); - Log.d(TAG, "creating tx for wallet: " + myWallet.getName()); + Log.d(TAG, "CREATE TX for wallet: " + myWallet.getName()); TxData txData = extras.getParcelable(REQUEST_CMD_TX_DATA); PendingTransaction pendingTransaction = myWallet.createTransaction( txData.dst_addr, txData.paymentId, txData.amount, txData.mixin, txData.priority); PendingTransaction.Status status = pendingTransaction.getStatus(); Log.d(TAG, "transaction status " + status); - Log.d(TAG, "transaction amount " + pendingTransaction.getAmount()); - Log.d(TAG, "transaction fee " + pendingTransaction.getFee()); if (status != PendingTransaction.Status.Status_Ok) { Log.d(TAG, "Create Transaction failed: " + pendingTransaction.getErrorString()); } @@ -294,7 +294,7 @@ public class WalletService extends Service { if (observer != null) observer.onCreatedTransaction(pendingTransaction); } else if (cmd.equals(REQUEST_CMD_SEND)) { Wallet myWallet = getWallet(); - Log.d(TAG, "send tx for wallet: " + myWallet.getName()); + Log.d(TAG, "SEND TX for wallet: " + myWallet.getName()); PendingTransaction pendingTransaction = myWallet.getPendingTransaction(); if (pendingTransaction.getStatus() != PendingTransaction.Status.Status_Ok) { Log.e(TAG, "PendingTransaction is " + pendingTransaction.getStatus()); diff --git a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java index 182daf5..f345452 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java +++ b/app/src/main/java/com/m2049r/xmrwallet/util/Helper.java @@ -46,7 +46,7 @@ public class Helper { dir.mkdirs(); // try to make it } if (!dir.isDirectory()) { - String msg = "Directory " + dir.getAbsolutePath() + " does not exists."; + String msg = "Directory " + dir.getAbsolutePath() + " does not exist."; Log.e(TAG, msg); throw new IllegalStateException(msg); } @@ -59,7 +59,7 @@ public class Helper { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { if (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { - Log.d("permission", "permission denied to WRITE_EXTERNAL_STORAGE - requesting it"); + Log.d(TAG, "Permission denied to WRITE_EXTERNAL_STORAGE - requesting it"); String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; context.requestPermissions(permissions, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); return false; diff --git a/app/src/main/res/layout/send_fragment.xml b/app/src/main/res/layout/send_fragment.xml index fcd2d0e..2a2c4f6 100644 --- a/app/src/main/res/layout/send_fragment.xml +++ b/app/src/main/res/layout/send_fragment.xml @@ -104,7 +104,7 @@ android:layout_marginTop="8dp" android:background="@color/colorPrimary" android:enabled="false" - android:text="@string/send_send_hint" /> + android:text="@string/send_prepare_hint" /> @@ -164,7 +163,6 @@ android:layout_height="wrap_content" android:layout_weight="2" android:layout_marginLeft="8dp" - android:text="@string/big_amount" android:textAlignment="textEnd" android:textSize="20sp" /> @@ -192,7 +190,6 @@ android:layout_height="wrap_content" android:layout_weight="2" android:layout_marginLeft="8dp" - android:text="@string/big_amount" android:textAlignment="textEnd" android:textSize="20sp" /> diff --git a/app/src/main/res/layout/wallet_fragment.xml b/app/src/main/res/layout/wallet_fragment.xml index 01c5f05..6f24ed2 100644 --- a/app/src/main/res/layout/wallet_fragment.xml +++ b/app/src/main/res/layout/wallet_fragment.xml @@ -128,6 +128,7 @@ android:background="@color/colorPrimary" android:enabled="true" android:text="@string/wallet_send_hint" + android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c432e7d..9a70556 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -100,7 +100,8 @@ Mixin Sweep Generate - Get rid of my monero! + Prepare + Get rid of my Monero! Amount Fee