@Test public void sendRequestExchangeRate() throws Exception { receiveATransaction(wallet, myAddress); SendRequest sendRequest = SendRequest.to(myAddress, Coin.COIN); sendRequest.exchangeRate = new ExchangeRate(Fiat.parseFiat("EUR", "500")); wallet.completeTx(sendRequest); assertEquals(sendRequest.exchangeRate, sendRequest.tx.getExchangeRate()); }
public void completeTx(SendRequest req) throws InsufficientMoneyException { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); Coin value = Coin.ZERO; boolean requiresInputs = req.tx.getType() != Transaction.Type.TRANSACTION_SUBTX_RESETKEY; boolean requiresNoFee = req.tx.getType() == Transaction.Type.TRANSACTION_SUBTX_RESETKEY; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } log.info("Completing send tx with {} outputs totalling {} and a fee of {}/kB", req.tx.getOutputs().size(), value.toFriendlyString(), req.feePerKb.toFriendlyString()); Coin totalInput = Coin.ZERO; for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); if (req.ensureMinRequiredFee && !req.emptyWallet) { int opReturnCount = 0; for (TransactionOutput output : req.tx.getOutputs()) { if (output.isDust()) throw new DustySendRequested(); if (output.getScriptPubKey().isOpReturn()) ++opReturnCount; } if (opReturnCount > 1) throw new MultipleOpReturnRequested(); } List<TransactionOutput> candidates = calculateAllSpendCandidates(true, req.missingSigsMode == MissingSigsMode.THROW); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (requiresNoFee) { ArrayList<TransactionOutput> gathered = new ArrayList<TransactionOutput>(); bestCoinSelection = new CoinSelection(Coin.valueOf(0), gathered); } else if (!req.emptyWallet) { FeeCalculation feeCalculation = calculateFee(req, value, originalInputs, req.ensureMinRequiredFee, candidates); bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(params.getMaxMoney(), candidates); candidates = null; req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); log.info(" emptying {}", bestCoinSelection.valueGathered.toFriendlyString()); } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); if (req.emptyWallet) { final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee, req.useInstantSend)) throw new CouldNotAdjustDownwards(); } if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); log.info(" with {} change", bestChangeOutput.getValue().toFriendlyString()); } if (req.shuffleOutputs) req.tx.shuffleOutputs(); if (requiresInputs && req.signInputs) signTransaction(req); final int size = req.tx.unsafeBitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) throw new ExceededMaxTransactionSize(); req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } }
Wallet extends BaseTaggableObject implements NewBestBlockListener, TransactionReceivedInBlockListener, PeerFilterProvider, KeyBag, TransactionBag, ReorganizeListener { public void completeTx(SendRequest req) throws InsufficientMoneyException { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); Coin value = Coin.ZERO; boolean requiresInputs = req.tx.getType() != Transaction.Type.TRANSACTION_SUBTX_RESETKEY; boolean requiresNoFee = req.tx.getType() == Transaction.Type.TRANSACTION_SUBTX_RESETKEY; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } log.info("Completing send tx with {} outputs totalling {} and a fee of {}/kB", req.tx.getOutputs().size(), value.toFriendlyString(), req.feePerKb.toFriendlyString()); Coin totalInput = Coin.ZERO; for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); if (req.ensureMinRequiredFee && !req.emptyWallet) { int opReturnCount = 0; for (TransactionOutput output : req.tx.getOutputs()) { if (output.isDust()) throw new DustySendRequested(); if (output.getScriptPubKey().isOpReturn()) ++opReturnCount; } if (opReturnCount > 1) throw new MultipleOpReturnRequested(); } List<TransactionOutput> candidates = calculateAllSpendCandidates(true, req.missingSigsMode == MissingSigsMode.THROW); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (requiresNoFee) { ArrayList<TransactionOutput> gathered = new ArrayList<TransactionOutput>(); bestCoinSelection = new CoinSelection(Coin.valueOf(0), gathered); } else if (!req.emptyWallet) { FeeCalculation feeCalculation = calculateFee(req, value, originalInputs, req.ensureMinRequiredFee, candidates); bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(params.getMaxMoney(), candidates); candidates = null; req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); log.info(" emptying {}", bestCoinSelection.valueGathered.toFriendlyString()); } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); if (req.emptyWallet) { final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee, req.useInstantSend)) throw new CouldNotAdjustDownwards(); } if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); log.info(" with {} change", bestChangeOutput.getValue().toFriendlyString()); } if (req.shuffleOutputs) req.tx.shuffleOutputs(); if (requiresInputs && req.signInputs) signTransaction(req); final int size = req.tx.unsafeBitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) throw new ExceededMaxTransactionSize(); req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } } }
Wallet extends BaseTaggableObject implements NewBestBlockListener, TransactionReceivedInBlockListener, PeerFilterProvider, KeyBag, TransactionBag, ReorganizeListener { public void completeTx(SendRequest req) throws InsufficientMoneyException { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); Coin value = Coin.ZERO; boolean requiresInputs = req.tx.getType() != Transaction.Type.TRANSACTION_SUBTX_RESETKEY; boolean requiresNoFee = req.tx.getType() == Transaction.Type.TRANSACTION_SUBTX_RESETKEY; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } log.info("Completing send tx with {} outputs totalling {} and a fee of {}/kB", req.tx.getOutputs().size(), value.toFriendlyString(), req.feePerKb.toFriendlyString()); Coin totalInput = Coin.ZERO; for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); if (req.ensureMinRequiredFee && !req.emptyWallet) { int opReturnCount = 0; for (TransactionOutput output : req.tx.getOutputs()) { if (output.isDust()) throw new DustySendRequested(); if (output.getScriptPubKey().isOpReturn()) ++opReturnCount; } if (opReturnCount > 1) throw new MultipleOpReturnRequested(); } List<TransactionOutput> candidates = calculateAllSpendCandidates(true, req.missingSigsMode == MissingSigsMode.THROW); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (requiresNoFee) { ArrayList<TransactionOutput> gathered = new ArrayList<TransactionOutput>(); bestCoinSelection = new CoinSelection(Coin.valueOf(0), gathered); } else if (!req.emptyWallet) { FeeCalculation feeCalculation = calculateFee(req, value, originalInputs, req.ensureMinRequiredFee, candidates); bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(params.getMaxMoney(), candidates); candidates = null; req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); log.info(" emptying {}", bestCoinSelection.valueGathered.toFriendlyString()); } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); if (req.emptyWallet) { final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee, req.useInstantSend)) throw new CouldNotAdjustDownwards(); } if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); log.info(" with {} change", bestChangeOutput.getValue().toFriendlyString()); } if (req.shuffleOutputs) req.tx.shuffleOutputs(); if (requiresInputs && req.signInputs) signTransaction(req); final int size = req.tx.unsafeBitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) throw new ExceededMaxTransactionSize(); req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } } Wallet(NetworkParameters params);  Wallet(Context context);  Wallet(NetworkParameters params, KeyChainGroup keyChainGroup); private  Wallet(Context context, KeyChainGroup keyChainGroup); }
Wallet extends BaseTaggableObject implements NewBestBlockListener, TransactionReceivedInBlockListener, PeerFilterProvider, KeyBag, TransactionBag, ReorganizeListener { public void completeTx(SendRequest req) throws InsufficientMoneyException { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); Coin value = Coin.ZERO; boolean requiresInputs = req.tx.getType() != Transaction.Type.TRANSACTION_SUBTX_RESETKEY; boolean requiresNoFee = req.tx.getType() == Transaction.Type.TRANSACTION_SUBTX_RESETKEY; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } log.info("Completing send tx with {} outputs totalling {} and a fee of {}/kB", req.tx.getOutputs().size(), value.toFriendlyString(), req.feePerKb.toFriendlyString()); Coin totalInput = Coin.ZERO; for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); if (req.ensureMinRequiredFee && !req.emptyWallet) { int opReturnCount = 0; for (TransactionOutput output : req.tx.getOutputs()) { if (output.isDust()) throw new DustySendRequested(); if (output.getScriptPubKey().isOpReturn()) ++opReturnCount; } if (opReturnCount > 1) throw new MultipleOpReturnRequested(); } List<TransactionOutput> candidates = calculateAllSpendCandidates(true, req.missingSigsMode == MissingSigsMode.THROW); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (requiresNoFee) { ArrayList<TransactionOutput> gathered = new ArrayList<TransactionOutput>(); bestCoinSelection = new CoinSelection(Coin.valueOf(0), gathered); } else if (!req.emptyWallet) { FeeCalculation feeCalculation = calculateFee(req, value, originalInputs, req.ensureMinRequiredFee, candidates); bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(params.getMaxMoney(), candidates); candidates = null; req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); log.info(" emptying {}", bestCoinSelection.valueGathered.toFriendlyString()); } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); if (req.emptyWallet) { final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee, req.useInstantSend)) throw new CouldNotAdjustDownwards(); } if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); log.info(" with {} change", bestChangeOutput.getValue().toFriendlyString()); } if (req.shuffleOutputs) req.tx.shuffleOutputs(); if (requiresInputs && req.signInputs) signTransaction(req); final int size = req.tx.unsafeBitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) throw new ExceededMaxTransactionSize(); req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } } Wallet(NetworkParameters params);  Wallet(Context context);  Wallet(NetworkParameters params, KeyChainGroup keyChainGroup); private  Wallet(Context context, KeyChainGroup keyChainGroup); static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed); static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath); static Wallet fromWatchingKey(NetworkParameters params, DeterministicKey watchKey); static Wallet fromWatchingKeyB58(NetworkParameters params, String watchKeyB58, long creationTimeSeconds); static Wallet fromKeys(NetworkParameters params, List<ECKey> keys); NetworkParameters getNetworkParameters(); DeterministicKeyChain getActiveKeyChain(); final void addTransactionSigner(TransactionSigner signer); List<TransactionSigner> getTransactionSigners(); DeterministicKey currentKey(KeyChain.KeyPurpose purpose); DeterministicKey currentReceiveKey(); Address currentAddress(KeyChain.KeyPurpose purpose); Address currentReceiveAddress(); DeterministicKey freshKey(KeyChain.KeyPurpose purpose); List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys); DeterministicKey freshReceiveKey(); Address freshAddress(KeyChain.KeyPurpose purpose); Address freshReceiveAddress(); List<ECKey> getIssuedReceiveKeys(); List<Address> getIssuedReceiveAddresses(); void upgradeToDeterministic(@Nullable KeyParameter aesKey); boolean isDeterministicUpgradeRequired(); List<Script> getWatchedScripts(); boolean removeKey(ECKey key); int getKeyChainGroupSize(); @VisibleForTesting int getKeyChainGroupCombinedKeyLookaheadEpochs(); List<ECKey> getImportedKeys(); Address currentChangeAddress(); Address getChangeAddress(); @Deprecated boolean addKey(ECKey key); boolean importKey(ECKey key); @Deprecated int addKeys(List<ECKey> keys); int importKeys(final List<ECKey> keys); int importKeysAndEncrypt(final List<ECKey> keys, CharSequence password); int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey); void addAndActivateHDChain(DeterministicKeyChain chain); void setKeyChainGroupLookaheadSize(int lookaheadSize); int getKeyChainGroupLookaheadSize(); void setKeyChainGroupLookaheadThreshold(int num); int getKeyChainGroupLookaheadThreshold(); DeterministicKey getWatchingKey(); boolean isWatching(); boolean isAddressWatched(Address address); boolean addWatchedAddress(final Address address); boolean addWatchedAddress(final Address address, long creationTime); int addWatchedAddresses(final List<Address> addresses, long creationTime); int addWatchedScripts(final List<Script> scripts); boolean removeWatchedAddress(final Address address); boolean removeWatchedAddresses(final List<Address> addresses); boolean removeWatchedScripts(final List<Script> scripts); List<Address> getWatchedAddresses(); @Override @Nullable ECKey findKeyFromPubHash(byte[] pubkeyHash); boolean hasKey(ECKey key); @Override boolean isPubKeyHashMine(byte[] pubkeyHash); @Override boolean isWatchedScript(Script script); @Override @Nullable ECKey findKeyFromPubKey(byte[] pubkey); @Override boolean isPubKeyMine(byte[] pubkey); @Nullable @Override RedeemData findRedeemDataFromScriptHash(byte[] payToScriptHash); @Override boolean isPayToScriptHashMine(byte[] payToScriptHash); DeterministicSeed getKeyChainSeed(); DeterministicKey getKeyByPath(List<ChildNumber> path); void encrypt(CharSequence password); void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey); void decrypt(CharSequence password); void decrypt(KeyParameter aesKey); boolean checkPassword(CharSequence password); boolean checkAESKey(KeyParameter aesKey); @Nullable KeyCrypter getKeyCrypter(); EncryptionType getEncryptionType(); boolean isEncrypted(); void changeEncryptionPassword(CharSequence currentPassword, CharSequence newPassword); void changeEncryptionKey(KeyCrypter keyCrypter, KeyParameter currentAesKey, KeyParameter newAesKey); List<Protos.Key> serializeKeyChainGroupToProtobuf(); void saveToFile(File temp, File destFile); void saveToFile(File f); void setAcceptRiskyTransactions(boolean acceptRiskyTransactions); boolean isAcceptRiskyTransactions(); void setRiskAnalyzer(RiskAnalysis.Analyzer analyzer); RiskAnalysis.Analyzer getRiskAnalyzer(); WalletFiles autosaveToFile(File f, long delayTime, TimeUnit timeUnit,
                                      @Nullable WalletFiles.Listener eventListener); void shutdownAutosaveAndWait(); void saveToFileStream(OutputStream f); NetworkParameters getParams(); Context getContext(); static Wallet loadFromFile(File file, @Nullable WalletExtension... walletExtensions); boolean isConsistent(); void isConsistentOrThrow(); static Wallet loadFromFileStream(InputStream stream, @Nullable WalletExtension... walletExtensions); @Override boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
                                              BlockChain.NewBlockType blockType,
                                              int relativityOffset); void receivePending(Transaction tx, @Nullable List<Transaction> dependencies, boolean overrideIsRelevant); void receiveLock(Transaction tx); boolean isTransactionRisky(Transaction tx, @Nullable List<Transaction> dependencies); void receivePending(Transaction tx, @Nullable List<Transaction> dependencies); boolean isPendingTransactionRelevant(Transaction tx); boolean isPendingTransactionLockRelevant(Transaction tx); boolean isTransactionRelevant(Transaction tx); @Override void receiveFromBlock(Transaction tx, StoredBlock block,
                                 BlockChain.NewBlockType blockType,
                                 int relativityOffset); @Override void notifyNewBestBlock(StoredBlock block); boolean maybeCommitTx(Transaction tx); void commitTx(Transaction tx); void addEventListener(WalletEventListener listener); @Deprecated void addEventListener(WalletEventListener listener, Executor executor); void addChangeEventListener(WalletChangeEventListener listener); void addChangeEventListener(Executor executor, WalletChangeEventListener listener); void addCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener); void addCoinsReceivedEventListener(Executor executor, WalletCoinsReceivedEventListener listener); void addCoinsSentEventListener(WalletCoinsSentEventListener listener); void addCoinsSentEventListener(Executor executor, WalletCoinsSentEventListener listener); void addKeyChainEventListener(KeyChainEventListener listener); void addKeyChainEventListener(Executor executor, KeyChainEventListener listener); void addReorganizeEventListener(WalletReorganizeEventListener listener); void addReorganizeEventListener(Executor executor, WalletReorganizeEventListener listener); void addScriptsChangeEventListener(ScriptsChangeEventListener listener); void addScriptChangeEventListener(Executor executor, ScriptsChangeEventListener listener); void addTransactionConfidenceEventListener(TransactionConfidenceEventListener listener); void addTransactionConfidenceEventListener(Executor executor, TransactionConfidenceEventListener listener); @Deprecated boolean removeEventListener(WalletEventListener listener); boolean removeChangeEventListener(WalletChangeEventListener listener); boolean removeCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener); boolean removeCoinsSentEventListener(WalletCoinsSentEventListener listener); boolean removeKeyChainEventListener(KeyChainEventListener listener); boolean removeReorganizeEventListener(WalletReorganizeEventListener listener); boolean removeScriptChangeEventListener(ScriptsChangeEventListener listener); boolean removeTransactionConfidenceEventListener(TransactionConfidenceEventListener listener); Set<Transaction> getTransactions(boolean includeDead); Iterable<WalletTransaction> getWalletTransactions(); void addWalletTransaction(WalletTransaction wtx); List<Transaction> getTransactionsByTime(); List<Transaction> getRecentTransactions(int numTransactions, boolean includeDead); @Nullable Transaction getTransaction(Sha256Hash hash); @Override Map<Sha256Hash, Transaction> getTransactionPool(Pool pool); void reset(); void clearTransactions(int fromHeight); List<TransactionOutput> getWatchedOutputs(boolean excludeImmatureCoinbases); void cleanup(); @VisibleForTesting int getPoolSize(WalletTransaction.Pool pool); @VisibleForTesting boolean poolContainsTxHash(final WalletTransaction.Pool pool, final Sha256Hash txHash); List<TransactionOutput> getUnspents(); @Override String toString(); String toString(boolean includePrivateKeys, boolean includeTransactions, boolean includeExtensions,
                           @Nullable AbstractBlockChain chain); Collection<Transaction> getPendingTransactions(); @Override long getEarliestKeyCreationTime(); @Nullable Sha256Hash getLastBlockSeenHash(); void setLastBlockSeenHash(@Nullable Sha256Hash lastBlockSeenHash); void setLastBlockSeenHeight(int lastBlockSeenHeight); void setLastBlockSeenTimeSecs(long timeSecs); long getLastBlockSeenTimeSecs(); @Nullable Date getLastBlockSeenTime(); int getLastBlockSeenHeight(); int getVersion(); void setVersion(int version); void setDescription(String description); String getDescription(); @Deprecated Coin getWatchedBalance(); @Deprecated Coin getWatchedBalance(CoinSelector selector); Coin getBalance(); Coin getBalance(BalanceType balanceType); Coin getBalance(CoinSelector selector); ListenableFuture<Coin> getBalanceFuture(final Coin value, final BalanceType type); Coin getTotalReceived(); Coin getTotalSent(); Transaction createSend(Address address, Coin value); Transaction sendCoinsOffline(SendRequest request); SendResult sendCoins(TransactionBroadcaster broadcaster, Address to, Coin value); SendResult sendCoins(TransactionBroadcaster broadcaster, SendRequest request); SendResult sendCoins(SendRequest request); Transaction sendCoins(Peer peer, SendRequest request); void completeTx(SendRequest req); void signTransaction(SendRequest req); List<TransactionOutput> calculateAllSpendCandidates(); @Deprecated List<TransactionOutput> calculateAllSpendCandidates(boolean excludeImmatureCoinbases); List<TransactionOutput> calculateAllSpendCandidates(boolean excludeImmatureCoinbases, boolean excludeUnsignable); boolean canSignFor(Script script); CoinSelector getCoinSelector(); void setCoinSelector(CoinSelector coinSelector); void allowSpendingUnconfirmedTransactions(); @Nullable UTXOProvider getUTXOProvider(); void setUTXOProvider(@Nullable UTXOProvider provider); @Override void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks); @Override void beginBloomFilterCalculation(); @Override @GuardedBy("keyChainGroupLock") void endBloomFilterCalculation(); @Override int getBloomFilterElementCount(); @Override boolean isRequiringUpdateAllBloomFilter(); BloomFilter getBloomFilter(double falsePositiveRate); @Override @GuardedBy("keyChainGroupLock") BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak); boolean checkForFilterExhaustion(FilteredBlock block); void addExtension(WalletExtension extension); WalletExtension addOrGetExistingExtension(WalletExtension extension); void addOrUpdateExtension(WalletExtension extension); Map<String, WalletExtension> getExtensions(); void deserializeExtension(WalletExtension extension, byte[] data); @Override void setTag(String tag, ByteString value); FeeCalculation calculateFee(SendRequest req, Coin value, List<TransactionInput> originalInputs,
                                       boolean needAtLeastReferenceFee, List<TransactionOutput> candidates); void setTransactionBroadcaster(@Nullable org.bitcoinj.core.TransactionBroadcaster broadcaster); void setKeyRotationTime(Date time); @Nullable Date getKeyRotationTime(); void setKeyRotationTime(long unixTimeSeconds); boolean isKeyRotating(ECKey key); @Deprecated ListenableFuture<List<Transaction>> maybeDoMaintenance(@Nullable KeyParameter aesKey, boolean andSend); ListenableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend); boolean hasKeyChain(ImmutableList<ChildNumber> path); void addKeyChain(ImmutableList<ChildNumber> path); }
Wallet extends BaseTaggableObject implements NewBestBlockListener, TransactionReceivedInBlockListener, PeerFilterProvider, KeyBag, TransactionBag, ReorganizeListener { public void completeTx(SendRequest req) throws InsufficientMoneyException { lock.lock(); try { checkArgument(!req.completed, "Given SendRequest has already been completed."); Coin value = Coin.ZERO; boolean requiresInputs = req.tx.getType() != Transaction.Type.TRANSACTION_SUBTX_RESETKEY; boolean requiresNoFee = req.tx.getType() == Transaction.Type.TRANSACTION_SUBTX_RESETKEY; for (TransactionOutput output : req.tx.getOutputs()) { value = value.add(output.getValue()); } log.info("Completing send tx with {} outputs totalling {} and a fee of {}/kB", req.tx.getOutputs().size(), value.toFriendlyString(), req.feePerKb.toFriendlyString()); Coin totalInput = Coin.ZERO; for (TransactionInput input : req.tx.getInputs()) if (input.getConnectedOutput() != null) totalInput = totalInput.add(input.getConnectedOutput().getValue()); else log.warn("SendRequest transaction already has inputs but we don't know how much they are worth - they will be added to fee."); value = value.subtract(totalInput); List<TransactionInput> originalInputs = new ArrayList<TransactionInput>(req.tx.getInputs()); if (req.ensureMinRequiredFee && !req.emptyWallet) { int opReturnCount = 0; for (TransactionOutput output : req.tx.getOutputs()) { if (output.isDust()) throw new DustySendRequested(); if (output.getScriptPubKey().isOpReturn()) ++opReturnCount; } if (opReturnCount > 1) throw new MultipleOpReturnRequested(); } List<TransactionOutput> candidates = calculateAllSpendCandidates(true, req.missingSigsMode == MissingSigsMode.THROW); CoinSelection bestCoinSelection; TransactionOutput bestChangeOutput = null; if (requiresNoFee) { ArrayList<TransactionOutput> gathered = new ArrayList<TransactionOutput>(); bestCoinSelection = new CoinSelection(Coin.valueOf(0), gathered); } else if (!req.emptyWallet) { FeeCalculation feeCalculation = calculateFee(req, value, originalInputs, req.ensureMinRequiredFee, candidates); bestCoinSelection = feeCalculation.bestCoinSelection; bestChangeOutput = feeCalculation.bestChangeOutput; } else { checkState(req.tx.getOutputs().size() == 1, "Empty wallet TX must have a single output only."); CoinSelector selector = req.coinSelector == null ? coinSelector : req.coinSelector; bestCoinSelection = selector.select(params.getMaxMoney(), candidates); candidates = null; req.tx.getOutput(0).setValue(bestCoinSelection.valueGathered); log.info(" emptying {}", bestCoinSelection.valueGathered.toFriendlyString()); } for (TransactionOutput output : bestCoinSelection.gathered) req.tx.addInput(output); if (req.emptyWallet) { final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee, req.useInstantSend)) throw new CouldNotAdjustDownwards(); } if (bestChangeOutput != null) { req.tx.addOutput(bestChangeOutput); log.info(" with {} change", bestChangeOutput.getValue().toFriendlyString()); } if (req.shuffleOutputs) req.tx.shuffleOutputs(); if (requiresInputs && req.signInputs) signTransaction(req); final int size = req.tx.unsafeBitcoinSerialize().length; if (size > Transaction.MAX_STANDARD_TX_SIZE) throw new ExceededMaxTransactionSize(); req.tx.getConfidence().setSource(TransactionConfidence.Source.SELF); req.tx.setPurpose(Transaction.Purpose.USER_PAYMENT); req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; log.info(" completed: {}", req.tx); } finally { lock.unlock(); } } Wallet(NetworkParameters params);  Wallet(Context context);  Wallet(NetworkParameters params, KeyChainGroup keyChainGroup); private  Wallet(Context context, KeyChainGroup keyChainGroup); static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed); static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath); static Wallet fromWatchingKey(NetworkParameters params, DeterministicKey watchKey); static Wallet fromWatchingKeyB58(NetworkParameters params, String watchKeyB58, long creationTimeSeconds); static Wallet fromKeys(NetworkParameters params, List<ECKey> keys); NetworkParameters getNetworkParameters(); DeterministicKeyChain getActiveKeyChain(); final void addTransactionSigner(TransactionSigner signer); List<TransactionSigner> getTransactionSigners(); DeterministicKey currentKey(KeyChain.KeyPurpose purpose); DeterministicKey currentReceiveKey(); Address currentAddress(KeyChain.KeyPurpose purpose); Address currentReceiveAddress(); DeterministicKey freshKey(KeyChain.KeyPurpose purpose); List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys); DeterministicKey freshReceiveKey(); Address freshAddress(KeyChain.KeyPurpose purpose); Address freshReceiveAddress(); List<ECKey> getIssuedReceiveKeys(); List<Address> getIssuedReceiveAddresses(); void upgradeToDeterministic(@Nullable KeyParameter aesKey); boolean isDeterministicUpgradeRequired(); List<Script> getWatchedScripts(); boolean removeKey(ECKey key); int getKeyChainGroupSize(); @VisibleForTesting int getKeyChainGroupCombinedKeyLookaheadEpochs(); List<ECKey> getImportedKeys(); Address currentChangeAddress(); Address getChangeAddress(); @Deprecated boolean addKey(ECKey key); boolean importKey(ECKey key); @Deprecated int addKeys(List<ECKey> keys); int importKeys(final List<ECKey> keys); int importKeysAndEncrypt(final List<ECKey> keys, CharSequence password); int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey); void addAndActivateHDChain(DeterministicKeyChain chain); void setKeyChainGroupLookaheadSize(int lookaheadSize); int getKeyChainGroupLookaheadSize(); void setKeyChainGroupLookaheadThreshold(int num); int getKeyChainGroupLookaheadThreshold(); DeterministicKey getWatchingKey(); boolean isWatching(); boolean isAddressWatched(Address address); boolean addWatchedAddress(final Address address); boolean addWatchedAddress(final Address address, long creationTime); int addWatchedAddresses(final List<Address> addresses, long creationTime); int addWatchedScripts(final List<Script> scripts); boolean removeWatchedAddress(final Address address); boolean removeWatchedAddresses(final List<Address> addresses); boolean removeWatchedScripts(final List<Script> scripts); List<Address> getWatchedAddresses(); @Override @Nullable ECKey findKeyFromPubHash(byte[] pubkeyHash); boolean hasKey(ECKey key); @Override boolean isPubKeyHashMine(byte[] pubkeyHash); @Override boolean isWatchedScript(Script script); @Override @Nullable ECKey findKeyFromPubKey(byte[] pubkey); @Override boolean isPubKeyMine(byte[] pubkey); @Nullable @Override RedeemData findRedeemDataFromScriptHash(byte[] payToScriptHash); @Override boolean isPayToScriptHashMine(byte[] payToScriptHash); DeterministicSeed getKeyChainSeed(); DeterministicKey getKeyByPath(List<ChildNumber> path); void encrypt(CharSequence password); void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey); void decrypt(CharSequence password); void decrypt(KeyParameter aesKey); boolean checkPassword(CharSequence password); boolean checkAESKey(KeyParameter aesKey); @Nullable KeyCrypter getKeyCrypter(); EncryptionType getEncryptionType(); boolean isEncrypted(); void changeEncryptionPassword(CharSequence currentPassword, CharSequence newPassword); void changeEncryptionKey(KeyCrypter keyCrypter, KeyParameter currentAesKey, KeyParameter newAesKey); List<Protos.Key> serializeKeyChainGroupToProtobuf(); void saveToFile(File temp, File destFile); void saveToFile(File f); void setAcceptRiskyTransactions(boolean acceptRiskyTransactions); boolean isAcceptRiskyTransactions(); void setRiskAnalyzer(RiskAnalysis.Analyzer analyzer); RiskAnalysis.Analyzer getRiskAnalyzer(); WalletFiles autosaveToFile(File f, long delayTime, TimeUnit timeUnit,
                                      @Nullable WalletFiles.Listener eventListener); void shutdownAutosaveAndWait(); void saveToFileStream(OutputStream f); NetworkParameters getParams(); Context getContext(); static Wallet loadFromFile(File file, @Nullable WalletExtension... walletExtensions); boolean isConsistent(); void isConsistentOrThrow(); static Wallet loadFromFileStream(InputStream stream, @Nullable WalletExtension... walletExtensions); @Override boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
                                              BlockChain.NewBlockType blockType,
                                              int relativityOffset); void receivePending(Transaction tx, @Nullable List<Transaction> dependencies, boolean overrideIsRelevant); void receiveLock(Transaction tx); boolean isTransactionRisky(Transaction tx, @Nullable List<Transaction> dependencies); void receivePending(Transaction tx, @Nullable List<Transaction> dependencies); boolean isPendingTransactionRelevant(Transaction tx); boolean isPendingTransactionLockRelevant(Transaction tx); boolean isTransactionRelevant(Transaction tx); @Override void receiveFromBlock(Transaction tx, StoredBlock block,
                                 BlockChain.NewBlockType blockType,
                                 int relativityOffset); @Override void notifyNewBestBlock(StoredBlock block); boolean maybeCommitTx(Transaction tx); void commitTx(Transaction tx); void addEventListener(WalletEventListener listener); @Deprecated void addEventListener(WalletEventListener listener, Executor executor); void addChangeEventListener(WalletChangeEventListener listener); void addChangeEventListener(Executor executor, WalletChangeEventListener listener); void addCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener); void addCoinsReceivedEventListener(Executor executor, WalletCoinsReceivedEventListener listener); void addCoinsSentEventListener(WalletCoinsSentEventListener listener); void addCoinsSentEventListener(Executor executor, WalletCoinsSentEventListener listener); void addKeyChainEventListener(KeyChainEventListener listener); void addKeyChainEventListener(Executor executor, KeyChainEventListener listener); void addReorganizeEventListener(WalletReorganizeEventListener listener); void addReorganizeEventListener(Executor executor, WalletReorganizeEventListener listener); void addScriptsChangeEventListener(ScriptsChangeEventListener listener); void addScriptChangeEventListener(Executor executor, ScriptsChangeEventListener listener); void addTransactionConfidenceEventListener(TransactionConfidenceEventListener listener); void addTransactionConfidenceEventListener(Executor executor, TransactionConfidenceEventListener listener); @Deprecated boolean removeEventListener(WalletEventListener listener); boolean removeChangeEventListener(WalletChangeEventListener listener); boolean removeCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener); boolean removeCoinsSentEventListener(WalletCoinsSentEventListener listener); boolean removeKeyChainEventListener(KeyChainEventListener listener); boolean removeReorganizeEventListener(WalletReorganizeEventListener listener); boolean removeScriptChangeEventListener(ScriptsChangeEventListener listener); boolean removeTransactionConfidenceEventListener(TransactionConfidenceEventListener listener); Set<Transaction> getTransactions(boolean includeDead); Iterable<WalletTransaction> getWalletTransactions(); void addWalletTransaction(WalletTransaction wtx); List<Transaction> getTransactionsByTime(); List<Transaction> getRecentTransactions(int numTransactions, boolean includeDead); @Nullable Transaction getTransaction(Sha256Hash hash); @Override Map<Sha256Hash, Transaction> getTransactionPool(Pool pool); void reset(); void clearTransactions(int fromHeight); List<TransactionOutput> getWatchedOutputs(boolean excludeImmatureCoinbases); void cleanup(); @VisibleForTesting int getPoolSize(WalletTransaction.Pool pool); @VisibleForTesting boolean poolContainsTxHash(final WalletTransaction.Pool pool, final Sha256Hash txHash); List<TransactionOutput> getUnspents(); @Override String toString(); String toString(boolean includePrivateKeys, boolean includeTransactions, boolean includeExtensions,
                           @Nullable AbstractBlockChain chain); Collection<Transaction> getPendingTransactions(); @Override long getEarliestKeyCreationTime(); @Nullable Sha256Hash getLastBlockSeenHash(); void setLastBlockSeenHash(@Nullable Sha256Hash lastBlockSeenHash); void setLastBlockSeenHeight(int lastBlockSeenHeight); void setLastBlockSeenTimeSecs(long timeSecs); long getLastBlockSeenTimeSecs(); @Nullable Date getLastBlockSeenTime(); int getLastBlockSeenHeight(); int getVersion(); void setVersion(int version); void setDescription(String description); String getDescription(); @Deprecated Coin getWatchedBalance(); @Deprecated Coin getWatchedBalance(CoinSelector selector); Coin getBalance(); Coin getBalance(BalanceType balanceType); Coin getBalance(CoinSelector selector); ListenableFuture<Coin> getBalanceFuture(final Coin value, final BalanceType type); Coin getTotalReceived(); Coin getTotalSent(); Transaction createSend(Address address, Coin value); Transaction sendCoinsOffline(SendRequest request); SendResult sendCoins(TransactionBroadcaster broadcaster, Address to, Coin value); SendResult sendCoins(TransactionBroadcaster broadcaster, SendRequest request); SendResult sendCoins(SendRequest request); Transaction sendCoins(Peer peer, SendRequest request); void completeTx(SendRequest req); void signTransaction(SendRequest req); List<TransactionOutput> calculateAllSpendCandidates(); @Deprecated List<TransactionOutput> calculateAllSpendCandidates(boolean excludeImmatureCoinbases); List<TransactionOutput> calculateAllSpendCandidates(boolean excludeImmatureCoinbases, boolean excludeUnsignable); boolean canSignFor(Script script); CoinSelector getCoinSelector(); void setCoinSelector(CoinSelector coinSelector); void allowSpendingUnconfirmedTransactions(); @Nullable UTXOProvider getUTXOProvider(); void setUTXOProvider(@Nullable UTXOProvider provider); @Override void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks); @Override void beginBloomFilterCalculation(); @Override @GuardedBy("keyChainGroupLock") void endBloomFilterCalculation(); @Override int getBloomFilterElementCount(); @Override boolean isRequiringUpdateAllBloomFilter(); BloomFilter getBloomFilter(double falsePositiveRate); @Override @GuardedBy("keyChainGroupLock") BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak); boolean checkForFilterExhaustion(FilteredBlock block); void addExtension(WalletExtension extension); WalletExtension addOrGetExistingExtension(WalletExtension extension); void addOrUpdateExtension(WalletExtension extension); Map<String, WalletExtension> getExtensions(); void deserializeExtension(WalletExtension extension, byte[] data); @Override void setTag(String tag, ByteString value); FeeCalculation calculateFee(SendRequest req, Coin value, List<TransactionInput> originalInputs,
                                       boolean needAtLeastReferenceFee, List<TransactionOutput> candidates); void setTransactionBroadcaster(@Nullable org.bitcoinj.core.TransactionBroadcaster broadcaster); void setKeyRotationTime(Date time); @Nullable Date getKeyRotationTime(); void setKeyRotationTime(long unixTimeSeconds); boolean isKeyRotating(ECKey key); @Deprecated ListenableFuture<List<Transaction>> maybeDoMaintenance(@Nullable KeyParameter aesKey, boolean andSend); ListenableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend); boolean hasKeyChain(ImmutableList<ChildNumber> path); void addKeyChain(ImmutableList<ChildNumber> path);  }