Sweep selected outputs

This commit is contained in:
pokkst 2022-09-22 06:07:39 -05:00
parent 3076777c53
commit af5076ce7d
No known key found for this signature in database
GPG key ID: 90C2ED85E67A50FF
7 changed files with 80 additions and 25 deletions

View file

@ -230,6 +230,25 @@ std::vector<std::string> java2cpp(JNIEnv *env, jobject arrayList) {
return result; return result;
} }
std::set<std::string> java2cpp_set(JNIEnv *env, jobject arrayList) {
jmethodID java_util_ArrayList_size = env->GetMethodID(class_ArrayList, "size", "()I");
jmethodID java_util_ArrayList_get = env->GetMethodID(class_ArrayList, "get",
"(I)Ljava/lang/Object;");
jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
std::set<std::string> result;
for (jint i = 0; i < len; i++) {
jstring element = static_cast<jstring>(env->CallObjectMethod(arrayList,
java_util_ArrayList_get, i));
const char *pchars = env->GetStringUTFChars(element, nullptr);
result.emplace(pchars);
env->ReleaseStringUTFChars(element, pchars);
env->DeleteLocalRef(element);
}
return result;
}
jobject cpp2java(JNIEnv *env, const std::vector<std::string> &vector) { jobject cpp2java(JNIEnv *env, const std::vector<std::string> &vector) {
jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V"); jmethodID java_util_ArrayList_ = env->GetMethodID(class_ArrayList, "<init>", "(I)V");
@ -961,8 +980,8 @@ Java_net_mynero_wallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject inst
jstring dst_addr, jstring payment_id, jstring dst_addr, jstring payment_id,
jlong amount, jint mixin_count, jlong amount, jint mixin_count,
jint priority, jint priority,
jint accountIndex) { jint accountIndex, jobject key_images) {
const std::set<std::string> _key_images = java2cpp_set(env, key_images);
const char *_dst_addr = env->GetStringUTFChars(dst_addr, nullptr); const char *_dst_addr = env->GetStringUTFChars(dst_addr, nullptr);
const char *_payment_id = env->GetStringUTFChars(payment_id, nullptr); const char *_payment_id = env->GetStringUTFChars(payment_id, nullptr);
Monero::PendingTransaction::Priority _priority = Monero::PendingTransaction::Priority _priority =
@ -972,7 +991,7 @@ Java_net_mynero_wallet_model_Wallet_createTransactionJ(JNIEnv *env, jobject inst
Monero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id, Monero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id,
amount, (uint32_t) mixin_count, amount, (uint32_t) mixin_count,
_priority, _priority,
(uint32_t) accountIndex); (uint32_t) accountIndex, {}, _key_images);
env->ReleaseStringUTFChars(dst_addr, _dst_addr); env->ReleaseStringUTFChars(dst_addr, _dst_addr);
env->ReleaseStringUTFChars(payment_id, _payment_id); env->ReleaseStringUTFChars(payment_id, _payment_id);
@ -1013,8 +1032,8 @@ Java_net_mynero_wallet_model_Wallet_createSweepTransaction(JNIEnv *env, jobject
jstring dst_addr, jstring payment_id, jstring dst_addr, jstring payment_id,
jint mixin_count, jint mixin_count,
jint priority, jint priority,
jint accountIndex) { jint accountIndex, jobject key_images) {
const std::set<std::string> _key_images = java2cpp_set(env, key_images);
const char *_dst_addr = env->GetStringUTFChars(dst_addr, nullptr); const char *_dst_addr = env->GetStringUTFChars(dst_addr, nullptr);
const char *_payment_id = env->GetStringUTFChars(payment_id, nullptr); const char *_payment_id = env->GetStringUTFChars(payment_id, nullptr);
Monero::PendingTransaction::Priority _priority = Monero::PendingTransaction::Priority _priority =
@ -1026,7 +1045,7 @@ Java_net_mynero_wallet_model_Wallet_createSweepTransaction(JNIEnv *env, jobject
Monero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id, Monero::PendingTransaction *tx = wallet->createTransaction(_dst_addr, _payment_id,
empty, (uint32_t) mixin_count, empty, (uint32_t) mixin_count,
_priority, _priority,
(uint32_t) accountIndex); (uint32_t) accountIndex, {}, _key_images);
env->ReleaseStringUTFChars(dst_addr, _dst_addr); env->ReleaseStringUTFChars(dst_addr, _dst_addr);
env->ReleaseStringUTFChars(payment_id, _payment_id); env->ReleaseStringUTFChars(payment_id, _payment_id);
@ -1064,9 +1083,13 @@ Java_net_mynero_wallet_model_Wallet_getCoinsJ(JNIEnv *env, jobject instance) {
jobject newCoinsInfo(JNIEnv *env, Monero::CoinsInfo *info) { jobject newCoinsInfo(JNIEnv *env, Monero::CoinsInfo *info) {
jmethodID c = env->GetMethodID(class_CoinsInfo, "<init>", jmethodID c = env->GetMethodID(class_CoinsInfo, "<init>",
"(J)V"); "(JZLjava/lang/String;)V");
jstring _key_image = env->NewStringUTF(info->keyImage().c_str());
jobject result = env->NewObject(class_CoinsInfo, c, jobject result = env->NewObject(class_CoinsInfo, c,
static_cast<jlong> (info->globalOutputIndex())); static_cast<jlong> (info->globalOutputIndex()),
info->spent(),
_key_image);
env->DeleteLocalRef(_key_image);
return result; return result;
} }

View file

@ -23,6 +23,9 @@ import net.mynero.wallet.model.PendingTransaction;
import net.mynero.wallet.model.Wallet; import net.mynero.wallet.model.Wallet;
import net.mynero.wallet.util.Helper; import net.mynero.wallet.util.Helper;
import java.util.ArrayList;
import java.util.List;
// https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents // https://stackoverflow.com/questions/2139134/how-to-send-an-object-from-one-android-activity-to-another-using-intents
public class TxData implements Parcelable { public class TxData implements Parcelable {
@ -41,6 +44,7 @@ public class TxData implements Parcelable {
private int mixin; private int mixin;
private PendingTransaction.Priority priority; private PendingTransaction.Priority priority;
private UserNotes userNotes; private UserNotes userNotes;
private ArrayList<String> preferredInputs;
public TxData() { public TxData() {
} }
@ -50,16 +54,19 @@ public class TxData implements Parcelable {
this.amount = txData.amount; this.amount = txData.amount;
this.mixin = txData.mixin; this.mixin = txData.mixin;
this.priority = txData.priority; this.priority = txData.priority;
this.preferredInputs = txData.preferredInputs;
} }
public TxData(String dstAddr, public TxData(String dstAddr,
long amount, long amount,
int mixin, int mixin,
PendingTransaction.Priority priority) { PendingTransaction.Priority priority,
ArrayList<String> preferredInputs) {
this.dstAddr = dstAddr; this.dstAddr = dstAddr;
this.amount = amount; this.amount = amount;
this.mixin = mixin; this.mixin = mixin;
this.priority = priority; this.priority = priority;
this.preferredInputs = preferredInputs;
} }
protected TxData(Parcel in) { protected TxData(Parcel in) {
@ -67,7 +74,7 @@ public class TxData implements Parcelable {
amount = in.readLong(); amount = in.readLong();
mixin = in.readInt(); mixin = in.readInt();
priority = PendingTransaction.Priority.fromInteger(in.readInt()); priority = PendingTransaction.Priority.fromInteger(in.readInt());
in.readStringList(preferredInputs);
} }
public String getDestinationAddress() { public String getDestinationAddress() {
@ -94,6 +101,10 @@ public class TxData implements Parcelable {
return 1.0 * amount / Helper.ONE_XMR; return 1.0 * amount / Helper.ONE_XMR;
} }
public ArrayList<String> getPreferredInputs() {
return preferredInputs;
}
public int getMixin() { public int getMixin() {
return mixin; return mixin;
} }

View file

@ -56,7 +56,9 @@ public class ReceiveBottomSheetDialog extends BottomSheetDialogFragment {
List<CoinsInfo> coins = WalletManager.getInstance().getWallet().getCoins().getAll(); List<CoinsInfo> coins = WalletManager.getInstance().getWallet().getCoins().getAll();
System.out.println("COINS::"); System.out.println("COINS::");
for(CoinsInfo coinsInfo : coins) { for(CoinsInfo coinsInfo : coins) {
System.out.println(coinsInfo.getGlobalOutputIndex()); if(!coinsInfo.isSpent()) {
System.out.println(coinsInfo.getKeyImage());
}
} }
} }

View file

@ -30,9 +30,13 @@ public class CoinsInfo implements Parcelable {
} }
long globalOutputIndex; long globalOutputIndex;
boolean spent;
String keyImage;
public CoinsInfo(long globalOutputIndex) { public CoinsInfo(long globalOutputIndex, boolean spent, String keyImage) {
this.globalOutputIndex = globalOutputIndex; this.globalOutputIndex = globalOutputIndex;
this.spent = spent;
this.keyImage = keyImage;
} }
protected CoinsInfo(Parcel in) { protected CoinsInfo(Parcel in) {
@ -55,6 +59,14 @@ public class CoinsInfo implements Parcelable {
return globalOutputIndex; return globalOutputIndex;
} }
public boolean isSpent() {
return spent;
}
public String getKeyImage() {
return keyImage;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;

View file

@ -24,6 +24,7 @@ import net.mynero.wallet.data.TxData;
import java.io.File; import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -276,32 +277,31 @@ public class Wallet {
return createTransaction( return createTransaction(
txData.getDestinationAddress(), txData.getDestinationAddress(),
txData.getAmount(), txData.getAmount(),
txData.getMixin(), txData.getPriority(),
txData.getPriority()); txData.getPreferredInputs());
} }
public PendingTransaction createTransaction(String dst_addr, public PendingTransaction createTransaction(String dst_addr,
long amount, int mixin_count, long amount, PendingTransaction.Priority priority, ArrayList<String> key_images) {
PendingTransaction.Priority priority) {
disposePendingTransaction(); disposePendingTransaction();
int _priority = priority.getValue(); int _priority = priority.getValue();
long txHandle = long txHandle =
(amount == SWEEP_ALL ? (amount == SWEEP_ALL ?
createSweepTransaction(dst_addr, "", mixin_count, _priority, createSweepTransaction(dst_addr, "", 0, _priority,
accountIndex) : accountIndex, key_images) :
createTransactionJ(dst_addr, "", amount, mixin_count, _priority, createTransactionJ(dst_addr, "", amount, 0, _priority,
accountIndex)); accountIndex, key_images));
pendingTransaction = new PendingTransaction(txHandle); pendingTransaction = new PendingTransaction(txHandle);
return pendingTransaction; return pendingTransaction;
} }
private native long createTransactionJ(String dst_addr, String payment_id, private native long createTransactionJ(String dst_addr, String payment_id,
long amount, int mixin_count, long amount, int mixin_count,
int priority, int accountIndex); int priority, int accountIndex, ArrayList<String> key_images);
private native long createSweepTransaction(String dst_addr, String payment_id, private native long createSweepTransaction(String dst_addr, String payment_id,
int mixin_count, int mixin_count,
int priority, int accountIndex); int priority, int accountIndex, ArrayList<String> key_images);
private native long createTransactionSingleJ(String key_image, String dst_addr, int priority); private native long createTransactionSingleJ(String key_image, String dst_addr, int priority);

View file

@ -28,6 +28,9 @@ import net.mynero.wallet.model.WalletListener;
import net.mynero.wallet.model.WalletManager; import net.mynero.wallet.model.WalletManager;
import net.mynero.wallet.util.Constants; import net.mynero.wallet.util.Constants;
import java.util.ArrayList;
import java.util.List;
/** /**
* Handy class for starting a new thread that has a looper. The looper can then be * Handy class for starting a new thread that has a looper. The looper can then be
@ -121,7 +124,9 @@ public class MoneroHandlerThread extends Thread implements WalletListener {
public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority) { public PendingTransaction createTx(String address, String amountStr, boolean sendAll, PendingTransaction.Priority feePriority) {
long amount = sendAll ? SWEEP_ALL : Wallet.getAmountFromString(amountStr); long amount = sendAll ? SWEEP_ALL : Wallet.getAmountFromString(amountStr);
return wallet.createTransaction(new TxData(address, amount, 0, feePriority)); ArrayList<String> preferredInputs = new ArrayList<>();
preferredInputs.add("");
return wallet.createTransaction(new TxData(address, amount, 0, feePriority, preferredInputs));
} }
public boolean sendTx(PendingTransaction pendingTx) { public boolean sendTx(PendingTransaction pendingTx) {

View file

@ -886,7 +886,8 @@ struct Wallet
optional<std::vector<uint64_t>> amount, uint32_t mixin_count, optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
PendingTransaction::Priority = PendingTransaction::Priority_Low, PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0, uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {}) = 0; std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) = 0;
/*! /*!
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored * \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
@ -905,7 +906,8 @@ struct Wallet
optional<uint64_t> amount, uint32_t mixin_count, optional<uint64_t> amount, uint32_t mixin_count,
PendingTransaction::Priority = PendingTransaction::Priority_Low, PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0, uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {}) = 0; std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) = 0;
/*! /*!
* \brief createTransactionSingle creates transaction with single input * \brief createTransactionSingle creates transaction with single input