class OrderMatchServiceImpl implements OrderMatchService {

    void matchOrders(long assetId) {
        AskOrder askOrder;
        BidOrder bidOrder;
        log.trace(">> match orders, assetId={}, stack={}", assetId, StackTraceUtils.lastNStacktrace(5));
        int index = 0;
        while ((askOrder = orderAskService.getNextOrder(assetId)) != null
            && (bidOrder = orderBidService.getNextOrder(assetId)) != null) {

            log.trace(">> match orders LOOP, assetId={}, index={}, askOrder={}, bidOrder={}",
                assetId, index, askOrder, bidOrder);
            if (askOrder.getPriceATM() > bidOrder.getPriceATM()) {
                log.trace(">> match orders, STOP LOOP, assetId={}", assetId);
                break;
            }

            Trade trade = tradeService.addTrade(assetId, askOrder, bidOrder);
            log.trace("match orders TRADE, assetId={}, trade={}", assetId, trade);

            orderAskService.updateQuantityATU(Math.subtractExact(askOrder.getQuantityATU(), trade.getQuantityATU()), askOrder);
            Account askAccount = accountService.getAccount(askOrder.getAccountId());
            accountService.addToBalanceAndUnconfirmedBalanceATM(askAccount, LedgerEvent.ASSET_TRADE, askOrder.getId(),
                Math.multiplyExact(trade.getQuantityATU(), trade.getPriceATM()));
            accountAssetService.addToAssetBalanceATU(askAccount, LedgerEvent.ASSET_TRADE, askOrder.getId(), assetId, -trade.getQuantityATU());

            orderBidService.updateQuantityATU(Math.subtractExact(bidOrder.getQuantityATU(), trade.getQuantityATU()), bidOrder);
            Account bidAccount = accountService.getAccount(bidOrder.getAccountId());
            accountAssetService.addToAssetAndUnconfirmedAssetBalanceATU(bidAccount, LedgerEvent.ASSET_TRADE, bidOrder.getId(),
                assetId, trade.getQuantityATU());
            accountService.addToBalanceATM(bidAccount, LedgerEvent.ASSET_TRADE, bidOrder.getId(),
                -Math.multiplyExact(trade.getQuantityATU(), trade.getPriceATM()));
            accountService.addToUnconfirmedBalanceATM(bidAccount, LedgerEvent.ASSET_TRADE, bidOrder.getId(),
                Math.multiplyExact(trade.getQuantityATU(), (bidOrder.getPriceATM() - trade.getPriceATM())));
            log.trace("<< match orders, END LOOP, assetId={}, index={}", assetId, index);
            index++;
        }
        log.trace("<< DONE match orders, assetId={}", assetId);
    }

    @Inject public  OrderMatchServiceImpl(
        final AccountService accountService,
        final AccountAssetService accountAssetService,
        @AskOrderService final OrderService<AskOrder, ColoredCoinsAskOrderPlacement> orderAskService,
        @BidOrderService final OrderService<BidOrder, ColoredCoinsBidOrderPlacement> orderBidService,
        final TradeService tradeService
    );

}