{"action":"created","issue":{"url":"https://api.github.com/repos/ccxt/ccxt/issues/1399","repository_url":"https://api.github.com/repos/ccxt/ccxt","labels_url":"https://api.github.com/repos/ccxt/ccxt/issues/1399/labels{/name}","comments_url":"https://api.github.com/repos/ccxt/ccxt/issues/1399/comments","events_url":"https://api.github.com/repos/ccxt/ccxt/issues/1399/events","html_url":"https://github.com/ccxt/ccxt/issues/1399","id":290249384,"number":1399,"title":"rateLimits","user":{"login":"michnovka","id":16553087,"avatar_url":"https://avatars1.githubusercontent.com/u/16553087?v=4","gravatar_id":"","url":"https://api.github.com/users/michnovka","html_url":"https://github.com/michnovka","followers_url":"https://api.github.com/users/michnovka/followers","following_url":"https://api.github.com/users/michnovka/following{/other_user}","gists_url":"https://api.github.com/users/michnovka/gists{/gist_id}","starred_url":"https://api.github.com/users/michnovka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michnovka/subscriptions","organizations_url":"https://api.github.com/users/michnovka/orgs","repos_url":"https://api.github.com/users/michnovka/repos","events_url":"https://api.github.com/users/michnovka/events{/privacy}","received_events_url":"https://api.github.com/users/michnovka/received_events","type":"User","site_admin":false},"labels":[{"id":604886969,"url":"https://api.github.com/repos/ccxt/ccxt/labels/question","name":"question","color":"cc317c","default":true}],"state":"open","locked":false,"assignee":{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false},"assignees":[{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false}],"milestone":null,"comments":8,"created_at":"2018-01-21T05:53:37Z","updated_at":"2018-02-09T01:06:39Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"\r\nI was wondering how you come up with rateLimit values for given exchanges. They are usually > 1000 (as I understand this is in ms), but on exchanges which publish their limits its more like 1000/min and 1,000,000/day which comes to about 87ms rateLimit instead.\r\n\r\nI would also like to spark conversation about implementing rateLimit natively into all libs so that we do not have to care about ddos protection in our code. \r\n\r\nThis is what I use now in my code:\r\n\r\n```\r\n\r\nlet _EXCHANGES_API_LAST_CALLED = {};\r\n\r\nfunction APICallTimeLog(exchange_id){\r\n    _EXCHANGES_API_LAST_CALLED[exchange_id] = Date.now();\r\n}\r\n\r\nasync function APISleep(exchange_id){\r\n\r\n    let sleep = (ms) => new Promise (resolve => setTimeout (resolve, ms));\r\n\r\n    let wait_time = APICallWait(exchange_id);\r\n\r\n    if(wait_time)\r\n        await sleep(wait_time);\r\n\r\n    APICallTimeLog(exchange_id);\r\n\r\n}\r\n\r\nfunction APICallWait(exchange_id){\r\n    if(!_EXCHANGES_API_LAST_CALLED[exchange_id])\r\n        return 0;\r\n\r\n    let last_called_time = parseInt(_EXCHANGES_API_LAST_CALLED[exchange_id]);\r\n\r\n    let wait = last_called_time + config.exchanges[exchange_id].rateLimit - Date.now();\r\n\r\n    if(wait < 0)\r\n        return 0;\r\n\r\n    return wait;\r\n}\r\n```\r\n\r\nand then during API communications:\r\n\r\n```\r\n\r\n            let promise = (async () => {\r\n\r\n                await APISleep(exchange_id);\r\n\r\n                return await exchange.fetchTickers();\r\n            })();\r\n\r\n```\r\n\r\nwould be nice if all this were under the hood implemented. I am willing to look into this if there is interest, thanks for your opinion"},"comment":{"url":"https://api.github.com/repos/ccxt/ccxt/issues/comments/364302655","html_url":"https://github.com/ccxt/ccxt/issues/1399#issuecomment-364302655","issue_url":"https://api.github.com/repos/ccxt/ccxt/issues/1399","id":364302655,"user":{"login":"kroitor","id":1294454,"avatar_url":"https://avatars3.githubusercontent.com/u/1294454?v=4","gravatar_id":"","url":"https://api.github.com/users/kroitor","html_url":"https://github.com/kroitor","followers_url":"https://api.github.com/users/kroitor/followers","following_url":"https://api.github.com/users/kroitor/following{/other_user}","gists_url":"https://api.github.com/users/kroitor/gists{/gist_id}","starred_url":"https://api.github.com/users/kroitor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kroitor/subscriptions","organizations_url":"https://api.github.com/users/kroitor/orgs","repos_url":"https://api.github.com/users/kroitor/repos","events_url":"https://api.github.com/users/kroitor/events{/privacy}","received_events_url":"https://api.github.com/users/kroitor/received_events","type":"User","site_admin":false},"created_at":"2018-02-09T01:06:39Z","updated_at":"2018-02-09T01:06:39Z","author_association":"OWNER","body":"@michnovka sorry, I didn't quite get the last question and missed it somehow, can you elaborate please? Most of details are already described in my initial answer above. Do you mean something beyond that?"}}
{"actor":{"display_login":"kroitor"}}