use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.
the class RicochetMeta method getHop0Tx.
private Transaction getHop0Tx(List<UTXO> utxos, long spendAmount, String destination, long fee, boolean samouraiFeeViaBIP47, long nTimeLock) {
List<MyTransactionOutPoint> unspent = new ArrayList<MyTransactionOutPoint>();
long totalValueSelected = 0L;
for (UTXO u : utxos) {
totalValueSelected += u.getValue();
unspent.addAll(u.getOutpoints());
}
// Log.d("RicochetMeta", "spendAmount:" + spendAmount);
// Log.d("RicochetMeta", "fee:" + fee);
// Log.d("RicochetMeta", "totalValueSelected:" + totalValueSelected);
BigInteger samouraiFeeAmount = samouraiFeeAmountV2;
long changeAmount = totalValueSelected - (spendAmount + fee);
// Log.d("RicochetMeta", "changeAmount:" + changeAmount);
HashMap<String, BigInteger> receivers = new HashMap<String, BigInteger>();
if (changeAmount > 0L) {
String change_address = BIP84Util.getInstance(context).getAddressAt(AddressFactory.CHANGE_CHAIN, BIP84Util.getInstance(context).getWallet().getAccount(0).getChange().getAddrIdx()).getBech32AsString();
receivers.put(change_address, BigInteger.valueOf(changeAmount));
}
if (samouraiFeeViaBIP47) {
// Samourai fee paid in the hops
receivers.put(destination, BigInteger.valueOf(spendAmount));
} else {
if (nTimeLock > 0L) {
receivers.put(SamouraiWallet.getInstance().isTestNet() ? TESTNET_NLOCKTIME_SAMOURAI_RICOCHET_TX_FEE_ADDRESS : SAMOURAI_NLOCKTIME_RICOCHET_TX_FEE_ADDRESS, samouraiFeeAmount);
} else {
receivers.put(SamouraiWallet.getInstance().isTestNet() ? TESTNET_SAMOURAI_RICOCHET_TX_FEE_ADDRESS : SAMOURAI_RICOCHET_TX_FEE_ADDRESS, samouraiFeeAmount);
}
receivers.put(destination, BigInteger.valueOf(spendAmount - samouraiFeeAmount.longValue()));
}
Transaction tx = SendFactory.getInstance(context).makeTransaction(0, unspent, receivers);
if (nTimeLock > 0L) {
tx.setLockTime(nTimeLock);
}
tx = SendFactory.getInstance(context).signTransaction(tx, 0);
return tx;
}
use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.
the class RicochetMeta method script.
public JSONObject script(long spendAmount, long feePerKBAmount, String strDestination, int nbHops, String strPCode, boolean samouraiFeeViaBIP47, boolean useTimeLock) {
JSONObject jObj = new JSONObject();
try {
BigInteger biSpend = BigInteger.valueOf(spendAmount);
// default 4 hops min. for base fee, each additional hop 0.001
BigInteger biSamouraiFee = BigInteger.valueOf(samouraiFeeAmountV2.longValue() * ((nbHops - defaultNbHops) + 1));
BigInteger biFeePerKB = BigInteger.valueOf(feePerKBAmount);
long latestBlock = APIFactory.getInstance(context).getLatestBlockHeight();
long nTimeLock = 0L;
if (useTimeLock && latestBlock > 0L) {
nTimeLock = latestBlock;
}
jObj.put("ts", System.currentTimeMillis() / 1000L);
jObj.put("hops", nbHops);
jObj.put("spend_amount", biSpend.longValue());
jObj.put("samourai_fee", biSamouraiFee.longValue());
jObj.put("samourai_fee_via_bip47", samouraiFeeViaBIP47);
jObj.put("feeKB", biFeePerKB.longValue());
jObj.put("destination", strDestination);
if (strPCode != null) {
jObj.put("pcode", strPCode);
}
if (useTimeLock) {
jObj.put("nTimeLock", nTimeLock);
}
JSONObject jHop = new JSONObject();
JSONArray jHops = new JSONArray();
int hopSz = 0;
if (samouraiFeeViaBIP47) {
hopSz = FeeUtil.getInstance().estimatedSize(1, 2);
} else {
hopSz = FeeUtil.getInstance().estimatedSize(1, 1);
}
BigInteger biFeePerHop = FeeUtil.getInstance().calculateFee(hopSz, biFeePerKB);
Pair<List<UTXO>, BigInteger> pair = getHop0UTXO(spendAmount, nbHops, biFeePerHop.longValue(), samouraiFeeViaBIP47);
List<UTXO> utxos = pair.getLeft();
long totalValueSelected = 0L;
for (UTXO u : utxos) {
totalValueSelected += u.getValue();
}
// Log.d("RicochetMeta", "totalValueSelected (return):" + totalValueSelected);
// hop0 'leaves' wallet, change returned to wallet
BigInteger hop0 = biSpend.add(biSamouraiFee).add(biFeePerHop.multiply(BigInteger.valueOf((long) nbHops)));
// BigInteger hop0Fee = FeeUtil.getInstance().calculateFee(hop0sz, biFeePerKB);
BigInteger hop0Fee = pair.getRight();
// Log.d("RicochetMeta", "hop0Fee (return):" + hop0Fee.longValue());
Transaction txHop0 = getHop0Tx(utxos, hop0.longValue(), getDestinationAddress(index), hop0Fee.longValue(), samouraiFeeViaBIP47, nTimeLock);
if (txHop0 == null) {
return null;
}
// Log.d("RicochetMeta", "searching for:" + getDestinationAddress(index));
int prevTxN = 0;
for (int i = 0; i < txHop0.getOutputs().size(); i++) {
Script script = txHop0.getOutputs().get(i).getScriptPubKey();
// Log.d("RicochetMeta", "script:" + Hex.toHexString(script.getProgram()));
String address = null;
if (Hex.toHexString(script.getProgram()).startsWith("0014")) {
String hrp = null;
if (SamouraiWallet.getInstance().getCurrentNetworkParams() instanceof TestNet3Params) {
hrp = "tb";
} else {
hrp = "bc";
}
try {
String _script = Hex.toHexString(script.getProgram());
address = Bech32Segwit.encode(hrp, (byte) 0x00, Hex.decode(_script.substring(4).getBytes()));
} catch (Exception e) {
;
}
// Log.d("RicochetMeta", "bech32:" + address);
} else {
address = new Script(script.getProgram()).getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
// Log.d("RicochetMeta", "address from script:" + address);
}
if (address.equals(getDestinationAddress(index))) {
prevTxN = i;
// Log.d("RicochetMeta", "tx output n:" + prevTxN);
break;
}
}
jHop.put("seq", 0);
jHop.put("spend_amount", hop0.longValue());
jHop.put("fee", hop0Fee.longValue());
jHop.put("fee_per_hop", biFeePerHop.longValue());
jHop.put("index", index);
jHop.put("destination", getDestinationAddress(index));
// Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
int prevIndex = index;
index++;
jHop.put("tx", new String(Hex.encode(txHop0.bitcoinSerialize())));
jHop.put("hash", txHop0.getHash().toString());
if (useTimeLock) {
jHop.put("nTimeLock", nTimeLock);
}
jHops.put(jHop);
List<Pair<String, Long>> samouraiFees = new ArrayList<Pair<String, Long>>();
if (samouraiFeeViaBIP47) {
long baseVal = samouraiFeeAmountV2.longValue() / 4L;
long totalVal = 0L;
SecureRandom random = new SecureRandom();
int _outgoingIdx = BIP47Meta.getInstance().getOutgoingIdx(BIP47Meta.strSamouraiDonationPCode);
for (int i = 0; i < 4; i++) {
int val = random.nextInt(25000);
int sign = random.nextInt(1);
if (sign == 0) {
val *= -1L;
}
long feeVal = 0L;
if (i == 3) {
feeVal = samouraiFeeAmountV2.longValue() - totalVal;
} else {
feeVal = baseVal + val;
totalVal += feeVal;
}
//
try {
PaymentCode pcode = new PaymentCode(BIP47Meta.strSamouraiDonationPCode);
PaymentAddress paymentAddress = BIP47Util.getInstance(context).getSendAddress(pcode, _outgoingIdx + i);
// String strAddress = paymentAddress.getSendECKey().toAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
//
// derive as bech32
//
SegwitAddress segwitAddress = new SegwitAddress(paymentAddress.getSendECKey().getPubKey(), SamouraiWallet.getInstance().getCurrentNetworkParams());
String strAddress = segwitAddress.getBech32AsString();
samouraiFees.add(Pair.of(strAddress, feeVal));
// samouraiFees.add(Pair.of(strAddress, 200000L / 4L));
} catch (Exception e) {
samouraiFees.add(Pair.of(SendNotifTxFactory.SAMOURAI_NOTIF_TX_FEE_ADDRESS, feeVal));
}
}
}
Transaction txHop = null;
String prevTxHash = txHop0.getHash().toString();
String prevScriptPubKey = Hex.toHexString(txHop0.getOutput(prevTxN).getScriptPubKey().getProgram());
BigInteger remainingSamouraiFee = BigInteger.ZERO;
long prevSpendValue = hop0.longValue();
if (!samouraiFeeViaBIP47) {
prevSpendValue -= biSamouraiFee.longValue();
} else {
remainingSamouraiFee = samouraiFeeAmountV2;
}
int _hop = 0;
for (int i = (nbHops - 1); i >= 0; i--) {
_hop++;
BigInteger hopx = null;
if (samouraiFeeViaBIP47) {
remainingSamouraiFee = remainingSamouraiFee.subtract(BigInteger.valueOf(samouraiFees.get(_hop - 1).getRight()));
hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i))).add(remainingSamouraiFee);
} else {
hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i)));
}
if (useTimeLock && latestBlock > 0L) {
nTimeLock = latestBlock + _hop;
}
// Log.d("RicochetMeta", "doing hop:" + _hop);
if (samouraiFeeViaBIP47 && ((_hop - 1) < 4)) {
txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, samouraiFees.get(_hop - 1), nTimeLock);
} else {
txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, null, nTimeLock);
}
if (txHop == null) {
return null;
}
jHop = new JSONObject();
jHop.put("seq", (nbHops - i));
jHop.put("spend_amount", hopx.longValue());
jHop.put("fee", biFeePerHop.longValue());
jHop.put("prev_tx_hash", prevTxHash);
jHop.put("prev_tx_n", prevTxN);
jHop.put("prev_spend_value", prevSpendValue);
jHop.put("script", prevScriptPubKey);
jHop.put("tx", new String(Hex.encode(txHop.bitcoinSerialize())));
jHop.put("hash", txHop.getHash().toString());
if (useTimeLock) {
jHop.put("nTimeLock", nTimeLock);
}
if (_hop < nbHops) {
jHop.put("index", index);
jHop.put("destination", getDestinationAddress(index));
// Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
prevIndex = index;
index++;
} else {
jHop.put("destination", strDestination);
// Log.d("RicochetMeta", "destination:" + strDestination);
}
if (samouraiFeeViaBIP47) {
jObj.put("samourai_fee_address", samouraiFees.get(_hop - 1).getLeft());
jObj.put("samourai_fee_amount", samouraiFees.get(_hop - 1).getRight());
}
jHops.put(jHop);
prevTxHash = txHop.getHash().toString();
prevTxN = 0;
prevSpendValue = hopx.longValue();
prevScriptPubKey = Hex.toHexString(txHop.getOutputs().get(0).getScriptPubKey().getProgram());
}
jObj.put("hops", jHops);
BigInteger totalAmount = hop0.add(hop0Fee);
jObj.put("total_spend", totalAmount.longValue());
} catch (JSONException je) {
return null;
}
System.out.println("RicochetMeta:" + jObj.toString());
return jObj;
}
use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.
the class APIFactory method parseUnspentOutputs.
private synchronized boolean parseUnspentOutputs(String unspents) {
if (unspents != null) {
try {
JSONObject jsonObj = new JSONObject(unspents);
if (jsonObj == null || !jsonObj.has("unspent_outputs")) {
return false;
}
JSONArray utxoArray = jsonObj.getJSONArray("unspent_outputs");
if (utxoArray == null || utxoArray.length() == 0) {
return false;
}
for (int i = 0; i < utxoArray.length(); i++) {
JSONObject outDict = utxoArray.getJSONObject(i);
byte[] hashBytes = Hex.decode((String) outDict.get("tx_hash"));
Sha256Hash txHash = Sha256Hash.wrap(hashBytes);
int txOutputN = ((Number) outDict.get("tx_output_n")).intValue();
BigInteger value = BigInteger.valueOf(((Number) outDict.get("value")).longValue());
String script = (String) outDict.get("script");
byte[] scriptBytes = Hex.decode(script);
int confirmations = ((Number) outDict.get("confirmations")).intValue();
String path = null;
try {
String address = null;
if (Bech32Util.getInstance().isBech32Script(script)) {
address = Bech32Util.getInstance().getAddressFromScript(script);
} else {
address = new Script(scriptBytes).getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
}
if (outDict.has("xpub")) {
JSONObject xpubObj = (JSONObject) outDict.get("xpub");
path = (String) xpubObj.get("path");
String m = (String) xpubObj.get("m");
unspentPaths.put(address, path);
if (m.equals(BIP49Util.getInstance(context).getWallet().getAccount(0).xpubstr())) {
// assume account 0
unspentBIP49.put(address, 0);
} else if (m.equals(BIP84Util.getInstance(context).getWallet().getAccount(0).xpubstr())) {
// assume account 0
unspentBIP84.put(address, 0);
} else {
unspentAccounts.put(address, AddressFactory.getInstance(context).xpub2account().get(m));
}
} else if (outDict.has("pubkey")) {
int idx = BIP47Meta.getInstance().getIdx4AddrLookup().get(outDict.getString("pubkey"));
BIP47Meta.getInstance().getIdx4AddrLookup().put(address, idx);
String pcode = BIP47Meta.getInstance().getPCode4AddrLookup().get(outDict.getString("pubkey"));
BIP47Meta.getInstance().getPCode4AddrLookup().put(address, pcode);
debug("APIFactory", outDict.getString("pubkey") + "," + pcode);
debug("APIFactory", outDict.getString("pubkey") + "," + idx);
} else {
;
}
// Construct the output
MyTransactionOutPoint outPoint = new MyTransactionOutPoint(txHash, txOutputN, value, scriptBytes, address);
outPoint.setConfirmations(confirmations);
if (utxos.containsKey(script)) {
utxos.get(script).getOutpoints().add(outPoint);
} else {
UTXO utxo = new UTXO();
utxo.getOutpoints().add(outPoint);
utxo.setPath(path);
utxos.put(script, utxo);
}
if (Bech32Util.getInstance().isBech32Script(script)) {
UTXOFactory.getInstance().addP2WPKH(txHash.toString(), txOutputN, script, utxos.get(script));
} else if (Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
UTXOFactory.getInstance().addP2SH_P2WPKH(txHash.toString(), txOutputN, script, utxos.get(script));
} else {
UTXOFactory.getInstance().addP2PKH(txHash.toString(), txOutputN, script, utxos.get(script));
}
} catch (Exception e) {
e.printStackTrace();
}
}
long amount = 0L;
for (String key : utxos.keySet()) {
for (MyTransactionOutPoint out : utxos.get(key).getOutpoints()) {
debug("APIFactory", "utxo:" + out.getAddress() + "," + out.getValue());
debug("APIFactory", "utxo:" + utxos.get(key).getPath());
amount += out.getValue().longValue();
}
}
debug("APIFactory", "utxos by value (post-parse):" + amount);
return true;
} catch (JSONException je) {
;
}
}
return false;
}
use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.
the class APIFactory method parseUnspentOutputsForSweep.
private synchronized UTXO parseUnspentOutputsForSweep(String unspents) {
UTXO utxo = null;
if (unspents != null) {
try {
JSONObject jsonObj = new JSONObject(unspents);
if (jsonObj == null || !jsonObj.has("unspent_outputs")) {
return null;
}
JSONArray utxoArray = jsonObj.getJSONArray("unspent_outputs");
if (utxoArray == null || utxoArray.length() == 0) {
return null;
}
for (int i = 0; i < utxoArray.length(); i++) {
JSONObject outDict = utxoArray.getJSONObject(i);
byte[] hashBytes = Hex.decode((String) outDict.get("tx_hash"));
Sha256Hash txHash = Sha256Hash.wrap(hashBytes);
int txOutputN = ((Number) outDict.get("tx_output_n")).intValue();
BigInteger value = BigInteger.valueOf(((Number) outDict.get("value")).longValue());
String script = (String) outDict.get("script");
byte[] scriptBytes = Hex.decode(script);
int confirmations = ((Number) outDict.get("confirmations")).intValue();
try {
String address = null;
if (Bech32Util.getInstance().isBech32Script(script)) {
address = Bech32Util.getInstance().getAddressFromScript(script);
debug("address parsed:", address);
} else {
address = new Script(scriptBytes).getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
}
// Construct the output
MyTransactionOutPoint outPoint = new MyTransactionOutPoint(txHash, txOutputN, value, scriptBytes, address);
outPoint.setConfirmations(confirmations);
if (utxo == null) {
utxo = new UTXO();
}
utxo.getOutpoints().add(outPoint);
} catch (Exception e) {
;
}
}
} catch (JSONException je) {
;
}
}
return utxo;
}
use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.
the class CahootsUtil method doSTONEWALLx2_2.
//
// sender
//
public Cahoots doSTONEWALLx2_2(STONEWALLx2 stonewall1) throws Exception {
Transaction transaction = stonewall1.getTransaction();
debug("CahootsUtil", "step2 tx:" + org.spongycastle.util.encoders.Hex.toHexString(transaction.bitcoinSerialize()));
int nbIncomingInputs = transaction.getInputs().size();
List<UTXO> utxos = getCahootsUTXO(stonewall1.getAccount());
Collections.shuffle(utxos);
debug("CahootsUtil", "BIP84 utxos:" + utxos.size());
List<String> seenTxs = new ArrayList<String>();
for (TransactionInput input : transaction.getInputs()) {
if (!seenTxs.contains(input.getOutpoint().getHash().toString())) {
seenTxs.add(input.getOutpoint().getHash().toString());
}
}
List<UTXO> selectedUTXO = new ArrayList<UTXO>();
long totalSelectedAmount = 0L;
int nbTotalSelectedOutPoints = 0;
for (int step = 0; step < 3; step++) {
if (stonewall1.getCounterpartyAccount() == 0) {
step = 2;
}
List<String> _seenTxs = seenTxs;
selectedUTXO = new ArrayList<UTXO>();
nbTotalSelectedOutPoints = 0;
for (UTXO utxo : utxos) {
switch(step) {
case 0:
if (utxo.getPath() != null && utxo.getPath().length() > 3 && utxo.getPath().charAt(2) != '0') {
continue;
}
break;
case 1:
if (utxo.getPath() != null && utxo.getPath().length() > 3 && utxo.getPath().charAt(2) != '1') {
continue;
}
break;
default:
break;
}
UTXO _utxo = new UTXO();
for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
if (!_seenTxs.contains(outpoint.getTxHash().toString())) {
_utxo.getOutpoints().add(outpoint);
_seenTxs.add(outpoint.getTxHash().toString());
}
}
if (_utxo.getOutpoints().size() > 0) {
selectedUTXO.add(_utxo);
totalSelectedAmount += _utxo.getValue();
nbTotalSelectedOutPoints += _utxo.getOutpoints().size();
debug("CahootsUtil", "BIP84 selected utxo:" + _utxo.getValue());
}
if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 4).longValue() + stonewall1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
break;
}
}
if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 4).longValue() + stonewall1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
break;
}
}
if (!(totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 4).longValue() + stonewall1.getSpendAmount() + SamouraiWallet.bDust.longValue())) {
return null;
}
debug("CahootsUtil", "BIP84 selected utxos:" + selectedUTXO.size());
long fee = FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 4).longValue();
debug("CahootsUtil", "fee:" + fee);
if (fee % 2L != 0) {
fee++;
}
debug("CahootsUtil", "fee pair:" + fee);
stonewall1.setFeeAmount(fee);
debug("CahootsUtil", "destination:" + stonewall1.getDestination());
if (transaction.getOutputs() != null && transaction.getOutputs().size() == 2) {
int idx = -1;
for (int i = 0; i < 2; i++) {
byte[] buf = transaction.getOutputs().get(i).getScriptBytes();
byte[] script = new byte[buf.length];
script[0] = 0x00;
System.arraycopy(buf, 1, script, 1, script.length - 1);
debug("CahootsUtil", "script:" + new Script(script).toString());
debug("CahootsUtil", "script hex:" + Hex.toHexString(script));
debug("CahootsUtil", "address from script:" + Bech32Util.getInstance().getAddressFromScript(new Script(script)));
if (Bech32Util.getInstance().getAddressFromScript(new Script(script)).equalsIgnoreCase(stonewall1.getCollabChange())) {
idx = i;
break;
}
}
if (idx == 0 || idx == 1) {
Coin value = transaction.getOutputs().get(idx).getValue();
Coin _value = Coin.valueOf(value.longValue() - (fee / 2L));
debug("CahootsUtil", "output value post fee:" + _value);
transaction.getOutputs().get(idx).setValue(_value);
stonewall1.getPSBT().setTransaction(transaction);
} else {
return null;
}
} else {
return null;
}
NetworkParameters params = stonewall1.getParams();
//
//
// step2: B verif, utxos -> A (take smallest that cover amount)
//
//
String zpub = BIP84Util.getInstance(context).getWallet().getAccountAt(stonewall1.getAccount()).zpubstr();
HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>> inputsB = new HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>>();
for (UTXO utxo : selectedUTXO) {
for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
_TransactionOutPoint _outpoint = new _TransactionOutPoint(outpoint);
ECKey eckey = SendFactory.getPrivKey(_outpoint.getAddress(), stonewall1.getAccount());
String path = APIFactory.getInstance(context).getUnspentPaths().get(_outpoint.getAddress());
inputsB.put(_outpoint, Triple.of(eckey.getPubKey(), FormatsUtil.getInstance().getFingerprintFromXPUB(zpub), path));
}
}
// spender change output
HashMap<_TransactionOutput, Triple<byte[], byte[], String>> outputsB = new HashMap<_TransactionOutput, Triple<byte[], byte[], String>>();
if (stonewall1.getAccount() == WhirlpoolMeta.getInstance(context).getWhirlpoolPostmix()) {
int idx = AddressFactory.getInstance(context).getHighestPostChangeIdx();
SegwitAddress segwitAddress = BIP84Util.getInstance(context).getAddressAt(stonewall1.getAccount(), 1, idx);
Pair<Byte, byte[]> pair0 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress.getBech32AsString());
byte[] scriptPubKey_B0 = Bech32Segwit.getScriptPubkey(pair0.getLeft(), pair0.getRight());
_TransactionOutput output_B0 = new _TransactionOutput(params, null, Coin.valueOf((totalSelectedAmount - stonewall1.getSpendAmount()) - (fee / 2L)), scriptPubKey_B0);
outputsB.put(output_B0, Triple.of(segwitAddress.getECKey().getPubKey(), stonewall1.getFingerprint(), "M/1/" + idx));
} else {
int idx = BIP84Util.getInstance(context).getWallet().getAccount(0).getChange().getAddrIdx();
SegwitAddress segwitAddress = BIP84Util.getInstance(context).getAddressAt(0, 1, idx);
Pair<Byte, byte[]> pair0 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress.getBech32AsString());
byte[] scriptPubKey_B0 = Bech32Segwit.getScriptPubkey(pair0.getLeft(), pair0.getRight());
_TransactionOutput output_B0 = new _TransactionOutput(params, null, Coin.valueOf((totalSelectedAmount - stonewall1.getSpendAmount()) - (fee / 2L)), scriptPubKey_B0);
outputsB.put(output_B0, Triple.of(segwitAddress.getECKey().getPubKey(), stonewall1.getFingerprint(), "M/1/" + idx));
}
STONEWALLx2 stonewall2 = new STONEWALLx2(stonewall1);
stonewall2.inc(inputsB, outputsB, null);
return stonewall2;
}
Aggregations