private void parsePaymentRequest(Protos.PaymentRequest request) throws PaymentProtocolException { try { if (request == null) throw new PaymentProtocolException("request cannot be null"); if (request.getPaymentDetailsVersion() != 1) throw new PaymentProtocolException.InvalidVersion( "Version 1 required. Received version " + request.getPaymentDetailsVersion()); paymentRequest = request; if (!request.hasSerializedPaymentDetails()) throw new PaymentProtocolException("No PaymentDetails"); paymentDetails = Protos.PaymentDetails.newBuilder() .mergeFrom(request.getSerializedPaymentDetails()) .build(); if (paymentDetails == null) throw new PaymentProtocolException("Invalid PaymentDetails"); if (!paymentDetails.hasNetwork()) params = MainNetParams.get(); else params = NetworkParameters.fromPmtProtocolID(paymentDetails.getNetwork()); if (params == null) throw new PaymentProtocolException.InvalidNetwork( "Invalid network " + paymentDetails.getNetwork()); if (paymentDetails.getOutputsCount() < 1) throw new PaymentProtocolException.InvalidOutputs("No outputs"); for (Protos.Output output : paymentDetails.getOutputsList()) { if (output.hasAmount()) totalValue = totalValue.add(Coin.valueOf(output.getAmount())); } // This won't ever happen in practice. It would only happen if the user provided outputs // that are obviously invalid. Still, we don't want to silently overflow. if (params.hasMaxMoney() && totalValue.compareTo(params.getMaxMoney()) > 0) throw new PaymentProtocolException.InvalidOutputs("The outputs are way too big."); } catch (InvalidProtocolBufferException e) { throw new PaymentProtocolException(e); } }
@Test public void testGetOpenTransactionOutputs() throws Exception { final int UNDOABLE_BLOCKS_STORED = 10; store = createStore(params, UNDOABLE_BLOCKS_STORED); chain = new FullPrunedBlockChain(params, store); // Check that we aren't accidentally leaving any references // to the full StoredUndoableBlock's lying around (ie memory leaks) ECKey outKey = new ECKey(); int height = 1; // Build some blocks on genesis block to create a spendable output Block rollingBlock = params .getGenesisBlock() .createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++); chain.add(rollingBlock); Transaction transaction = rollingBlock.getTransactions().get(0); TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash()); byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes(); for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) { rollingBlock = rollingBlock.createNextBlockWithCoinbase( Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++); chain.add(rollingBlock); } rollingBlock = rollingBlock.createNextBlock(null); // Create bitcoin spend of 1 BTC. ECKey toKey = new ECKey(); Coin amount = Coin.valueOf(100000000); Address address = new Address(params, toKey.getPubKeyHash()); Coin totalAmount = Coin.ZERO; Transaction t = new Transaction(params); t.addOutput(new TransactionOutput(params, t, amount, toKey)); t.addSignedInput(spendableOutput, new Script(spendableOutputScriptPubKey), outKey); rollingBlock.addTransaction(t); rollingBlock.solve(); chain.add(rollingBlock); totalAmount = totalAmount.add(amount); List<UTXO> outputs = store.getOpenTransactionOutputs(Lists.newArrayList(address)); assertNotNull(outputs); assertEquals("Wrong Number of Outputs", 1, outputs.size()); UTXO output = outputs.get(0); assertEquals("The address is not equal", address.toString(), output.getAddress()); assertEquals("The amount is not equal", totalAmount, output.getValue()); outputs = null; output = null; try { store.close(); } catch (Exception e) { } }
/** * Returns the outstanding amount of money sent back to us for all channels to this server added * together. */ public Coin getBalanceForServer(Sha256Hash id) { Coin balance = Coin.ZERO; lock.lock(); try { Set<StoredClientChannel> setChannels = mapChannels.get(id); for (StoredClientChannel channel : setChannels) { synchronized (channel) { if (channel.close != null) continue; balance = balance.add(channel.valueToMe); } } return balance; } finally { lock.unlock(); } }
@Override protected void run() { try { runInterceptHook(); checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null"); Coin sellerPayoutAmount = FeePolicy.SECURITY_DEPOSIT; Coin buyerPayoutAmount = sellerPayoutAmount.add(trade.getTradeAmount()); // We use the sellers LastBlockSeenHeight, which might be different to the buyers one. // If lock time is 0 we set lockTimeAsBlockHeight to 0 to mark it as "not set". // In the tradewallet we apply the locktime only if it is set, otherwise we use the default // values for // transaction locktime and sequence number long lockTime = trade.getOffer().getPaymentMethod().getLockTime(); long lockTimeAsBlockHeight = 0; if (lockTime > 0) lockTimeAsBlockHeight = processModel.getTradeWalletService().getLastBlockSeenHeight() + lockTime; trade.setLockTimeAsBlockHeight(lockTimeAsBlockHeight); byte[] payoutTxSignature = processModel .getTradeWalletService() .sellerSignsPayoutTx( trade.getDepositTx(), buyerPayoutAmount, sellerPayoutAmount, processModel.tradingPeer.getPayoutAddressString(), processModel.getAddressEntry(), lockTimeAsBlockHeight, processModel.tradingPeer.getTradeWalletPubKey(), processModel.getTradeWalletPubKey(), processModel.getArbitratorPubKey(trade.getArbitratorAddress())); processModel.setPayoutTxSignature(payoutTxSignature); complete(); } catch (Throwable t) { failed(t); } }
@Test public void testUTXOProviderWithWallet() throws Exception { final int UNDOABLE_BLOCKS_STORED = 10; store = createStore(params, UNDOABLE_BLOCKS_STORED); chain = new FullPrunedBlockChain(params, store); // Check that we aren't accidentally leaving any references // to the full StoredUndoableBlock's lying around (ie memory leaks) ECKey outKey = new ECKey(); int height = 1; // Build some blocks on genesis block to create a spendable output. Block rollingBlock = params .getGenesisBlock() .createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++); chain.add(rollingBlock); Transaction transaction = rollingBlock.getTransactions().get(0); TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash()); byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes(); for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) { rollingBlock = rollingBlock.createNextBlockWithCoinbase( Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++); chain.add(rollingBlock); } rollingBlock = rollingBlock.createNextBlock(null); // Create 1 BTC spend to a key in this wallet (to ourselves). Wallet wallet = new Wallet(params); assertEquals( "Available balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE)); assertEquals( "Estimated balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); wallet.setUTXOProvider(store); ECKey toKey = wallet.freshReceiveKey(); Coin amount = Coin.valueOf(100000000); Transaction t = new Transaction(params); t.addOutput(new TransactionOutput(params, t, amount, toKey)); t.addSignedInput(spendableOutput, new Script(spendableOutputScriptPubKey), outKey); rollingBlock.addTransaction(t); rollingBlock.solve(); chain.add(rollingBlock); // Create another spend of 1/2 the value of BTC we have available using the wallet (store coin // selector). ECKey toKey2 = new ECKey(); Coin amount2 = amount.divide(2); Address address2 = new Address(params, toKey2.getPubKeyHash()); Wallet.SendRequest req = Wallet.SendRequest.to(address2, amount2); wallet.completeTx(req); wallet.commitTx(req.tx); Coin fee = req.fee; // There should be one pending tx (our spend). assertEquals( "Wrong number of PENDING.4", 1, wallet.getPoolSize(WalletTransaction.Pool.PENDING)); Coin totalPendingTxAmount = Coin.ZERO; for (Transaction tx : wallet.getPendingTransactions()) { totalPendingTxAmount = totalPendingTxAmount.add(tx.getValueSentToMe(wallet)); } // The availbale balance should be the 0 (as we spent the 1 BTC that's pending) and estimated // should be 1/2 - fee BTC assertEquals( "Available balance is incorrect", Coin.ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE)); assertEquals( "Estimated balance is incorrect", amount2.subtract(fee), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals("Pending tx amount is incorrect", amount2.subtract(fee), totalPendingTxAmount); try { store.close(); } catch (Exception e) { } }
/** * function that updates debit/credit/balance/price in fiat and Transaction History table * * @param services */ private void updateWalletsSummary(List<WalletService> services) { Coin totalDebit = Coin.ZERO; Coin totalCredit = Coin.ZERO; Coin totalBalance = Coin.ZERO; double priceInFiat = 0.00d; String confidence = ""; // update debit/credit/balance and price in fiat List<TransactionWrapper> transactions = new ArrayList<>(); for (WalletService service : services) { try { Wallet wallet = service.getWallet(); totalBalance = totalBalance.add(wallet.getBalance()); for (Transaction trx : wallet.getTransactionsByTime()) { if (trx.getConfidence().equals(TransactionConfidence.ConfidenceType.DEAD)) continue; Coin amount = trx.getValue(wallet); if (amount.isPositive()) { totalCredit = totalCredit.add(amount); } else { totalDebit = totalDebit.add(amount); } transactions.add(new TransactionWrapper(trx, wallet, amount)); } } catch (Exception e) { logger.error("Unable to update wallet details"); } } pnlDashboardStats.setTotalBalance(MonetaryFormat.BTC.noCode().format(totalBalance).toString()); // pnlDashboardStats.setTotalDebit(MonetaryFormat.BTC.noCode().format(totalDebit).toString()); // pnlDashboardStats.setTotalCredit(MonetaryFormat.BTC.noCode().format(totalCredit).toString()); priceInFiat = Double.valueOf(MonetaryFormat.BTC.noCode().format(totalBalance).toString()); priceInFiat *= BitcoinCurrencyRateApi.get().getCurrentRateValue(); pnlDashboardStats.setPriceInFiat( String.format("%.2f", priceInFiat), "", ConfigManager.config().getSelectedCurrency()); pnlDashboardStats.setExchangeRate( ConfigManager.config().getSelectedCurrency(), String.format("%.2f", BitcoinCurrencyRateApi.get().getCurrentRateValue())); Collections.sort( transactions, new Comparator<TransactionWrapper>() { @Override public int compare(TransactionWrapper o1, TransactionWrapper o2) { return o2.getTransaction() .getUpdateTime() .compareTo(o1.getTransaction().getUpdateTime()); } }); // update Transaction History table DefaultTableModel model = (DefaultTableModel) tblTransactions.getModel(); model.setRowCount(0); for (TransactionWrapper wrapper : transactions) { Transaction transaction = wrapper.getTransaction(); if (transaction.getConfidence().getDepthInBlocks() > 6) confidence = "<html>6<sup>+</sup></html>"; else confidence = transaction.getConfidence().getDepthInBlocks() + ""; Coin amount = wrapper.getAmount(); Coin fee = transaction.getFee(); String amountString = MonetaryFormat.BTC.noCode().format(amount).toString(); String feeString = fee != null ? MonetaryFormat.BTC.noCode().format(fee).toString() : "0.00"; Address from = transaction.getInput(0).getFromAddress(); Address to = transaction .getOutput(0) .getAddressFromP2PKHScript(wrapper.getWallet().getNetworkParameters()); boolean credit = amount.isPositive(); model.addRow( new Object[] { Utils.formatTransactionDate(transaction.getUpdateTime()), from, to, credit ? "Credit" : "Debit", amountString, feeString, "", confidence }); } Coin balanceAfter = Coin.ZERO; for (int index = transactions.size() - 1; index >= 0; index--) { balanceAfter = balanceAfter.add(Coin.parseCoin((String) model.getValueAt(index, 4))); model.setValueAt(MonetaryFormat.BTC.noCode().format(balanceAfter).toString(), index, 6); } }