/** {@inheritDoc} */
  @Override
  public void txEnd(GridCacheTx tx, boolean commit) throws GridException {
    init();

    Session ses = tx.removeMeta(ATTR_SES);

    if (ses != null) {
      Transaction hTx = ses.getTransaction();

      if (hTx != null) {
        try {
          if (commit) {
            ses.flush();

            hTx.commit();
          } else hTx.rollback();

          if (log.isDebugEnabled())
            log.debug("Transaction ended [xid=" + tx.xid() + ", commit=" + commit + ']');
        } catch (HibernateException e) {
          throw new GridException(
              "Failed to end transaction [xid=" + tx.xid() + ", commit=" + commit + ']', e);
        } finally {
          ses.close();
        }
      }
    }
  }
 /** Returns a {@link Wallet.SendRequest} suitable for broadcasting to the network. */
 public Wallet.SendRequest getSendRequest() {
   Transaction tx = new Transaction(params);
   for (Protos.Output output : paymentDetails.getOutputsList())
     tx.addOutput(
         new TransactionOutput(
             params, tx, Coin.valueOf(output.getAmount()), output.getScript().toByteArray()));
   return Wallet.SendRequest.forTx(tx).fromPaymentDetails(paymentDetails);
 }
  /**
   * Rolls back hibernate session.
   *
   * @param ses Hibernate session.
   * @param tx Cache ongoing transaction.
   */
  private void rollback(SharedSessionContract ses, GridCacheTx tx) {
    // Rollback only if there is no cache transaction,
    // otherwise txEnd() will do all required work.
    if (tx == null) {
      Transaction hTx = ses.getTransaction();

      if (hTx != null && hTx.isActive()) hTx.rollback();
    }
  }
  /**
   * Ends hibernate session.
   *
   * @param ses Hibernate session.
   * @param tx Cache ongoing transaction.
   */
  private void end(Session ses, GridCacheTx tx) {
    // Commit only if there is no cache transaction,
    // otherwise txEnd() will do all required work.
    if (tx == null) {
      Transaction hTx = ses.getTransaction();

      if (hTx != null && hTx.isActive()) hTx.commit();

      ses.close();
    }
  }
 /**
  * Generates a Payment message based on the information in the PaymentRequest. Provide
  * transactions built by the wallet. If the PaymentRequest did not specify a payment_url, returns
  * null.
  *
  * @param txns list of transactions to be included with the Payment message.
  * @param refundAddr will be used by the merchant to send money back if there was a problem.
  * @param memo is a message to include in the payment message sent to the merchant.
  */
 @Nullable
 public Protos.Payment getPayment(
     List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo)
     throws IOException, PaymentProtocolException.InvalidNetwork {
   if (paymentDetails.hasPaymentUrl()) {
     for (Transaction tx : txns)
       if (!tx.getParams().equals(params))
         throw new PaymentProtocolException.InvalidNetwork(params.getPaymentProtocolId());
     return PaymentProtocol.createPaymentMessage(
         txns, totalValue, refundAddr, memo, getMerchantData());
   } else {
     return null;
   }
 }
  /** {@inheritDoc} */
  @Override
  public void onSessionEnd(CacheStoreSession ses, boolean commit) {
    Session hibSes = ses.attach(null);

    if (hibSes != null) {
      try {
        Transaction tx = hibSes.getTransaction();

        if (commit) {
          hibSes.flush();

          if (tx.isActive()) tx.commit();
        } else if (tx.isActive()) tx.rollback();
      } catch (HibernateException e) {
        throw new CacheWriterException(
            "Failed to end store session [tx=" + ses.transaction() + ']', e);
      } finally {
        hibSes.close();
      }
    }
  }
 /**
  * Generates a Payment message based on the information in the PaymentRequest. Provide
  * transactions built by the wallet. If the PaymentRequest did not specify a payment_url, returns
  * null.
  *
  * @param txns list of transactions to be included with the Payment message.
  * @param refundAddr will be used by the merchant to send money back if there was a problem.
  * @param memo is a message to include in the payment message sent to the merchant.
  */
 public @Nullable Protos.Payment getPayment(
     List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo)
     throws IOException {
   if (!paymentDetails.hasPaymentUrl()) return null;
   Protos.Payment.Builder payment = Protos.Payment.newBuilder();
   if (paymentDetails.hasMerchantData()) payment.setMerchantData(paymentDetails.getMerchantData());
   if (refundAddr != null) {
     Protos.Output.Builder refundOutput = Protos.Output.newBuilder();
     refundOutput.setAmount(totalValue.longValue());
     refundOutput.setScript(
         ByteString.copyFrom(ScriptBuilder.createOutputScript(refundAddr).getProgram()));
     payment.addRefundTo(refundOutput);
   }
   if (memo != null) {
     payment.setMemo(memo);
   }
   for (Transaction txn : txns) {
     txn.verify();
     ByteArrayOutputStream o = new ByteArrayOutputStream();
     txn.bitcoinSerialize(o);
     payment.addTransactions(ByteString.copyFrom(o.toByteArray()));
   }
   return payment.build();
 }