Пример #1
0
  asset::operator std::string()const
  { try {

     auto rounded_amnt = get_rounded_amount();
     std::string int_part = fc::to_string(uint64_t(rounded_amnt/BTS_BLOCKCHAIN_SHARE) );
     uint64_t fract = uint64_t(rounded_amnt % BTS_BLOCKCHAIN_SHARE + BTS_BLOCKCHAIN_SHARE);
     return  int_part  + "." + fc::to_string(fract).substr(1) + " " + fc::to_string(unit); 

  } FC_RETHROW_EXCEPTIONS( warn, "unable to convert asset to string" ) }
Пример #2
0
 asset& asset::operator -= ( const asset& o )
 {
    FC_ASSERT( unit == o.unit );
    auto old = *this;;
    amount -= o.amount;
    if( amount > old.amount ) 
    {
       if( get_rounded_amount() == 0 )
       {
           amount = 0;
           return *this;
       }
       FC_THROW_EXCEPTION( exception, "asset addition underflow  ${a} - ${b} = ${c}", 
                           ("a", old)("b",o)("c",*this) );
    }
    return *this;
 }
Пример #3
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) ) }
Пример #4
0
 asset    get_rounded_asset()const { return asset( get_rounded_amount(),unit); }