コード例 #1
0
   signed_transaction    wallet::transfer( const asset& amnt, const bts::address& to )
   { try {
       auto   change_address = get_new_address();

       std::unordered_set<bts::address> req_sigs; 
       asset  total_in;

       signed_transaction trx; 
       trx.inputs    = my->collect_inputs( amnt, total_in, req_sigs );

       asset change = total_in - amnt;

       trx.outputs.push_back( trx_output( claim_by_signature_output( to ), amnt) );
       trx.outputs.push_back( trx_output( claim_by_signature_output( change_address ), change) );

       trx.sigs.clear();
       my->sign_transaction( trx, req_sigs );

       uint32_t trx_bytes = fc::raw::pack( trx ).size();
       asset    fee( my->_current_fee_rate * trx_bytes );

       if( amnt.unit == asset::bts )
       {
          if( total_in >= amnt + fee )
          {
              change = change - fee;
              trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change );
              if( change == asset() ) trx.outputs.pop_back(); // no change required
          }
          else
          {
              elog( "NOT ENOUGH TO COVER AMOUNT + FEE... GRAB MORE.." );
              // TODO: this function should be recursive here, but having 2x the fee should be good enough
              fee = fee + fee; // double the fee in this case to cover the growth
              req_sigs.clear();
              total_in = asset();
              trx.inputs = my->collect_inputs( amnt+fee, total_in, req_sigs );
              change =  total_in - amnt - fee;
              trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change );
              if( change == asset() ) trx.outputs.pop_back(); // no change required
          }
       }
       else /// fee is in bts, but we are transferring something else
       {
           if( change.amount == fc::uint128_t(0) ) trx.outputs.pop_back(); // no change required

           // TODO: this function should be recursive here, but having 2x the fee should be good enough, some
           // transactions may overpay in this case, but this can be optimized later to reduce fees.. for now
           fee = fee + fee; // double the fee in this case to cover the growth
           asset total_fee_in;
           auto extra_in = my->collect_inputs( fee, total_fee_in, req_sigs );
           trx.inputs.insert( trx.inputs.end(), extra_in.begin(), extra_in.end() );
           trx.outputs.push_back( trx_output( claim_by_signature_output( change_address ), total_fee_in - fee ) );
       }

       trx.sigs.clear();
       my->sign_transaction(trx, req_sigs);
       
       return trx;
   } FC_RETHROW_EXCEPTIONS( warn, "${amnt} to ${to}", ("amnt",amnt)("to",to) ) }
コード例 #2
0
   signed_transaction    wallet::short_sell( const asset& borrow_amnt, const price& ratio )
   { try {
       auto   amnt = borrow_amnt * ratio;
       FC_ASSERT( borrow_amnt.unit != asset::bts, "You cannot short sell BTS" );
       auto   change_address = get_new_address();

       auto bts_in = amnt;

       signed_transaction trx; 
       std::unordered_set<bts::address> req_sigs; 
       asset  total_in;

       asset in_with_fee = bts_in; // TODO: add fee proportional to trx size...

       trx.inputs    = my->collect_inputs( in_with_fee, total_in, req_sigs );
       asset change  = total_in - bts_in;

       trx.outputs.push_back( trx_output( claim_by_long_output( change_address, ratio ), amnt) );
       trx.outputs.push_back( trx_output( claim_by_signature_output( change_address ), change) );

       trx.sigs.clear();
       my->sign_transaction( trx, req_sigs );

       uint32_t trx_bytes = fc::raw::pack( trx ).size();
       asset    fee( my->_current_fee_rate * trx_bytes );

       if( total_in >= amnt + fee )
       {
           change = change - fee;
           trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change );
           if( change == asset() ) trx.outputs.pop_back(); // no change required
       }
       else
       {
           elog( "NOT ENOUGH TO COVER AMOUNT + FEE... GRAB MORE.." );
           // TODO: this function should be recursive here, but having 2x the fee should be good enough
           fee = fee + fee; // double the fee in this case to cover the growth
           req_sigs.clear();
           total_in = asset();
           trx.inputs = my->collect_inputs( amnt+fee, total_in, req_sigs );
           change =  total_in - amnt - fee;
           trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change );
           if( change == asset() ) trx.outputs.pop_back(); // no change required
       }

       trx.sigs.clear();
       my->sign_transaction(trx, req_sigs);


       my->_data.open_short_sells[ output_reference( trx.id(), 0 ) ] = trx.outputs[0];

       return trx;
   } FC_RETHROW_EXCEPTIONS( warn, "${amnt} @ ${price}", ("amnt",borrow_amnt)("price",ratio) ) }
コード例 #3
0
   signed_transaction    wallet::cancel_bid( const output_reference& bid )
   { try {
       signed_transaction trx; 
       std::unordered_set<bts::address> req_sigs; 
       auto bid_out_itr = my->_data.open_bids.find(bid);
       FC_ASSERT( bid_out_itr != my->_data.open_bids.end() );

       auto bid_out = bid_out_itr->second.as<claim_by_bid_output>();

       // TODO: collect fee for this transaction
       
       trx.inputs.push_back( trx_input( bid ) );
       trx.outputs.push_back( trx_output( claim_by_signature_output( bid_out.pay_address ), 
                                          bid_out_itr->second.amount, bid_out_itr->second.unit ) );

       req_sigs.insert( bid_out.pay_address);
       my->sign_transaction( trx, req_sigs );

       return trx;
   } FC_RETHROW_EXCEPTIONS( warn, "unable to find bid", ("bid",bid) ) }
コード例 #4
0
ファイル: blockchain_db.cpp プロジェクト: wackou/BitShares
            /**
             *  Pushes a new transaction into matched that pairs all bids/asks for a single quote/base pair
             */
            void match_orders( std::vector<signed_transaction>& matched,  asset::type quote, asset::type base )
            { try {
               ilog( "match orders.." );
               auto asks = _market_db.get_asks( quote, base );
               auto bids = _market_db.get_bids( quote, base );
               wlog( "asks: ${asks}", ("asks",asks) );
               wlog( "bids: ${bids}", ("bids",bids) );

               fc::optional<trx_output>             ask_change;    // stores a claim_by_bid or claim_by_long
               fc::optional<trx_output>             bid_change;    // stores a claim_by_bid

               address                              bid_payout_address; // current bid owner
               address                              ask_payout_address;

               signed_transaction market_trx;
               market_trx.timestamp = fc::time_point::now();

               const uint64_t zero = 0ull;
               asset pay_asker( zero, quote );
               asset pay_bidder( zero, base );
               asset loan_amount( zero, quote );
               asset collateral_amount(zero,base);
               asset bidder_change(zero,quote); // except for longs?
               asset asker_change(zero,base);


               /** asks are sorted from low to high, so we start
                * with the lowest ask, and check to see if there are
                * any bids that are greaterthan or equal to the ask, if
                * there are then either the full bid or full ask will be
                * filled.  If the full bid is filled, then move on to the
                * next bid, and save the leftover ask.  If the left over
                * ask is filled, then move to the next ask.
                *
                * When there are no more pairs that can be matched, exit
                * the loop and any partial payouts are made.  
                */
               auto ask_itr = asks.begin();
               auto bid_itr = bids.rbegin();
               trx_output working_ask;
               trx_output working_bid;

               if( ask_itr != asks.end() ) working_ask = get_output( ask_itr->location );
               if( bid_itr != bids.rend() ) working_bid = get_output( bid_itr->location );

               bool has_change = false;

               while( ask_itr != asks.end() && 
                      bid_itr != bids.rend()    )
               { 
                 // asset      working_ask_tmp_amount; // store fractional working ask amounts here..
                  
                  /*
                  if( ask_change ) {  working_ask = *ask_change;                         }
                  else             {  working_ask = get_output( ask_itr->location );  
                                      working_ask_tmp_amount = working_ask.get_amount();  }

                  if( bid_change ) {  working_bid = *bid_change;                      }
                  else             {  working_bid = get_output( bid_itr->location );  }
                  */

                  claim_by_bid_output ask_claim = working_ask.as<claim_by_bid_output>();

                  wlog( "working bid: ${b}", ("b", working_bid ) );
                  wlog( "working ask: ${a}", ("a", working_ask ) );

                  ask_payout_address = ask_claim.pay_address;

                  if( working_bid.claim_func == claim_by_long )
                  {
                     auto long_claim = working_bid.as<claim_by_long_output>();
                     if( long_claim.ask_price < ask_claim.ask_price )
                     {
                        ilog( "\n\n                                  BID ${BID}  >>>>   ASK ${ASK}\n\n", ("BID",long_claim.ask_price)("ASK",ask_claim.ask_price) );
                        break; // exit the while loop, no more trades can occur
                     }
                     has_change = true;
                     bid_payout_address = long_claim.pay_address;

                     // for the purposes of shorts and longs, one asset type is BTS and the other
                     // is one of the BitAssets which I will just call 'usd' for clairty.
                     // The bids are an offer to take a short position which means they have an input
                     // of BTS but are really offering USD to buy BTS... they BTS purchased with this
                     // "new" USD is then placed into the collateral.

                     asset bid_amount_bts = working_bid.get_amount(); // * long_claim.ask_price;
                     asset bid_amount_usd = bid_amount_bts * long_claim.ask_price;

                     asset ask_amount_bts = working_ask.get_amount(); // * long_claim.ask_price;
                     asset ask_amount_usd = ask_amount_bts * ask_claim.ask_price;

                     ilog( "ask_usd ${ask_usd}   bid_usd ${bid_usd}", ("ask_usd",ask_amount_usd)("bid_usd",bid_amount_usd) );
                     ilog( "ask_bts ${ask_bts}   bid_bts ${bid_bts}", ("ask_bts",ask_amount_bts)("bid_bts",bid_amount_bts) );


                     if( ask_amount_usd < bid_amount_usd )
                     { // then we have filled the ask
                         pay_asker         += ask_amount_usd;
                         loan_amount       += ask_amount_usd;
                         collateral_amount += ask_amount_bts +  ask_amount_usd * long_claim.ask_price;
                         ilog( "bid amount bts ${bid_bts}  - ${pay_asker} * ${price} = ${result}",
                               ("bid_bts",bid_amount_bts)("pay_asker",pay_asker)("price",long_claim.ask_price)("result",pay_asker*long_claim.ask_price) );
                         bidder_change     = bid_amount_bts - (ask_amount_usd * long_claim.ask_price);

                        // ask_change.reset();
                         working_ask.amount = 0;
                         // TODO: trunctate here??? 
                         working_bid.amount = bidder_change.get_rounded_amount();
                        // bid_change       = working_bid;

                         market_trx.inputs.push_back( ask_itr->location );
                         if( pay_asker.amount > static_cast<uint64_t>(0ull) )
                            market_trx.outputs.push_back( trx_output( claim_by_signature_output( ask_claim.pay_address ), pay_asker) );
                         pay_asker = asset(static_cast<uint64_t>(0ull),pay_asker.unit);
                         ++ask_itr;
                         if( ask_itr != asks.end() )  working_ask = get_output( ask_itr->location );
                     }
                     else // we have filled the bid (short sell) 
                     {
                         pay_asker         += bid_amount_usd;
                         loan_amount       += bid_amount_usd;
                         collateral_amount += bid_amount_bts + (bid_amount_usd * ask_claim.ask_price);
                         ilog( "ask_amount_bts ${bid_bts}  - ${loan_amount} * ${price} = ${result}",
                               ("bid_bts",ask_amount_bts)("loan_amount",loan_amount)("price",ask_claim.ask_price)("result",loan_amount*ask_claim.ask_price) );
                         asker_change       = ask_amount_bts - (bid_amount_usd* ask_claim.ask_price);

                         working_bid.amount = 0;
                         working_ask.amount     = asker_change.get_rounded_amount();
                        // working_ask_tmp_amount = asker_change;
                         ask_change             = working_ask;

                         market_trx.inputs.push_back( bid_itr->location );
                         market_trx.outputs.push_back( 
                                 trx_output( claim_by_cover_output( loan_amount, long_claim.pay_address ), collateral_amount) );

                         loan_amount       = asset(static_cast<uint64_t>(0ull),loan_amount.unit);
                         collateral_amount = asset();
                         ++bid_itr;
                         if( bid_itr != bids.rend() ) working_bid = get_output( bid_itr->location );

                         if( working_ask.amount < 10 )
                         {
                            market_trx.inputs.push_back( ask_itr->location );
                            ilog( "ASK CLAIM ADDR ${A} amnt ${a}", ("A",ask_claim.pay_address)("a",pay_asker) );
                            if( pay_asker != asset(static_cast<uint64_t>(0ull),pay_asker.unit) )
                            {
                                market_trx.outputs.push_back( trx_output( claim_by_signature_output( ask_claim.pay_address ), pay_asker) );
                            }
                            pay_asker = asset(pay_asker.unit);
                            ++ask_itr;
                            if( ask_itr != asks.end() )  working_ask = get_output( ask_itr->location );
                         }
                     }
                  }
                  else if( working_bid.claim_func == claim_by_bid )
                  {
                     claim_by_bid_output bid_claim = working_bid.as<claim_by_bid_output>();
                     if( bid_claim.ask_price  < ask_claim.ask_price )
                     {
                        break; // exit the while loop, no more trades can occur
                     }
                     has_change = true;
                     bid_payout_address = bid_claim.pay_address;
                     // fort he purposese of long/long trades assets may be of any type, but
                     // we will assume bids are in usd and asks are in bts for naming convention
                     // purposes.
                     
                     asset bid_amount_usd = working_bid.get_amount();
                     asset bid_amount_bts = bid_amount_usd * bid_claim.ask_price;

                     asset ask_amount_bts = working_ask.get_amount();
                     asset ask_amount_usd = ask_amount_bts * ask_claim.ask_price;
                     ilog( "bid in ${b} expected ${e}", ("b",bid_amount_usd)("e",bid_amount_bts) );
                     ilog( "ask in ${a} expected ${e}", ("a",ask_amount_bts)("e",ask_amount_usd) );

                     if( ask_amount_usd.get_rounded_amount() < bid_amount_usd.get_rounded_amount() )
                     { // then we have filled the ask
                        ilog("ilog ${x} < ${y}???", ("x",ask_amount_usd.amount)("y",bid_amount_usd.amount));
                        pay_asker          += ask_amount_usd;
                        ilog(".");
                        auto delta_bidder  = ask_amount_usd * bid_claim.ask_price;
                        pay_bidder         += delta_bidder; 
                        bidder_change      = bid_amount_usd - delta_bidder * bid_claim.ask_price;

                        ask_change.reset();
                        working_ask.amount = 0;
                        working_bid.amount = bidder_change.get_rounded_amount();
                        bid_change = working_bid;

                        market_trx.inputs.push_back( ask_itr->location );
                        ilog( "ASK CLAIM ADDR ${A} amnt ${a}", ("A",ask_claim.pay_address)("a",pay_asker) );
                        ilog( "BID CHANGE ${C}", ("C", working_bid ) );
                        if( pay_asker > asset(static_cast<uint64_t>(0ull),pay_asker.unit) )
                        {
                          market_trx.outputs.push_back( trx_output( claim_by_signature_output( ask_claim.pay_address ), pay_asker) );
                        }
                        pay_asker = asset(pay_asker.unit);
                        ++ask_itr;
                        if( ask_itr != asks.end() )  working_ask = get_output( ask_itr->location );
                     }
                     else // then we have filled the bid or we have filled BOTH
                     {
                        ilog(".");
                        pay_bidder    += bid_amount_bts;
                        ilog(".");
                        auto delta_asker =  bid_amount_bts * ask_claim.ask_price;
                        pay_asker     += delta_asker;

                        working_bid.amount = 0;

                        if( bid_amount_usd.get_rounded_amount() != ask_amount_usd.get_rounded_amount() )
                        {
                           asker_change  = ask_amount_bts -  delta_asker * ask_claim.ask_price;
                           working_ask.amount = asker_change.get_rounded_amount();
                        }
                        else
                        {
                           working_ask.amount = 0;
                        }

                        market_trx.inputs.push_back( bid_itr->location );
                        ilog( "BID CLAIM ADDR ${A} ${a}", ("A",bid_claim.pay_address)("a",pay_bidder) );
                        market_trx.outputs.push_back( trx_output( claim_by_signature_output( bid_claim.pay_address ), pay_bidder) );
                        pay_bidder = asset(static_cast<uint64_t>(0ull),pay_bidder.unit);

                        ++bid_itr;
                        if( bid_itr != bids.rend() ) working_bid = get_output( bid_itr->location );

                        if( working_ask.amount < 10 )
                        {
                           market_trx.inputs.push_back( ask_itr->location );
                           ilog( "ASK CLAIM ADDR ${A} amnt ${a}", ("A",ask_claim.pay_address)("a",pay_asker) );
                           if( pay_asker.amount > 0 )
                              market_trx.outputs.push_back( trx_output( claim_by_signature_output( ask_claim.pay_address ), pay_asker) );
                           pay_asker = asset(static_cast<uint64_t>(0ull),pay_asker.unit);
                           ++ask_itr;
                           if( ask_itr != asks.end() )  working_ask = get_output( ask_itr->location );
                        }
                     }
                  }
                  else
                  {
                     FC_ASSERT( !"Bid must either be a claim by bid or claim by long",
                                "", ("bid", working_bid) );  
                  }
               } // while( ... ) 
               if( has_change && working_ask.amount > 10  )
               {
                  FC_ASSERT( ask_itr != asks.end() );
                  if( pay_asker.amount > 0 )
                  {
                     market_trx.inputs.push_back( ask_itr->location );
                     market_trx.outputs.push_back( working_ask );
                     market_trx.outputs.push_back( trx_output( claim_by_signature_output( ask_payout_address ), pay_asker ) );
                  }
               }
               if( has_change && working_bid.amount > 10 )
               {
                  FC_ASSERT( bid_itr != bids.rend() );
                  if( collateral_amount.amount > 10 )
                  {
                     market_trx.inputs.push_back( bid_itr->location );
                     market_trx.outputs.push_back( working_bid );
                     market_trx.outputs.push_back( trx_output( claim_by_cover_output( loan_amount, bid_payout_address ), collateral_amount) );
                  }
                  else if( working_bid.claim_func == claim_by_bid )
                  {
                     if( pay_bidder.amount > 10 )
                     {
                        market_trx.inputs.push_back( bid_itr->location );
                        market_trx.outputs.push_back( working_bid );
                        market_trx.outputs.push_back( trx_output( claim_by_signature_output( bid_payout_address ), pay_bidder ) );
                     }
                  }
               }
              
               wlog( "Market Transaction: ${trx}", ("trx", market_trx) );
               if( market_trx.inputs.size() )
               {
                   FC_ASSERT( market_trx.outputs.size() );
                   FC_ASSERT( market_trx.inputs.size() );
                   matched.push_back(market_trx);
               }
               //ilog( "done match orders.." );
            } FC_RETHROW_EXCEPTIONS( warn, "", ("quote",quote)("base",base) ) }
コード例 #5
0
            void match_orders( std::vector<signed_transaction>& matched,  asset::type quote, asset::type base )
            { try {
               ilog( "match orders.." );
               auto bids = _market_db.get_bids( quote, base );
               auto asks = _market_db.get_asks( quote, base );
               wlog( "asks: ${asks}", ("asks",asks) );
               wlog( "bids: ${bids}", ("bids",bids) );

               fc::optional<trx_output>  ask_change;
               fc::optional<trx_output>  bid_change;
               fc::optional<trx_output>  cover_change;

               address                   bid_payout_address;
               fc::optional<asset>       bid_payout;

               asset                                cover_collat;       
               fc::optional<claim_by_cover_output>  cover_payout;


               signed_transaction market_trx;
               market_trx.timestamp = fc::time_point::now();


               /** asks are sorted from low to high, so we start
                * with the lowest ask, and check to see if there are
                * any bids that are greaterthan or equal to the ask, if
                * there are then either the full bid or full ask will be
                * filled.  If the full bid is filled, then move on to the
                * next bid, and save the leftover ask.  If the left over
                * ask is filled, then move to the next ask.
                *
                * When there are no more pairs that can be matched, exit
                * the loop and any partial payouts are made.  
                */
               auto ask_itr = asks.begin();
               auto bid_itr = bids.rbegin();
               while( ask_itr != asks.end() &&
                      bid_itr != bids.rend() )
               { 
                  trx_output working_ask;
                  trx_output working_bid;

                  if( ask_change ) {  working_ask = *ask_change; }
                  else             {  working_ask = get_output( ask_itr->location );  }

                  if( bid_change ) {  working_bid = *bid_change; }
                  else             {  working_bid = get_output( bid_itr->location);   }

                  claim_by_bid_output bid_claim = working_bid.as<claim_by_bid_output>();

                  if( working_ask.claim_func == claim_by_long )
                  {
                     auto long_claim = working_ask.as<claim_by_long_output>();
                     if( long_claim.ask_price > bid_claim.ask_price )
                     {
                        break; // exit the while loop, no more trades can occur
                     }
                     asset bid_amount = working_bid.get_amount() * bid_claim.ask_price;
                     asset ask_amount = working_ask.get_amount() * long_claim.ask_price;
                     FC_ASSERT( bid_amount.unit == ask_amount.unit );

                     auto  trade_amount = std::min(bid_amount,ask_amount);

                     ilog( "bid amount: ${b} @ ${bp}  ask amount: ${a} @ ${ap}", ("b",bid_amount)("a",ask_amount)("bp",bid_claim.ask_price)("ap",long_claim.ask_price) );

                     asset bid_change_amount   = working_bid.get_amount();
                     bid_change_amount        -= trade_amount * bid_claim.ask_price;
                     ilog( "bid change.. ${c}", ("c",bid_change_amount) );
                     
                     asset ask_change_amount   = working_ask.get_amount();
                     ask_change_amount        -= trade_amount * long_claim.ask_price;
                     ilog( "ask change.. ${c}", ("c",ask_change_amount) );
                      
                     if( ask_change_amount != bid_change_amount  && ask_change_amount != asset(0,working_bid.unit) )
                     {
                       FC_ASSERT( !"At least one of the bid or ask should be completely filled", "", 
                                  ("ask_change_amount",ask_change_amount)("bid_change_amount",bid_change_amount) );
                     }
                     
                     bid_payout_address = bid_claim.pay_address;
                     auto bid_payout_amount  = bid_amount - (bid_change_amount * bid_claim.ask_price);

                     if( bid_payout ) { *bid_payout += bid_payout_amount; }
                     else             { bid_payout   = bid_payout_amount; }

                     if( cover_payout ) 
                     { 
                        cover_payout->payoff_amount += trade_amount.get_rounded_amount();
                        cover_collat                += (trade_amount * long_claim.ask_price)*2;
                     }
                     else
                     {
                        cover_payout                = claim_by_cover_output();
                        cover_payout->owner         = long_claim.pay_address;
                        cover_payout->payoff_unit   = trade_amount.unit;
                        cover_payout->payoff_amount = trade_amount.get_rounded_amount();
                        cover_collat                = (trade_amount * long_claim.ask_price)*2;
                     }

                     if( bid_change_amount != asset(0, working_bid.unit) )
                     {
                        // TODO: accumulate fractional parts, round at the end?....
                        working_bid.amount = bid_change_amount.get_rounded_amount(); 
                        bid_change = working_bid;
                        elog( "we DID NOT fill the bid..." );
                     }
                     else // we have filled the bid!  
                     {
                        elog( "we filled the bid..." );
                        market_trx.inputs.push_back( bid_itr->location );
                        market_trx.outputs.push_back( 
                                trx_output( claim_by_signature_output( bid_claim.pay_address ), bid_payout->get_rounded_asset() ) );
                        bid_change.reset();
                        bid_payout.reset();
                        ++bid_itr;
                     }

                     if( ask_change_amount != asset( 0, working_bid.unit ) )
                     {
                        working_ask.amount = ask_change_amount.get_rounded_amount();
                        ask_change = working_ask;
                     }
                     else // we have filled the ask!
                     {
                        market_trx.inputs.push_back( ask_itr->location );
                        market_trx.outputs.push_back( trx_output( *cover_payout, cover_collat ) );
                        ask_change.reset();
                        cover_payout.reset();
                        ++ask_itr;
                     }
                  }
                  else if( working_ask.claim_func == claim_by_bid )
                  {
                     FC_ASSERT( !"Not Implemented" );
                     claim_by_bid_output ask_claim = working_ask.as<claim_by_bid_output>();
                     if( ask_claim.ask_price > bid_claim.ask_price )
                     {
                        break;
                     }
                     // TODO: implement straight trades..
                  }
                  else
                  {
                     FC_ASSERT( !"Ask must either be a claim by bid or claim by long",
                                "", ("ask", working_ask) );  
                  }

               } // while( ... ) 
               if( ask_change && ask_itr != asks.end()  ) market_trx.inputs.push_back( ask_itr->location );
               if( bid_change && bid_itr != bids.rend() ) market_trx.inputs.push_back( bid_itr->location );
              
               if( ask_change )
               { 
                  ilog( "ask_change: ${ask_change}", ("ask_change",ask_change) ); 
                  market_trx.outputs.push_back( *ask_change ); 
               }
               if( bid_change )
               {
                  ilog( "bid_change: ${bid_change}", ("bid_change",bid_change) ); 
                  market_trx.outputs.push_back( *bid_change ); 
               }
               if( bid_payout ) 
               {
                   ilog( "bid_payout ${payout}", ("payout",bid_payout) );
                   market_trx.outputs.push_back( 
                            trx_output( claim_by_signature_output( bid_payout_address ), *bid_payout ) );
               }
               else
               {
                    wlog ( "NO BID PAYOUT" );
               }
               if( cover_payout ) 
               {
                   ilog( "cover_payout ${payout}", ("payout",cover_payout) );
                   market_trx.outputs.push_back( trx_output( *cover_payout, cover_collat ) );
               }
               wlog( "Market Transaction: ${trx}", ("trx", market_trx) );
               if( market_trx.inputs.size() )
               {
                   FC_ASSERT( market_trx.outputs.size() );
                   matched.push_back(market_trx);
               }

               //ilog( "done match orders.." );
            } FC_RETHROW_EXCEPTIONS( warn, "", ("quote",quote)("base",base) ) }