Search in sources :

Example 36 with TransactionInput

use of org.bitcoinj.core.TransactionInput in project samourai-wallet-android by Samourai-Wallet.

the class SendActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_send);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    SendActivity.this.getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    if (SamouraiWallet.getInstance().getShowTotalBalance()) {
        if (SamouraiWallet.getInstance().getCurrentSelectedAccount() == 2) {
            selectedAccount = 1;
        } else {
            selectedAccount = 0;
        }
    } else {
        selectedAccount = 0;
    }
    tvMaxPrompt = (TextView) findViewById(R.id.max_prompt);
    tvMax = (TextView) findViewById(R.id.max);
    try {
        balance = APIFactory.getInstance(SendActivity.this).getXpubAmounts().get(HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(selectedAccount).xpubstr());
    } catch (IOException ioe) {
        balance = 0L;
    } catch (MnemonicException.MnemonicLengthException mle) {
        balance = 0L;
    } catch (java.lang.NullPointerException npe) {
        balance = 0L;
    }
    final String strAmount;
    NumberFormat nf = NumberFormat.getInstance(Locale.US);
    nf.setMaximumFractionDigits(8);
    nf.setMinimumFractionDigits(1);
    nf.setMinimumIntegerDigits(1);
    strAmount = nf.format(balance / 1e8);
    tvMax.setText(strAmount + " " + getDisplayUnits());
    tvMaxPrompt.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            edAmountBTC.setText(strAmount);
            return false;
        }
    });
    tvMax.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            edAmountBTC.setText(strAmount);
            return false;
        }
    });
    DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance(Locale.US);
    DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
    defaultSeparator = Character.toString(symbols.getDecimalSeparator());
    strFiat = PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.CURRENT_FIAT, "USD");
    btc_fx = ExchangeRateFactory.getInstance(SendActivity.this).getAvgPrice(strFiat);
    tvFiatSymbol = (TextView) findViewById(R.id.fiatSymbol);
    tvFiatSymbol.setText(getDisplayUnits() + "-" + strFiat);
    edAddress = (EditText) findViewById(R.id.destination);
    textWatcherAddress = new TextWatcher() {

        public void afterTextChanged(Editable s) {
            validateSpend();
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            ;
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            ;
        }
    };
    edAddress.addTextChangedListener(textWatcherAddress);
    edAddress.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // final int DRAWABLE_LEFT = 0;
            // final int DRAWABLE_TOP = 1;
            final int DRAWABLE_RIGHT = 2;
            if (event.getAction() == MotionEvent.ACTION_UP && event.getRawX() >= (edAddress.getRight() - edAddress.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
                final List<String> entries = new ArrayList<String>();
                entries.addAll(BIP47Meta.getInstance().getSortedByLabels(false));
                final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(SendActivity.this, android.R.layout.select_dialog_singlechoice);
                for (int i = 0; i < entries.size(); i++) {
                    arrayAdapter.add(BIP47Meta.getInstance().getDisplayLabel(entries.get(i)));
                }
                AlertDialog.Builder dlg = new AlertDialog.Builder(SendActivity.this);
                dlg.setIcon(R.drawable.ic_launcher);
                dlg.setTitle(R.string.app_name);
                dlg.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // Toast.makeText(SendActivity.this, BIP47Meta.getInstance().getDisplayLabel(entries.get(which)), Toast.LENGTH_SHORT).show();
                        // Toast.makeText(SendActivity.this, entries.get(which), Toast.LENGTH_SHORT).show();
                        processPCode(entries.get(which), null);
                    }
                });
                dlg.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
                dlg.show();
                return true;
            }
            return false;
        }
    });
    edAmountBTC = (EditText) findViewById(R.id.amountBTC);
    edAmountFiat = (EditText) findViewById(R.id.amountFiat);
    textWatcherBTC = new TextWatcher() {

        public void afterTextChanged(Editable s) {
            edAmountBTC.removeTextChangedListener(this);
            edAmountFiat.removeTextChangedListener(textWatcherFiat);
            int max_len = 8;
            NumberFormat btcFormat = NumberFormat.getInstance(Locale.US);
            btcFormat.setMaximumFractionDigits(max_len + 1);
            btcFormat.setMinimumFractionDigits(0);
            double d = 0.0;
            try {
                d = NumberFormat.getInstance(Locale.US).parse(s.toString()).doubleValue();
                String s1 = btcFormat.format(d);
                if (s1.indexOf(defaultSeparator) != -1) {
                    String dec = s1.substring(s1.indexOf(defaultSeparator));
                    if (dec.length() > 0) {
                        dec = dec.substring(1);
                        if (dec.length() > max_len) {
                            edAmountBTC.setText(s1.substring(0, s1.length() - 1));
                            edAmountBTC.setSelection(edAmountBTC.getText().length());
                            s = edAmountBTC.getEditableText();
                        }
                    }
                }
            } catch (NumberFormatException nfe) {
                ;
            } catch (ParseException pe) {
                ;
            }
            if (d > 21000000.0) {
                edAmountFiat.setText("0.00");
                edAmountFiat.setSelection(edAmountFiat.getText().length());
                edAmountBTC.setText("0");
                edAmountBTC.setSelection(edAmountBTC.getText().length());
                Toast.makeText(SendActivity.this, R.string.invalid_amount, Toast.LENGTH_SHORT).show();
            } else {
                edAmountFiat.setText(MonetaryUtil.getInstance().getFiatFormat(strFiat).format(d * btc_fx));
                edAmountFiat.setSelection(edAmountFiat.getText().length());
            }
            edAmountFiat.addTextChangedListener(textWatcherFiat);
            edAmountBTC.addTextChangedListener(this);
            validateSpend();
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            ;
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            ;
        }
    };
    edAmountBTC.addTextChangedListener(textWatcherBTC);
    textWatcherFiat = new TextWatcher() {

        public void afterTextChanged(Editable s) {
            edAmountFiat.removeTextChangedListener(this);
            edAmountBTC.removeTextChangedListener(textWatcherBTC);
            int max_len = 2;
            NumberFormat fiatFormat = NumberFormat.getInstance(Locale.US);
            fiatFormat.setMaximumFractionDigits(max_len + 1);
            fiatFormat.setMinimumFractionDigits(0);
            double d = 0.0;
            try {
                d = NumberFormat.getInstance(Locale.US).parse(s.toString()).doubleValue();
                String s1 = fiatFormat.format(d);
                if (s1.indexOf(defaultSeparator) != -1) {
                    String dec = s1.substring(s1.indexOf(defaultSeparator));
                    if (dec.length() > 0) {
                        dec = dec.substring(1);
                        if (dec.length() > max_len) {
                            edAmountFiat.setText(s1.substring(0, s1.length() - 1));
                            edAmountFiat.setSelection(edAmountFiat.getText().length());
                        }
                    }
                }
            } catch (NumberFormatException nfe) {
                ;
            } catch (ParseException pe) {
                ;
            }
            if ((d / btc_fx) > 21000000.0) {
                edAmountFiat.setText("0.00");
                edAmountFiat.setSelection(edAmountFiat.getText().length());
                edAmountBTC.setText("0");
                edAmountBTC.setSelection(edAmountBTC.getText().length());
                Toast.makeText(SendActivity.this, R.string.invalid_amount, Toast.LENGTH_SHORT).show();
            } else {
                edAmountBTC.setText(MonetaryUtil.getInstance().getBTCFormat().format(d / btc_fx));
                edAmountBTC.setSelection(edAmountBTC.getText().length());
            }
            edAmountBTC.addTextChangedListener(textWatcherBTC);
            edAmountFiat.addTextChangedListener(this);
            validateSpend();
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            ;
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
            ;
        }
    };
    edAmountFiat.addTextChangedListener(textWatcherFiat);
    SPEND_TYPE = PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.USE_BIP126, true) ? SPEND_BIP126 : SPEND_SIMPLE;
    if (SPEND_TYPE > SPEND_BIP126) {
        SPEND_TYPE = SPEND_BIP126;
        PrefsUtil.getInstance(SendActivity.this).setValue(PrefsUtil.SPEND_TYPE, SPEND_BIP126);
    }
    swRicochet = (Switch) findViewById(R.id.ricochet);
    swRicochet.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                SPEND_TYPE = SPEND_RICOCHET;
            } else {
                SPEND_TYPE = PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.SPEND_TYPE, SPEND_BIP126);
            }
        }
    });
    btLowFee = (Button) findViewById(R.id.low_fee);
    btAutoFee = (Button) findViewById(R.id.auto_fee);
    btPriorityFee = (Button) findViewById(R.id.priority_fee);
    btCustomFee = (Button) findViewById(R.id.custom_fee);
    tvFeePrompt = (TextView) findViewById(R.id.current_fee_prompt);
    FEE_TYPE = PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.CURRENT_FEE_TYPE, FEE_NORMAL);
    long lo = FeeUtil.getInstance().getLowFee().getDefaultPerKB().longValue() / 1000L;
    long mi = FeeUtil.getInstance().getNormalFee().getDefaultPerKB().longValue() / 1000L;
    long hi = FeeUtil.getInstance().getHighFee().getDefaultPerKB().longValue() / 1000L;
    if (lo == mi && mi == hi) {
        lo = (long) ((double) mi * 0.85);
        hi = (long) ((double) mi * 1.15);
        SuggestedFee lo_sf = new SuggestedFee();
        lo_sf.setDefaultPerKB(BigInteger.valueOf(lo * 1000L));
        FeeUtil.getInstance().setLowFee(lo_sf);
        SuggestedFee hi_sf = new SuggestedFee();
        hi_sf.setDefaultPerKB(BigInteger.valueOf(hi * 1000L));
        FeeUtil.getInstance().setHighFee(hi_sf);
    } else if (lo == mi || mi == hi) {
        mi = (lo + hi) / 2L;
        SuggestedFee mi_sf = new SuggestedFee();
        mi_sf.setDefaultPerKB(BigInteger.valueOf(mi * 1000L));
        FeeUtil.getInstance().setNormalFee(mi_sf);
    } else {
        ;
    }
    switch(FEE_TYPE) {
        case FEE_LOW:
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getLowFee());
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.BOLD);
            btAutoFee.setTypeface(null, Typeface.NORMAL);
            btPriorityFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            tvFeePrompt.setText(getText(R.string.fee_low_priority) + " " + getText(R.string.blocks_to_cf));
            break;
        case FEE_PRIORITY:
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getHighFee());
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.NORMAL);
            btAutoFee.setTypeface(null, Typeface.NORMAL);
            btPriorityFee.setTypeface(null, Typeface.BOLD);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            tvFeePrompt.setText(getText(R.string.fee_high_priority) + " " + getText(R.string.blocks_to_cf));
            break;
        default:
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getNormalFee());
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.NORMAL);
            btAutoFee.setTypeface(null, Typeface.BOLD);
            btPriorityFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            tvFeePrompt.setText(getText(R.string.fee_mid_priority) + " " + getText(R.string.blocks_to_cf));
            break;
    }
    btLowFee.setText((FeeUtil.getInstance().getLowFee().getDefaultPerKB().longValue() / 1000L) + "\n" + getString(R.string.sat_b));
    btPriorityFee.setText((FeeUtil.getInstance().getHighFee().getDefaultPerKB().longValue() / 1000L) + "\n" + getString(R.string.sat_b));
    btAutoFee.setText((FeeUtil.getInstance().getNormalFee().getDefaultPerKB().longValue() / 1000L) + "\n" + getString(R.string.sat_b));
    btLowFee.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getLowFee());
            PrefsUtil.getInstance(SendActivity.this).setValue(PrefsUtil.CURRENT_FEE_TYPE, FEE_LOW);
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.BOLD);
            btAutoFee.setTypeface(null, Typeface.NORMAL);
            btPriorityFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setText(R.string.custom_fee);
            tvFeePrompt.setText(getText(R.string.fee_low_priority) + " " + getText(R.string.blocks_to_cf));
        }
    });
    btAutoFee.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getNormalFee());
            PrefsUtil.getInstance(SendActivity.this).setValue(PrefsUtil.CURRENT_FEE_TYPE, FEE_NORMAL);
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.NORMAL);
            btAutoFee.setTypeface(null, Typeface.BOLD);
            btPriorityFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setText(R.string.custom_fee);
            tvFeePrompt.setText(getText(R.string.fee_mid_priority) + " " + getText(R.string.blocks_to_cf));
        }
    });
    btPriorityFee.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            FeeUtil.getInstance().setSuggestedFee(FeeUtil.getInstance().getHighFee());
            PrefsUtil.getInstance(SendActivity.this).setValue(PrefsUtil.CURRENT_FEE_TYPE, FEE_PRIORITY);
            btLowFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btAutoFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btPriorityFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.blue));
            btCustomFee.setBackgroundColor(SendActivity.this.getResources().getColor(R.color.darkgrey));
            btLowFee.setTypeface(null, Typeface.NORMAL);
            btAutoFee.setTypeface(null, Typeface.NORMAL);
            btPriorityFee.setTypeface(null, Typeface.BOLD);
            btCustomFee.setTypeface(null, Typeface.NORMAL);
            btCustomFee.setText(R.string.custom_fee);
            tvFeePrompt.setText(getText(R.string.fee_high_priority) + " " + getText(R.string.blocks_to_cf));
        }
    });
    btCustomFee.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            doCustomFee();
        }
    });
    btSend = (Button) findViewById(R.id.send);
    btSend.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            btSend.setClickable(false);
            btSend.setActivated(false);
            double btc_amount = 0.0;
            try {
                btc_amount = NumberFormat.getInstance(Locale.US).parse(edAmountBTC.getText().toString().trim()).doubleValue();
            // Log.i("SendFragment", "amount entered:" + btc_amount);
            } catch (NumberFormatException nfe) {
                btc_amount = 0.0;
            } catch (ParseException pe) {
                btc_amount = 0.0;
            }
            double dAmount = btc_amount;
            long amount = (long) (Math.round(dAmount * 1e8));
            ;
            // Log.i("SendActivity", "amount:" + amount);
            final String address = strDestinationBTCAddress == null ? edAddress.getText().toString() : strDestinationBTCAddress;
            final int accountIdx = selectedAccount;
            final boolean isSegwitChange = (FormatsUtil.getInstance().isValidBech32(address) || Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) || PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.USE_LIKE_TYPED_CHANGE, true) == false;
            final HashMap<String, BigInteger> receivers = new HashMap<String, BigInteger>();
            receivers.put(address, BigInteger.valueOf(amount));
            // store current change index to restore value in case of sending fail
            int change_index = 0;
            if (isSegwitChange) {
                change_index = BIP49Util.getInstance(SendActivity.this).getWallet().getAccount(0).getChange().getAddrIdx();
            } else {
                try {
                    change_index = HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().getAddrIdx();
                // Log.d("SendActivity", "storing change index:" + change_index);
                } catch (IOException ioe) {
                    ;
                } catch (MnemonicException.MnemonicLengthException mle) {
                    ;
                }
            }
            // get all UTXO
            List<UTXO> utxos = null;
            // if possible, get UTXO by input 'type': p2pkh or p2sh-p2wpkh, else get all UTXO
            long neededAmount = 0L;
            if (FormatsUtil.getInstance().isValidBech32(address) || Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
                neededAmount += FeeUtil.getInstance().estimatedFeeSegwit(0, UTXOFactory.getInstance().getCountP2SH_P2WPKH(), 4).longValue();
            // Log.d("SendActivity", "segwit:" + neededAmount);
            } else {
                neededAmount += FeeUtil.getInstance().estimatedFeeSegwit(UTXOFactory.getInstance().getCountP2PKH(), 0, 4).longValue();
            // Log.d("SendActivity", "p2pkh:" + neededAmount);
            }
            neededAmount += amount;
            neededAmount += SamouraiWallet.bDust.longValue();
            if ((FormatsUtil.getInstance().isValidBech32(address) || Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) && (UTXOFactory.getInstance().getP2SH_P2WPKH().size() > 0 && UTXOFactory.getInstance().getTotalP2SH_P2WPKH() > neededAmount)) {
                utxos = new ArrayList<UTXO>(UTXOFactory.getInstance().getP2SH_P2WPKH().values());
            // Log.d("SendActivity", "segwit utxos:" + utxos.size());
            } else if ((UTXOFactory.getInstance().getP2PKH().size() > 0) && (UTXOFactory.getInstance().getTotalP2PKH() > neededAmount)) {
                utxos = new ArrayList<UTXO>(UTXOFactory.getInstance().getP2PKH().values());
            // Log.d("SendActivity", "p2pkh utxos:" + utxos.size());
            } else {
                utxos = APIFactory.getInstance(SendActivity.this).getUtxos(true);
            // Log.d("SendActivity", "all filtered utxos:" + utxos.size());
            }
            final List<UTXO> selectedUTXO = new ArrayList<UTXO>();
            long totalValueSelected = 0L;
            long change = 0L;
            BigInteger fee = null;
            // insufficient funds
            if (amount > balance) {
                Toast.makeText(SendActivity.this, R.string.insufficient_funds, Toast.LENGTH_SHORT).show();
            } else // entire balance (can only be simple spend)
            if (amount == balance) {
                // make sure we are using simple spend
                SPEND_TYPE = SPEND_SIMPLE;
                // Log.d("SendActivity", "amount == balance");
                // take all utxos, deduct fee
                selectedUTXO.addAll(utxos);
                for (UTXO u : selectedUTXO) {
                    totalValueSelected += u.getValue();
                }
            // Log.d("SendActivity", "balance:" + balance);
            // Log.d("SendActivity", "total value selected:" + totalValueSelected);
            } else {
                ;
            }
            org.apache.commons.lang3.tuple.Pair<ArrayList<MyTransactionOutPoint>, ArrayList<TransactionOutput>> pair = null;
            if (SPEND_TYPE == SPEND_RICOCHET) {
                boolean samouraiFeeViaBIP47 = false;
                if (BIP47Meta.getInstance().getOutgoingStatus(BIP47Meta.strSamouraiDonationPCode) == BIP47Meta.STATUS_SENT_CFM) {
                    samouraiFeeViaBIP47 = true;
                }
                final JSONObject jObj = RicochetMeta.getInstance(SendActivity.this).script(amount, FeeUtil.getInstance().getSuggestedFee().getDefaultPerKB().longValue(), address, 4, strPCode, samouraiFeeViaBIP47);
                if (jObj != null) {
                    try {
                        long totalAmount = jObj.getLong("total_spend");
                        if (totalAmount > balance) {
                            Toast.makeText(SendActivity.this, R.string.insufficient_funds, Toast.LENGTH_SHORT).show();
                            return;
                        }
                        String msg = getText(R.string.ricochet_spend1) + " " + address + " " + getText(R.string.ricochet_spend2) + " " + Coin.valueOf(totalAmount).toPlainString() + " " + getText(R.string.ricochet_spend3);
                        AlertDialog.Builder dlg = new AlertDialog.Builder(SendActivity.this).setTitle(R.string.app_name).setMessage(msg).setCancelable(false).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                            public void onClick(DialogInterface dialog, int whichButton) {
                                RicochetMeta.getInstance(SendActivity.this).add(jObj);
                                dialog.dismiss();
                                Intent intent = new Intent(SendActivity.this, RicochetActivity.class);
                                startActivityForResult(intent, RICOCHET);
                            }
                        }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                            public void onClick(DialogInterface dialog, int whichButton) {
                                dialog.dismiss();
                            }
                        });
                        if (!isFinishing()) {
                            dlg.show();
                        }
                        return;
                    } catch (JSONException je) {
                        return;
                    }
                }
                return;
            } else // if BIP126 try both hetero/alt, if fails change type to SPEND_SIMPLE
            if (SPEND_TYPE == SPEND_BIP126) {
                List<UTXO> _utxos = utxos;
                // Collections.shuffle(_utxos);
                // sort in descending order by value
                Collections.sort(_utxos, new UTXO.UTXOComparator());
                // hetero
                pair = SendFactory.getInstance(SendActivity.this).heterogeneous(_utxos, BigInteger.valueOf(amount), address);
                if (pair == null) {
                    // Collections.sort(_utxos, new UTXO.UTXOComparator());
                    // alt
                    pair = SendFactory.getInstance(SendActivity.this).altHeterogeneous(_utxos, BigInteger.valueOf(amount), address);
                }
                if (pair == null) {
                    // can't do BIP126, revert to SPEND_SIMPLE
                    SPEND_TYPE = SPEND_SIMPLE;
                }
            } else {
                ;
            }
            // simple spend (less than balance)
            if (SPEND_TYPE == SPEND_SIMPLE) {
                List<UTXO> _utxos = utxos;
                // sort in ascending order by value
                Collections.sort(_utxos, new UTXO.UTXOComparator());
                Collections.reverse(_utxos);
                // get smallest 1 UTXO > than spend + fee + dust
                for (UTXO u : _utxos) {
                    Pair<Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(u.getOutpoints());
                    if (u.getValue() >= (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFeeSegwit(outpointTypes.getLeft(), outpointTypes.getRight(), 2).longValue())) {
                        selectedUTXO.add(u);
                        totalValueSelected += u.getValue();
                        // Log.d("SendActivity", "nb inputs:" + u.getOutpoints().size());
                        break;
                    }
                }
                if (selectedUTXO.size() == 0) {
                    // sort in descending order by value
                    Collections.sort(_utxos, new UTXO.UTXOComparator());
                    int selected = 0;
                    int p2pkh = 0;
                    int p2wpkh = 0;
                    // get largest UTXOs > than spend + fee + dust
                    for (UTXO u : _utxos) {
                        selectedUTXO.add(u);
                        totalValueSelected += u.getValue();
                        selected += u.getOutpoints().size();
                        // Log.d("SendActivity", "value selected:" + u.getValue());
                        // Log.d("SendActivity", "total value selected/threshold:" + totalValueSelected + "/" + (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFee(selected, 2).longValue()));
                        Pair<Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(u.getOutpoints());
                        p2pkh += outpointTypes.getLeft();
                        p2wpkh += outpointTypes.getRight();
                        if (totalValueSelected >= (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFeeSegwit(p2pkh, p2wpkh, 2).longValue())) {
                            // Log.d("SendActivity", "nb inputs:" + selected);
                            break;
                        }
                    }
                }
            } else if (pair != null) {
                selectedUTXO.clear();
                receivers.clear();
                long inputAmount = 0L;
                long outputAmount = 0L;
                for (MyTransactionOutPoint outpoint : pair.getLeft()) {
                    UTXO u = new UTXO();
                    List<MyTransactionOutPoint> outs = new ArrayList<MyTransactionOutPoint>();
                    outs.add(outpoint);
                    u.setOutpoints(outs);
                    totalValueSelected += u.getValue();
                    selectedUTXO.add(u);
                    inputAmount += u.getValue();
                }
                for (TransactionOutput output : pair.getRight()) {
                    try {
                        Script script = new Script(output.getScriptBytes());
                        receivers.put(script.getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString(), BigInteger.valueOf(output.getValue().longValue()));
                        outputAmount += output.getValue().longValue();
                    } catch (Exception e) {
                        Toast.makeText(SendActivity.this, R.string.error_bip126_output, Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                change = outputAmount - amount;
                fee = BigInteger.valueOf(inputAmount - outputAmount);
            } else {
                Toast.makeText(SendActivity.this, R.string.cannot_select_utxo, Toast.LENGTH_SHORT).show();
                return;
            }
            // do spend here
            if (selectedUTXO.size() > 0) {
                // estimate fee for simple spend, already done if BIP126
                if (SPEND_TYPE == SPEND_SIMPLE) {
                    List<MyTransactionOutPoint> outpoints = new ArrayList<MyTransactionOutPoint>();
                    for (UTXO utxo : selectedUTXO) {
                        outpoints.addAll(utxo.getOutpoints());
                    }
                    Pair<Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(outpoints);
                    fee = FeeUtil.getInstance().estimatedFeeSegwit(outpointTypes.getLeft(), outpointTypes.getRight(), 2);
                }
                // Log.d("SendActivity", "spend type:" + SPEND_TYPE);
                // Log.d("SendActivity", "amount:" + amount);
                // Log.d("SendActivity", "total value selected:" + totalValueSelected);
                // Log.d("SendActivity", "fee:" + fee.longValue());
                // Log.d("SendActivity", "nb inputs:" + selectedUTXO.size());
                change = totalValueSelected - (amount + fee.longValue());
                // Log.d("SendActivity", "change:" + change);
                boolean changeIsDust = false;
                if (change < SamouraiWallet.bDust.longValue() && SPEND_TYPE == SPEND_SIMPLE) {
                    change = 0L;
                    fee = fee.add(BigInteger.valueOf(change));
                    amount = totalValueSelected - fee.longValue();
                    // Log.d("SendActivity", "fee:" + fee.longValue());
                    // Log.d("SendActivity", "change:" + change);
                    // Log.d("SendActivity", "amount:" + amount);
                    receivers.put(address, BigInteger.valueOf(amount));
                    changeIsDust = true;
                }
                final long _change = change;
                final BigInteger _fee = fee;
                final int _change_index = change_index;
                String dest = null;
                if (strPCode != null && strPCode.length() > 0) {
                    dest = BIP47Meta.getInstance().getDisplayLabel(strPCode);
                } else {
                    dest = address;
                }
                final String strPrivacyWarning;
                if (SendAddressUtil.getInstance().get(address) == 1) {
                    strPrivacyWarning = getString(R.string.send_privacy_warning) + "\n\n";
                } else {
                    strPrivacyWarning = "";
                }
                String strChangeIsDust = null;
                if (changeIsDust) {
                    strChangeIsDust = getString(R.string.change_is_dust) + "\n\n";
                } else {
                    strChangeIsDust = "";
                }
                String message = strChangeIsDust + strPrivacyWarning + "Send " + Coin.valueOf(amount).toPlainString() + " to " + dest + " (fee:" + Coin.valueOf(_fee.longValue()).toPlainString() + ")?\n";
                final long _amount = amount;
                AlertDialog.Builder builder = new AlertDialog.Builder(SendActivity.this);
                builder.setTitle(R.string.app_name);
                builder.setMessage(message);
                final CheckBox cbShowAgain;
                if (strPrivacyWarning.length() > 0) {
                    cbShowAgain = new CheckBox(SendActivity.this);
                    cbShowAgain.setText(R.string.do_not_repeat_sent_to);
                    cbShowAgain.setChecked(false);
                    builder.setView(cbShowAgain);
                } else {
                    cbShowAgain = null;
                }
                builder.setCancelable(false);
                builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                    public void onClick(final DialogInterface dialog, int whichButton) {
                        final ProgressDialog progress = new ProgressDialog(SendActivity.this);
                        progress.setCancelable(false);
                        progress.setTitle(R.string.app_name);
                        progress.setMessage(getString(R.string.please_wait_sending));
                        progress.show();
                        final List<MyTransactionOutPoint> outPoints = new ArrayList<MyTransactionOutPoint>();
                        for (UTXO u : selectedUTXO) {
                            outPoints.addAll(u.getOutpoints());
                        }
                        // add change
                        if (_change > 0L) {
                            if (SPEND_TYPE == SPEND_SIMPLE) {
                                if (isSegwitChange) {
                                    String change_address = BIP49Util.getInstance(SendActivity.this).getAddressAt(AddressFactory.CHANGE_CHAIN, BIP49Util.getInstance(SendActivity.this).getWallet().getAccount(0).getChange().getAddrIdx()).getAddressAsString();
                                    receivers.put(change_address, BigInteger.valueOf(_change));
                                } else {
                                    try {
                                        String change_address = HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().getAddressAt(HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().getAddrIdx()).getAddressString();
                                        receivers.put(change_address, BigInteger.valueOf(_change));
                                    } catch (IOException ioe) {
                                        Toast.makeText(SendActivity.this, R.string.error_change_output, Toast.LENGTH_SHORT).show();
                                        return;
                                    } catch (MnemonicException.MnemonicLengthException mle) {
                                        Toast.makeText(SendActivity.this, R.string.error_change_output, Toast.LENGTH_SHORT).show();
                                        return;
                                    }
                                }
                            } else if (SPEND_TYPE == SPEND_BIP126) {
                            // do nothing, change addresses included
                            } else {
                                ;
                            }
                        }
                        // make tx
                        Transaction tx = SendFactory.getInstance(SendActivity.this).makeTransaction(0, outPoints, receivers);
                        final RBFSpend rbf;
                        if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.RBF_OPT_IN, false) == true) {
                            rbf = new RBFSpend();
                            for (TransactionInput input : tx.getInputs()) {
                                boolean _isBIP49 = false;
                                String _addr = null;
                                Address _address = input.getConnectedOutput().getAddressFromP2PKHScript(SamouraiWallet.getInstance().getCurrentNetworkParams());
                                if (_address != null) {
                                    _addr = _address.toString();
                                }
                                if (_addr == null) {
                                    _addr = input.getConnectedOutput().getAddressFromP2SH(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
                                    _isBIP49 = true;
                                }
                                String path = APIFactory.getInstance(SendActivity.this).getUnspentPaths().get(_addr);
                                if (path != null) {
                                    if (_isBIP49) {
                                        rbf.addKey(input.getOutpoint().toString(), path + "/49");
                                    } else {
                                        rbf.addKey(input.getOutpoint().toString(), path);
                                    }
                                } else {
                                    String pcode = BIP47Meta.getInstance().getPCode4Addr(_addr);
                                    int idx = BIP47Meta.getInstance().getIdx4Addr(_addr);
                                    rbf.addKey(input.getOutpoint().toString(), pcode + "/" + idx);
                                }
                            }
                        } else {
                            rbf = null;
                        }
                        if (tx != null) {
                            tx = SendFactory.getInstance(SendActivity.this).signTransaction(tx);
                            final Transaction _tx = tx;
                            final String hexTx = new String(Hex.encode(tx.bitcoinSerialize()));
                            // Log.d("SendActivity", hexTx);
                            final String strTxHash = tx.getHashAsString();
                            if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.BROADCAST_TX, true) == false) {
                                if (progress != null && progress.isShowing()) {
                                    progress.dismiss();
                                }
                                doShowTx(hexTx, strTxHash);
                                return;
                            }
                            new Thread(new Runnable() {

                                @Override
                                public void run() {
                                    Looper.prepare();
                                    boolean isOK = false;
                                    String response = null;
                                    try {
                                        if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.USE_TRUSTED_NODE, false) == true) {
                                            if (TrustedNodeUtil.getInstance().isSet()) {
                                                response = PushTx.getInstance(SendActivity.this).trustedNode(hexTx);
                                                JSONObject jsonObject = new org.json.JSONObject(response);
                                                if (jsonObject.has("result")) {
                                                    if (jsonObject.getString("result").matches("^[A-Za-z0-9]{64}$")) {
                                                        isOK = true;
                                                    } else {
                                                        Toast.makeText(SendActivity.this, R.string.trusted_node_tx_error, Toast.LENGTH_SHORT).show();
                                                    }
                                                }
                                            } else {
                                                Toast.makeText(SendActivity.this, R.string.trusted_node_not_valid, Toast.LENGTH_SHORT).show();
                                            }
                                        } else {
                                            response = PushTx.getInstance(SendActivity.this).samourai(hexTx);
                                            if (response != null) {
                                                JSONObject jsonObject = new org.json.JSONObject(response);
                                                if (jsonObject.has("status")) {
                                                    if (jsonObject.getString("status").equals("ok")) {
                                                        isOK = true;
                                                    }
                                                }
                                            } else {
                                                Toast.makeText(SendActivity.this, R.string.pushtx_returns_null, Toast.LENGTH_SHORT).show();
                                            }
                                        }
                                        if (isOK) {
                                            if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.USE_TRUSTED_NODE, false) == false) {
                                                Toast.makeText(SendActivity.this, R.string.tx_sent, Toast.LENGTH_SHORT).show();
                                            } else {
                                                Toast.makeText(SendActivity.this, R.string.trusted_node_tx_sent, Toast.LENGTH_SHORT).show();
                                            }
                                            if (_change > 0L && SPEND_TYPE == SPEND_SIMPLE) {
                                                if (isSegwitChange) {
                                                    BIP49Util.getInstance(SendActivity.this).getWallet().getAccount(0).getChange().incAddrIdx();
                                                } else {
                                                    try {
                                                        HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().incAddrIdx();
                                                    } catch (IOException ioe) {
                                                        ;
                                                    } catch (MnemonicException.MnemonicLengthException mle) {
                                                        ;
                                                    }
                                                }
                                            }
                                            if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.RBF_OPT_IN, false) == true) {
                                                for (TransactionOutput out : _tx.getOutputs()) {
                                                    try {
                                                        if (!isSegwitChange && !address.equals(out.getAddressFromP2PKHScript(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString())) {
                                                            rbf.addChangeAddr(out.getAddressFromP2PKHScript(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString());
                                                        } else if (isSegwitChange && !address.equals(out.getAddressFromP2SH(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString())) {
                                                            rbf.addChangeAddr(out.getAddressFromP2SH(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString());
                                                        } else {
                                                            ;
                                                        }
                                                    } catch (NullPointerException npe) {
                                                        // test for bech32, skip for now as it's not a change address
                                                        ;
                                                    }
                                                }
                                                rbf.setHash(strTxHash);
                                                rbf.setSerializedTx(hexTx);
                                                RBFUtil.getInstance().add(rbf);
                                            }
                                            // increment counter if BIP47 spend
                                            if (strPCode != null && strPCode.length() > 0) {
                                                BIP47Meta.getInstance().getPCode4AddrLookup().put(address, strPCode);
                                                BIP47Meta.getInstance().inc(strPCode);
                                                SimpleDateFormat sd = new SimpleDateFormat("dd MMM");
                                                String strTS = sd.format(currentTimeMillis());
                                                String event = strTS + " " + SendActivity.this.getString(R.string.sent) + " " + MonetaryUtil.getInstance().getBTCFormat().format((double) _amount / 1e8) + " BTC";
                                                BIP47Meta.getInstance().setLatestEvent(strPCode, event);
                                                strPCode = null;
                                            }
                                            if (strPrivacyWarning.length() > 0 && cbShowAgain != null) {
                                                SendAddressUtil.getInstance().add(address, cbShowAgain.isChecked() ? false : true);
                                            } else if (SendAddressUtil.getInstance().get(address) == 0) {
                                                SendAddressUtil.getInstance().add(address, false);
                                            } else {
                                                SendAddressUtil.getInstance().add(address, true);
                                            }
                                            Intent intent = new Intent("com.samourai.wallet.BalanceFragment.REFRESH");
                                            intent.putExtra("notifTx", false);
                                            intent.putExtra("fetch", true);
                                            LocalBroadcastManager.getInstance(SendActivity.this).sendBroadcast(intent);
                                            View view = SendActivity.this.getCurrentFocus();
                                            if (view != null) {
                                                InputMethodManager imm = (InputMethodManager) SendActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
                                                imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
                                            }
                                            if (bViaMenu) {
                                                SendActivity.this.finish();
                                            } else {
                                                Intent _intent = new Intent(SendActivity.this, BalanceActivity.class);
                                                _intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                                                startActivity(_intent);
                                            }
                                        } else {
                                            Toast.makeText(SendActivity.this, R.string.tx_failed, Toast.LENGTH_SHORT).show();
                                            // reset change index upon tx fail
                                            if (isSegwitChange) {
                                                BIP49Util.getInstance(SendActivity.this).getWallet().getAccount(0).getChange().setAddrIdx(_change_index);
                                            } else {
                                                HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().setAddrIdx(_change_index);
                                            }
                                        }
                                    } catch (JSONException je) {
                                        Toast.makeText(SendActivity.this, "pushTx:" + je.getMessage(), Toast.LENGTH_SHORT).show();
                                    } catch (MnemonicException.MnemonicLengthException mle) {
                                        Toast.makeText(SendActivity.this, "pushTx:" + mle.getMessage(), Toast.LENGTH_SHORT).show();
                                    } catch (DecoderException de) {
                                        Toast.makeText(SendActivity.this, "pushTx:" + de.getMessage(), Toast.LENGTH_SHORT).show();
                                    } catch (IOException ioe) {
                                        Toast.makeText(SendActivity.this, "pushTx:" + ioe.getMessage(), Toast.LENGTH_SHORT).show();
                                    } finally {
                                        SendActivity.this.runOnUiThread(new Runnable() {

                                            @Override
                                            public void run() {
                                                btSend.setActivated(true);
                                                btSend.setClickable(true);
                                                progress.dismiss();
                                                dialog.dismiss();
                                            }
                                        });
                                    }
                                    Looper.loop();
                                }
                            }).start();
                        } else {
                            // Log.d("SendActivity", "tx error");
                            Toast.makeText(SendActivity.this, "tx error", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
                builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                    public void onClick(final DialogInterface dialog, int whichButton) {
                        try {
                            // reset change index upon 'NO'
                            if (isSegwitChange) {
                                BIP49Util.getInstance(SendActivity.this).getWallet().getAccount(0).getChange().setAddrIdx(_change_index);
                            } else {
                                HD_WalletFactory.getInstance(SendActivity.this).get().getAccount(0).getChange().setAddrIdx(_change_index);
                            }
                        } catch (Exception e) {
                            // Log.d("SendActivity", e.getMessage());
                            Toast.makeText(SendActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                        } finally {
                            SendActivity.this.runOnUiThread(new Runnable() {

                                @Override
                                public void run() {
                                    btSend.setActivated(true);
                                    btSend.setClickable(true);
                                    dialog.dismiss();
                                }
                            });
                        }
                    }
                });
                AlertDialog alert = builder.create();
                alert.show();
            }
        }
    });
    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        bViaMenu = extras.getBoolean("via_menu", false);
        String strUri = extras.getString("uri");
        strPCode = extras.getString("pcode");
        if (strUri != null && strUri.length() > 0) {
            processScan(strUri);
        }
        if (strPCode != null && strPCode.length() > 0) {
            processPCode(strPCode, null);
        }
    }
    validateSpend();
}
Also used : AlertDialog(android.app.AlertDialog) PaymentAddress(com.samourai.wallet.bip47.rpc.PaymentAddress) Address(org.bitcoinj.core.Address) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) RicochetActivity(com.samourai.wallet.ricochet.RicochetActivity) ProgressDialog(android.app.ProgressDialog) ArrayList(java.util.ArrayList) List(java.util.List) Script(org.bitcoinj.script.Script) SuggestedFee(com.samourai.wallet.send.SuggestedFee) JSONObject(org.json.JSONObject) Transaction(org.bitcoinj.core.Transaction) CheckBox(android.widget.CheckBox) BigInteger(java.math.BigInteger) TransactionOutput(org.bitcoinj.core.TransactionOutput) DialogInterface(android.content.DialogInterface) DecimalFormat(java.text.DecimalFormat) InputMethodManager(android.view.inputmethod.InputMethodManager) TransactionInput(org.bitcoinj.core.TransactionInput) MnemonicException(org.bitcoinj.crypto.MnemonicException) TextWatcher(android.text.TextWatcher) Editable(android.text.Editable) RBFSpend(com.samourai.wallet.send.RBFSpend) Pair(org.apache.commons.lang3.tuple.Pair) DecimalFormatSymbols(java.text.DecimalFormatSymbols) Bundle(android.os.Bundle) JSONException(org.json.JSONException) Intent(android.content.Intent) IOException(java.io.IOException) ImageView(android.widget.ImageView) View(android.view.View) TextView(android.widget.TextView) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) Point(android.graphics.Point) JSONException(org.json.JSONException) IOException(java.io.IOException) WriterException(com.google.zxing.WriterException) ParseException(java.text.ParseException) DecoderException(org.bouncycastle.util.encoders.DecoderException) FileNotFoundException(java.io.FileNotFoundException) MnemonicException(org.bitcoinj.crypto.MnemonicException) MotionEvent(android.view.MotionEvent) UTXO(com.samourai.wallet.send.UTXO) BlockedUTXO(com.samourai.wallet.send.BlockedUTXO) DecoderException(org.bouncycastle.util.encoders.DecoderException) ParseException(java.text.ParseException) SimpleDateFormat(java.text.SimpleDateFormat) ArrayAdapter(android.widget.ArrayAdapter) CompoundButton(android.widget.CompoundButton) NumberFormat(java.text.NumberFormat)

Aggregations

TransactionInput (org.bitcoinj.core.TransactionInput)36 Transaction (org.bitcoinj.core.Transaction)29 TransactionOutput (org.bitcoinj.core.TransactionOutput)20 TransactionOutPoint (org.bitcoinj.core.TransactionOutPoint)18 Script (org.bitcoinj.script.Script)16 ECKey (org.bitcoinj.core.ECKey)11 HashMap (java.util.HashMap)10 Address (org.bitcoinj.core.Address)9 Coin (org.bitcoinj.core.Coin)9 ArrayList (java.util.ArrayList)7 AddressFormatException (org.bitcoinj.core.AddressFormatException)7 RawTransactionInput (bisq.core.btc.data.RawTransactionInput)6 TransactionSignature (org.bitcoinj.crypto.TransactionSignature)6 ScriptException (org.bitcoinj.script.ScriptException)6 MyTransactionOutPoint (com.samourai.wallet.send.MyTransactionOutPoint)5 IOException (java.io.IOException)5 Sha256Hash (org.bitcoinj.core.Sha256Hash)5 MnemonicException (org.bitcoinj.crypto.MnemonicException)5 SendRequest (org.bitcoinj.wallet.SendRequest)5 BlockedUTXO (com.samourai.wallet.send.BlockedUTXO)4