From a8a89fbfa8dfc169530c8239f354d76e36047ed7 Mon Sep 17 00:00:00 2001 From: Pablo Criado-Perez Date: Mon, 28 Nov 2022 13:42:51 -0500 Subject: [PATCH 1/3] gemini - fetchMarketsFromApi --- js/gemini.js | 58 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/js/gemini.js b/js/gemini.js index 7fe6229d8125..a7c23fe828ba 100644 --- a/js/gemini.js +++ b/js/gemini.js @@ -232,7 +232,7 @@ module.exports = class gemini extends Exchange { }, }, 'options': { - 'fetchMarketsMethod': 'fetch_markets_from_web', + 'fetchMarketsMethod': 'fetch_markets_from_api', 'fetchTickerMethod': 'fetchTickerV1', // fetchTickerV1, fetchTickerV2, fetchTickerV1AndV2 'networkIds': { 'bitcoin': 'BTC', @@ -371,6 +371,17 @@ module.exports = class gemini extends Exchange { return result; } + parseMarketActive (status) { + const statuses = { + 'open': true, + 'closed': false, + 'cancel_only': true, + 'post_only': true, + 'limit_only': true, + }; + return this.safeValue (statuses, status, true); + } + async fetchMarketsFromAPI (params = {}) { const response = await this.publicGetV1Symbols (params); // @@ -381,14 +392,37 @@ module.exports = class gemini extends Exchange { // ] // const result = []; + let promises = []; for (let i = 0; i < response.length; i++) { - const marketId = response[i]; - const market = marketId; - const idLength = marketId.length - 0; - const baseId = marketId.slice (0, idLength - 3); - const quoteId = marketId.slice (idLength - 3, idLength); + let marketId = response[i]; + marketId = marketId.toUpperCase (); + const method = 'publicGetV1SymbolsDetailsSymbol'; + const request = { + 'symbol': marketId, + }; + // + // { + // "symbol": "BTCUSD", + // "base_currency": "BTC", + // "quote_currency": "USD", + // "tick_size": 1E-8, + // "quote_increment": 0.01, + // "min_order_size": "0.00001", + // "status": "open", + // "wrap_enabled": false + // } + // + promises.push (this[method] (this.extend (request, params))); + } + promises = await Promise.all (promises); + for (let i = 0; i < promises.length; i++) { + const response = promises[i]; + const marketId = this.safeString (response, 'symbol'); + const baseId = this.safeString (response, 'base_currency'); const base = this.safeCurrencyCode (baseId); + const quoteId = this.safeString (response, 'quote_currency'); const quote = this.safeCurrencyCode (quoteId); + const status = this.safeString (response, 'status'); result.push ({ 'id': marketId, 'symbol': base + '/' + quote, @@ -404,7 +438,7 @@ module.exports = class gemini extends Exchange { 'swap': false, 'future': false, 'option': false, - 'active': undefined, + 'active': this.parseMarketActive (status), 'contract': false, 'linear': undefined, 'inverse': undefined, @@ -414,8 +448,8 @@ module.exports = class gemini extends Exchange { 'strike': undefined, 'optionType': undefined, 'precision': { - 'price': undefined, - 'amount': undefined, + 'price': this.safeNumber (response, 'quote_increment'), + 'amount': this.safeNumber (response, 'tick_size'), }, 'limits': { 'leverage': { @@ -423,7 +457,7 @@ module.exports = class gemini extends Exchange { 'max': undefined, }, 'amount': { - 'min': undefined, + 'min': this.safeNumber (response, 'min_order_size'), 'max': undefined, }, 'price': { @@ -435,7 +469,7 @@ module.exports = class gemini extends Exchange { 'max': undefined, }, }, - 'info': market, + 'info': response, }); } return result; @@ -1317,7 +1351,7 @@ module.exports = class gemini extends Exchange { } nonce () { - return this.milliseconds (); + return this.seconds (); } async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { From 45de6d3d004fceae8fe9ea478da5a418b26eb978 Mon Sep 17 00:00:00 2001 From: Pablo Criado-Perez Date: Wed, 30 Nov 2022 17:50:09 +0100 Subject: [PATCH 2/3] add options to fetchDetails by symbol --- js/gemini.js | 69 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/js/gemini.js b/js/gemini.js index a7c23fe828ba..405d08cc04df 100644 --- a/js/gemini.js +++ b/js/gemini.js @@ -232,7 +232,11 @@ module.exports = class gemini extends Exchange { }, }, 'options': { - 'fetchMarketsMethod': 'fetch_markets_from_api', + 'fetchMarketsMethod': 'fetch_markets_from_web', + 'fetchMarketsFromAPI': { + 'fetchDetailsForAllSymbols': false, + 'fetchDetailsForMarketIds': [], + }, 'fetchTickerMethod': 'fetchTickerV1', // fetchTickerV1, fetchTickerV2, fetchTickerV1AndV2 'networkIds': { 'bitcoin': 'BTC', @@ -391,15 +395,63 @@ module.exports = class gemini extends Exchange { // ... // ] // - const result = []; - let promises = []; + const result = {}; for (let i = 0; i < response.length; i++) { - let marketId = response[i]; - marketId = marketId.toUpperCase (); + const marketId = response[i]; + const idLength = marketId.length - 0; + const baseId = marketId.slice (0, idLength - 3); // Not true for all markets + const quoteId = marketId.slice (idLength - 3, idLength); + const base = this.safeCurrencyCode (baseId); + const quote = this.safeCurrencyCode (quoteId); + result[marketId] = { + 'id': marketId, + 'symbol': base + '/' + quote, + 'swap': false, + 'future': false, + 'option': false, + 'active': undefined, + 'contract': false, + 'linear': undefined, + 'inverse': undefined, + 'strike': undefined, + 'optionType': undefined, + 'precision': { + 'price': undefined, + 'amount': undefined, + }, + 'limits': { + 'leverage': { + 'min': undefined, + 'max': undefined, + }, + 'amount': { + 'min': undefined, + 'max': undefined, + }, + 'price': { + 'max': undefined, + }, + }, + 'info': marketId, + }; + } + const options = this.safeValue (this.options, 'fetchMarketsFromAPI', {}); + const fetchDetailsForAllSymbols = this.safeValue (options, 'fetchDetailsForAllSymbols', false); + const fetchDetailsForMarketIds = this.safeValue (options, 'fetchDetailsForMarketIds', []); + let promises = []; + let marketIds = []; + if (fetchDetailsForAllSymbols) { + marketIds = response; + } else { + marketIds = fetchDetailsForMarketIds; + } + for (let i = 0; i < marketIds.length; i++) { + const marketId = marketIds[i]; const method = 'publicGetV1SymbolsDetailsSymbol'; const request = { 'symbol': marketId, }; + promises.push (this[method] (this.extend (request, params))); // // { // "symbol": "BTCUSD", @@ -412,18 +464,17 @@ module.exports = class gemini extends Exchange { // "wrap_enabled": false // } // - promises.push (this[method] (this.extend (request, params))); } promises = await Promise.all (promises); for (let i = 0; i < promises.length; i++) { const response = promises[i]; - const marketId = this.safeString (response, 'symbol'); + const marketId = this.safeStringLower (response, 'symbol'); const baseId = this.safeString (response, 'base_currency'); const base = this.safeCurrencyCode (baseId); const quoteId = this.safeString (response, 'quote_currency'); const quote = this.safeCurrencyCode (quoteId); const status = this.safeString (response, 'status'); - result.push ({ + result[marketId] = ({ 'id': marketId, 'symbol': base + '/' + quote, 'base': base, @@ -472,7 +523,7 @@ module.exports = class gemini extends Exchange { 'info': response, }); } - return result; + return this.toArray (result); } async fetchOrderBook (symbol, limit = undefined, params = {}) { From 20c19f4673316eaabd72c53f5e69d690883ff8c9 Mon Sep 17 00:00:00 2001 From: Pablo Criado-Perez Date: Fri, 16 Dec 2022 22:00:12 +0100 Subject: [PATCH 3/3] changed back to seconds and added retry --- js/gemini.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/js/gemini.js b/js/gemini.js index 405d08cc04df..0041137a75c2 100644 --- a/js/gemini.js +++ b/js/gemini.js @@ -233,6 +233,7 @@ module.exports = class gemini extends Exchange { }, 'options': { 'fetchMarketsMethod': 'fetch_markets_from_web', + 'fetchMarketFromWebRetries': 10, 'fetchMarketsFromAPI': { 'fetchDetailsForAllSymbols': false, 'fetchDetailsForMarketIds': [], @@ -275,7 +276,21 @@ module.exports = class gemini extends Exchange { } async fetchMarketsFromWeb (params = {}) { - const response = await this.webGetRestApi (params); + // This endpoint so we retry + const maxRetries = this.safeInteger (this.options, 'fetchMarketFromWebRetries', 10); + let response = undefined; + let retry = 0; + while (retry < maxRetries) { + try { + response = await this.webGetRestApi (params); + break; + } catch (e) { + retry = retry + 1; + if (retry === maxRetries) { + throw e; + } + } + } const sections = response.split ('

Symbols and minimums

'); const numSections = sections.length; const error = this.id + ' fetchMarketsFromWeb() the ' + this.name + ' API doc HTML markup has changed, breaking the parser of order limits and precision info for ' + this.name + ' markets.'; @@ -1402,7 +1417,7 @@ module.exports = class gemini extends Exchange { } nonce () { - return this.seconds (); + return this.milliseconds (); } async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {