mirror of https://github.com/m2049r/xmrwallet.git
PocketChange (#901)
This commit is contained in:
parent
bc4aa0f772
commit
bf1829f775
|
@ -8,8 +8,8 @@ android {
|
|||
applicationId "com.m2049r.xmrwallet"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 3200
|
||||
versionName "3.2.0 'Decoy Selection'"
|
||||
versionCode 3307
|
||||
versionName "3.3.7 'Pocket Change'"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
|
|
@ -34,8 +34,10 @@ extern "C"
|
|||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , LOG_TAG,__VA_ARGS__)
|
||||
|
||||
static JavaVM *cachedJVM;
|
||||
static jclass class_String;
|
||||
static jclass class_ArrayList;
|
||||
static jclass class_WalletListener;
|
||||
static jclass class_CoinsInfo;
|
||||
static jclass class_TransactionInfo;
|
||||
static jclass class_Transfer;
|
||||
static jclass class_Ledger;
|
||||
|
@ -43,6 +45,14 @@ static jclass class_WalletStatus;
|
|||
|
||||
std::mutex _listenerMutex;
|
||||
|
||||
//void jstringToString(JNIEnv *env, std::string &str, jstring jstr) {
|
||||
// if (!jstr) return;
|
||||
// const int len = env->GetStringUTFLength(jstr);
|
||||
// const char *chars = env->GetStringUTFChars(jstr, nullptr);
|
||||
// str.assign(chars, len);
|
||||
// env->ReleaseStringUTFChars(jstr, chars);
|
||||
//}
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
cachedJVM = jvm;
|
||||
LOGI("JNI_OnLoad");
|
||||
|
@ -52,8 +62,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
|||
}
|
||||
//LOGI("JNI_OnLoad ok");
|
||||
|
||||
class_String = static_cast<jclass>(jenv->NewGlobalRef(
|
||||
jenv->FindClass("java/lang/String")));
|
||||
class_ArrayList = static_cast<jclass>(jenv->NewGlobalRef(
|
||||
jenv->FindClass("java/util/ArrayList")));
|
||||
class_CoinsInfo = static_cast<jclass>(jenv->NewGlobalRef(
|
||||
jenv->FindClass("com/m2049r/xmrwallet/model/CoinsInfo")));
|
||||
class_TransactionInfo = static_cast<jclass>(jenv->NewGlobalRef(
|
||||
jenv->FindClass("com/m2049r/xmrwallet/model/TransactionInfo")));
|
||||
class_Transfer = static_cast<jclass>(jenv->NewGlobalRef(
|
||||
|
@ -951,6 +965,58 @@ Java_com_m2049r_xmrwallet_model_Wallet_rescanBlockchainAsyncJ(JNIEnv *env, jobje
|
|||
//TODO virtual void setAutoRefreshInterval(int millis) = 0;
|
||||
//TODO virtual int autoRefreshInterval() const = 0;
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_createTransactionMultDest(JNIEnv *env, jobject instance,
|
||||
jobjectArray destinations,
|
||||
jstring payment_id,
|
||||
jlongArray amounts,
|
||||
jint mixin_count,
|
||||
jint priority,
|
||||
jint accountIndex,
|
||||
jintArray subaddresses) {
|
||||
std::vector<std::string> dst_addr;
|
||||
std::vector<uint64_t> amount;
|
||||
|
||||
int destSize = env->GetArrayLength(destinations);
|
||||
assert(destSize == env->GetArrayLength(amounts));
|
||||
jlong *_amounts = env->GetLongArrayElements(amounts, nullptr);
|
||||
for (int i = 0; i < destSize; i++) {
|
||||
jstring dest = (jstring) env->GetObjectArrayElement(destinations, i);
|
||||
const char *_dest = env->GetStringUTFChars(dest, nullptr);
|
||||
dst_addr.emplace_back(_dest);
|
||||
env->ReleaseStringUTFChars(dest, _dest);
|
||||
amount.emplace_back((uint64_t) _amounts[i]);
|
||||
}
|
||||
env->ReleaseLongArrayElements(amounts, _amounts, 0);
|
||||
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
if (subaddresses != nullptr) {
|
||||
int subaddrSize = env->GetArrayLength(subaddresses);
|
||||
jint *_subaddresses = env->GetIntArrayElements(subaddresses, nullptr);
|
||||
for (int i = 0; i < subaddrSize; i++) {
|
||||
subaddr_indices.insert((uint32_t) _subaddresses[i]);
|
||||
}
|
||||
env->ReleaseIntArrayElements(subaddresses, _subaddresses, 0);
|
||||
}
|
||||
|
||||
const char *_payment_id = env->GetStringUTFChars(payment_id, nullptr);
|
||||
|
||||
Monero::PendingTransaction::Priority _priority =
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority);
|
||||
|
||||
Monero::Wallet *wallet = getHandle<Monero::Wallet>(env, instance);
|
||||
|
||||
Monero::PendingTransaction *tx =
|
||||
wallet->createTransactionMultDest(dst_addr, _payment_id,
|
||||
amount, (uint32_t) mixin_count,
|
||||
_priority,
|
||||
(uint32_t) accountIndex,
|
||||
subaddr_indices);
|
||||
|
||||
env->ReleaseStringUTFChars(payment_id, _payment_id);
|
||||
return reinterpret_cast<jlong>(tx);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject instance,
|
||||
jstring dst_addr, jstring payment_id,
|
||||
|
@ -1019,6 +1085,36 @@ Java_com_m2049r_xmrwallet_model_Wallet_disposeTransaction(JNIEnv *env, jobject i
|
|||
wallet->disposeTransaction(_pendingTransaction);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_estimateTransactionFee(JNIEnv *env, jobject instance,
|
||||
jobjectArray addresses,
|
||||
jlongArray amounts,
|
||||
jint priority) {
|
||||
|
||||
std::vector<std::pair<std::string, uint64_t>> destinations;
|
||||
|
||||
int destSize = env->GetArrayLength(addresses);
|
||||
assert(destSize == env->GetArrayLength(amounts));
|
||||
jlong *_amounts = env->GetLongArrayElements(amounts, nullptr);
|
||||
for (int i = 0; i < destSize; i++) {
|
||||
std::pair<std::string, uint64_t> pair;
|
||||
jstring dest = (jstring) env->GetObjectArrayElement(addresses, i);
|
||||
const char *_dest = env->GetStringUTFChars(dest, nullptr);
|
||||
pair.first = _dest;
|
||||
env->ReleaseStringUTFChars(dest, _dest);
|
||||
pair.second = ((uint64_t) _amounts[i]);
|
||||
destinations.emplace_back(pair);
|
||||
}
|
||||
env->ReleaseLongArrayElements(amounts, _amounts, 0);
|
||||
|
||||
Monero::PendingTransaction::Priority _priority =
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority);
|
||||
|
||||
Monero::Wallet *wallet = getHandle<Monero::Wallet>(env, instance);
|
||||
|
||||
return static_cast<jlong>(wallet->estimateTransactionFee(destinations, _priority));
|
||||
}
|
||||
|
||||
//virtual bool exportKeyImages(const std::string &filename) = 0;
|
||||
//virtual bool importKeyImages(const std::string &filename) = 0;
|
||||
|
||||
|
@ -1032,6 +1128,12 @@ Java_com_m2049r_xmrwallet_model_Wallet_getHistoryJ(JNIEnv *env, jobject instance
|
|||
|
||||
//virtual AddressBook * addressBook() const = 0;
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_getCoinsJ(JNIEnv *env, jobject instance) {
|
||||
Monero::Wallet *wallet = getHandle<Monero::Wallet>(env, instance);
|
||||
return reinterpret_cast<jlong>(wallet->coins());
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Wallet_setListenerJ(JNIEnv *env, jobject instance,
|
||||
jobject javaListener) {
|
||||
|
@ -1270,7 +1372,62 @@ jobject newTransactionInfo(JNIEnv *env, Monero::TransactionInfo *info) {
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
jobject cpp2java(JNIEnv *env, const std::vector<Monero::TransactionInfo *> &vector) {
|
||||
// Coins
|
||||
|
||||
jobject newCoinsInfo(JNIEnv *env, Monero::CoinsInfo *info) {
|
||||
jstring _hash = env->NewStringUTF(info->hash().c_str());
|
||||
|
||||
jmethodID c = env->GetMethodID(class_CoinsInfo, "<init>", "(IIJJLjava/lang/String;ZZJZ)V");
|
||||
jobject result = env->NewObject(class_CoinsInfo, c,
|
||||
static_cast<jint> (info->subaddrAccount()),
|
||||
static_cast<jint> (info->subaddrIndex()),
|
||||
static_cast<jlong> (info->amount()),
|
||||
static_cast<jlong> (info->blockHeight()),
|
||||
_hash,
|
||||
info->spent(),
|
||||
info->frozen(),
|
||||
static_cast<jlong> (info->unlockTime()),
|
||||
info->unlocked());
|
||||
env->DeleteLocalRef(_hash);
|
||||
return result;
|
||||
}
|
||||
|
||||
jobject coinsInfoArrayList(JNIEnv *env, const std::vector<Monero::CoinsInfo *> &vector,
|
||||
uint32_t accountIndex, bool unspentOnly) {
|
||||
|
||||
jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V");
|
||||
jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add",
|
||||
"(Ljava/lang/Object;)Z");
|
||||
|
||||
jobject arrayList = env->NewObject(class_ArrayList, java_util_ArrayList_,
|
||||
static_cast<jint> (vector.size()));
|
||||
for (Monero::CoinsInfo *s: vector) {
|
||||
if (s->subaddrAccount() != accountIndex) continue;
|
||||
if (s->spent() && unspentOnly) continue;
|
||||
jobject info = newCoinsInfo(env, s);
|
||||
env->CallBooleanMethod(arrayList, java_util_ArrayList_add, info);
|
||||
env->DeleteLocalRef(info);
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Coins_getCount(JNIEnv *env, jobject instance) {
|
||||
Monero::Coins *coins = getHandle<Monero::Coins>(env, instance);
|
||||
return coins->count();
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_Coins_refresh(JNIEnv *env, jobject instance, jint accountIndex,
|
||||
jboolean unspentOnly) {
|
||||
Monero::Coins *coins = getHandle<Monero::Coins>(env, instance);
|
||||
coins->refresh();
|
||||
return coinsInfoArrayList(env, coins->getAll(), (uint32_t) accountIndex, unspentOnly);
|
||||
}
|
||||
|
||||
jobject
|
||||
transactionInfoArrayList(JNIEnv *env, const std::vector<Monero::TransactionInfo *> &vector,
|
||||
uint32_t accountIndex) {
|
||||
|
||||
jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V");
|
||||
jmethodID java_util_ArrayList_add = env->GetMethodID(class_ArrayList, "add",
|
||||
|
@ -1279,6 +1436,7 @@ jobject cpp2java(JNIEnv *env, const std::vector<Monero::TransactionInfo *> &vect
|
|||
jobject arrayList = env->NewObject(class_ArrayList, java_util_ArrayList_,
|
||||
static_cast<jint> (vector.size()));
|
||||
for (Monero::TransactionInfo *s: vector) {
|
||||
if (s->subaddrAccount() != accountIndex) continue;
|
||||
jobject info = newTransactionInfo(env, s);
|
||||
env->CallBooleanMethod(arrayList, java_util_ArrayList_add, info);
|
||||
env->DeleteLocalRef(info);
|
||||
|
@ -1287,11 +1445,12 @@ jobject cpp2java(JNIEnv *env, const std::vector<Monero::TransactionInfo *> &vect
|
|||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_TransactionHistory_refreshJ(JNIEnv *env, jobject instance) {
|
||||
Java_com_m2049r_xmrwallet_model_TransactionHistory_refreshJ(JNIEnv *env, jobject instance,
|
||||
jint accountIndex) {
|
||||
Monero::TransactionHistory *history = getHandle<Monero::TransactionHistory>(env,
|
||||
instance);
|
||||
history->refresh();
|
||||
return cpp2java(env, history->getAll());
|
||||
return transactionInfoArrayList(env, history->getAll(), (uint32_t) accountIndex);
|
||||
}
|
||||
|
||||
// TransactionInfo is implemented in Java - no need here
|
||||
|
@ -1326,19 +1485,19 @@ Java_com_m2049r_xmrwallet_model_PendingTransaction_commit(JNIEnv *env, jobject i
|
|||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_PendingTransaction_getAmount(JNIEnv *env, jobject instance) {
|
||||
Monero::PendingTransaction *tx = getHandle<Monero::PendingTransaction>(env, instance);
|
||||
return tx->amount();
|
||||
return static_cast<jlong>(tx->amount());
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_PendingTransaction_getDust(JNIEnv *env, jobject instance) {
|
||||
Monero::PendingTransaction *tx = getHandle<Monero::PendingTransaction>(env, instance);
|
||||
return tx->dust();
|
||||
return static_cast<jlong>(tx->dust());
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_PendingTransaction_getFee(JNIEnv *env, jobject instance) {
|
||||
Monero::PendingTransaction *tx = getHandle<Monero::PendingTransaction>(env, instance);
|
||||
return tx->fee();
|
||||
return static_cast<jlong>(tx->fee());
|
||||
}
|
||||
|
||||
// TODO this returns a vector of strings - deal with this later - for now return first one
|
||||
|
@ -1355,7 +1514,7 @@ Java_com_m2049r_xmrwallet_model_PendingTransaction_getFirstTxIdJ(JNIEnv *env, jo
|
|||
JNIEXPORT jlong JNICALL
|
||||
Java_com_m2049r_xmrwallet_model_PendingTransaction_getTxCount(JNIEnv *env, jobject instance) {
|
||||
Monero::PendingTransaction *tx = getHandle<Monero::PendingTransaction>(env, instance);
|
||||
return tx->txCount();
|
||||
return static_cast<jlong>(tx->txCount());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -658,11 +658,11 @@ public class LoginActivity extends BaseActivity
|
|||
break;
|
||||
case NetworkType_Testnet:
|
||||
toolbar.setSubtitle(getString(R.string.connect_testnet));
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark));
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, androidx.appcompat.R.attr.colorPrimaryDark));
|
||||
break;
|
||||
case NetworkType_Stagenet:
|
||||
toolbar.setSubtitle(getString(R.string.connect_stagenet));
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark));
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, androidx.appcompat.R.attr.colorPrimaryDark));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("NetworkType unknown: " + net);
|
||||
|
|
|
@ -79,6 +79,7 @@ public class TxFragment extends Fragment {
|
|||
private TextView tvTxPaymentId;
|
||||
private TextView tvTxBlockheight;
|
||||
private TextView tvTxAmount;
|
||||
private TextView tvTxPocketChangeAmount;
|
||||
private TextView tvTxFee;
|
||||
private TextView tvTxTransfers;
|
||||
private TextView etTxNotes;
|
||||
|
@ -116,6 +117,7 @@ public class TxFragment extends Fragment {
|
|||
tvTxPaymentId = view.findViewById(R.id.tvTxPaymentId);
|
||||
tvTxBlockheight = view.findViewById(R.id.tvTxBlockheight);
|
||||
tvTxAmount = view.findViewById(R.id.tvTxAmount);
|
||||
tvTxPocketChangeAmount = view.findViewById(R.id.tvTxPocketChangeAmount);
|
||||
tvTxFee = view.findViewById(R.id.tvTxFee);
|
||||
tvTxTransfers = view.findViewById(R.id.tvTxTransfers);
|
||||
etTxNotes = view.findViewById(R.id.etTxNotes);
|
||||
|
@ -249,8 +251,10 @@ public class TxFragment extends Fragment {
|
|||
}
|
||||
String sign = (info.direction == TransactionInfo.Direction.Direction_In ? "+" : "-");
|
||||
|
||||
long realAmount = info.amount;
|
||||
tvTxAmount.setText(sign + Wallet.getDisplayAmount(realAmount));
|
||||
tvTxAmount.setText(sign + Wallet.getDisplayAmount(info.amount));
|
||||
final long pcAmount = info.getPocketChangeAmount();
|
||||
tvTxPocketChangeAmount.setVisibility(pcAmount > 0 ? View.VISIBLE : View.GONE);
|
||||
tvTxPocketChangeAmount.setText(getString(R.string.pocketchange_tx_detail, Wallet.getDisplayAmount(pcAmount)));
|
||||
|
||||
if ((info.fee > 0)) {
|
||||
String fee = Wallet.getDisplayAmount(info.fee);
|
||||
|
|
|
@ -52,8 +52,8 @@ import com.m2049r.xmrwallet.data.BarcodeData;
|
|||
import com.m2049r.xmrwallet.data.Subaddress;
|
||||
import com.m2049r.xmrwallet.data.TxData;
|
||||
import com.m2049r.xmrwallet.data.UserNotes;
|
||||
import com.m2049r.xmrwallet.dialog.CreditsFragment;
|
||||
import com.m2049r.xmrwallet.dialog.HelpFragment;
|
||||
import com.m2049r.xmrwallet.dialog.PocketChangeFragment;
|
||||
import com.m2049r.xmrwallet.fragment.send.SendAddressWizardFragment;
|
||||
import com.m2049r.xmrwallet.fragment.send.SendFragment;
|
||||
import com.m2049r.xmrwallet.ledger.LedgerProgressDialog;
|
||||
|
@ -82,7 +82,8 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
WalletFragment.DrawerLocker,
|
||||
NavigationView.OnNavigationItemSelectedListener,
|
||||
SubaddressFragment.Listener,
|
||||
SubaddressInfoFragment.Listener {
|
||||
SubaddressInfoFragment.Listener,
|
||||
PocketChangeFragment.Listener {
|
||||
|
||||
public static final String REQUEST_ID = "id";
|
||||
public static final String REQUEST_PW = "pw";
|
||||
|
@ -285,8 +286,6 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
onWalletRescan();
|
||||
} else if (itemId == R.id.action_info) {
|
||||
onWalletDetails();
|
||||
} else if (itemId == R.id.action_credits) {
|
||||
CreditsFragment.display(getSupportFragmentManager());
|
||||
} else if (itemId == R.id.action_share) {
|
||||
onShareTxInfo();
|
||||
} else if (itemId == R.id.action_help_tx_info) {
|
||||
|
@ -301,6 +300,8 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
HelpFragment.display(getSupportFragmentManager(), R.string.help_send);
|
||||
} else if (itemId == R.id.action_rename) {
|
||||
onAccountRename();
|
||||
} else if (itemId == R.id.action_pocketchange) {
|
||||
PocketChangeFragment.display(getSupportFragmentManager(), getWallet().getPocketChangeSetting());
|
||||
} else if (itemId == R.id.action_subaddresses) {
|
||||
showSubaddresses(true);
|
||||
} else if (itemId == R.id.action_streetmode) {
|
||||
|
@ -422,7 +423,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
break;
|
||||
case NetworkType_Stagenet:
|
||||
case NetworkType_Testnet:
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark));
|
||||
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, androidx.appcompat.R.attr.colorPrimaryDark));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported Network: " + WalletManager.getInstance().getNetworkType());
|
||||
|
@ -628,6 +629,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
|
||||
@Override
|
||||
public void onWalletStarted(final Wallet.Status walletStatus) {
|
||||
loadPocketChangeSettings();
|
||||
runOnUiThread(() -> {
|
||||
dismissProgressDialog();
|
||||
if (walletStatus == null) {
|
||||
|
@ -1104,6 +1106,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
|
||||
public void setAccountIndex(int accountIndex) {
|
||||
getWallet().setAccountIndex(accountIndex);
|
||||
loadPocketChangeSettings();
|
||||
selectedSubaddressIndex = 0;
|
||||
}
|
||||
|
||||
|
@ -1214,4 +1217,19 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
|
|||
b.putInt("subaddressIndex", subaddressIndex);
|
||||
replaceFragmentWithTransition(view, new SubaddressInfoFragment(), null, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPocketChange(Wallet.PocketChangeSetting setting) {
|
||||
SharedPreferences.Editor editor = getPrefs().edit();
|
||||
editor.putString(getWallet().getAddress() + "_PC", setting.toPrefString());
|
||||
editor.apply();
|
||||
getWallet().setPocketChangeSetting(setting);
|
||||
}
|
||||
|
||||
|
||||
public void loadPocketChangeSettings() {
|
||||
final String settings = getPrefs().getString(getWallet().getAddress() + "_PC", "0");
|
||||
getWallet().setPocketChangeSetting(Wallet.PocketChangeSetting.from(settings));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public class WalletFragment extends Fragment
|
|||
flExchange = view.findViewById(R.id.flExchange);
|
||||
((ProgressBar) view.findViewById(R.id.pbExchange)).getIndeterminateDrawable().
|
||||
setColorFilter(
|
||||
ThemeHelper.getThemedColor(getContext(), R.attr.colorPrimaryVariant),
|
||||
ThemeHelper.getThemedColor(getContext(), com.google.android.material.R.attr.colorPrimaryVariant),
|
||||
android.graphics.PorterDuff.Mode.MULTIPLY);
|
||||
|
||||
tvProgress = view.findViewById(R.id.tvProgress);
|
||||
|
|
|
@ -270,7 +270,7 @@ public class NodeInfo extends Node {
|
|||
(hostAddress.isOnion() ? " .onion " : ""), " " + info));
|
||||
view.setText(text);
|
||||
if (isError)
|
||||
view.setTextColor(ThemeHelper.getThemedColor(ctx, R.attr.colorError));
|
||||
view.setTextColor(ThemeHelper.getThemedColor(ctx, androidx.appcompat.R.attr.colorError));
|
||||
else
|
||||
view.setTextColor(ThemeHelper.getThemedColor(ctx, android.R.attr.textColorSecondary));
|
||||
}
|
||||
|
|
|
@ -19,92 +19,88 @@ package com.m2049r.xmrwallet.data;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.m2049r.xmrwallet.model.CoinsInfo;
|
||||
import com.m2049r.xmrwallet.model.PendingTransaction;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import timber.log.Timber;
|
||||
|
||||
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
|
||||
@ToString
|
||||
public class TxData implements Parcelable {
|
||||
@Getter
|
||||
private String[] destinations = new String[1];
|
||||
@Getter
|
||||
private long[] amounts = new long[1];
|
||||
@Getter
|
||||
@Setter
|
||||
private int mixin;
|
||||
@Getter
|
||||
@Setter
|
||||
private PendingTransaction.Priority priority;
|
||||
@Getter
|
||||
private int[] subaddresses;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private UserNotes userNotes;
|
||||
|
||||
public TxData() {
|
||||
}
|
||||
|
||||
public TxData(TxData txData) {
|
||||
this.dstAddr = txData.dstAddr;
|
||||
this.amount = txData.amount;
|
||||
this.mixin = txData.mixin;
|
||||
this.priority = txData.priority;
|
||||
}
|
||||
|
||||
public TxData(String dstAddr,
|
||||
long amount,
|
||||
int mixin,
|
||||
PendingTransaction.Priority priority) {
|
||||
this.dstAddr = dstAddr;
|
||||
this.amount = amount;
|
||||
this.mixin = mixin;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getDestinationAddress() {
|
||||
return dstAddr;
|
||||
public String getDestination() {
|
||||
return destinations[0];
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
return amounts[0];
|
||||
}
|
||||
|
||||
public double getAmountAsDouble() {
|
||||
return 1.0 * amount / Helper.ONE_XMR;
|
||||
public long getPocketChangeAmount() {
|
||||
long change = 0;
|
||||
for (int i = 1; i < amounts.length; i++) {
|
||||
change += amounts[i];
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
public int getMixin() {
|
||||
return mixin;
|
||||
}
|
||||
|
||||
public PendingTransaction.Priority getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setDestinationAddress(String dstAddr) {
|
||||
this.dstAddr = dstAddr;
|
||||
public void setDestination(String destination) {
|
||||
destinations[0] = destination;
|
||||
}
|
||||
|
||||
public void setAmount(long amount) {
|
||||
this.amount = amount;
|
||||
amounts[0] = amount;
|
||||
}
|
||||
|
||||
public void setAmount(double amount) {
|
||||
this.amount = Wallet.getAmountFromDouble(amount);
|
||||
setAmount(Wallet.getAmountFromDouble(amount));
|
||||
}
|
||||
|
||||
public void setMixin(int mixin) {
|
||||
this.mixin = mixin;
|
||||
private void resetPocketChange() {
|
||||
if (destinations.length > 1) {
|
||||
final String destination = getDestination();
|
||||
destinations = new String[1];
|
||||
destinations[0] = destination;
|
||||
final long amount = getAmount();
|
||||
amounts = new long[1];
|
||||
amounts[0] = amount;
|
||||
}
|
||||
|
||||
public void setPriority(PendingTransaction.Priority priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public UserNotes getUserNotes() {
|
||||
return userNotes;
|
||||
}
|
||||
|
||||
public void setUserNotes(UserNotes userNotes) {
|
||||
this.userNotes = userNotes;
|
||||
}
|
||||
|
||||
private String dstAddr;
|
||||
private long amount;
|
||||
private int mixin;
|
||||
private PendingTransaction.Priority priority;
|
||||
|
||||
private UserNotes userNotes;
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(dstAddr);
|
||||
out.writeLong(amount);
|
||||
out.writeInt(destinations.length);
|
||||
out.writeStringArray(destinations);
|
||||
out.writeLongArray(amounts);
|
||||
out.writeInt(mixin);
|
||||
out.writeInt(priority.getValue());
|
||||
}
|
||||
|
@ -121,11 +117,13 @@ public class TxData implements Parcelable {
|
|||
};
|
||||
|
||||
protected TxData(Parcel in) {
|
||||
dstAddr = in.readString();
|
||||
amount = in.readLong();
|
||||
int len = in.readInt();
|
||||
destinations = new String[len];
|
||||
in.readStringArray(destinations);
|
||||
amounts = new long[len];
|
||||
in.readLongArray(amounts);
|
||||
mixin = in.readInt();
|
||||
priority = PendingTransaction.Priority.fromInteger(in.readInt());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -133,17 +131,117 @@ public class TxData implements Parcelable {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("dstAddr:");
|
||||
sb.append(dstAddr);
|
||||
sb.append(",amount:");
|
||||
sb.append(amount);
|
||||
sb.append(",mixin:");
|
||||
sb.append(mixin);
|
||||
sb.append(",priority:");
|
||||
sb.append(priority);
|
||||
return sb.toString();
|
||||
//////////////////////////
|
||||
/// PocketChange Stuff ///
|
||||
//////////////////////////
|
||||
|
||||
final static public int POCKETCHANGE_IDX = 1; // subaddress index of first pocketchange slot
|
||||
final static public int POCKETCHANGE_SLOTS = 10; // number of pocketchange slots
|
||||
final static public int POCKETCHANGE_IDX_MAX = POCKETCHANGE_IDX + POCKETCHANGE_SLOTS - 1;
|
||||
|
||||
@Data
|
||||
static private class PocketChangeSlot {
|
||||
private long amount;
|
||||
private long spendableAmount;
|
||||
|
||||
public void add(CoinsInfo coin) {
|
||||
amount += coin.getAmount();
|
||||
if (coin.isSpendable()) spendableAmount += coin.getAmount();
|
||||
}
|
||||
}
|
||||
|
||||
// returns null if it can't create a PocketChange Transaction
|
||||
// it assumes there is enough reserve to deal with fees - otherwise we get an error on
|
||||
// creating the actual transaction
|
||||
// String destination, long amount are already set!
|
||||
public void createPocketChange(Wallet wallet) {
|
||||
Wallet.PocketChangeSetting setting = wallet.getPocketChangeSetting();
|
||||
if (!setting.isEnabled()) {
|
||||
resetPocketChange();
|
||||
return;
|
||||
}
|
||||
if ((destinations.length != 1) || (destinations[0] == null))
|
||||
throw new IllegalStateException("invalid destinations");
|
||||
if ((amounts.length != 1))
|
||||
throw new IllegalStateException("invalid amount");
|
||||
|
||||
final long amount = getAmount();
|
||||
// find spendable slot, and all non-slot outputs (spendableSubaddressIdx)
|
||||
int usableSubaddressIdx = -1;
|
||||
List<CoinsInfo> coins = wallet.getCoinsInfos(true);
|
||||
Set<Integer> spendableSubaddressIdx = new HashSet<>();
|
||||
PocketChangeSlot reserves = new PocketChangeSlot(); // everything not in a slot spendable
|
||||
PocketChangeSlot[] slots = new PocketChangeSlot[POCKETCHANGE_SLOTS];
|
||||
for (int i = 0; i < POCKETCHANGE_SLOTS; i++) {
|
||||
slots[i] = new PocketChangeSlot();
|
||||
}
|
||||
for (CoinsInfo coin : coins) {
|
||||
int subaddressIdx = coin.getAddressIndex();
|
||||
if ((subaddressIdx < POCKETCHANGE_IDX) || (subaddressIdx > POCKETCHANGE_IDX_MAX)) { // spendableSubaddressIdx
|
||||
reserves.add(coin);
|
||||
spendableSubaddressIdx.add(subaddressIdx);
|
||||
} else { // PocketChange slot
|
||||
final int slotIdx = subaddressIdx - POCKETCHANGE_IDX;
|
||||
slots[slotIdx].add(coin);
|
||||
if (slots[slotIdx].getSpendableAmount() >= amount) {
|
||||
usableSubaddressIdx = subaddressIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
long spendableAmount = reserves.getSpendableAmount();
|
||||
final long pocketChangeAmount = setting.getAmount();
|
||||
if (spendableAmount < pocketChangeAmount)
|
||||
return; // do conventional transaction
|
||||
Timber.d("usableSubaddressIdx=%d", usableSubaddressIdx);
|
||||
if (usableSubaddressIdx >= 0) {
|
||||
spendableSubaddressIdx.add(usableSubaddressIdx);
|
||||
spendableAmount += slots[usableSubaddressIdx - POCKETCHANGE_IDX].getAmount();
|
||||
} else {
|
||||
// use everything
|
||||
spendableSubaddressIdx.clear();
|
||||
}
|
||||
spendableAmount -= amount; // reserve the amount we need
|
||||
// now we have the <usableSubaddressIdx> and all spendableSubaddressIdx subaddresses to use and how much spendableSubaddressIdx we have
|
||||
// find any slots to fill if possible:
|
||||
List<Integer> slotsToFill = new ArrayList<>();
|
||||
List<Long> slotToFillAmounts = new ArrayList<>();
|
||||
for (int i = 0; i < POCKETCHANGE_SLOTS; i++) {
|
||||
if (slots[i].getAmount() < pocketChangeAmount) {
|
||||
final long topupAmount = pocketChangeAmount - slots[i].getAmount();
|
||||
if (topupAmount <= spendableAmount) {
|
||||
slotsToFill.add(i);
|
||||
slotToFillAmounts.add(topupAmount);
|
||||
spendableAmount -= topupAmount;
|
||||
Timber.d("FILL %d with %d", i, topupAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String[] destinations;
|
||||
long[] amounts;
|
||||
while (true) {
|
||||
destinations = new String[slotsToFill.size() + 1];
|
||||
destinations[0] = getDestination();
|
||||
amounts = new long[slotsToFill.size() + 1];
|
||||
amounts[0] = getAmount();
|
||||
if (slotsToFill.size() == 0) break;
|
||||
for (int i = 0; i < slotsToFill.size(); i++) {
|
||||
destinations[i + 1] = wallet.getSubaddress(slotsToFill.get(i) + POCKETCHANGE_IDX);
|
||||
amounts[i + 1] = slotToFillAmounts.get(i);
|
||||
}
|
||||
final long fees = wallet.estimateTransactionFee(this) * 10; // pessimistic
|
||||
if (fees < spendableAmount) break;
|
||||
spendableAmount += slotToFillAmounts.get(0);
|
||||
slotsToFill.remove(0);
|
||||
slotToFillAmounts.remove(0);
|
||||
}
|
||||
|
||||
this.destinations = destinations;
|
||||
this.amounts = amounts;
|
||||
subaddresses = new int[spendableSubaddressIdx.size()];
|
||||
int i = 0;
|
||||
for (int subaddressIdx : spendableSubaddressIdx) {
|
||||
subaddresses[i++] = subaddressIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,10 +41,6 @@ public class TxDataBtc extends TxData {
|
|||
super();
|
||||
}
|
||||
|
||||
public TxDataBtc(TxDataBtc txDataBtc) {
|
||||
super(txDataBtc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.slider.Slider;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
import com.m2049r.xmrwallet.model.Wallet;
|
||||
import com.m2049r.xmrwallet.util.Helper;
|
||||
|
||||
public class PocketChangeFragment extends DialogFragment implements Slider.OnChangeListener {
|
||||
static final String TAG = "PocketChangeFragment";
|
||||
static final String ENABLED = "enabled";
|
||||
static final String TICK = "tick";
|
||||
|
||||
public static PocketChangeFragment newInstance(boolean enabled, int tick) {
|
||||
PocketChangeFragment fragment = new PocketChangeFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(ENABLED, enabled ? 1 : 0);
|
||||
bundle.putInt(TICK, tick);
|
||||
fragment.setArguments(bundle);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static void display(FragmentManager fm, @NonNull Wallet.PocketChangeSetting setting) {
|
||||
FragmentTransaction ft = fm.beginTransaction();
|
||||
Fragment prev = fm.findFragmentByTag(TAG);
|
||||
if (prev != null) {
|
||||
ft.remove(prev);
|
||||
}
|
||||
PocketChangeFragment.newInstance(setting.isEnabled(), getTick(setting.getAmount())).show(ft, TAG);
|
||||
}
|
||||
|
||||
SwitchMaterial switchPocketChange;
|
||||
Slider slider;
|
||||
TextView tvProgressLabel;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_pocketchange_setting, null);
|
||||
boolean enabled = false;
|
||||
int progress = 0;
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments != null) {
|
||||
enabled = arguments.getInt(ENABLED) > 0;
|
||||
progress = arguments.getInt(TICK);
|
||||
}
|
||||
|
||||
final View llAmount = view.findViewById(R.id.llAmount);
|
||||
switchPocketChange = view.findViewById(R.id.switchPocketChange);
|
||||
switchPocketChange.setOnCheckedChangeListener((buttonView, isChecked) -> llAmount.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE));
|
||||
slider = view.findViewById(R.id.seekbar);
|
||||
slider.addOnChangeListener(this);
|
||||
switchPocketChange.setChecked(enabled);
|
||||
tvProgressLabel = view.findViewById(R.id.seekbar_value);
|
||||
slider.setValue(progress);
|
||||
llAmount.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
|
||||
onValueChange(slider, slider.getValue(), false);
|
||||
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity())
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.label_apply,
|
||||
(dialog, whichButton) -> {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity instanceof Listener) {
|
||||
((Listener) activity).setPocketChange(Wallet.PocketChangeSetting.of(switchPocketChange.isChecked(), getAmount()));
|
||||
}
|
||||
}
|
||||
);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private long getAmount() {
|
||||
return Wallet.getAmountFromDouble(getAmount((int) slider.getValue()));
|
||||
}
|
||||
|
||||
private static final double[] AMOUNTS = {0.1, 0.2, 0.3, 0.5, 0.8, 1.3};
|
||||
|
||||
private static double getAmount(int i) {
|
||||
return AMOUNTS[i];
|
||||
}
|
||||
|
||||
// find the closest amount we have
|
||||
private static int getTick(long amount) {
|
||||
int enabled = amount > 0 ? 1 : -1;
|
||||
amount = Math.abs(amount);
|
||||
double lastDiff = Double.MAX_VALUE;
|
||||
for (int i = 0; i < AMOUNTS.length; i++) {
|
||||
final double diff = Math.abs(Helper.ONE_XMR * AMOUNTS[i] - amount);
|
||||
if (lastDiff < diff) return i - 1;
|
||||
lastDiff = diff;
|
||||
}
|
||||
return enabled * (AMOUNTS.length - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
||||
tvProgressLabel.setText(getString(R.string.pocketchange_amount, getAmount((int) value)));
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void setPocketChange(Wallet.PocketChangeSetting setting);
|
||||
}
|
||||
}
|
|
@ -411,10 +411,10 @@ public class SendAddressWizardFragment extends SendWizardFragment {
|
|||
if (txData instanceof TxDataBtc) {
|
||||
((TxDataBtc) txData).setBtcAddress(etAddress.getEditText().getText().toString());
|
||||
((TxDataBtc) txData).setBtcSymbol(selectedCrypto.getSymbol());
|
||||
txData.setDestinationAddress(null);
|
||||
txData.setDestination(null);
|
||||
ServiceHelper.ASSET = selectedCrypto.getSymbol().toLowerCase();
|
||||
} else {
|
||||
txData.setDestinationAddress(etAddress.getEditText().getText().toString());
|
||||
txData.setDestination(etAddress.getEditText().getText().toString());
|
||||
ServiceHelper.ASSET = null;
|
||||
}
|
||||
txData.setUserNotes(new UserNotes(etNotes.getEditText().getText().toString()));
|
||||
|
|
|
@ -23,6 +23,8 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||
import com.m2049r.xmrwallet.R;
|
||||
import com.m2049r.xmrwallet.data.BarcodeData;
|
||||
import com.m2049r.xmrwallet.data.TxData;
|
||||
|
|
|
@ -348,7 +348,7 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
|
|||
}
|
||||
showProgress(3, getString(R.string.label_send_progress_create_tx));
|
||||
final TxData txData = sendListener.getTxData();
|
||||
txData.setDestinationAddress(xmrtoOrder.getXmrAddress());
|
||||
txData.setDestination(xmrtoOrder.getXmrAddress());
|
||||
txData.setAmount(xmrtoOrder.getXmrAmount());
|
||||
getActivityCallback().onPrepareSend(xmrtoOrder.getOrderId(), txData);
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public class SendBtcSuccessWizardFragment extends SendWizardFragment {
|
|||
isResumed = true;
|
||||
|
||||
btcData = (TxDataBtc) sendListener.getTxData();
|
||||
tvTxAddress.setText(btcData.getDestinationAddress());
|
||||
tvTxAddress.setText(btcData.getDestination());
|
||||
|
||||
final PendingTx committedTx = sendListener.getCommittedTx();
|
||||
if (committedTx != null) {
|
||||
|
|
|
@ -64,12 +64,14 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
|
|||
private TextView tvTxAddress;
|
||||
private TextView tvTxNotes;
|
||||
private TextView tvTxAmount;
|
||||
private TextView tvTxChange;
|
||||
private TextView tvTxFee;
|
||||
private TextView tvTxTotal;
|
||||
private View llProgress;
|
||||
private View bSend;
|
||||
private View llConfirmSend;
|
||||
private View pbProgressSend;
|
||||
private View llPocketChange;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
|
@ -83,12 +85,14 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
|
|||
tvTxAddress = view.findViewById(R.id.tvTxAddress);
|
||||
tvTxNotes = view.findViewById(R.id.tvTxNotes);
|
||||
tvTxAmount = view.findViewById(R.id.tvTxAmount);
|
||||
tvTxChange = view.findViewById(R.id.tvTxChange);
|
||||
tvTxFee = view.findViewById(R.id.tvTxFee);
|
||||
tvTxTotal = view.findViewById(R.id.tvTxTotal);
|
||||
|
||||
llProgress = view.findViewById(R.id.llProgress);
|
||||
pbProgressSend = view.findViewById(R.id.pbProgressSend);
|
||||
llConfirmSend = view.findViewById(R.id.llConfirmSend);
|
||||
llPocketChange = view.findViewById(R.id.llPocketChange);
|
||||
|
||||
bSend = view.findViewById(R.id.bSend);
|
||||
bSend.setEnabled(false);
|
||||
|
@ -181,7 +185,7 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
|
|||
isResumed = true;
|
||||
|
||||
final TxData txData = sendListener.getTxData();
|
||||
tvTxAddress.setText(txData.getDestinationAddress());
|
||||
tvTxAddress.setText(txData.getDestination());
|
||||
UserNotes notes = sendListener.getTxData().getUserNotes();
|
||||
if ((notes != null) && (!notes.note.isEmpty())) {
|
||||
tvTxNotes.setText(notes.note);
|
||||
|
@ -206,7 +210,14 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
|
|||
tvTxAmount.setText(getString(R.string.street_sweep_amount));
|
||||
tvTxTotal.setText(getString(R.string.street_sweep_amount));
|
||||
} else {
|
||||
tvTxAmount.setText(Wallet.getDisplayAmount(pendingTransaction.getAmount()));
|
||||
tvTxAmount.setText(Wallet.getDisplayAmount(pendingTransaction.getNetAmount()));
|
||||
final long change = pendingTransaction.getPocketChange();
|
||||
if (change > 0) {
|
||||
llPocketChange.setVisibility(View.VISIBLE);
|
||||
tvTxChange.setText(Wallet.getDisplayAmount(change));
|
||||
} else {
|
||||
llPocketChange.setVisibility(View.GONE);
|
||||
}
|
||||
tvTxTotal.setText(Wallet.getDisplayAmount(
|
||||
pendingTransaction.getFee() + pendingTransaction.getAmount()));
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public class SendSuccessWizardFragment extends SendWizardFragment {
|
|||
Helper.hideKeyboard(getActivity());
|
||||
|
||||
final TxData txData = sendListener.getTxData();
|
||||
tvTxAddress.setText(txData.getDestinationAddress());
|
||||
tvTxAddress.setText(txData.getDestination());
|
||||
|
||||
final PendingTx committedTx = sendListener.getCommittedTx();
|
||||
if (committedTx != null) {
|
||||
|
|
|
@ -189,7 +189,6 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||
}
|
||||
|
||||
private void showLock() {
|
||||
Timber.d("UNLOCK %d:%d", infoItem.unlockTime, infoItem.blockheight);
|
||||
if (infoItem.unlockTime == 0) {
|
||||
ivLock.setVisibility(View.GONE);
|
||||
return;
|
||||
|
@ -220,7 +219,7 @@ public class TransactionInfoAdapter extends RecyclerView.Adapter<TransactionInfo
|
|||
ivTxType.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
String displayAmount = Helper.getDisplayAmount(infoItem.amount, Helper.DISPLAY_DIGITS_INFO);
|
||||
String displayAmount = Helper.getDisplayAmount(infoItem.getNetAmount(), Helper.DISPLAY_DIGITS_INFO);
|
||||
if (infoItem.direction == TransactionInfo.Direction.Direction_Out) {
|
||||
tvAmount.setText(context.getString(R.string.tx_list_amount_negative, displayAmount));
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 java.util.List;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class Coins {
|
||||
static {
|
||||
System.loadLibrary("monerujo");
|
||||
}
|
||||
|
||||
private long handle;
|
||||
|
||||
public Coins(long handle) {
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public List<CoinsInfo> getAll(int accountIndex, boolean unspentOnly) {
|
||||
return refresh(accountIndex, unspentOnly);
|
||||
}
|
||||
|
||||
private native List<CoinsInfo> refresh(int accountIndex, boolean unspentOnly);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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 lombok.Value;
|
||||
|
||||
// this is not the CoinsInfo from the API as that is owned by the Coins object
|
||||
// this is a POJO
|
||||
@Value
|
||||
public class CoinsInfo {
|
||||
int accountIndex;
|
||||
int addressIndex;
|
||||
long amount;
|
||||
long blockheight;
|
||||
String txHash;
|
||||
boolean spent;
|
||||
boolean frozen;
|
||||
long unlockTime;
|
||||
boolean unlocked;
|
||||
|
||||
public boolean isSpendable() {
|
||||
return !spent && unlocked;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class PendingTransaction {
|
||||
static {
|
||||
System.loadLibrary("monerujo");
|
||||
|
@ -63,8 +66,6 @@ public class PendingTransaction {
|
|||
Priority(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
|
@ -95,4 +96,11 @@ public class PendingTransaction {
|
|||
|
||||
public native long getTxCount();
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private long pocketChange;
|
||||
|
||||
public long getNetAmount() {
|
||||
return getAmount() - pocketChange;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
package com.m2049r.xmrwallet.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
|
@ -61,22 +63,14 @@ public class TransactionHistory {
|
|||
|
||||
private List<TransactionInfo> transactions = new ArrayList<>();
|
||||
|
||||
void refreshWithNotes(Wallet wallet) {
|
||||
public void refreshWithNotes(Wallet wallet) {
|
||||
refresh();
|
||||
loadNotes(wallet);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
List<TransactionInfo> transactionInfos = refreshJ();
|
||||
Timber.d("refresh size=%d", transactionInfos.size());
|
||||
for (Iterator<TransactionInfo> iterator = transactionInfos.iterator(); iterator.hasNext(); ) {
|
||||
TransactionInfo info = iterator.next();
|
||||
if (info.accountIndex != accountIndex) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
transactions = transactionInfos;
|
||||
transactions = refreshJ(accountIndex);
|
||||
}
|
||||
|
||||
private native List<TransactionInfo> refreshJ();
|
||||
private native List<TransactionInfo> refreshJ(int accountIndex);
|
||||
}
|
||||
|
|
|
@ -101,6 +101,23 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
|
|||
this.unlockTime = unlockTime;
|
||||
this.subaddressLabel = subaddressLabel;
|
||||
this.transfers = transfers;
|
||||
calcNetAmount();
|
||||
}
|
||||
|
||||
@Getter
|
||||
private long netAmount;
|
||||
|
||||
public long getPocketChangeAmount() {
|
||||
return amount - netAmount;
|
||||
}
|
||||
|
||||
private void calcNetAmount() {
|
||||
netAmount = amount;
|
||||
if ((direction == TransactionInfo.Direction.Direction_Out) && (transfers != null)) {
|
||||
for (int i = 1; i < transfers.size(); i++) {
|
||||
netAmount -= transfers.get(i).amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConfirmed() {
|
||||
|
@ -138,6 +155,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
|
|||
out.writeString(txKey);
|
||||
out.writeString(notes);
|
||||
out.writeString(address);
|
||||
out.writeLong(netAmount);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<TransactionInfo> CREATOR = new Parcelable.Creator<TransactionInfo>() {
|
||||
|
@ -169,6 +187,7 @@ public class TransactionInfo implements Parcelable, Comparable<TransactionInfo>
|
|||
txKey = in.readString();
|
||||
notes = in.readString();
|
||||
address = in.readString();
|
||||
netAmount = in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,10 +25,13 @@ import com.m2049r.xmrwallet.data.TxData;
|
|||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.Value;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class Wallet {
|
||||
|
@ -67,9 +70,7 @@ public class Wallet {
|
|||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return (getStatus() == StatusEnum.Status_Ok)
|
||||
&& ((getConnectionStatus() == null) ||
|
||||
(getConnectionStatus() == ConnectionStatus.ConnectionStatus_Connected));
|
||||
return (getStatus() == StatusEnum.Status_Ok) && ((getConnectionStatus() == null) || (getConnectionStatus() == ConnectionStatus.ConnectionStatus_Connected));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -110,23 +111,17 @@ public class Wallet {
|
|||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum Device {
|
||||
Device_Undefined(0, 0),
|
||||
Device_Software(50, 200),
|
||||
Device_Ledger(5, 20);
|
||||
Device_Undefined(0, 0), Device_Software(50, 200), Device_Ledger(5, 20);
|
||||
private final int accountLookahead;
|
||||
private final int subaddressLookahead;
|
||||
}
|
||||
|
||||
public enum StatusEnum {
|
||||
Status_Ok,
|
||||
Status_Error,
|
||||
Status_Critical
|
||||
Status_Ok, Status_Error, Status_Critical
|
||||
}
|
||||
|
||||
public enum ConnectionStatus {
|
||||
ConnectionStatus_Disconnected,
|
||||
ConnectionStatus_Connected,
|
||||
ConnectionStatus_WrongVersion
|
||||
ConnectionStatus_Disconnected, ConnectionStatus_Connected, ConnectionStatus_WrongVersion
|
||||
}
|
||||
|
||||
public native String getSeed(String offset);
|
||||
|
@ -168,16 +163,14 @@ public class Wallet {
|
|||
private native String getAddressJ(int accountIndex, int addressIndex);
|
||||
|
||||
public Subaddress getSubaddressObject(int accountIndex, int subAddressIndex) {
|
||||
return new Subaddress(accountIndex, subAddressIndex,
|
||||
getSubaddress(subAddressIndex), getSubaddressLabel(subAddressIndex));
|
||||
return new Subaddress(accountIndex, subAddressIndex, getSubaddress(subAddressIndex), getSubaddressLabel(subAddressIndex));
|
||||
}
|
||||
|
||||
public Subaddress getSubaddressObject(int subAddressIndex) {
|
||||
Subaddress subaddress = getSubaddressObject(accountIndex, subAddressIndex);
|
||||
long amount = 0;
|
||||
for (TransactionInfo info : getHistory().getAll()) {
|
||||
if ((info.addressIndex == subAddressIndex)
|
||||
&& (info.direction == TransactionInfo.Direction.Direction_In)) {
|
||||
if ((info.addressIndex == subAddressIndex) && (info.direction == TransactionInfo.Direction.Direction_In)) {
|
||||
amount += info.amount;
|
||||
}
|
||||
}
|
||||
|
@ -217,13 +210,10 @@ public class Wallet {
|
|||
|
||||
// virtual std::string keysFilename() const = 0;
|
||||
public boolean init(long upper_transaction_size_limit) {
|
||||
return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit,
|
||||
WalletManager.getInstance().getDaemonUsername(),
|
||||
WalletManager.getInstance().getDaemonPassword());
|
||||
return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit, WalletManager.getInstance().getDaemonUsername(), WalletManager.getInstance().getDaemonPassword());
|
||||
}
|
||||
|
||||
private native boolean initJ(String daemon_address, long upper_transaction_size_limit,
|
||||
String daemon_username, String daemon_password);
|
||||
private native boolean initJ(String daemon_address, long upper_transaction_size_limit, String daemon_username, String daemon_password);
|
||||
|
||||
// virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0;
|
||||
// virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0;
|
||||
|
@ -335,36 +325,23 @@ public class Wallet {
|
|||
}
|
||||
}
|
||||
|
||||
public PendingTransaction createTransaction(TxData txData) {
|
||||
return createTransaction(
|
||||
txData.getDestinationAddress(),
|
||||
txData.getAmount(),
|
||||
txData.getMixin(),
|
||||
txData.getPriority());
|
||||
}
|
||||
private native long createTransactionMultDest(String[] destinations, String payment_id, long[] amounts, int mixin_count, int priority, int accountIndex, int[] subaddresses);
|
||||
|
||||
public PendingTransaction createTransaction(String dst_addr,
|
||||
long amount, int mixin_count,
|
||||
PendingTransaction.Priority priority) {
|
||||
public PendingTransaction createTransaction(TxData txData) {
|
||||
disposePendingTransaction();
|
||||
int _priority = priority.getValue();
|
||||
long txHandle =
|
||||
(amount == SWEEP_ALL ?
|
||||
createSweepTransaction(dst_addr, "", mixin_count, _priority,
|
||||
accountIndex) :
|
||||
createTransactionJ(dst_addr, "", amount, mixin_count, _priority,
|
||||
accountIndex));
|
||||
int _priority = txData.getPriority().getValue();
|
||||
final boolean sweepAll = txData.getAmount() == SWEEP_ALL;
|
||||
Timber.d("TxData: %s", txData);
|
||||
long txHandle = (sweepAll ? createSweepTransaction(txData.getDestination(), "", txData.getMixin(), _priority, accountIndex) :
|
||||
createTransactionMultDest(txData.getDestinations(), "", txData.getAmounts(), txData.getMixin(), _priority, accountIndex, txData.getSubaddresses()));
|
||||
pendingTransaction = new PendingTransaction(txHandle);
|
||||
pendingTransaction.setPocketChange(txData.getPocketChangeAmount());
|
||||
return pendingTransaction;
|
||||
}
|
||||
|
||||
private native long createTransactionJ(String dst_addr, String payment_id,
|
||||
long amount, int mixin_count,
|
||||
int priority, int accountIndex);
|
||||
private native long createTransactionJ(String dst_addr, String payment_id, long amount, int mixin_count, int priority, int accountIndex);
|
||||
|
||||
private native long createSweepTransaction(String dst_addr, String payment_id,
|
||||
int mixin_count,
|
||||
int priority, int accountIndex);
|
||||
private native long createSweepTransaction(String dst_addr, String payment_id, int mixin_count, int priority, int accountIndex);
|
||||
|
||||
|
||||
public PendingTransaction createSweepUnmixableTransaction() {
|
||||
|
@ -381,7 +358,13 @@ public class Wallet {
|
|||
|
||||
public native void disposeTransaction(PendingTransaction pendingTransaction);
|
||||
|
||||
//virtual bool exportKeyImages(const std::string &filename) = 0;
|
||||
public long estimateTransactionFee(TxData txData) {
|
||||
return estimateTransactionFee(txData.getDestinations(), txData.getAmounts(), txData.getPriority().getValue());
|
||||
}
|
||||
|
||||
private native long estimateTransactionFee(String[] destinations, long[] amounts, int priority);
|
||||
|
||||
//virtual bool exportKeyImages(const std::string &filename) = 0;
|
||||
//virtual bool importKeyImages(const std::string &filename) = 0;
|
||||
|
||||
|
||||
|
@ -403,6 +386,22 @@ public class Wallet {
|
|||
}
|
||||
|
||||
//virtual AddressBook * addressBook() const = 0;
|
||||
|
||||
public List<CoinsInfo> getCoinsInfos(boolean unspentOnly) {
|
||||
return getCoins().getAll(accountIndex, unspentOnly);
|
||||
}
|
||||
|
||||
private Coins coins = null;
|
||||
|
||||
private Coins getCoins() {
|
||||
if (coins == null) {
|
||||
coins = new Coins(getCoinsJ());
|
||||
}
|
||||
return coins;
|
||||
}
|
||||
|
||||
private native long getCoinsJ();
|
||||
|
||||
//virtual void setListener(WalletListener *) = 0;
|
||||
|
||||
private native long setListenerJ(WalletListener listener);
|
||||
|
@ -444,8 +443,7 @@ public class Wallet {
|
|||
if (label.equals(NEW_ACCOUNT_NAME)) {
|
||||
String address = getAddress(accountIndex);
|
||||
int len = address.length();
|
||||
label = address.substring(0, 6) +
|
||||
"\u2026" + address.substring(len - 6, len);
|
||||
label = address.substring(0, 6) + "\u2026" + address.substring(len - 6, len);
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
@ -504,4 +502,22 @@ public class Wallet {
|
|||
|
||||
private native int getDeviceTypeJ();
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
PocketChangeSetting pocketChangeSetting = PocketChangeSetting.of(false, 0);
|
||||
|
||||
@Value(staticConstructor = "of")
|
||||
static public class PocketChangeSetting {
|
||||
boolean enabled;
|
||||
long amount;
|
||||
|
||||
public String toPrefString() {
|
||||
return Long.toString((enabled ? 1 : -1) * amount);
|
||||
}
|
||||
|
||||
static public PocketChangeSetting from(String prefString) {
|
||||
long value = Long.parseLong(prefString);
|
||||
return of(value > 0, Math.abs(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -318,9 +318,10 @@ public class WalletService extends Service {
|
|||
|
||||
TxData txData = extras.getParcelable(REQUEST_CMD_TX_DATA);
|
||||
String txTag = extras.getString(REQUEST_CMD_TX_TAG);
|
||||
assert txData != null;
|
||||
txData.createPocketChange(myWallet);
|
||||
PendingTransaction pendingTransaction = myWallet.createTransaction(txData);
|
||||
PendingTransaction.Status status = pendingTransaction.getStatus();
|
||||
Timber.d("transaction status %s", status);
|
||||
if (status != PendingTransaction.Status.Status_Ok) {
|
||||
Timber.w("Create Transaction failed: %s", pendingTransaction.getErrorString());
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ public class ExchangeEditText extends LinearLayout {
|
|||
|
||||
// make progress circle gray
|
||||
pbExchange.getIndeterminateDrawable().
|
||||
setColorFilter(ThemeHelper.getThemedColor(getContext(), R.attr.colorPrimaryVariant),
|
||||
setColorFilter(ThemeHelper.getThemedColor(getContext(), com.google.android.material.R.attr.colorPrimaryVariant),
|
||||
android.graphics.PorterDuff.Mode.MULTIPLY);
|
||||
|
||||
sCurrencyA.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
|
|
|
@ -177,7 +177,7 @@ public class ExchangeView extends LinearLayout {
|
|||
|
||||
// make progress circle gray
|
||||
pbExchange.getIndeterminateDrawable().
|
||||
setColorFilter(ThemeHelper.getThemedColor(getContext(), R.attr.colorPrimaryVariant),
|
||||
setColorFilter(ThemeHelper.getThemedColor(getContext(), com.google.android.material.R.attr.colorPrimaryVariant),
|
||||
android.graphics.PorterDuff.Mode.MULTIPLY);
|
||||
|
||||
sCurrencyA.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
|
|
|
@ -23,7 +23,7 @@ public class PasswordEntryView extends TextInputLayout implements TextWatcher {
|
|||
}
|
||||
|
||||
public PasswordEntryView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs, R.attr.textInputStyle);
|
||||
super(context, attrs, com.google.android.material.R.attr.textInputStyle);
|
||||
}
|
||||
|
||||
public PasswordEntryView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorPrimaryVariant"
|
||||
android:pathData="M15,4c-4.42,0 -8,3.58 -8,8s3.58,8 8,8 8,-3.58 8,-8 -3.58,-8 -8,-8zM15,18c-3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6 6,2.69 6,6 -2.69,6 -6,6z" />
|
||||
<path
|
||||
android:fillColor="?attr/colorPrimaryVariant"
|
||||
android:pathData="M3,12c0,-2.61 1.67,-4.83 4,-5.65V4.26C3.55,5.15 1,8.27 1,12s2.55,6.85 6,7.74v-2.09c-2.33,-0.82 -4,-3.04 -4,-5.65z" />
|
||||
</vector>
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_toll" />
|
||||
|
||||
<TextView
|
||||
style="@style/MoneroText.Large"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pocketchange_title"
|
||||
android:textAlignment="textStart" />
|
||||
|
||||
<TextView
|
||||
style="@style/MoneroText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/header_top"
|
||||
android:text="@string/pocketchange_info"
|
||||
android:textAlignment="textStart" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="@dimen/header_top"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<TextView
|
||||
style="@style/MoneroLabel.Heading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/pocketchange_create_title" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switchPocketChange"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llAmount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="@dimen/header_top"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<TextView
|
||||
style="@style/MoneroLabel.Heading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/tx_amount" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/seekbar_value"
|
||||
style="@style/MoneroLabel.Heading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/pocketchange_amount" />
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:stepSize="1"
|
||||
android:value="1"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="5"
|
||||
app:labelBehavior="gone"
|
||||
app:tickVisible="true" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
|
@ -38,7 +38,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<RelativeLayout
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
style="@style/MoneroText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAlignment="textStart"
|
||||
tools:text="4AdkPJoxn7JCvAby9szgnt93MSEwdnxdhaASxbTBm6x5dCwmsDep2UYN4FhStDn5i11nsJbpU7oj59ahg8gXb1Mg3viqCuk" />
|
||||
|
||||
|
@ -103,6 +103,31 @@
|
|||
tools:text="143.008000000000" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llPocketChange"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
style="@style/MoneroLabel.Gray"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/pocketchange_title"
|
||||
android:textAlignment="textStart" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTxChange"
|
||||
style="@style/MoneroText.Gray"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:textAlignment="textEnd"
|
||||
tools:text="143.008000000000" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -59,6 +59,15 @@
|
|||
android:transitionName="@string/tx_details_transition_name"
|
||||
tools:text="+ 1,092.00229" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTxPocketChangeAmount"
|
||||
style="@style/MoneroText.PosPocketChange"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:selectAllOnFocus="true"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="PocketChange 1,092.00229" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTxFee"
|
||||
style="@style/MoneroText.PosFee"
|
||||
|
|
|
@ -10,28 +10,16 @@
|
|||
android:title="@string/menu_streetmode"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_rename"
|
||||
android:orderInCategory="200"
|
||||
android:title="@string/menu_rename"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_subaddresses"
|
||||
android:orderInCategory="250"
|
||||
android:title="@string/subbaddress_title"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_help_wallet"
|
||||
android:orderInCategory="300"
|
||||
android:orderInCategory="150"
|
||||
android:title="@string/menu_help"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_credits"
|
||||
android:orderInCategory="400"
|
||||
android:title="@string/label_credits"
|
||||
android:id="@+id/action_rename"
|
||||
android:orderInCategory="200"
|
||||
android:title="@string/menu_rename"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
|
@ -45,4 +33,17 @@
|
|||
android:orderInCategory="600"
|
||||
android:title="@string/menu_rescan"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_subaddresses"
|
||||
android:orderInCategory="700"
|
||||
android:title="@string/subbaddress_title"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_pocketchange"
|
||||
android:orderInCategory="800"
|
||||
android:title="@string/pocketchange_title"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
|
@ -442,4 +442,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -443,4 +443,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -444,4 +444,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -442,4 +442,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
<resources>
|
||||
<string name="wallet_activity_name">Monedero</string>
|
||||
|
||||
<string name="menu_about">Acerca De</string>
|
||||
<string name="menu_about">Legal</string>
|
||||
<string name="menu_privacy">Política de Privacidad</string>
|
||||
|
||||
<string name="menu_share">Compartir</string>
|
||||
<string name="menu_help">Ayuda</string>
|
||||
<string name="menu_receive">Recibir</string>
|
||||
<string name="menu_rename">Renombrar</string>
|
||||
<string name="menu_rename">Cambiar nombre</string>
|
||||
<string name="menu_backup">Copia de seguridad</string>
|
||||
<string name="menu_changepw">Cambiar contraseña</string>
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
<string name="label_ok">Aceptar</string>
|
||||
<string name="label_cancel">Cancelar</string>
|
||||
<string name="label_close">Cerrar</string>
|
||||
<string name="label_wallet_advanced_details">Información más detallada</string>
|
||||
<string name="label_wallet_advanced_details">Detalle de claves</string>
|
||||
|
||||
<string name="label_send_success">¡Éxito!</string>
|
||||
<string name="label_send_done">Hecho</string>
|
||||
|
@ -39,12 +39,12 @@
|
|||
<string name="label_send_address">Dirección de Destino</string>
|
||||
<string name="label_send_notes">Notas</string>
|
||||
|
||||
<string name="backup_progress">Copia de seguridad en progreso</string>
|
||||
<string name="archive_progress">Archivado en progreso</string>
|
||||
<string name="rename_progress">Cambio de nombre en progreso</string>
|
||||
<string name="changepw_progress">Cambiando contraseña en progreso</string>
|
||||
<string name="backup_progress">Copia de seguridad en progreso…</string>
|
||||
<string name="archive_progress">Archivado en progreso…</string>
|
||||
<string name="rename_progress">Cambio de nombre en progreso…</string>
|
||||
<string name="changepw_progress">Cambiando contraseña en progreso…</string>
|
||||
|
||||
<string name="service_progress">Guardando todo\n¡Puede llevar un tiempo!</string>
|
||||
<string name="service_progress">Cerrando el monedero…\n¡Puede tardar un tiempo!</string>
|
||||
|
||||
<string name="backup_success">Copia de seguridad exitosa</string>
|
||||
<string name="backup_failed">¡Copia de seguridad fallida!</string>
|
||||
|
@ -55,19 +55,19 @@
|
|||
<string name="label_daemon">Nodo</string>
|
||||
<string name="status_wallet_loading">Cargando monedero…</string>
|
||||
<string name="status_wallet_unloaded">Monedero guardado</string>
|
||||
<string name="status_wallet_unload_failed">¡Guardado de monedero fallido!</string>
|
||||
<string name="status_wallet_unload_failed">¡Fallo al guardar el monedero!</string>
|
||||
<string name="status_wallet_connecting">Conectando…</string>
|
||||
<string name="status_wallet_connect_failed">¡Conexión con el nodo fallida!\nComprueba el usuario/contraseña</string>
|
||||
<string name="status_wallet_node_invalid">¡Nodo inválido!\nInténtalo con otro.</string>
|
||||
<string name="status_wallet_connect_ioex">¡No se puede alcanzar el nodo!\nInténtalo de nuevo o prueba otro.</string>
|
||||
<string name="status_wallet_connect_ioex">¡No se puede conectar con el nodo!\nInténtalo de nuevo o prueba otro.</string>
|
||||
|
||||
<string name="status_wallet_disconnected">Desconectado</string>
|
||||
|
||||
<string name="status_transaction_failed">Transacción fallida: %1$s</string>
|
||||
|
||||
<string name="service_busy">Todavía estoy ocupado con tu último monedero …</string>
|
||||
<string name="service_busy">Todavía estoy ocupado con el último monedero …</string>
|
||||
|
||||
<string name="prompt_rename">Renombrar %1$s</string>
|
||||
<string name="prompt_rename">Nuevo nombre para %1$s</string>
|
||||
|
||||
<string name="prompt_changepw">Nueva contraseña para %1$s</string>
|
||||
<string name="prompt_changepwB">Repetir contraseña para %1$s</string>
|
||||
|
@ -88,21 +88,21 @@
|
|||
|
||||
<string name="xmr_unconfirmed_amount">+ %1$s %2$s sin confirmar</string>
|
||||
|
||||
<string name="service_description">Servicio de Monerujo</string>
|
||||
<string name="service_description">Monedero abierto</string>
|
||||
|
||||
<string name="status_synced">Sincronizado:</string>
|
||||
<string name="status_remaining">bloques restantes</string>
|
||||
<string name="status_syncing">Escaneando:</string>
|
||||
|
||||
<string name="message_strorage_not_writable">¡No se puede escribir en el almacenamiento externo! ¡Pánico!</string>
|
||||
<string name="message_strorage_not_writable">¡Oh no! ¡No se puede escribir en el almacenamiento externo!</string>
|
||||
<string name="message_strorage_not_permitted">¡De verdad necesitamos ese permiso para el almacenamiento externo!</string>
|
||||
<string name="message_camera_not_permitted">Sin cámara = ¡Sin escaneo de QR!</string>
|
||||
<string name="message_camera_not_permitted">¡No se puede escanear un QR sin acceso a la cámara!</string>
|
||||
|
||||
<string name="label_copy_viewkey">Clave de Vista</string>
|
||||
<string name="label_copy_address">Dirección Pública</string>
|
||||
<string name="message_copy_viewkey">¡Clave de vista copiada al portapapeles!</string>
|
||||
<string name="message_copy_address">¡Dirección del monedero copiada al portapapeles!</string>
|
||||
<string name="message_nocopy">¡Copia desactivada por motivos de seguridad!</string>
|
||||
<string name="message_nocopy">¡Copia no permitida para tu seguridad!</string>
|
||||
|
||||
<string name="message_exchange_failed">¡No se ha podido obtener la tasa de cambio!\nUsa XMR/XMR o inténtalo de nuevo</string>
|
||||
|
||||
|
@ -112,25 +112,24 @@
|
|||
<string name="generate_fingerprint_hint">Permitir abrir usando huella dactilar</string>
|
||||
<string name="generate_fingerprint_warn"><![CDATA[
|
||||
<strong>Autenticación por huella</strong>
|
||||
<p>Con la autenticación por huella dactilar activada, puedes acceder al balance y recibir fondos
|
||||
<p>Con la autenticación por huella dactilar activada, puedes abrir tu monedero y recibir fondos
|
||||
sin la necesidad de ingresar tu contraseña.</p>
|
||||
<p>Sin embargo, por seguridad extra, Monerujo va a requerir tu contraseña para ver la información
|
||||
sensible de tu monedero o enviar fondos.</p>
|
||||
<p>Sin embargo, para tu seguridad, Monerujo va a requerir tu contraseña para ver los secretos de tu monedero o enviar fondos.</p>
|
||||
<strong>Advertencia de seguridad</strong>
|
||||
<p>Si bien es cómodo, recuerda que cualquier persona que tenga acceso a tu huella dactilar
|
||||
va a ser capaz de mirar el balance de tu monedero.</p>
|
||||
<p>Por ejemplo, un actor malicioso cercano podría abrir tu monedero con tu dedo mientras duermes.</p>
|
||||
<p>Por ejemplo, alguien podría abrir tu monedero con tu dedo mientras duermes.</p>
|
||||
<strong>¿Estás seguro de activar esta función?</strong>
|
||||
]]></string>
|
||||
<string name="generate_bad_passwordB">Contraseñas no coinciden</string>
|
||||
<string name="generate_empty_passwordB">Contraseña no puede estar vacía</string>
|
||||
<string name="generate_empty_passwordB">La contraseña no puede estar vacía</string>
|
||||
<string name="generate_buttonGenerate">¡Házme ya un monedero!</string>
|
||||
<string name="generate_button_accept">¡Ya anote todo!</string>
|
||||
|
||||
<string name="generate_wallet_name">¡Dame un nombre!</string>
|
||||
<string name="generate_wallet_exists">¡El monedero ya existe!</string>
|
||||
<string name="generate_wallet_dot">No puede empezar con .</string>
|
||||
<string name="generate_wallet_creating">Creando monedero</string>
|
||||
<string name="generate_wallet_creating">Creando monedero…</string>
|
||||
<string name="generate_wallet_created">Monedero creada</string>
|
||||
|
||||
<string name="generate_restoreheight_error">Introduce un número o una fecha (AAAA-MM-DD)</string>
|
||||
|
@ -140,17 +139,17 @@
|
|||
<string name="generate_wallet_type_seed">Semilla</string>
|
||||
<string name="generate_wallet_type_view">Ver</string>
|
||||
|
||||
<string name="generate_address_hint">Dirección Pública</string>
|
||||
<string name="generate_viewkey_hint">Clave de Vista</string>
|
||||
<string name="generate_spendkey_hint">Clave de Gasto</string>
|
||||
<string name="generate_mnemonic_hint">Semilla Mnemotécnica de 25 Palabras</string>
|
||||
<string name="generate_restoreheight_hint">Altura o Fecha (YYYY-MM-DD) de Restauración</string>
|
||||
<string name="generate_address_hint">Dirección pública</string>
|
||||
<string name="generate_viewkey_hint">Clave de vista</string>
|
||||
<string name="generate_spendkey_hint">Clave de gasto</string>
|
||||
<string name="generate_mnemonic_hint">Semilla mnemotécnica</string>
|
||||
<string name="generate_restoreheight_hint">Altura o fecha (YYYY-MM-DD) de restauración</string>
|
||||
|
||||
<string name="generate_address_label">Dirección Pública</string>
|
||||
<string name="generate_viewkey_label">Clave de Vista</string>
|
||||
<string name="generate_spendkey_label">Clave de Gasto</string>
|
||||
<string name="generate_mnemonic_label">Semilla Mnemotécnica</string>
|
||||
<string name="generate_crazypass_label">Contraseña de restauración para el archivo del monedero</string>
|
||||
<string name="generate_address_label">Dirección pública</string>
|
||||
<string name="generate_viewkey_label">Clave de vista</string>
|
||||
<string name="generate_spendkey_label">Clave de gasto</string>
|
||||
<string name="generate_mnemonic_label">Semilla mnemotécnica</string>
|
||||
<string name="generate_crazypass_label">Clave loca para restaurar el monedero</string>
|
||||
|
||||
<string name="generate_check_key">Introduce una clave válida</string>
|
||||
<string name="generate_check_address">Introduce una dirección válida</string>
|
||||
|
@ -181,19 +180,19 @@
|
|||
|
||||
<string name="tx_timestamp">Marca de tiempo</string>
|
||||
<string name="tx_id">ID de Transacción</string>
|
||||
<string name="tx_key">Clave de Transacción</string>
|
||||
<string name="tx_key">Clave de transacción</string>
|
||||
<string name="tx_destination">Destino</string>
|
||||
<string name="tx_paymentId">ID de Pago</string>
|
||||
<string name="tx_paymentId">ID de pago</string>
|
||||
<string name="tx_blockheight">Bloque</string>
|
||||
<string name="tx_amount">Monto</string>
|
||||
<string name="tx_fee">Comisión</string>
|
||||
<string name="tx_transfers">Transferencias</string>
|
||||
<string name="tx_notes">Notas</string>
|
||||
<string name="tx_notes_hint">(opcional)</string>
|
||||
<string name="tx_title">Detalles de la Transacción</string>
|
||||
<string name="tx_title">Detalles de la transacción</string>
|
||||
|
||||
<string name="tx_pending">PENDIENTE</string>
|
||||
<string name="tx_failed">FALLIDO</string>
|
||||
<string name="tx_failed">FALLIDA</string>
|
||||
|
||||
<string name="receive_amount_hint">Monto</string>
|
||||
<string name="receive_cannot_open">¡No se ha podido abrir el monedero!</string>
|
||||
|
@ -202,19 +201,19 @@
|
|||
<string name="receive_amount_negative">Min. 0</string>
|
||||
<string name="receive_amount_nan">XMR no es un número</string>
|
||||
|
||||
<string name="details_alert_message">Se va a mostrar información delicada.\n¡Mira por encima del hombro!</string>
|
||||
<string name="details_alert_message">Se va a mostrar información delicada. Cualquiera con acceso a ella tendría control sobre tus fondos.\n¡Mira detrás tuyo!</string>
|
||||
<string name="details_alert_yes">Estoy seguro</string>
|
||||
<string name="details_alert_no">¡Llévame de vuelta!</string>
|
||||
<string name="details_title">Detalles</string>
|
||||
<string name="details_alert_no">No muestres nada</string>
|
||||
<string name="details_title">Secretos del monedero</string>
|
||||
|
||||
<string name="delete_alert_message">Este monedero será borrado. Tus fondos se irán para siempre a menos que tengas tu semilla o una copia de seguridad funcional para recuperarlo.</string>
|
||||
<string name="delete_alert_yes">¡Sí, hazlo!</string>
|
||||
<string name="delete_alert_no">¡No, gracias!</string>
|
||||
<string name="delete_alert_message">Este monedero será borrado.\nTus fondos se perderán para siempre sino tienes tu semilla mnemotéctica o una copia de seguridad y su correspondiente clave loca para recuperarla.\nPuedes encontrar ambas entre los secretos de tu monedero.</string>
|
||||
<string name="delete_alert_yes">Sí, hazlo</string>
|
||||
<string name="delete_alert_no">No lo hagas</string>
|
||||
|
||||
<string name="fab_create_new">Crear nuevo monedero</string>
|
||||
<string name="fab_restore_viewonly">Restaurar monedero de sólo vista</string>
|
||||
<string name="fab_restore_key">Restaurar monedero con claves privadas</string>
|
||||
<string name="fab_restore_seed">Restaurar monedero con semilla de 25 palabras</string>
|
||||
<string name="fab_restore_key">Restaurar monedero con claves</string>
|
||||
<string name="fab_restore_seed">Restaurar monedero con semilla</string>
|
||||
<string name="info_xmrto"><![CDATA[
|
||||
<b>Ingresaste una dirección %1$s</b><br/>
|
||||
<i>Vas a enviar XMR y el destinatario recibirá %1$s usando el servicio <b>SideShift.ai</b>.</i>
|
||||
|
@ -223,22 +222,22 @@
|
|||
<string name="info_send_xmrto_paid">Confirmación pendiente</string>
|
||||
<string name="info_send_xmrto_unpaid">Pago pendiente</string>
|
||||
<string name="info_send_xmrto_error">Error de SideShift.ai (%1$s)</string>
|
||||
<string name="info_send_xmrto_sent">%1$s Enviados!</string>
|
||||
<string name="info_send_xmrto_sent">%1$s enviados!</string>
|
||||
<string name="info_send_xmrto_query">Consultando …</string>
|
||||
<string name="info_send_xmrto_parms"><![CDATA[
|
||||
<b>Puedes enviar %1$s — %2$s %4$s</b>.<br/>
|
||||
<i><b>SideShift.ai</b> está ofreciendo una tasa de cambio de <b>%3$s %4$s/XMR</b> <u>en este momento</u></i>.
|
||||
]]></string>
|
||||
<string name="send_available_btc">Saldo: %2$s %3$s (%1$s XMR)</string>
|
||||
<string name="label_send_progress_xmrto_create">Creando orden SideShift.ai</string>
|
||||
<string name="label_send_progress_xmrto_query">Consultando orden SideShift.ai</string>
|
||||
<string name="label_send_progress_create_tx">Preparando transacción Monero</string>
|
||||
<string name="label_send_progress_queryparms">Consultando parámetros SideShift.ai</string>
|
||||
<string name="label_generic_xmrto_error">ERROR SideShift.ai</string>
|
||||
<string name="label_send_progress_xmrto_create">Creando orden en SideShift.ai</string>
|
||||
<string name="label_send_progress_xmrto_query">Consultando orden en SideShift.ai</string>
|
||||
<string name="label_send_progress_create_tx">Preparando transacción de Monero</string>
|
||||
<string name="label_send_progress_queryparms">Consultando parámetros en SideShift.ai</string>
|
||||
<string name="label_generic_xmrto_error">Error de SideShift.ai</string>
|
||||
<string name="text_generic_xmrto_error">Código: %1$d</string>
|
||||
<string name="text_retry">Toca para reintentar</string>
|
||||
<string name="text_noretry_monero">Parece que estamos atascados!</string>
|
||||
<string name="text_noretry">Oh-oh, parece que SideShift.ai no está disponible ahora!</string>
|
||||
<string name="text_noretry_monero">¡Parece que está atascada!</string>
|
||||
<string name="text_noretry">Oh no, parece que SideShift.ai no está disponible ahora.</string>
|
||||
<string name="text_send_btc_amount">%1$s %3$s = %2$s XMR</string>
|
||||
<string name="text_send_btc_rate">(Cambio: %1$s %2$s/XMR)</string>
|
||||
<string name="label_send_btc_xmrto_info">Visita https://sideshift.ai para soporte y rastreo</string>
|
||||
|
@ -246,42 +245,42 @@
|
|||
<string name="label_send_btc_xmrto_key">Clave secreta SideShift.ai</string>
|
||||
<string name="label_send_btc_address">Dirección %1$s destino</string>
|
||||
<string name="label_send_btc_amount">Monto</string>
|
||||
<string name="send_xmrto_timeout">Oye, tardaste demasiado!</string>
|
||||
<string name="send_xmrto_timeout">¡Oye, tardaste demasiado!</string>
|
||||
<string name="label_copy_xmrtokey">Clave</string>
|
||||
<string name="message_copy_xmrtokey">¡Clave copiada al portapapeles!</string>
|
||||
<string name="send_send_label">Enviar mis preciados moneroj</string>
|
||||
<string name="send_send_timed_label">Gastar mis preciados moneroj (%1$s)</string>
|
||||
<string name="send_send_timed_label">Enviar mis preciados moneroj (%1$s)</string>
|
||||
<string name="send_address_invalid">No es una dirección válida</string>
|
||||
<string name="send_fee_btc_label">Comisión (XMR)</string>
|
||||
<string name="send_total_btc_label">Total (XMR)</string>
|
||||
<string name="send_amount">%1$s XMR</string>
|
||||
<string name="send_fee">+%1$s Comisión</string>
|
||||
<string name="about_whoami">Soy Monerujo</string>
|
||||
<string name="info_send_xmrto_success_order_label">Orden SideShift.ai</string>
|
||||
<string name="about_whoami">Monerujo</string>
|
||||
<string name="info_send_xmrto_success_order_label">Orden de SideShift.ai</string>
|
||||
|
||||
<string name="info_xmrto_enabled">Pago en BTC activado, toca para más info.</string>
|
||||
<string name="info_ledger_enabled">Ledger activado, toca para más info.</string>
|
||||
|
||||
<string name="accounts_drawer_new">Crear Cuenta</string>
|
||||
<string name="accounts_drawer_new">Crear cuenta</string>
|
||||
<string name="accounts_new">Nueva cuenta agregada #%1$d</string>
|
||||
<string name="tx_account"># de cuenta</string>
|
||||
|
||||
<string name="send_sweepall">¡Enviar todos los fondos confirmados en esta cuenta!</string>
|
||||
<string name="send_sweepall">¿Quieres enviar todos los fondos de esta cuenta?</string>
|
||||
<string name="tx_subaddress">Subdirección</string>
|
||||
<string name="generate_address_label_sub">Subdirecciones Públicas #%1$d: %2$s</string>
|
||||
<string name="generate_address_label_sub">Subdirecciones públicas #%1$d: %2$s</string>
|
||||
|
||||
<string name="menu_language">Lenguaje</string>
|
||||
<string name="language_system_default">Usar Idioma del Sistema</string>
|
||||
<string name="menu_language">Idioma</string>
|
||||
<string name="language_system_default">Usar el del sistema</string>
|
||||
|
||||
<string name="fab_restore_ledger">Restaurar desde Ledger Nano</string>
|
||||
|
||||
<string name="progress_ledger_progress">Comunicándose con Ledger</string>
|
||||
<string name="progress_ledger_confirm">¡Confirmación en Ledger requerida!</string>
|
||||
<string name="progress_ledger_confirm">Esperando confirmación en Ledger</string>
|
||||
<string name="progress_ledger_lookahead">Recuperando subdirecciones</string>
|
||||
<string name="progress_ledger_verify">Verificando claves</string>
|
||||
<string name="progress_ledger_opentx">Realizando cálculos alocados</string>
|
||||
<string name="progress_ledger_mlsag">Cosas de hash</string>
|
||||
<string name="open_wallet_ledger_missing">Por favor (re)conecta el dispositivo Ledger</string>
|
||||
<string name="progress_ledger_opentx">Realizando cálculos locos…</string>
|
||||
<string name="progress_ledger_mlsag">Hasheando…</string>
|
||||
<string name="open_wallet_ledger_missing">Por favor reconecta el dispositivo Ledger</string>
|
||||
|
||||
<string name="accounts_progress_new">Creando cuenta</string>
|
||||
|
||||
|
@ -291,45 +290,45 @@
|
|||
<string name="receive_desc_hint">Descripción (opcional)</string>
|
||||
|
||||
<string name="send_address_not_openalias">Dirección OpenAlias no disponible</string>
|
||||
<string name="send_address_openalias">OpenAlias asegurado ✔</string>
|
||||
<string name="send_address_openalias">OpenAlias seguro ✔</string>
|
||||
<string name="send_address_resolve_openalias">Resolviendo OpenAlias…</string>
|
||||
<string name="send_address_no_dnssec">OpenAlias sin DNSSEC - la drección puede ser falsificada</string>
|
||||
<string name="send_address_no_dnssec">OpenAlias sin DNSSEC - la dirección podría ser falsificada</string>
|
||||
|
||||
<string name="status_wallet_connect_wrongversion">Versión de nodo incompatible - ¡por favor actualiza!</string>
|
||||
|
||||
<string name="menu_info">Detalles</string><!--Changed to: Show Secrets!-->
|
||||
<string name="menu_info">Ver secretos</string><!--Changed to: Show Secrets!-->
|
||||
|
||||
<string name="menu_streetmode">Modo Público</string>
|
||||
<string name="menu_streetmode">Modo calle</string>
|
||||
|
||||
<string name="info_nodes_enabled">Nodo-o-matiC habilitado, toque para más información.</string>
|
||||
<string name="info_nodes_enabled">Nodo-matiC habilitado, toque para más información.</string>
|
||||
<string name="node_height">Último bloque actualizado: %1$s</string>
|
||||
<string name="label_nodes">Nodos</string>
|
||||
<string name="node_name_hint">Nombre del Nodo (Opcional)</string>
|
||||
<string name="node_address_hint">Nombre del Host</string>
|
||||
<string name="node_name_hint">Nombre (Opcional)</string>
|
||||
<string name="node_address_hint">Dirección del nodo</string>
|
||||
<string name="node_port_hint">Puerto</string>
|
||||
<string name="node_user_hint">Usuario (Opcional)</string>
|
||||
<string name="node_pass_hint">Contraseña (Opcional)</string>
|
||||
<string name="node_host_unresolved">No se puede resolver el host</string>
|
||||
<string name="node_host_empty">¡Necesitamos esto!</string>
|
||||
<string name="node_port_numeric">Debe ser numérico</string>
|
||||
<string name="node_host_unresolved">No se puede encontrar al nodo</string>
|
||||
<string name="node_host_empty">¡Necesitas esto!</string>
|
||||
<string name="node_port_numeric">Debe ser un número</string>
|
||||
<string name="node_port_range">Debe ser 1–65535</string>
|
||||
<string name="node_fab_add">Agregar Nodo</string>
|
||||
<string name="node_refresh_hint">¡Toca para refrescar!</string>
|
||||
<string name="node_test_error">ERROR DE CONECCIÓN %1$d</string>
|
||||
<string name="node_general_error">ERROR DE CONECCIÓN</string>
|
||||
<string name="node_test_error">ERROR AL CONECTAR %1$d</string>
|
||||
<string name="node_general_error">No se pudo conectar</string>
|
||||
<string name="node_auth_error">AUTENTIFICACIÓN FALLIDA</string>
|
||||
<string name="node_result_label">Resultados de la prueba:</string>
|
||||
<string name="node_result">Altura: %1$s (v%2$d), Ping: %3$.0fms, IP: %4$s</string>
|
||||
<string name="node_testing">Probando el IP: %1$s …</string>
|
||||
<string name="node_result_label">Resultados:</string>
|
||||
<string name="node_result">Altura: %1$s (v%2$d)\nPing: %3$.0fms\nIP: %4$s</string>
|
||||
<string name="node_testing">Probando al IP: %1$s…</string>
|
||||
<string name="node_refresh_wait">Por favor espera a que termine el escaneo</string>
|
||||
<string name="node_create_hint">Toca para seleccionar o agregar nodos</string>
|
||||
<string name="node_pull_hint">Agrega nodos manualmente o tira para buscar</string>
|
||||
<string name="node_scanning">Escaneando la red…</string>
|
||||
<string name="node_create_hint">Toca para elegir un nodo</string>
|
||||
<string name="node_pull_hint">Tira para refrescar</string>
|
||||
<string name="node_scanning">Buscando nodos…</string>
|
||||
<string name="node_nobookmark">Mejores %1$d nodos marcados automáticamente</string>
|
||||
<string name="label_test">Probar</string><!--note: as in "Test a network connection"-->
|
||||
|
||||
<!-- please verify this means "Receiver" or "Recipient" as in "Receiver in the transaction" -->
|
||||
<string name="send_address_hint">Receptor</string>
|
||||
<string name="send_address_hint">Dirección del receptor</string>
|
||||
|
||||
<string name="street_sweep_amount">TODO!</string> <!-- as in: "everything in the account" = "all the money" -->
|
||||
|
||||
|
@ -339,26 +338,26 @@
|
|||
<string name="bad_ledger_seed">¡Semilla de Ledger inválida!</string>
|
||||
<string name="prompt_ledger_seed_warn">¡Ingresar tu semilla de Ledger aquí implica un riesgo importante!</string>
|
||||
|
||||
<string name="label_restoreheight">Altura de Restauración</string> <!-- Restore Height -->
|
||||
<string name="label_restoreheight">Altura de restauración</string> <!-- Restore Height -->
|
||||
|
||||
<string name="toast_ledger_start_app">Arrancar aplicación de Monero en %1$s</string>
|
||||
|
||||
<string name="menu_rescan">¡Re-escanear!</string>
|
||||
<string name="menu_rescan">Re-escanear</string>
|
||||
|
||||
<string name="onboarding_agree">¡Entendido!</string>
|
||||
<string name="onboarding_button_next">Siguiente</string>
|
||||
<string name="onboarding_button_ready">¡Estoy listo!</string>
|
||||
|
||||
<string name="onboarding_welcome_title">¡Bienvenido a Monerujo!</string>
|
||||
<string name="onboarding_welcome_information">Esta aplicación te permite crear y usar monederos de Monero. Puedes guardar tus dulces moneroj en ellos.</string>
|
||||
<string name="onboarding_seed_title">Mantén segura tu semilla</string>
|
||||
<string name="onboarding_seed_information">La semilla otorga acceso total a quien la posee. Si la pierdes, nadie puede ayudarte a recuperarla y perderás tus preciados moneroj.</string>
|
||||
<string name="onboarding_xmrto_title">Enviar Criptos</string>
|
||||
<string name="onboarding_xmrto_information">Monerujo tiene SideShift.ai incorporado. Simplemente pega o escanea una dirección de BTC, LTC, ETH, DASH o DOGE y podrás enviar esas monedas usando tu XMR.</string>
|
||||
<string name="onboarding_welcome_information">Esta aplicación te permite crear y usar monederos. Puedes recibir y enviar dulces moneros con ella.</string>
|
||||
<string name="onboarding_seed_title">Escribe tu semilla mnemotécnica</string>
|
||||
<string name="onboarding_seed_information">Esas palabras otorgan acceso total a tus fondos a quien las tengan. Si la pierdes, nadie puede ayudarte y perderás tus preciados moneros.</string>
|
||||
<string name="onboarding_xmrto_title">Cambia Monero</string>
|
||||
<string name="onboarding_xmrto_information">Monerujo tiene SideShift.ai incorporado. Simplemente ingresa una dirección de BTC, LTC, ETH, DASH o DOGE y podrás enviar esas monedas usando XMR.</string>
|
||||
<string name="onboarding_nodes_title">Nodos, a tu manera</string>
|
||||
<string name="onboarding_nodes_information">Los nodos son tu conexión con la red de Monero. Elige entre usar nodos públicos, o ir totalmente ciberpunk conectándote al tuyo propio.</string>
|
||||
<string name="onboarding_fpsend_title">Enviar con tu huella</string>
|
||||
<string name="onboarding_fpsend_information">Ahora puedes enviar XMR con sólo tu huella dactilar si lo deseas. Para forzar el pedido de contraseña, simplemente desactiva la opción de huella.</string>
|
||||
<string name="onboarding_nodes_information">Los nodos son tu conexión con la red de Monero. Elige entre nodos públicos, o totalmente ciberpunk conectándote al tuyo propio.</string>
|
||||
<string name="onboarding_fpsend_title">Envia con un dedo</string>
|
||||
<string name="onboarding_fpsend_information">Ahora puedes enviar XMR con sólo tu huella dactilar si lo deseas. Para extra seguridad, simplemente desactiva la opción y usa tu contraseña.</string>
|
||||
|
||||
<string name="menu_daynight">Tema</string>
|
||||
<string-array name="daynight_themes">
|
||||
|
@ -368,7 +367,7 @@
|
|||
</string-array>
|
||||
<string name="gunther_says">No hay nada aquí.\nPor favor crea o restaura un monedero.</string>
|
||||
|
||||
<string name="menu_default_nodes">Restaurar los nodos por defecto</string>
|
||||
<string name="menu_default_nodes">Agregar nodos públicos</string>
|
||||
<string name="toast_default_nodes">Restauración ya en proceso…</string>
|
||||
|
||||
<string name="node_updated_now">Último bloque hace %1$d segundos</string>
|
||||
|
@ -393,46 +392,51 @@
|
|||
<b>Por favor ingresa o escanea una dirección de Monero.</b>
|
||||
]]></string>
|
||||
|
||||
<string name="subbaddress_title">Subdirecciones</string>
|
||||
<string name="subbaddress_title">Subdirecciones de la cuenta</string>
|
||||
<string name="subbaddress_name_hint">Nombre de la subdirección</string>
|
||||
<string name="max_subaddress_warning">Demasiadas direcciones sin usar. ¡Usa alguna antes de crear más!</string>
|
||||
<string name="max_account_warning">Demasiadas cuentas sin usar. ¡Usa alguna antes de crear más!</string>
|
||||
<string name="subaddress_tx_label">Transacciones recibidas en esta subdirección:</string>
|
||||
<string name="subaddress_notx_label">Aún no hay transacciones recibidas en esta subdirección.</string>
|
||||
<string name="subaddress_select_label">Elige una subdirección</string>
|
||||
<string name="subaddress_details_hint">Presiona largo para ver detalles</string>
|
||||
<string name="subaddress_details_hint">Mantén presionado para ver los detalles</string>
|
||||
|
||||
<string name="menu_delete">Delete</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">Delete failed!</string>
|
||||
<string name="menu_delete">Eliminar</string><!-- like: "Delete wallet!" -->
|
||||
<string name="delete_failed">¡Falló la eliminación!</string>
|
||||
|
||||
<string name="menu_restore">Import wallet</string>
|
||||
<string name="restore_failed">Import failed!</string>
|
||||
<string name="menu_restore">Importar monedero</string>
|
||||
<string name="restore_failed">¡Falló la importación!</string>
|
||||
|
||||
<string name="menu_deletecache">Reset wallet!</string>
|
||||
<string name="deletecache_alert_message">This wallet will be reset, losing all off-chain data (like notes, account & subaddress names, private transaction keys, …)! Use this ONLY if this wallet is corrupt and does not load!</string>
|
||||
<string name="menu_deletecache">Restaurar</string>
|
||||
<string name="deletecache_alert_message">Este monedero será restaurado, y perderá toda la información personalizada (notas, nombres de cuentas y subdirecciones, claves particulares de transacciones…) Tus fondos no se verán comprometidos, pero usa esto SÓLO si el monedero está corrupto y no se puede abrir.</string>
|
||||
|
||||
<string name="node_tor_error">Tor required</string>
|
||||
<string name="node_waiting">\u00A0WAITING FOR NODE\u00A0</string>
|
||||
<string name="tor_enable_background">"Allow Background Starts" in Orbot Settings to use Tor!</string>
|
||||
<string name="tor_noshift">SideShift.ai doesn\'t support Tor.\nDisable Tor to swap XMR.</string>
|
||||
<string name="node_tor_error">Requiere Tor</string>
|
||||
<string name="node_waiting">\u00A0ESPERANDO AL NODO\u00A0</string>
|
||||
<string name="tor_enable_background">Selecciona "Permitir inicios en segundo plano" en los ajustes de Orbot para usar Tor</string>
|
||||
<string name="tor_noshift">SideShift.ai no soporta Tor.\nDesactiva Tor para cambiar XMR.</string>
|
||||
|
||||
<string name="label_seed_offset_encrypt">Seed encryption (EXPERIMENTAL)</string>
|
||||
<string name="seed_offset_hint">Seed Offset Phrase (optional)</string>
|
||||
<string name="label_seed_offset_encrypt">Semilla encriptada (EXPERIMENTAL)</string>
|
||||
<string name="seed_offset_hint">Palabra clave adicional</string>
|
||||
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="title_iface">Interface</string> <!-- like: User Intreface -->
|
||||
<string name="title_info">Information</string>
|
||||
<string name="setting_daynight">Day / Night</string>
|
||||
<string name="menu_settings">Ajustes</string>
|
||||
<string name="title_iface">Interfaz</string> <!-- like: User Interface -->
|
||||
<string name="title_info">Información</string>
|
||||
<string name="setting_daynight">Modo</string>
|
||||
|
||||
<string name="setting_theme">Style</string>
|
||||
<string name="setting_theme">Tema</string>
|
||||
<string-array name="themes">
|
||||
<item>Classic</item>
|
||||
<item>Baldaŭ</item> <!-- do not translate this one -->
|
||||
</string-array>
|
||||
|
||||
<string name="message_qr_failed">Failed to create QR for sharing!</string>
|
||||
<string name="message_qr_failed">¡Error al crear QR!</string>
|
||||
|
||||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
<string name="tx_locked">Monto trabado hasta el bloque %1$d (faltan %2$d bloques ≈ %3$,.2f días)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
<string name="label_streetmode">Modo calle activado\nSólo se ºmostrarán transacciones nuevas</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -442,4 +442,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -682,4 +682,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -448,4 +448,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -446,4 +446,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -447,4 +447,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -447,4 +447,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -444,4 +444,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -444,4 +444,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -437,4 +437,9 @@ aqui.</string>
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -448,4 +448,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_amount">10 × %1$3.1f XMR</string>
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -444,4 +444,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -448,4 +448,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -445,4 +445,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -443,4 +443,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -436,4 +436,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -442,4 +442,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -448,4 +448,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -369,4 +369,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -443,4 +443,9 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -22,4 +22,5 @@
|
|||
<attr name="streetColorB" format="reference" />
|
||||
<attr name="noticeColor" format="reference" />
|
||||
<attr name="toolbarTextColor" format="reference" />
|
||||
|
||||
</resources>
|
|
@ -520,4 +520,13 @@
|
|||
<string name="tx_locked">Transaction amount locked until block %1$d (in %2$d blocks ≈ %3$,.2f days)</string>
|
||||
|
||||
<string name="label_streetmode">Street Mode enabled\nOnly new transactions will be shown</string>
|
||||
|
||||
<string name="pocketchange_title" translatable="false">PocketChange</string>
|
||||
<string name="pocketchange_amount" translatable="false">10 × %1$3.1f XMR</string>
|
||||
<string name="pocketchange_tx_detail" translatable="false">PocketChange +%1$s</string>
|
||||
|
||||
<string name="pocketchange_info">To reduce waiting time on repeated spending, Monerujo can create spare change at the expense of higher fees. It\'ll try to create and maintain 10 coins of the selected amount.</string>
|
||||
<string name="pocketchange_create_title">Create Change</string>
|
||||
|
||||
<string name="label_apply">APPLY</string>
|
||||
</resources>
|
||||
|
|
|
@ -158,6 +158,12 @@
|
|||
<item name="android:textStyle">normal</item>
|
||||
</style>
|
||||
|
||||
<style name="MoneroText.PosPocketChange">
|
||||
<item name="android:textSize">10sp</item>
|
||||
<item name="android:textColor">?attr/positiveColor</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
</style>
|
||||
|
||||
<style name="MoneroText.PosNote">
|
||||
<item name="android:textSize">12sp</item>
|
||||
<!--item name="android:textColor">#FF4A4A4A</item-->
|
||||
|
|
|
@ -1 +1 @@
|
|||
MONERUJO_monero feature_v0.18.2.2 with monero release-v0.18.2.2-monerujo
|
||||
MONERUJO_monero feature_coins with monero release-v0.18.2.2-monerujo
|
||||
|
|
|
@ -260,6 +260,47 @@ struct AddressBook
|
|||
virtual int lookupPaymentID(const std::string &payment_id) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The CoinsInfo - interface for displaying coins information
|
||||
*/
|
||||
struct CoinsInfo
|
||||
{
|
||||
virtual ~CoinsInfo() = 0;
|
||||
|
||||
virtual uint64_t blockHeight() const = 0;
|
||||
virtual std::string hash() const = 0;
|
||||
virtual size_t internalOutputIndex() const = 0;
|
||||
virtual uint64_t globalOutputIndex() const = 0;
|
||||
virtual bool spent() const = 0;
|
||||
virtual bool frozen() const = 0;
|
||||
virtual uint64_t spentHeight() const = 0;
|
||||
virtual uint64_t amount() const = 0;
|
||||
virtual bool rct() const = 0;
|
||||
virtual bool keyImageKnown() const = 0;
|
||||
virtual size_t pkIndex() const = 0;
|
||||
virtual uint32_t subaddrIndex() const = 0;
|
||||
virtual uint32_t subaddrAccount() const = 0;
|
||||
virtual std::string address() const = 0;
|
||||
virtual std::string addressLabel() const = 0;
|
||||
virtual std::string keyImage() const = 0;
|
||||
virtual uint64_t unlockTime() const = 0;
|
||||
virtual bool unlocked() const = 0;
|
||||
virtual std::string pubKey() const = 0;
|
||||
virtual bool coinbase() const = 0;
|
||||
};
|
||||
|
||||
struct Coins
|
||||
{
|
||||
virtual ~Coins() = 0;
|
||||
virtual int count() const = 0;
|
||||
virtual CoinsInfo * coin(int index) const = 0;
|
||||
virtual std::vector<CoinsInfo*> getAll() const = 0;
|
||||
virtual void refresh() = 0;
|
||||
virtual void setFrozen(int index) = 0;
|
||||
virtual void thaw(int index) = 0;
|
||||
virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
|
||||
};
|
||||
|
||||
struct SubaddressRow {
|
||||
public:
|
||||
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
|
||||
|
@ -937,6 +978,7 @@ struct Wallet
|
|||
|
||||
virtual TransactionHistory * history() = 0;
|
||||
virtual AddressBook * addressBook() = 0;
|
||||
virtual Coins * coins() = 0;
|
||||
virtual Subaddress * subaddress() = 0;
|
||||
virtual SubaddressAccount * subaddressAccount() = 0;
|
||||
virtual void setListener(WalletListener *) = 0;
|
||||
|
|
|
@ -19,5 +19,5 @@ org.gradle.jvmargs=-Xmx2048m
|
|||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonFinalResIds=false
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#Mon May 22 20:01:18 CEST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
Loading…
Reference in New Issue