void Exchange_BTCe::setupApi(QtBitcoinTrader *mainClass, bool tickOnly) { tickerOnly=tickOnly; if(!tickerOnly) { connect(mainClass,SIGNAL(reloadOrders()),this,SLOT(reloadOrders())); connect(mainClass,SIGNAL(apiBuy(double, double)),this,SLOT(buy(double, double))); connect(mainClass,SIGNAL(apiSell(double, double)),this,SLOT(sell(double, double))); connect(mainClass,SIGNAL(cancelOrderByOid(QByteArray)),this,SLOT(cancelOrder(QByteArray))); connect(this,SIGNAL(ordersChanged(QString)),mainClass,SLOT(ordersChanged(QString))); connect(mainClass,SIGNAL(cancelOrderByOid(QByteArray)),this,SLOT(cancelOrder(QByteArray))); connect(mainClass,SIGNAL(getHistory(bool)),this,SLOT(getHistory(bool))); connect(this,SIGNAL(ordersLogChanged(QString)),mainClass,SLOT(ordersLogChanged(QString))); connect(this,SIGNAL(orderCanceled(QByteArray)),mainClass,SLOT(orderCanceled(QByteArray))); connect(this,SIGNAL(ordersIsEmpty()),mainClass,SLOT(ordersIsEmpty())); }
void Exchange::setupApi(QtBitcoinTrader *mainClass, bool tickOnly)//Execute only once { QSettings settingsParams(":/Resources/Exchanges/"+currencyMapFile+".ini",QSettings::IniFormat); QStringList symbolList=settingsParams.childGroups(); QList<CurrencyPairItem> *newCurrPairs=new QList<CurrencyPairItem>; for(int n=0;n<symbolList.count();n++) { CurrencyPairItem currentPair=defaultCurrencyParams; currentPair.name=settingsParams.value(symbolList.at(n)+"/Symbol","").toByteArray(); if(currentPair.name.length()!=6)continue; currentPair.setSymbol(currentPair.name.toLatin1()); currentPair.name.insert(3,"/"); currentPair.currRequestSecond=settingsParams.value(symbolList.at(n)+"/RequestSecond","").toByteArray(); if(!currentPair.currRequestSecond.isEmpty()) currentPair.name.append(" ["+currentPair.currRequestSecond+"]"); currentPair.currRequestPair=settingsParams.value(symbolList.at(n)+"/Request","").toByteArray(); if(currentPair.currRequestPair.isEmpty())continue; currentPair.priceDecimals=settingsParams.value(symbolList.at(n)+"/PriceDecimals","").toInt(); currentPair.priceMin=settingsParams.value(symbolList.at(n)+"/PriceMin","").toDouble(); currentPair.tradeVolumeMin=settingsParams.value(symbolList.at(n)+"/TradeVolumeMin","").toDouble(); currentPair.tradePriceMin=settingsParams.value(symbolList.at(n)+"/TradePriceMin","").toDouble(); currentPair.currADecimals=settingsParams.value(symbolList.at(n)+"/ItemDecimals").toInt(); currentPair.currBDecimals=settingsParams.value(symbolList.at(n)+"/ValueDecimals").toInt(); (*newCurrPairs)<<currentPair; } connect(this,SIGNAL(setCurrencyPairsList(QList<CurrencyPairItem>*)),mainClass,SLOT(setCurrencyPairsList(QList<CurrencyPairItem>*))); emit setCurrencyPairsList(newCurrPairs); tickerOnly=tickOnly; if(!tickerOnly) { connect(mainClass,SIGNAL(apiBuy(QString, double, double)),this,SLOT(buy(QString, double, double))); connect(mainClass,SIGNAL(apiSell(QString, double, double)),this,SLOT(sell(QString, double, double))); connect(mainClass,SIGNAL(cancelOrderByOid(QString, QByteArray)),this,SLOT(cancelOrder(QString, QByteArray))); connect(mainClass,SIGNAL(getHistory(bool)),this,SLOT(getHistory(bool))); connect(this,SIGNAL(orderBookChanged(QString, QList<OrderItem> *)),mainClass,SLOT(orderBookChanged(QString, QList<OrderItem> *))); connect(this,SIGNAL(historyChanged(QList<HistoryItem>*)),mainClass,SLOT(historyChanged(QList<HistoryItem>*))); connect(this,SIGNAL(orderCanceled(QString, QByteArray)),mainClass,SLOT(orderCanceled(QString, QByteArray))); connect(this,SIGNAL(ordersIsEmpty()),mainClass,SLOT(ordersIsEmpty())); }
void Exchange_BitCurex::dataReceivedAuth(QByteArray data, int reqType) { if(debugLevel)logThread->writeLog("RCV: "+data); if(data.size()<4)return; if(data.at(0)==QLatin1Char('<'))return; bool success=true; switch(reqType) { case 103: //ticker if(data.startsWith("{\"lowest_tx_price_h\": \"")) { QByteArray tickerHigh=getMidData("\"highest_tx_price_h\": \"","\", \"",&data); if(!tickerHigh.isEmpty()) { double newTickerHigh=tickerHigh.toDouble(); if(newTickerHigh!=lastTickerHigh) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"High",newTickerHigh); lastTickerHigh=newTickerHigh; } QByteArray tickerLow=getMidData("\"lowest_tx_price_h\": \"","\", \"",&data); if(!tickerLow.isEmpty()) { double newTickerLow=tickerLow.toDouble(); if(newTickerLow!=lastTickerLow) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Low",newTickerLow); lastTickerLow=newTickerLow; } QByteArray tickerSell=getMidData("\"best_bid_h\": \"","\", \"",&data); if(!tickerSell.isEmpty()) { double newTickerSell=tickerSell.toDouble(); if(newTickerSell!=lastTickerSell) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Sell",newTickerSell); lastTickerSell=newTickerSell; } QByteArray tickerBuy=getMidData("\"best_ask_h\": \"","\", \"",&data); if(!tickerBuy.isEmpty()) { double newTickerBuy=tickerBuy.toDouble(); if(newTickerBuy!=lastTickerBuy) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Buy",newTickerBuy); lastTickerBuy=newTickerBuy; } QByteArray tickerVolume=getMidData("\"total_volume_h\": \"","\", \"",&data); if(!tickerVolume.isEmpty()) { double newTickerVolume=tickerVolume.toDouble(); if(newTickerVolume!=lastTickerVolume) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Volume",newTickerVolume); lastTickerVolume=newTickerVolume; } QByteArray tickerLast=getMidData("\"last_tx_price_h\": \"","\", \"",&data); if(!tickerLast.isEmpty()) { double newTickerLast=tickerLast.toDouble(); if(newTickerLast!=lastTickerLast) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newTickerLast); lastTickerLast=newTickerLast; } } else success=false; break;//ticker case 109: //trades if(data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"trades\": [{\"")) { QStringList tradeList=QString(data).split("}, {"); QList<TradesItem> *newTradesItems=new QList<TradesItem>; TradesItem newItem; for(int n=tradeList.count()-1;n>=0;n--) { QByteArray tradeData=tradeList.at(n).toLatin1()+"}"; newItem.date=getMidData("\"ts\": ",", \"",&tradeData).toUInt(); if(newItem.date<startTradesDate)continue; quint32 currentTid=getMidData("\"txid\": ",", \"",&tradeData).toUInt(); if(lastFetchTid>=currentTid)continue; lastFetchTid=currentTid; newItem.price=getMidData("\"price\": ",", \"",&tradeData).toDouble(); newItem.amount=getMidData("\"amount\": ",", \"",&tradeData).toDouble(); newItem.orderType=getMidData("\"type\": \"","\"}",&tradeData)=="ask"?-1:1; newItem.symbol=baseValues.currentPair.symbol; if(newItem.isValid())(*newTradesItems)<<newItem; else if(debugLevel)logThread->writeLog("Invalid trades fetch data line:"+tradeData,2); } if(newItem.price>0&&lastTradesDate<newItem.date) { lastTradesDate=newItem.date; IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newItem.price); lastTickerLast=newItem.price; } if(newTradesItems->count())emit addLastTrades(baseValues.currentPair.symbol,newTradesItems); else delete newTradesItems; } else if(!data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""))success=false; break;//trades case 111: //depth if(data.startsWith("{\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"bids\": [")) { emit depthRequestReceived(); if(lastDepthData!=data) { lastDepthData=data; depthAsks=new QList<DepthItem>; depthBids=new QList<DepthItem>; QMap<double,double> currentAsksMap; QStringList asksList=QString(getMidData("asks\": [[","]]",&data)).split("], ["); double groupedPrice=0.0; double groupedVolume=0.0; int rowCounter=0; for(int n=0;n<asksList.count();n++) { if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break; QStringList currentPair=asksList.at(n).split(", "); if(currentPair.count()!=2)continue; double priceDouble=currentPair.first().toDouble(); double amount=currentPair.last().toDouble(); if(baseValues.groupPriceValue>0.0) { if(n==0) { emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,true); groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue); groupedVolume=amount; } else { bool matchCurrentGroup=priceDouble<groupedPrice+baseValues.groupPriceValue; if(matchCurrentGroup)groupedVolume+=amount; if(!matchCurrentGroup||n==asksList.count()-1) { depthSubmitOrder(baseValues.currentPair.symbol, ¤tAsksMap,groupedPrice+baseValues.groupPriceValue,groupedVolume,true); rowCounter++; groupedVolume=amount; groupedPrice+=baseValues.groupPriceValue; } } } else { depthSubmitOrder(baseValues.currentPair.symbol, ¤tAsksMap,priceDouble,amount,true); rowCounter++; } } QList<double> currentAsksList=lastDepthAsksMap.keys(); for(int n=0;n<currentAsksList.count();n++) if(currentAsksMap.value(currentAsksList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol, currentAsksList.at(n),0.0,true); lastDepthAsksMap=currentAsksMap; QMap<double,double> currentBidsMap; QStringList bidsList=QString(getMidData("bids\": [[","]]",&data)).split("], ["); groupedPrice=0.0; groupedVolume=0.0; rowCounter=0; for(int n=0;n<bidsList.count();n++) { if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break; QStringList currentPair=bidsList.at(n).split(", "); if(currentPair.count()!=2)continue; double priceDouble=currentPair.first().toDouble(); double amount=currentPair.last().toDouble(); if(baseValues.groupPriceValue>0.0) { if(n==0) { emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,false); groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue); groupedVolume=amount; } else { bool matchCurrentGroup=priceDouble>groupedPrice-baseValues.groupPriceValue; if(matchCurrentGroup)groupedVolume+=amount; if(!matchCurrentGroup||n==asksList.count()-1) { depthSubmitOrder(baseValues.currentPair.symbol, ¤tBidsMap,groupedPrice-baseValues.groupPriceValue,groupedVolume,false); rowCounter++; groupedVolume=amount; groupedPrice-=baseValues.groupPriceValue; } } } else { depthSubmitOrder(baseValues.currentPair.symbol, ¤tBidsMap,priceDouble,amount,false); rowCounter++; } } QList<double> currentBidsList=lastDepthBidsMap.keys(); for(int n=0;n<currentBidsList.count();n++) if(currentBidsMap.value(currentBidsList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol, currentBidsList.at(n),0.0,false); lastDepthBidsMap=currentBidsMap; emit depthSubmitOrders(baseValues.currentPair.symbol,depthAsks, depthBids); depthAsks=0; depthBids=0; } } else if(!data.startsWith("{\"symbol\": \"")) { if(debugLevel)logThread->writeLog("Invalid depth data:"+data,2); success=false; } break; case 202: //info if(data.startsWith("{\"status\": \"ok\", \"data\": {\"")) { QByteArray fundsData=getMidData("data\": {","}",&data); QByteArray btcBalance=getMidData(baseValues.currentPair.currAStrLow+"\": \"","\"",&fundsData); if(!btcBalance.isEmpty()) { double newBtcBalance=btcBalance.toDouble(); if(lastBtcBalance!=newBtcBalance)emit accBtcBalanceChanged(baseValues.currentPair.symbol,newBtcBalance); lastBtcBalance=newBtcBalance; } QByteArray usdBalance=getMidData("\""+baseValues.currentPair.currBStrLow+"\": \"","\"",&fundsData); if(!usdBalance.isEmpty()) { double newUsdBalance=usdBalance.toDouble(); if(newUsdBalance!=lastUsdBalance)emit accUsdBalanceChanged(baseValues.currentPair.symbol,newUsdBalance); lastUsdBalance=newUsdBalance; } QByteArray fee=getMidData("\"fee\": ",",",&data); if(!fee.isEmpty()) { double newFee=fee.toDouble(); if(newFee!=lastFee)emit accFeeChanged(baseValues.currentPair.symbol,newFee); lastFee=newFee; } } else success=false; break;//info case 204://orders if(data.startsWith("{\"status\": \"ok\", \"data\": [{\"")) { if(lastOrders!=data) { lastOrders=data; QStringList ordersList=QString(data).split("}, {"); QList<OrderItem> *orders=new QList<OrderItem>; for(int n=0;n<ordersList.count();n++) { OrderItem currentOrder; QByteArray currentOrderData=ordersList.at(n).toLatin1()+"}"; currentOrder.oid=getMidData("id\": \"","\"}",¤tOrderData); QByteArray tempDate=getMidData("issued\": ",", \"",¤tOrderData); tempDate.chop(3); currentOrder.date=tempDate.toUInt(); currentOrder.type=getMidData("type\": \"","\", \"",¤tOrderData)=="ask"; currentOrder.amount=getMidData("volume\": \"","\", \"",¤tOrderData).toDouble(); currentOrder.price=getMidData("limit\": \"","\", \"",¤tOrderData).toDouble(); currentOrder.symbol="BTC"+getMidData("currency\": \"","\", \"",¤tOrderData).toUpper(); currentOrder.status=1; if(currentOrder.isValid())(*orders)<<currentOrder; } emit orderBookChanged(baseValues.currentPair.symbol,orders); } } else if(data.startsWith("{\"status\": \"ok\", \"data\": [")) emit ordersIsEmpty(); else success=false; break;//orders case 305: //order/cancel if(data.startsWith("{\"status\": \"ok\", \"data\": [{\"")) { QByteArray oid=getMidData("id\": \"","\"",&data); if(!oid.isEmpty())emit orderCanceled(baseValues.currentPair.symbol,oid); } else success=false; break;//order/cancel case 306: if(debugLevel)logThread->writeLog("Buy OK: "+data,2);break;//order/buy case 307: if(debugLevel)logThread->writeLog("Sell OK: "+data,2);break;//order/sell case 208: ///history if(data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"trades\": [")) { if(lastHistory!=data) { lastHistory=data; QStringList dataList=QString(data).split("}, {"); QList<HistoryItem> *historyItems=new QList<HistoryItem>; quint32 currentId; quint32 maxId=0; for(int n=dataList.count()-1;n>=0;n--) { QByteArray curLog=dataList.at(n).toLatin1()+"}"; currentId=getMidData("txid\": ",", \"",&curLog).toUInt(); if(currentId<=lastHistoryId)break; if(n==dataList.count()-1)maxId=currentId; HistoryItem currentHistoryItem; QByteArray logType=getMidData("type\": \"","\"}",&curLog); if(logType=="ask")currentHistoryItem.type=2; else if(logType=="bid")currentHistoryItem.type=1; if(currentHistoryItem.type) { currentHistoryItem.symbol=baseValues.currentPair.symbol; currentHistoryItem.dateTimeInt=getMidData("ts\": ",", \"",&curLog).toUInt(); currentHistoryItem.price=getMidData("price\": ",", \"",&curLog).toDouble(); currentHistoryItem.volume=getMidData("amount\": ",", \"",&curLog).toDouble(); if(currentHistoryItem.isValid())(*historyItems)<<currentHistoryItem; } } if(maxId>lastHistoryId)lastHistoryId=maxId; emit historyChanged(historyItems); } } else success=false; break;//money/wallet/history default: break; } static int authErrorCount=0; if(reqType>=200 && reqType<300) { if(!success) { authErrorCount++; if(authErrorCount>2) { QString authErrorString=getMidData("data\": \"","\"",&data); if(debugLevel)logThread->writeLog("API error: "+authErrorString.toLatin1()+" ReqType: "+QByteArray::number(reqType),2); if(authErrorString=="auth_error")authErrorString=julyTr("TRUNAUTHORIZED","Invalid API key."); else if(authErrorString=="nonce_error")authErrorString=julyTr("THIS_PROFILE_ALREADY_USED","Invalid nonce parameter."); if(!authErrorString.isEmpty())emit showErrorMessage(authErrorString); } } else authErrorCount=0; } static int errorCount=0; if(!success) { QString errorString; errorString=getMidData("{\"status\": \"error\", \"data\": \"","\"",&data); errorCount++; if(errorCount<3)return; if(debugLevel)logThread->writeLog("API error: "+errorString.toLatin1()+" ReqType:"+QByteArray::number(reqType),2); if(errorString.isEmpty())return; if(errorString==QLatin1String("no orders"))return; if(reqType<300)emit showErrorMessage("I:>"+errorString); } else errorCount=0; }
void Exchange_BitMarket::dataReceivedAuth(QByteArray data, int reqType) { if(debugLevel)logThread->writeLog("RCV: "+data); if(data.size()&&data.at(0)==QLatin1Char('<'))return; bool success=true; QString errorString=""; switch(reqType) { case 103: //ticker if(data.startsWith("{\"ask\":")) { QByteArray tickerHigh=getMidData("\"high\":",",\"",&data); if(!tickerHigh.isEmpty()) { double newTickerHigh=tickerHigh.toDouble(); if(newTickerHigh!=lastTickerHigh) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"High",newTickerHigh); lastTickerHigh=newTickerHigh; } QByteArray tickerLow=getMidData("\"low\":",",\"",&data); if(!tickerLow.isEmpty()) { double newTickerLow=tickerLow.toDouble(); if(newTickerLow!=lastTickerLow) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Low",newTickerLow); lastTickerLow=newTickerLow; } QByteArray tickerSell=getMidData("\"bid\":",",\"",&data); if(!tickerSell.isEmpty()) { double newTickerSell=tickerSell.toDouble(); if(newTickerSell!=lastTickerSell) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Sell",newTickerSell); lastTickerSell=newTickerSell; } QByteArray tickerBuy=getMidData("\"ask\":",",\"",&data); if(!tickerBuy.isEmpty()) { double newTickerBuy=tickerBuy.toDouble(); if(newTickerBuy!=lastTickerBuy) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Buy",newTickerBuy); lastTickerBuy=newTickerBuy; } QByteArray tickerVolume=getMidData("\"volume\":","}",&data); if(!tickerVolume.isEmpty()) { double newTickerVolume=tickerVolume.toDouble(); if(newTickerVolume!=lastTickerVolume) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Volume",newTickerVolume); lastTickerVolume=newTickerVolume; } QByteArray tickerLast=getMidData("\"last\":",",\"",&data); if(!tickerLast.isEmpty()) { double newTickerLast=tickerLast.toDouble(); if(newTickerLast!=lastTickerLast) IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newTickerLast); lastTickerLast=newTickerLast; } if(isFirstTicker) { emit firstTicker(); isFirstTicker=false; } } else { success=false; errorString+="Invalid ticker data. "; } break;//ticker case 109: //trades if(data.startsWith("[{\"amount\":")) { QStringList tradeList=QString(data).split("},{"); QList<TradesItem> *newTradesItems=new QList<TradesItem>; quint32 currentTid=0; for(int n=tradeList.count()-1;n>=0;n--) { QByteArray tradeData=tradeList.at(n).toLatin1()+"}"; TradesItem newItem; newItem.date=getMidData("\"date\":",",\"",&tradeData).toUInt(); currentTid=getMidData("\"tid\":",",\"",&tradeData).toUInt(); if(lastFetchTid<0&&newItem.date<-lastFetchTid)continue; if(currentTid<1000||lastFetchTid>=currentTid)continue; lastFetchTid=currentTid; newItem.price=getMidData("\"price\":",",\"",&tradeData).toDouble(); newItem.amount=getMidData("\"amount\":",",\"",&tradeData).toDouble(); newItem.orderType=getMidData("\"type\":\"","\"",&tradeData)=="ask"?1:-1; newItem.symbol=baseValues.currentPair.symbol; if(newItem.isValid())(*newTradesItems)<<newItem; else if(debugLevel)logThread->writeLog("Invalid trades fetch data line:"+tradeData,2); if(n==0&&lastTickerDate<newItem.date) { lastTickerDate=newItem.date; IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newItem.price); } } if(newTradesItems->count())emit addLastTrades(baseValues.currentPair.symbol,newTradesItems); else delete newTradesItems; if(currentTid>1000)lastTradesTid=QByteArray::number(currentTid); } else if(data!="[]"){ success=false; errorString+="Invalid trades data. "; } break;//trades case 111: //depth if(data.startsWith("{\"asks\":[[")) { emit depthRequestReceived(); if(lastDepthData!=data) { lastDepthData=data; depthAsks=new QList<DepthItem>; depthBids=new QList<DepthItem>; QMap<double,double> currentAsksMap; QStringList asksList=QString(getMidData("asks\":[[","]]",&data)).split("],["); double groupedPrice=0.0; double groupedVolume=0.0; int rowCounter=0; for(int n=0;n<asksList.count();n++) { if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break; QStringList currentPair=asksList.at(n).split(","); if(currentPair.count()!=2)continue; double priceDouble=currentPair.first().toDouble(); double amount=currentPair.last().toDouble(); if(baseValues.groupPriceValue>0.0) { if(n==0) { emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,true); groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue); groupedVolume=amount; } else { bool matchCurrentGroup=priceDouble<groupedPrice+baseValues.groupPriceValue; if(matchCurrentGroup)groupedVolume+=amount; if(!matchCurrentGroup||n==asksList.count()-1) { depthSubmitOrder(baseValues.currentPair.symbol, ¤tAsksMap,groupedPrice+baseValues.groupPriceValue,groupedVolume,true); rowCounter++; groupedVolume=amount; groupedPrice+=baseValues.groupPriceValue; } } } else { depthSubmitOrder(baseValues.currentPair.symbol, ¤tAsksMap,priceDouble,amount,true); rowCounter++; } } QList<double> currentAsksList=lastDepthAsksMap.keys(); for(int n=0;n<currentAsksList.count();n++) if(currentAsksMap.value(currentAsksList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol, currentAsksList.at(n),0.0,true); lastDepthAsksMap=currentAsksMap; QMap<double,double> currentBidsMap; QStringList bidsList=QString(getMidData("bids\":[[","]]",&data)).split("],["); groupedPrice=0.0; groupedVolume=0.0; rowCounter=0; for(int n=0;n<bidsList.count();n++) { if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break; QStringList currentPair=bidsList.at(n).split(","); if(currentPair.count()!=2)continue; double priceDouble=currentPair.first().toDouble(); double amount=currentPair.last().toDouble(); if(baseValues.groupPriceValue>0.0) { if(n==0) { emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,false); groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue); groupedVolume=amount; } else { bool matchCurrentGroup=priceDouble>groupedPrice-baseValues.groupPriceValue; if(matchCurrentGroup)groupedVolume+=amount; if(!matchCurrentGroup||n==asksList.count()-1) { depthSubmitOrder(baseValues.currentPair.symbol, ¤tBidsMap,groupedPrice-baseValues.groupPriceValue,groupedVolume,false); rowCounter++; groupedVolume=amount; groupedPrice-=baseValues.groupPriceValue; } } } else { depthSubmitOrder(baseValues.currentPair.symbol, ¤tBidsMap,priceDouble,amount,false); rowCounter++; } } QList<double> currentBidsList=lastDepthBidsMap.keys(); for(int n=0;n<currentBidsList.count();n++) if(currentBidsMap.value(currentBidsList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol, currentBidsList.at(n),0.0,false); lastDepthBidsMap=currentBidsMap; emit depthSubmitOrders(baseValues.currentPair.symbol,depthAsks, depthBids); depthAsks=0; depthBids=0; } } else { success=false; errorString+="Invalid depth data. "; if(debugLevel)logThread->writeLog("Invalid depth data:"+data,2); } break; case 202: //info if(data.startsWith("{\"success\":true,\"data\":{\"balances\":{\"available\":")) { QByteArray fundsData=getMidData("available\":{","}",&data)+","; QByteArray btcBalance=getMidData("\""+baseValues.currentPair.currAStr+"\":",",",&fundsData); if(!btcBalance.isEmpty()) { double newBtcBalance=btcBalance.toDouble(); if(lastBtcBalance!=newBtcBalance)emit accBtcBalanceChanged(baseValues.currentPair.symbol,newBtcBalance); lastBtcBalance=newBtcBalance; } QByteArray usdBalance=getMidData("\""+baseValues.currentPair.currBStr+"\":",",",&fundsData); if(!usdBalance.isEmpty()) { double newUsdBalance=usdBalance.toDouble(); if(newUsdBalance!=lastUsdBalance)emit accUsdBalanceChanged(baseValues.currentPair.symbol,newUsdBalance); lastUsdBalance=newUsdBalance; } } else { success=false; errorString+="Invalid info data. "; } break;//info case 204://orders if(data.startsWith("{\"success\":true,\"data\":{\"buy\":[")) { if(lastOrders!=data){ lastOrders=data; if(data.startsWith("{\"success\":true,\"data\":{\"buy\":[],\"sell\":[]}")) { emit ordersIsEmpty(); break; } QByteArray dataBuy=getMidData("\"buy\":[{","}],",&data)+"},{"+getMidData("\"sell\":[{","}]",&data); QStringList ordersList=QString(dataBuy).split("},{"); if(ordersList.count()==0)return; QList<OrderItem> *orders=new QList<OrderItem>; for(int n=0;n<ordersList.count();n++) { OrderItem currentOrder; QByteArray currentOrderData=ordersList.at(n).toLatin1()+"}"; currentOrder.oid=getMidData("\"id\":",",",¤tOrderData); currentOrder.date=getMidData("\"time\":","}",¤tOrderData).toUInt(); currentOrder.type=getMidData("\"type\":\"","\"",¤tOrderData)=="sell"; currentOrder.amount=getMidData("\"amount\":",",",¤tOrderData).toDouble(); currentOrder.price=getMidData("\"rate\":",",",¤tOrderData).toDouble(); currentOrder.symbol=getMidData("\"market\":\"","\"",¤tOrderData); currentOrder.status=1; if(currentOrder.isValid())(*orders)<<currentOrder; } emit orderBookChanged(baseValues.currentPair.symbol,orders); } } else { success=false; errorString+="Invalid orders data. "; } break;//orders case 305: //order/cancel { if(!cancelingOrderIDs.isEmpty()) { if(data.startsWith("{\"success\":true"))emit orderCanceled(baseValues.currentPair.symbol,cancelingOrderIDs.first()); if(debugLevel)logThread->writeLog("Order canceled:"+cancelingOrderIDs.first(),2); cancelingOrderIDs.removeFirst(); } dataReceivedAuth(data,202); } break;//order/cancel case 306: { if(debugLevel)logThread->writeLog("Buy OK: "+data,2); if(data.startsWith("{\"error\"")){ success=false; errorString+="Invalid order/buy data. "; } } break;//order/buy case 307: { if(debugLevel)logThread->writeLog("Sell OK: "+data,2); if(data.startsWith("{\"error\"")){ success=false; errorString+="Invalid order/sell data. "; } } break;//order/sell case 208: ///history if(data.startsWith("{\"success\":true,\"data\":{\"total\":")) { QByteArray historyData=getMidData("\"results\":[{","}]}",&data)+"^"; if(lastHistory!=historyData) { lastHistory=historyData; if(historyData=="^")break; QString newLog(historyData); QStringList dataList=newLog.split("},{"); if(dataList.count()==0)return; quint32 currentId; quint32 maxId=0; QList<HistoryItem> *historyItems=new QList<HistoryItem>; for(int n=0;n<dataList.count();n++) { QByteArray curLog(dataList.at(n).toLatin1()); currentId=getMidData("id\":",",",&curLog).toUInt(); if(currentId<=lastHistoryId)break; if(n==0)maxId=currentId; HistoryItem currentHistoryItem; QByteArray logType=getMidData("type\":\"","\"",&curLog); if(logType=="sell")currentHistoryItem.type=1;else if(logType=="buy")currentHistoryItem.type=2; if(currentHistoryItem.type) { currentHistoryItem.symbol=getMidData("currencyCrypto\":\"","\"",&curLog)+getMidData("currencyFiat\":\"","\"",&curLog); currentHistoryItem.dateTimeInt=getMidData("time\":",",",&curLog).toUInt(); currentHistoryItem.price=getMidData("rate\":",",",&curLog).toDouble(); currentHistoryItem.volume=getMidData("amountCrypto\":",",",&curLog).toDouble(); if(currentHistoryItem.isValid())(*historyItems)<<currentHistoryItem; } } if(maxId>lastHistoryId)lastHistoryId=maxId; emit historyChanged(historyItems); } } else { success=false; errorString+="Invalid history data. "; } break;//money/wallet/history default: break; } static int errorCount=0; if(!success) { errorCount++;if(errorCount<2)return; QByteArray errorMsg=getMidData("errorMsg\":\"","\"",&data);errorString+="Error message: "+errorMsg; if(debugLevel)logThread->writeLog("API error: "+errorString.toLatin1()+" ReqType:"+QByteArray::number(reqType),2); if(errorMsg=="Invalid nonce value"||errorMsg=="")return; emit showErrorMessage("I:>"+errorString); } else errorCount=0; }