class DexTransferMoneyTransaction extends DEX {

    @Override
    public void validateAttachment(Transaction transaction) throws AplException.ValidationException {
        // IMPORTANT! Validation should restrict sending this transaction without money freezing and out of the dex scope
        DexControlOfFrozenMoneyAttachment attachment = (DexControlOfFrozenMoneyAttachment) transaction.getAttachment();
        DexService dexService = lookupDexService();
        ExchangeContract dexContract = dexService.getDexContractById(attachment.getContractId());

        if (dexContract == null) {
            throw new AplException.NotCurrentlyValidException("Contract does not exist: id - " + attachment.getContractId());
        }
        if (dexContract.getRecipient() != transaction.getSenderId() && dexContract.getSender() != transaction.getSenderId()) {
            throw new AplException.NotCurrentlyValidException("Account" + transaction.getSenderId() + " is not a party of the contract. Expected - " + dexContract.getRecipient() + " or  " + dexContract.getSender());
        }
        boolean isSender = dexContract.getSender() == transaction.getSenderId();
        long recipient = isSender ? dexContract.getRecipient() : dexContract.getSender();
        if (recipient != transaction.getRecipientId()) {
            throw new AplException.NotCurrentlyValidException("Tx recipient differs from account, specified in the contract");
        }
        long transactionId = Convert.parseUnsignedLong(isSender ? dexContract.getTransferTxId() : dexContract.getCounterTransferTxId());
        if (transactionId == 0) {
            throw new AplException.NotCurrentlyValidException("Contract transaction was not pre confirmed or missing");
        }
        if (transaction.getId() != transactionId) {
            throw new AplException.NotCurrentlyValidException("Transaction was not registered in the contract. ");
        }
        long recipientOrderId = isSender ? dexContract.getCounterOrderId() : dexContract.getOrderId();
        DexOrder recipientOrder = dexService.getOrder(recipientOrderId);
        if (recipientOrder == null) {
            throw new AplException.NotCurrentlyValidException("Contract: " + dexContract.getId() + " refer to non-existent order: " + recipientOrderId);
        }
        if (recipientOrder.getAccountId() != transaction.getRecipientId()) {
            throw new AplException.NotCurrentlyValidException("Order" + recipientOrderId + " should belong to the account: " + transaction.getRecipientId());
        }
        if (recipientOrder.getStatus() != OrderStatus.WAITING_APPROVAL) {
            throw new AplException.NotCurrentlyValidException("Inconsistent order state for id: " + recipientOrder + ", expected - " + OrderStatus.WAITING_APPROVAL + ", got " + recipientOrder.getStatus());
        }
        if (recipientOrder.getType() != OrderType.BUY) {
            throw new AplException.NotCurrentlyValidException("Required BUY type for order " + recipientOrderId);
        }
    }

}