/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = "https://cex.io/api/balance/"; $logger->info($url); try { $this->throttle($logger); $post_data = $this->generatePostData($account); $logger->info($post_data); $raw = Fetch::post($url, $post_data); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getContent(), $e); } $json = Fetch::jsonDecode($raw); if (isset($json['error'])) { throw new AccountFetchException($json['error']); } $result = array(); foreach ($this->fetchSupportedCurrencies($factory, $logger) as $cur) { $code = $this->getCEXioCode($cur); if (isset($json[$code])) { $result[$cur] = array('available' => $json[$code]['available']); if (isset($json[$code]['orders'])) { $result[$cur]['reserved'] = $json[$code]['orders']; $result[$cur]['confirmed'] = $result[$cur]['available'] + $result[$cur]['reserved']; } else { $result[$cur]['confirmed'] = $result[$cur]['available']; } } } return $result; }
function fetchAllRates(Logger $logger) { $params = $this->generatePostData("getmarkets"); $url = "https://www.cryptsy.com/api"; $logger->info($url); $raw = Fetch::post($url, $params['post'], array(), $params['headers']); $json = Fetch::jsonDecode($raw); if (!$json['success']) { throw new ExchangeRateException($json['error']); } $result = array(); foreach ($json['return'] as $market) { $key = $market['label']; if ($market['last_trade'] == 0) { $logger->info("Ignoring '{$key}' market: last trade price is 0"); continue; } $currency1 = $this->getCurrencyCode($market['secondary_currency_code']); $currency2 = $this->getCurrencyCode($market['primary_currency_code']); $rate = array("currency1" => $currency1, "currency2" => $currency2, "last_trade" => $market['last_trade'], "volume" => $market['current_volume'], 'low' => $market['low_trade'], 'high' => $market['high_trade']); if ($this->shouldSwitch($currency1, $currency2)) { $rate = array('currency1' => $rate['currency2'], 'currency2' => $rate['currency1'], 'last_trade' => 1 / $rate['last_trade'], 'volume' => $rate['volume'] / $rate['last_trade'], 'low' => $rate['high'] == 0 ? 0 : 1 / $rate['high'], 'high' => $rate['low'] == 0 ? 0 : 1 / $rate['low']); } $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $this->getItBitCode($currency2) . $this->getItBitCode($currency1); $url = "https://www.itbit.com/api/v2/markets/" . $key . "/orders"; $logger->info($url); $orders = Fetch::jsonDecode(Fetch::get($url)); if (isset($orders['message'])) { throw new ExternalAPIException($orders['message']); } if (!isset($orders['bids']) || count($orders['bids']) == 0) { throw new ExternalAPIException("No bids for {$key}"); } if (!isset($orders['asks']) || count($orders['asks']) == 0) { throw new ExternalAPIException("No asks for {$key}"); } $this->throttle($logger); $url = "https://www.itbit.com/api/v2/markets/" . $key . "/trades?since=0"; $logger->info($url); // TODO keep track of last trade ID and use that as ?since parameter $trades = Fetch::jsonDecode(Fetch::get($url)); $rate = array("currency1" => $currency1, "currency2" => $currency2, "last_trade" => $trades[0]['price'], "bid" => $orders['bids'][0][0], "ask" => $orders['asks'][0][0]); $result[] = $rate; } return $result; }
/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = "https://bitminter.com/api/users"; $logger->info($url); $options = array(CURLOPT_HTTPHEADER => array("Authorization: key=" . $account['api_key'])); try { $this->throttle($logger); $raw = Fetch::get($url, $options); } catch (FetchHttpException $e) { if (!$e->getContent()) { throw new AccountFetchException("Empty response: Have you enabled the API perk?"); } throw new AccountFetchException($e->getContent(), $e); } if ($raw === "Access denied") { throw new AccountFetchException("Access denied"); } if (!$raw) { throw new AccountFetchException("Empty response: Have you enabled the API perk?"); } $json = Fetch::jsonDecode($raw); if (isset($json['message'])) { throw new AccountFetchException($json['message']); } return array('btc' => array('confirmed' => isset($json['balances']['BTC']) ? $json['balances']['BTC'] : 0, 'hashrate' => $json['hash_rate'] * 1000000.0, 'workers' => $json['active_workers']), 'nmc' => array('confirmed' => isset($json['balances']['NMC']) ? $json['balances']['NMC'] : 0, 'hashrate' => $json['hash_rate'] * 1000000.0, 'workers' => $json['active_workers'])); }
/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = "https://www.bitmarket.pl/api2/"; $logger->info($url); try { $this->throttle($logger); $post_data = $this->generatePostData($account); $logger->info($post_data['post_data']); $raw = Fetch::post($url, $post_data['post_data'], array(), $post_data['headers']); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getMessage(), $e); } $json = Fetch::jsonDecode($raw); if (isset($json['errorMsg'])) { throw new AccountFetchException($json['errorMsg']); } if (isset($json['error'])) { throw new AccountFetchException($json['error']); } $result = array(); foreach ($this->fetchSupportedCurrencies($factory, $logger) as $cur) { $result[$cur] = array('available' => $json['data']['balances']['available'][$this->getBitMarketPlCode($cur)]); if (isset($json['data']['balances']['blocked'][$this->getBitMarketPlCode($cur)])) { $result[$cur]['blocked'] = $json['data']['balances']['blocked'][$this->getBitMarketPlCode($cur)]; $result[$cur]['confirmed'] = $result[$cur]['available'] + $result[$cur]['blocked']; } else { $result[$cur]['confirmed'] = $result[$cur]['available']; } } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $this->getANXPROCode($currency2) . $this->getANXPROCode($currency1); $url = "https://anxpro.com/api/2/" . $key . "/money/ticker"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!$json['data']['buy']['value']) { $logger->info("Ignoring pair {$key}: bid is zero"); continue; } if (!$json['data']['sell']['value']) { $logger->info("Ignoring pair {$key}: ask is zero"); continue; } if (!isset($json['data']['last']['value'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => $currency1, "currency2" => $currency2, "bid" => $json['data']['buy']['value'], "ask" => $json['data']['sell']['value'], "last_trade" => $json['data']['last']['value'], "volume" => $json['data']['vol']['value'], "high" => $json['data']['high']['value'], "low" => $json['data']['low']['value'], "vwap" => $json['data']['vwap']['value'], "avg" => $json['data']['avg']['value']); $result[] = $rate; } return $result; }
/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $vircurex_balance_count = rand(0, 0xffff); $result = array(); foreach ($this->fetchSupportedCurrencies($factory, $logger) as $cur) { $currency = $this->getVircurexCode($cur); $timestamp = gmdate('Y-m-d\\TH:i:s'); // UTC time $id = md5(time() . "_" . rand(0, 9999) . "_" . $vircurex_balance_count++); $token = hash('sha256', $account['api_secret'] . ";" . $account['api_username'] . ";" . $timestamp . ";" . $id . ";" . "get_balance" . ";" . $currency); $url = "https://api.vircurex.com/api/get_balance.json?account=" . urlencode($account['api_username']) . "&id=" . urlencode($id) . "&token=" . urlencode($token) . "×tamp=" . urlencode($timestamp) . "¤cy=" . urlencode($currency); $logger->info($url); $this->throttle($logger); $raw = Fetch::get($url); $json = Fetch::jsonDecode($raw); if (isset($json['statustxt']) && $json['statustxt']) { throw new AccountFetchException($json['statustxt'] . " for currency {$currency}"); } if (isset($json['statustext']) && $json['statustext']) { throw new AccountFetchException($json['statustext'] . " for currency {$currency}"); } $result[$cur] = array('confirmed' => $json['balance'], 'available' => $json['availablebalance']); } return $result; }
function fetchAllRates(Logger $logger) { $url = "https://www.coins-e.com/api/v2/markets/data/"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); $result = array(); $retired = 0; foreach ($json as $key => $market) { if ($market['status'] == 'retired') { $retired++; continue; } if ($market['marketstat']['ltp'] == 0) { $logger->info("Ignoring '{$key}' market: last trade price is 0"); continue; } $pairs = explode("_", $key, 2); $currency1 = $this->getCurrencyCode($pairs[0]); $currency2 = $this->getCurrencyCode($pairs[1]); $rate = array("currency1" => $currency2, "currency2" => $currency1, "last_trade" => $market['marketstat']['ltp'], "bid" => $market['marketstat']['bid'], "ask" => $market['marketstat']['ask'], "volume" => $market['marketstat']['24h']['volume'], "high" => $market['marketstat']['24h']['h'], "low" => $market['marketstat']['24h']['l'], "avg" => $market['marketstat']['24h']['avg_rate']); $result[] = $rate; } $logger->info("Ignored {$retired} retired markets"); return $result; }
function fetchAllRates(Logger $logger) { $url = "https://api.vircurex.com/api/get_info_for_currency.json"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); $result = array(); $ignored = 0; foreach ($json as $pair2 => $pairs) { if ($pair2 == "status") { continue; } foreach ($pairs as $pair1 => $market) { if ($market['last_trade'] == 0 || $market['lowest_ask'] == 0 || $market['highest_bid'] == 0) { // ignore empty markets $ignored++; continue; } $currency1 = $this->getCurrencyCode($pair1); $currency2 = $this->getCurrencyCode($pair2); if (CurrencyOrder::hasOrder($currency1) && CurrencyOrder::hasOrder($currency2)) { if (!CurrencyOrder::isOrdered($currency1, $currency2)) { // do not duplicate ordered currencies continue; } } $rate = array("currency1" => $currency1, "currency2" => $currency2, "last_trade" => $market['last_trade'], "volume" => $market['volume'], 'bid' => $market['highest_bid'], 'ask' => $market['lowest_ask']); $result[] = $rate; } } $logger->info("Ignored " . $ignored . " markets with last trade price of 0"); return $result; }
function getAccountLines($address, Logger $logger) { $url = $this->url; $logger->info($url); $data = array("method" => "account_lines", "params" => array(array("account" => $address))); $json = Fetch::jsonDecode(Fetch::post($url, json_encode($data))); return $json['result']['lines']; }
/** * * @throws {@link DifficultyException} if something happened and the balance could not be obtained. */ function getDifficulty(Logger $logger) { $url = sprintf("%sdifficulty", $this->url); $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); $value = $json['difficulty']; $logger->info("Difficulty: " . number_format($value)); return $value; }
function fetchAllRates(Logger $logger) { $url = "https://data.btcchina.com/data/ticker"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['ticker']['last'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => "cny", "currency2" => "btc", "bid" => $json['ticker']['buy'], "ask" => $json['ticker']['sell'], "last_trade" => $json['ticker']['last'], "volume" => $json['ticker']['vol'], "high" => $json['ticker']['high'], "low" => $json['ticker']['low'], "vwap" => $json['ticker']['vwap'], "open" => $json['ticker']['open']); return array($rate); }
function fetchAllRates(Logger $logger) { $url = "https://bitnz.com/api/0/ticker"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['last'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => "nzd", "currency2" => "btc", "bid" => $json['bid'], "ask" => $json['ask'], "last_trade" => $json['last'], "volume" => $json['volume'], "high" => $json['high'], "low" => $json['low'], "vwap" => $json['vwap']); return array($rate); }
function getDifficulty(Logger $logger) { $url = $this->info_url; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['Difficulty'])) { throw new DifficultyException("Could not find difficulty"); } $value = $json['Difficulty']; $logger->info("Difficulty: " . number_format($value)); return $value; }
function getBlockCount(Logger $logger) { $url = $this->blocks_url; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (isset($json['data'][0]['nm_height'])) { $value = $json['data'][0]['nm_height']; $logger->info("Block count: " . number_format($value)); } else { throw new BlockException("Could not find block count for currency '" . $this->currency->getCode() . "'"); } return $value; }
function getBalance($address, Logger $logger) { $url = sprintf("http://api.blockscan.com/api2?module=address&action=balance&btc_address=%s&asset=%s", $address, $this->asset_name); $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if ($json['status'] == "error") { throw new BalanceException($json['message']); } else { $balance = $json['data'][0]['balance']; } $logger->info("Blockchain balance for " . htmlspecialchars($address) . ": " . $balance); return $balance; }
/** * @return the Proof of Work difficulty */ function getDifficulty(Logger $logger) { if (!$this->info_url) { throw new DifficultyException("No known difficulty URL for currency '" . $this->currency->getCode() . "'"); } $url = $this->info_url; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['powInt'])) { throw new BlockException("Could not find block height"); } $value = $json['powInt']; $logger->info("Difficulty: " . number_format($value)); return $value; }
function fetchAllRates(Logger $logger) { $url = "https://www.havelockinvestments.com/r/tickerfull"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); $result = array(); foreach ($json as $security) { // skip any zero-traded symbols if ($security['last'] == 0) { continue; } $result[$security['symbol']] = array('currency' => 'btc', 'security' => $security['symbol'], 'name' => $security['name'], 'last_trade' => $security['last'], 'units' => $security['units'], 'volume' => $security['1d']['vol'], 'high' => $security['1d']['max'], 'low' => $security['1d']['min']); } return $result; }
function getDifficulty(Logger $logger) { if (!$this->info_url) { throw new DifficultyException("No known difficulty URL for currency '" . $this->currency->getCode() . "'"); } $url = $this->info_url; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); try { $data = Fetch::checkJSend($json); } catch (JSendException $e) { throw new BlockException($e->getMessage(), $e); } $value = $data['last_block']['difficulty']; $logger->info("Difficulty: " . number_format($value)); return $value; }
/** * * @throws {@link DifficultyException} if something happened and the balance could not be obtained. */ function getDifficulty(Logger $logger) { $url = $this->info_url; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (isset($json['info']['difficulty']['proof-of-work'])) { $value = $json['info']['difficulty']['proof-of-work']; } else { if (isset($json['info']['difficulty'])) { $value = $json['info']['difficulty']; } else { throw new DifficultyException("Difficulty was not present"); } } $logger->info("Difficulty: " . number_format($value)); return $value; }
function fetchAllRates(Logger $logger) { $url = "https://bittrex.com/api/v1.1/public/getmarketsummaries"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!$json['success']) { throw new ExchangeRateException($json['message']); } $result = array(); foreach ($json['result'] as $market) { $pairs = explode("-", $market['MarketName'], 2); $currency1 = $this->getCurrencyCode($pairs[0]); $currency2 = $this->getCurrencyCode($pairs[1]); $rate = array("currency1" => $currency1, "currency2" => $currency2, "bid" => $market['Bid'], "ask" => $market['Ask'], "last_trade" => $market['Last'], "volume" => $market['BaseVolume'], "high" => $market['High'], "low" => $market['Low']); $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $this->getBitcurexCode($currency1); $url = "https://bitcurex.com/api/" . $key . "/ticker.json"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['last_tx_price'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => $currency1, "currency2" => $currency2, "last_trade" => $json['last_tx_price'] / 10000.0, "bid" => $json['best_bid'] / 10000.0, "ask" => $json['best_ask'] / 10000.0, "avg" => $json['average_price'] / 10000.0, "volume" => $json['last24_volume'] / 100000000.0); $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $this->getBit2cCode($currency2) . $this->getBit2cCode($currency1); $url = "https://www.bit2c.co.il/Exchanges/" . $key . "/Ticker.json"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['ll'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => $currency1, "currency2" => $currency2, "bid" => $json['h'], "ask" => $json['l'], "last_trade" => $json['ll'], "volume" => $json['a'], "avg" => $json['av']); $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $this->getBitmarketPlCode($currency2) . $this->getBitmarketPlCode($currency1); $url = "https://www.bitmarket.pl/json/" . $key . "/ticker.json"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['last'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => $currency1, "currency2" => $currency2, "bid" => $json['bid'], "ask" => $json['ask'], "last_trade" => $json['last'], "volume" => $json['volume'], "low" => $json['low'], "high" => $json['high'], "vwap" => $json['vwap']); $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $url = "http://data.bter.com/api/1/tickers"; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); $result = array(); foreach ($json as $key => $market) { if ($market['last'] == 0) { // ignore any broken markets continue; } $pairs = explode("_", $key, 2); $currency1 = $this->getCurrencyCode($pairs[0]); $currency2 = $this->getCurrencyCode($pairs[1]); $rate = array("currency1" => $currency2, "currency2" => $currency1, "bid" => $market['buy'], "ask" => $market['sell'], "last_trade" => $market['last'], "volume" => $market['vol_' . $pairs[0]], "high" => $market['high'], "low" => $market['low']); $result[] = $rate; } return $result; }
function fetchAllRates(Logger $logger) { $result = array(); foreach ($this->fetchMarkets($logger) as $pair) { $this->throttle($logger); $currency1 = $pair[0]; $currency2 = $pair[1]; $key = $currency2 . "-" . $currency1; $url = "https://api.virtex.com:443/v1/market/ticker?market=" . $key; $logger->info($url); $json = Fetch::jsonDecode(Fetch::get($url)); if (!isset($json['last'])) { throw new ExchangeRateException("Could not find any last rate"); } $rate = array("currency1" => $currency1, "currency2" => $currency2, "bid" => $json['bid'], "ask" => $json['ask'], "last_trade" => $json['last'], "volume" => $json['volume'], "low" => $json['low'], "high" => $json['high']); $result[] = $rate; } return $result; }
protected function havelockQuery($url, $post_data, Logger $logger) { $logger->info($url); try { $this->throttle($logger); $raw = Fetch::post($url, $post_data); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getMessage(), $e); } if ($raw === "Access denied") { throw new AccountFetchException($raw); } $json = Fetch::jsonDecode($raw); if (isset($json['message']) && $json['message']) { throw new AccountFetchException($json['message']); } if (is_array($json) && !$json) { throw new AccountFetchException("Havelock API returned an empty array"); } return $json; }
/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = "https://www.bit2c.co.il/Account/Balance/v2"; $logger->info($url); try { $this->throttle($logger); $post_data = $this->generatePostData($account); $logger->info($post_data['post_data']); $raw = Fetch::post($url, $post_data['post_data'], array(), $post_data['headers']); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getMessage(), $e); } $json = Fetch::jsonDecode($raw); if (isset($json['error'])) { throw new AccountFetchException($json['error']); } $result = array(); foreach ($this->fetchSupportedCurrencies($factory, $logger) as $cur) { $result[$cur] = array('confirmed' => $json[$this->getBit2cCode($cur)]); } return $result; }
/** * @return all account balances * @throws AccountFetchException if something bad happened */ public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = $this->getBalanceURL(); $logger->info($url); try { $this->throttle($logger); $post_data = $this->generatePostData($account); $logger->info($post_data['post_data']); $raw = Fetch::post($url, $post_data['post_data'], array(), $post_data['headers']); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getMessage(), $e); } $json = Fetch::jsonDecode($raw); if (isset($json['error'])) { throw new AccountFetchException($json['error']); } $result = array(); foreach ($this->fetchSupportedCurrencies($factory, $logger) as $cur) { $result[$cur] = array('confirmed' => $json['data']['Wallets'][$this->getANXCode($cur)]['Balance']['value'], 'available' => $json['data']['Wallets'][$this->getANXCode($cur)]['Available_Balance']['value'], 'daily_withdrawl' => $json['data']['Wallets'][$this->getANXCode($cur)]['Daily_Withdrawal_Limit']['value'], 'max_widthdrawl' => $json['data']['Wallets'][$this->getANXCode($cur)]['Max_Withdraw']['value']); } return $result; }
public function fetchBalances($account, CurrencyFactory $factory, Logger $logger) { $url = "https://www.btcguild.com/api.php?api_key=" . $account['api_key']; $logger->info($url); try { $this->throttle($logger, 15); $raw = Fetch::get($url); } catch (FetchHttpException $e) { throw new AccountFetchException($e->getContent(), $e); } try { $json = Fetch::jsonDecode($raw); } catch (FetchException $e) { throw new AccountFetchException($raw, $e); } $workers = count($json['workers']); $hashrate = 0; foreach ($json['workers'] as $worker) { $hashrate += $worker['hash_rate']; } return array('btc' => array('confirmed' => $json['user']['unpaid_rewards'], 'total' => $json['user']['total_rewards'], 'paid' => $json['user']['paid_rewards'], '24h' => $json['user']['past_24h_rewards'], 'hashrate' => $hashrate * 1000000.0, 'workers' => $workers), 'nmc' => array('confirmed' => $json['user']['unpaid_rewards_nmc'], 'total' => $json['user']['total_rewards_nmc'], 'paid' => $json['user']['paid_rewards_nmc'], '24h' => $json['user']['past_24h_rewards_nmc'], 'hashrate' => $hashrate * 1000000.0, 'workers' => $workers)); }