protected TransactionSummary transform(
      Transaction tx, int time, int height, int blockChainHeight) {
    long value = 0;
    Address destAddress = null;
    for (TransactionOutput output : tx.outputs) {
      if (isMine(output.script)) {
        value += output.value;
      } else {
        destAddress = output.script.getAddress(_network);
      }
    }

    if (tx.isCoinbase()) {
      // For coinbase transactions there is nothing to subtract
    } else {
      for (TransactionInput input : tx.inputs) {
        // find parent output
        TransactionOutputEx funding = _backing.getParentTransactionOutput(input.outPoint);
        if (funding == null) {
          _logger.logError("Unable to find parent output for: " + input.outPoint);
          continue;
        }
        if (isMine(funding)) {
          value -= funding.value;
        }
      }
    }

    int confirmations;
    if (height == -1) {
      confirmations = 0;
    } else {
      confirmations = Math.max(0, blockChainHeight - height + 1);
    }

    // only track a destinationAddress if it is an outgoing transaction (i.e. send money to someone)
    // to prevent the user that he tries to return money to an address he got bitcoin from.
    if (value >= 0) {
      destAddress = null;
    }

    boolean isQueuedOutgoing = _backing.isOutgoingTransaction(tx.getHash());

    return new TransactionSummary(
        tx.getHash(),
        value,
        time,
        height,
        confirmations,
        isQueuedOutgoing,
        com.google.common.base.Optional.fromNullable(destAddress));
  }
  @Override
  public List<TransactionOutputSummary> getUnspentTransactionOutputSummary() {
    // Note that this method is not synchronized, and we might fetch the transaction history while
    // synchronizing
    // accounts. That should be ok as we write to the DB in a sane order.

    // Get all unspent outputs for this account
    Collection<TransactionOutputEx> outputs = _backing.getAllUnspentOutputs();

    // Transform it to a list of summaries
    List<TransactionOutputSummary> list = new ArrayList<TransactionOutputSummary>();
    int blockChainHeight = getBlockChainHeight();
    for (TransactionOutputEx output : outputs) {

      ScriptOutput script = ScriptOutput.fromScriptBytes(output.script);
      Address address;
      if (script == null) {
        address = Address.getNullAddress(_network);
        // This never happens as we have parsed this script before
      } else {
        address = script.getAddress(_network);
      }
      int confirmations;
      if (output.height == -1) {
        confirmations = 0;
      } else {
        confirmations = Math.max(0, blockChainHeight - output.height + 1);
      }

      TransactionOutputSummary summary =
          new TransactionOutputSummary(
              output.outPoint, output.value, output.height, confirmations, address);
      list.add(summary);
    }
    // Sort & return
    Collections.sort(list);
    return list;
  }