private static void send(PaymentSession session) { try { System.out.println("Payment Request"); System.out.println("Amount: " + session.getValue().doubleValue() / 100000 + "mDOGE"); System.out.println("Date: " + session.getDate()); System.out.println("Memo: " + session.getMemo()); if (session.pkiVerificationData != null) { System.out.println("Pki-Verified Name: " + session.pkiVerificationData.name); if (session.pkiVerificationData.orgName != null) System.out.println("Pki-Verified Org: " + session.pkiVerificationData.orgName); System.out.println( "PKI data verified by: " + session.pkiVerificationData.rootAuthorityName); } final Wallet.SendRequest req = session.getSendRequest(); if (password != null) { if (!wallet.checkPassword(password)) { System.err.println("Password is incorrect."); return; } req.aesKey = wallet.getKeyCrypter().deriveKey(password); } wallet.completeTx(req); // may throw InsufficientMoneyException. if (options.has("offline")) { wallet.commitTx(req.tx); return; } setup(); // No refund address specified, no user-specified memo field. ListenableFuture<PaymentSession.Ack> future = session.sendPayment(ImmutableList.of(req.tx), null, null); if (future == null) { // No payment_url for submission so, broadcast and wait. peers.startAndWait(); peers.broadcastTransaction(req.tx).get(); } else { PaymentSession.Ack ack = future.get(); wallet.commitTx(req.tx); System.out.println("Memo from server: " + ack.getMemo()); } } catch (PaymentRequestException e) { System.err.println("Failed to send payment " + e.getMessage()); System.exit(1); } catch (VerificationException e) { System.err.println("Failed to send payment " + e.getMessage()); System.exit(1); } catch (ExecutionException e) { System.err.println("Failed to send payment " + e.getMessage()); System.exit(1); } catch (IOException e) { System.err.println("Invalid payment " + e.getMessage()); System.exit(1); } catch (InterruptedException e1) { // Ignore. } catch (InsufficientMoneyException e) { System.err.println( "Insufficient funds: have " + Utils.bitcoinValueToFriendlyString(wallet.getBalance())); } catch (BlockStoreException e) { throw new RuntimeException(e); } }
private static void wait(WaitForEnum waitFor) throws BlockStoreException { final CountDownLatch latch = new CountDownLatch(1); setup(); switch (waitFor) { case EVER: break; case WALLET_TX: wallet.addEventListener( new AbstractWalletEventListener() { private void handleTx(Transaction tx) { System.out.println(tx.getHashAsString()); latch.countDown(); // Wake up main thread. } @Override public void onCoinsReceived( Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { // Runs in a peer thread. super.onCoinsReceived(wallet, tx, prevBalance, newBalance); handleTx(tx); } @Override public void onCoinsSent( Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { // Runs in a peer thread. super.onCoinsSent(wallet, tx, prevBalance, newBalance); handleTx(tx); } }); break; case BLOCK: peers.addEventListener( new AbstractPeerEventListener() { @Override public void onBlocksDownloaded(Peer peer, Block block, int blocksLeft) { super.onBlocksDownloaded(peer, block, blocksLeft); // Check if we already ran. This can happen if a block being received triggers // download of more // blocks, or if we receive another block whilst the peer group is shutting down. if (latch.getCount() == 0) return; System.out.println(block.getHashAsString()); latch.countDown(); } }); break; case BALANCE: // Check if the balance already meets the given condition. if (condition.matchBitcoins(wallet.getBalance(Wallet.BalanceType.ESTIMATED))) { latch.countDown(); break; } wallet.addEventListener( new AbstractWalletEventListener() { @Override public synchronized void onChange() { super.onChange(); saveWallet(walletFile); BigInteger balance = wallet.getBalance(Wallet.BalanceType.ESTIMATED); if (condition.matchBitcoins(balance)) { System.out.println(Utils.bitcoinValueToFriendlyString(balance)); latch.countDown(); } } }); break; } peers.start(); try { latch.await(); } catch (InterruptedException e) { // Ignore. } }
private static void send( List<String> outputs, BigInteger fee, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { try { // Convert the input strings to outputs. Transaction t = new Transaction(params); for (String spec : outputs) { String[] parts = spec.split(":"); if (parts.length != 2) { System.err.println("Malformed output specification, must have two parts separated by :"); return; } String destination = parts[0]; try { BigInteger value = Utils.toNanoCoins(parts[1]); if (destination.startsWith("0")) { boolean compressed = destination.startsWith("02") || destination.startsWith("03"); // Treat as a raw public key. BigInteger pubKey = new BigInteger(destination, 16); ECKey key = new ECKey(null, pubKey.toByteArray(), compressed); t.addOutput(value, key); } else { // Treat as an address. Address addr = new Address(params, destination); t.addOutput(value, addr); } } catch (WrongNetworkException e) { System.err.println( "Malformed output specification, address is for a different network: " + parts[0]); return; } catch (AddressFormatException e) { System.err.println( "Malformed output specification, could not parse as address: " + parts[0]); return; } catch (NumberFormatException e) { System.err.println( "Malformed output specification, could not parse as value: " + parts[1]); } } Wallet.SendRequest req = Wallet.SendRequest.forTx(t); if (t.getOutputs().size() == 1 && t.getOutput(0).getValue().equals(wallet.getBalance())) { log.info("Emptying out wallet, recipient may get less than what you expect"); req.emptyWallet = true; } req.fee = fee; if (allowUnconfirmed) { wallet.allowSpendingUnconfirmedTransactions(); } if (password != null) { if (!wallet.checkPassword(password)) { System.err.println("Password is incorrect."); return; } req.aesKey = wallet.getKeyCrypter().deriveKey(password); } wallet.completeTx(req); try { if (lockTimeStr != null) { t.setLockTime(Transaction.parseLockTimeStr(lockTimeStr)); // For lock times to take effect, at least one output must have a non-final sequence // number. t.getInputs().get(0).setSequenceNumber(0); // And because we modified the transaction after it was completed, we must re-sign the // inputs. t.signInputs(Transaction.SigHash.ALL, wallet); } } catch (ParseException e) { System.err.println("Could not understand --locktime of " + lockTimeStr); return; } catch (ScriptException e) { throw new RuntimeException(e); } t = req.tx; // Not strictly required today. System.out.println(t.getHashAsString()); if (options.has("offline")) { wallet.commitTx(t); return; } setup(); peers.startAndWait(); // Wait for peers to connect, the tx to be sent to one of them and for it to be propagated // across the // network. Once propagation is complete and we heard the transaction back from all our peers, // it will // be committed to the wallet. peers.broadcastTransaction(t).get(); // Hack for regtest/single peer mode, as we're about to shut down and won't get an ACK from // the remote end. List<Peer> peerList = peers.getConnectedPeers(); if (peerList.size() == 1) peerList.get(0).ping().get(); } catch (BlockStoreException e) { throw new RuntimeException(e); } catch (KeyCrypterException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } catch (InsufficientMoneyException e) { System.err.println( "Insufficient funds: have " + Utils.bitcoinValueToFriendlyString(wallet.getBalance())); } }