kucoin exchange api + balances and icons

Signed-off-by: Tanguy Pruvot <tanguy.pruvot@gmail.com>
This commit is contained in:
Tanguy Pruvot 2018-01-07 16:57:11 +01:00
parent 7729b5c2ef
commit ab5e411529
12 changed files with 322 additions and 5 deletions

View file

@ -16,6 +16,7 @@ define('EXCH_CRYPTOPIA_SECRET', '');
define('EXCH_EMPOEX_SECKEY', '');
define('EXCH_HITBTC_SECRET', '');
define('EXCH_KRAKEN_SECRET','');
define('EXCH_KUCOIN_SECRET', '');
define('EXCH_LIVECOIN_SECRET', '');
define('EXCH_NOVA_SECRET','');
define('EXCH_POLONIEX_SECRET', '');

View file

@ -49,12 +49,15 @@ define('EXCH_BLEUTRADE_KEY', '');
define('EXCH_BTER_KEY', '');
define('EXCH_YOBIT_KEY', '');
define('EXCH_CCEX_KEY', '');
define('EXCH_CEXIO_ID', '');
define('EXCH_CEXIO_KEY', '');
define('EXCH_COINMARKETS_USER', '');
define('EXCH_COINMARKETS_PIN', '');
define('EXCH_BITSTAMP_ID','');
define('EXCH_BITSTAMP_KEY','');
define('EXCH_HITBTC_KEY','');
define('EXCH_KRAKEN_KEY', '');
define('EXCH_KUCOIN_KEY', '');
define('EXCH_LIVECOIN_KEY', '');
define('EXCH_NOVA_KEY', '');
define('EXCH_STOCKSEXCHANGE_KEY', '');

View file

@ -56,6 +56,7 @@ class CoindbCommand extends CConsoleCommand
$nbUpdated += $this->grabBittrexIcons(); // can be huge ones
$nbUpdated += $this->grabCoinExchangeIcons();
$nbUpdated += $this->grabAlcurexIcons();
$nbUpdated += $this->grabKuCoinIcons();
$nbUpdated += $this->grabNovaIcons();
echo "total updated: $nbUpdated\n";
@ -504,8 +505,7 @@ class CoindbCommand extends CConsoleCommand
echo "alcurex: try to download new icons...\n";
foreach ($coins as $coin) {
$coin = getdbo('db_coins', $coin["id"]);
$symbol = $coin->symbol;
if (!empty($coin->symbol2)) $symbol = $coin->symbol2;
$symbol = $coin->getOfficialSymbol();
$local = $this->basePath."/images/coin-{$symbol}.png";
try {
$data = @ file_get_contents($url.strtoupper($symbol).'.png');
@ -525,6 +525,41 @@ class CoindbCommand extends CConsoleCommand
return $nbUpdated;
}
/**
* Icon grabber - KuCoin
*/
public function grabKuCoinIcons()
{
$url = 'https://assets.kucoin.com/www/1.2.0/assets/coins/';//QLC.png
$nbUpdated = 0;
$sql = "SELECT DISTINCT coins.id FROM coins INNER JOIN markets M ON M.coinid = coins.id ".
"WHERE M.name='kucoin' AND IFNULL(coins.image,'') = ''";
$coins = dbolist($sql);
if (empty($coins))
return 0;
echo "kucoin: try to download new icons...\n";
foreach ($coins as $coin) {
$coin = getdbo('db_coins', $coin["id"]);
$symbol = $coin->getOfficialSymbol();
$local = $this->basePath."/images/coin-{$symbol}.png";
try {
$data = @ file_get_contents($url.$symbol.'.png');
} catch (Exception $e) {
continue;
}
if (strlen($data) < 2048) continue;
echo $symbol." icon found\n";
file_put_contents($local, $data);
if (filesize($local) > 0) {
$coin->image = "/images/coin-{$symbol}.png";
$nbUpdated += $coin->save();
}
}
if ($nbUpdated)
echo "$nbUpdated icons downloaded from kucoin\n";
return $nbUpdated;
}
/**
* Icon grabber - NovaExchange
*/
@ -540,8 +575,7 @@ class CoindbCommand extends CConsoleCommand
echo "nova: try to download new icons...\n";
foreach ($coins as $coin) {
$coin = getdbo('db_coins', $coin["id"]);
$symbol = $coin->symbol;
if (!empty($coin->symbol2)) $symbol = $coin->symbol2;
$symbol = $coin->getOfficialSymbol();
$local = $this->basePath."/images/coin-{$symbol}.png";
try {
$data = @ file_get_contents($url.strtolower($symbol).'.png');

View file

@ -181,6 +181,11 @@ class ExchangeCommand extends CConsoleCommand
$balance = kraken_api_user('Balance');
echo("kraken btc: ".json_encode($balance)."\n");
}
if (!empty(EXCH_KUCOIN_KEY)) {
$balance = kucoin_api_user('account/BTC/balance');
if (!is_object($balance) || !isset($balance->data)) echo "kucoin error ".json_encode($balance)."\n";
else echo("kucoin: ".json_encode($balance->data)."\n");
}
if (!empty(EXCH_LIVECOIN_KEY)) {
$livecoin = new LiveCoinApi;
$balance = $livecoin->getBalances('BTC');

View file

@ -14,6 +14,7 @@ function BackendPricesUpdate()
updatePoloniexMarkets();
updateBleutradeMarkets();
updateKrakenMarkets();
updateKuCoinMarkets();
updateCCexMarkets();
updateCryptopiaMarkets();
updateHitBTCMarkets();
@ -1167,6 +1168,62 @@ function updateEmpoexMarkets()
}
}
function updateKuCoinMarkets()
{
$exchange = 'kucoin';
if (exchange_get($exchange, 'disabled')) return;
$markets = kucoin_api_query('open/symbols','market=BTC');
if(!is_object($markets) || !isset($markets->data) || empty($markets->data)) return;
$coininfo = NULL; //kucoin_api_query('market/open/coins');
if(!is_object($coininfo) || !isset($coininfo->data) || empty($coininfo->data)) {
$coininfo = NULL;
}
$list = getdbolist('db_markets', "name='$exchange'");
foreach($list as $market)
{
$coin = getdbo('db_coins', $market->coinid);
if(!$coin) continue;
$symbol = $coin->getOfficialSymbol();
if (market_get($exchange, $symbol, "disabled")) {
$market->disabled = 1;
$market->message = 'disabled from settings';
$market->save();
continue;
}
$pair = strtoupper($symbol).'-BTC';
foreach ($markets->data as $ticker) {
if ($ticker->symbol != $pair) continue;
$market->price = AverageIncrement($market->price, $ticker->buy);
$market->price2 = AverageIncrement($market->price2, $ticker->sell);
if (!empty($coininfo)) foreach ($coininfo->data as $info) {
if ($info->coin == $symbol) {
//todo: $market->withdrawfee = $info->withdrawMinFee;
break;
}
}
$market->txfee = $ticker->feeRate * 100; // is 0.1% for trades (0.001)
$market->priority = -1;
$market->pricetime = time();
if (floatval($ticker->vol) > 0.01)
$market->save();
if (empty($coin->price2)) {
$coin->price = $market->price;
$coin->price2 = $market->price2;
$coin->save();
}
}
}
}
function updateLiveCoinMarkets()
{
$exchange = 'livecoin';
@ -1489,7 +1546,7 @@ function updateShapeShiftMarkets()
$market->price = AverageIncrement($market->price, $ticker['rate']);
$market->price2 = AverageIncrement($market->price2, $ticker['rate']);
$market->txfee = $ticker['minerFee'];
$market->txfee = $ticker['minerFee'] * 100;
$market->pricetime = time();
$market->priority = -1; // not ready for trading
$market->save();

View file

@ -259,6 +259,20 @@ function updateRawcoins()
}
}
if (!exchange_get('kucoin', 'disabled')) {
$list = kucoin_api_query('market/open/coins');
if(is_object($list) && isset($list->data) && !empty($list->data))
{
dborun("UPDATE markets SET deleted=true WHERE name='kucoin'");
foreach($list->data as $item) {
$symbol = $item->coin;
$name = $item->name;
if (strpos($item->withdrawRemark,'Ethereum')) continue;
updateRawCoin('kucoin', $symbol, $name);
}
}
}
if (!exchange_get('livecoin', 'disabled')) {
$list = livecoin_api_query('exchange/ticker');
if(is_array($list))

View file

@ -29,6 +29,7 @@ require_once("alcurex.php");
require_once("binance.php");
require_once("cryptopia.php");
require_once("hitbtc.php");
require_once("kucoin.php");
require_once("livecoin.php");
require_once("nova.php");
require_once("coinexchange.php");
@ -101,6 +102,8 @@ function getMarketUrl($coin, $marketName)
$url = "http://jubi.com/coin/{$lowsymbol}";
else if($market == 'hitbtc')
$url = "https://hitbtc.com/exchange/{$symbol}-to-{$base}";
else if($market == 'kucoin')
$url = "https://www.kucoin.com/#/trade.pro/{$symbol}-{$base}";
else if($market == 'livecoin')
$url = "https://www.livecoin.net/trade/?currencyPair={$symbol}%2F{$base}";
else if($market == 'nova')

View file

@ -0,0 +1,133 @@
<?php
// see https://kucoinapidocs.docs.apiary.io/
// https://api.kucoin.com/v1/open/symbols/?market=BTC
function kucoin_api_query($method, $params='', $returnType='object')
{
$url = "https://api.kucoin.com/v1/$method/";
if (!empty($params))
$url .= "?$params";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; KuCoin API PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
curl_setopt($ch, CURLOPT_ENCODING , '');
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$execResult = curl_exec($ch);
if ($returnType == 'object')
$ret = json_decode($execResult);
else
$ret = json_decode($execResult,true);
return $ret;
}
// https://api.kucoin.com/v1/account/<coin>/wallet/address
function kucoin_api_user($method, $params=NULL, $isPostMethod=false)
{
require_once('/etc/yiimp/keys.php');
if (!defined('EXCH_KUCOIN_SECRET')) define('EXCH_KUCOIN_SECRET', '');
if (empty(EXCH_KUCOIN_KEY) || empty(EXCH_KUCOIN_SECRET)) return false;
$api_host = 'https://api.kucoin.com';
$mt = explode(' ', microtime());
$nonce = $mt[1].substr($mt[0], 2, 3);
$url = $endpoint = "/v1/$method";
$tosign = "$endpoint/$nonce/";
if (empty($params)) $params = array();
$query = http_build_query($params);
if (strlen($query) && !$isPostMethod) {
$url .= '&'.$query; $query = '';
}
if ($isPostMethod) $post_data = $params;
$hmac = strtolower(hash_hmac('sha256', base64_encode($tosign.$query), EXCH_KUCOIN_SECRET));
$headers = array(
'Content-Type: application/json;charset=UTF-8',
'KC-API-KEY: '.EXCH_KUCOIN_KEY,
'KC-API-NONCE: '.$nonce,
'KC-API-SIGNATURE: '.$hmac,
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_host.$url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($isPostMethod) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; KuCoin API PHP client; '.php_uname('s').'; PHP/'.phpversion().')');
curl_setopt($ch, CURLOPT_ENCODING , '');
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//curl_setopt($ch, CURLOPT_VERBOSE, 1);
$res = curl_exec($ch);
if($res === false) {
$e = curl_error($ch);
debuglog("kucoin: $e");
curl_close($ch);
return false;
}
$result = json_decode($res);
if(!is_object($result) && !is_array($result)) {
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
debuglog("kucoin: $method failed ($status) ".strip_data($res));
}
curl_close($ch);
return $result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// manual update of one market
function kucoin_update_market($market)
{
$exchange = 'kucoin';
if (is_string($market))
{
$symbol = $market;
$coin = getdbosql('db_coins', "symbol=:sym", array(':sym'=>$symbol));
if(!$coin) return false;
$pair = $symbol.'-BTC';
$market = getdbosql('db_markets', "coinid={$coin->id} AND name='$exchange'");
if(!$market) return false;
} else if (is_object($market)) {
$coin = getdbo('db_coins', $market->coinid);
if(!$coin) return false;
$symbol = $coin->getOfficialSymbol();
$pair = $symbol.'-BTC';
if (!empty($market->base_coin)) $pair = $symbol.'-'.$market->base_coin;
}
$t1 = microtime(true);
$query = kucoin_api_query("$pair/open/tick");
if(!is_object($query) || !isset($query->data)) return false;
$ticker = $ticker->data;
$price2 = ((double) $ticker->buy + (double)$ticker->sell)/2;
$market->price2 = AverageIncrement($market->price2, $price2);
$market->price = AverageIncrement($market->price, $ticker->buy);
$market->pricetime = time();
$market->save();
$apims = round((microtime(true) - $t1)*1000,3);
user()->setFlash('message', "$exchange $symbol price updated in $apims ms");
return true;
}

View file

@ -0,0 +1,56 @@
<?php
function doKuCoinCancelOrder($OrderID=false)
{
if(!$OrderID) return;
// todo
}
function doKuCoinTrading($quick=false)
{
$exchange = 'kucoin';
$updatebalances = true;
if (exchange_get($exchange, 'disabled')) return;
$data = kucoin_api_user('account/balance');
if (!is_object($data) || !isset($data->data)) return;
$savebalance = getdbosql('db_balances', "name='$exchange'");
if (is_array($data->data))
foreach($data->data as $balance)
{
if ($balance->coinType == 'BTC') {
if (is_object($savebalance)) {
$savebalance->balance = $balance->balance;
$savebalance->save();
}
continue;
}
if ($updatebalances) {
// store available balance in market table
$coins = getdbolist('db_coins', "symbol=:symbol OR symbol2=:symbol",
array(':symbol'=>$balance->coinType)
);
if (empty($coins)) continue;
foreach ($coins as $coin) {
$market = getdbosql('db_markets',
"coinid=:coinid AND name='$exchange' ORDER BY balance"
, array(':coinid'=>$coin->id)
);
if (!$market) continue;
$market->balance = $balance->balance;
$market->ontrade = $balance->freezeBalance;
$market->balancetime = time();
$market->save();
}
}
}
if (!YAAMP_ALLOW_EXCHANGE) return;
// real trading, todo..
}

View file

@ -10,6 +10,7 @@ require_once('alcurex_trading.php');
require_once('coinsmarkets_trading.php');
require_once('cryptopia_trading.php');
require_once('hitbtc_trading.php');
require_once('kucoin_trading.php');
require_once('livecoin_trading.php');
require_once('nova_trading.php');
@ -37,6 +38,9 @@ function cancelExchangeOrder($order=false)
case 'hitbtc':
doHitBTCCancelOrder($order->uuid);
break;
case 'kucoin':
doKuCoinCancelOrder($order->uuid);
break;
case 'livecoin':
doLiveCoinCancelOrder($order->uuid);
break;
@ -113,6 +117,11 @@ function runExchange($exchangeName=false)
updateKrakenMarkets();
break;
case 'kucoin':
doKuCoinTrading(true);
updateKucoinMarkets();
break;
case 'livecoin':
doLiveCoinTrading(true);
updateLiveCoinMarkets();

View file

@ -39,6 +39,7 @@ if (!defined('EXCH_HITBTC_KEY')) define('EXCH_HITBTC_KEY', '');
if (!defined('EXCH_POLONIEX_KEY')) define('EXCH_POLONIEX_KEY', '');
if (!defined('EXCH_YOBIT_KEY')) define('EXCH_YOBIT_KEY', '');
if (!defined('EXCH_KRAKEN_KEY')) define('EXCH_KRAKEN_KEY', '');
if (!defined('EXCH_KUCOIN_KEY')) define('EXCH_KUCOIN_KEY', '');
if (!defined('EXCH_LIVECOIN_KEY')) define('EXCH_LIVECOIN_KEY', '');
if (!defined('EXCH_NOVA_KEY')) define('EXCH_NOVA_KEY', '');
if (!defined('EXCH_STOCKSEXCHANGE_KEY')) define('EXCH_STOCKSEXCHANGE_KEY', '');

View file

@ -147,6 +147,7 @@ class CronjobController extends CommonController
doCCexTrading();
doBterTrading();
doBleutradeTrading();
doKuCoinTrading();
doNovaTrading();
doCoinsMarketsTrading();
break;