@@ -103,72 +103,85 @@ protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketS
103103 {
104104 string html = await RequestMaker.MakeRequestAsync("/rest-api", "https://docs.gemini.com");
105105 int startPos = html.IndexOf("<h1 id=\"symbols-and-minimums\">Symbols and minimums</h1>");
106- if (startPos >= 0)
106+ if (startPos < 0)
107107 {
108- startPos = html.IndexOf("<tbody>", startPos);
109- if (startPos >= 0)
108+ throw new ApplicationException("Gemini html for symbol metadata is missing expected h1 tag and id");
109+ }
110+
111+ startPos = html.IndexOf("<tbody>", startPos);
112+ if (startPos < 0)
113+ {
114+ throw new ApplicationException("Gemini html for symbol metadata is missing start tbody tag");
115+ }
116+
117+ int endPos = html.IndexOf("</tbody>", startPos);
118+ if (endPos < 0)
119+ {
120+ throw new ApplicationException("Gemini html for symbol metadata is missing ending tbody tag");
121+ }
122+
123+ string table = html.Substring(startPos, endPos - startPos + "</tbody>".Length);
124+ string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + table;
125+ XmlDocument doc = new XmlDocument();
126+ doc.LoadXml(xml);
127+ if (doc.ChildNodes.Count < 2)
128+ {
129+ throw new ApplicationException("Gemini html for symbol metadata does not have the expected number of nodes");
130+ }
131+
132+ XmlNode root = doc.ChildNodes.Item(1);
133+ foreach (XmlNode tr in root.ChildNodes)
134+ {
135+ // <tr>
136+ // <th>Symbol</th>
137+ // <th>Minimum Order Size</th>
138+ // <th>Tick Size</th>
139+ // <th>Quote Currency Price Increment</th>
140+
141+ // <td>btcusd</td>
142+ // <td>0.00001 BTC (1e-5)</td>
143+ // <td>0.00000001 BTC (1e-8)</td>
144+ // <td>0.01 USD</td>
145+ // </tr>
146+
147+ if (tr.ChildNodes.Count != 4)
110148 {
111- int endPos = html.IndexOf("</tbody>", startPos);
112- string table = html.Substring(startPos, endPos - startPos + "</tbody>".Length);
113- string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + table;
114- XmlDocument doc = new XmlDocument();
115- doc.LoadXml(xml);
116- if (doc.ChildNodes.Count > 1)
117- {
118- XmlNode root = doc.ChildNodes.Item(1);
119- foreach (XmlNode tr in root.ChildNodes)
120- {
121- // <tr>
122- // <th>Symbol</th>
123- // <th>Minimum Order Size</th>
124- // <th>Tick Size</th>
125- // <th>Quote Currency Price Increment</th>
126-
127- // <td>btcusd</td>
128- // <td>0.00001 BTC (1e-5)</td>
129- // <td>0.00000001 BTC (1e-8)</td>
130- // <td>0.01 USD</td>
131- // </tr>
132-
133- if (tr.ChildNodes.Count == 4)
134- {
135- ExchangeMarket market = new ExchangeMarket { IsActive = true };
136- XmlNode symbolNode = tr.ChildNodes.Item(0);
137- XmlNode minOrderSizeNode = tr.ChildNodes.Item(1);
138- XmlNode tickSizeNode = tr.ChildNodes.Item(2);
139- XmlNode incrementNode = tr.ChildNodes.Item(3);
140- string symbol = symbolNode.InnerText;
141- int minOrderSizePos = minOrderSizeNode.InnerText.IndexOf(' ');
142- if (minOrderSizePos < 0)
143- {
144- throw new ArgumentException("Min order size text does not have a space after the number");
145- }
146- decimal minOrderSize = minOrderSizeNode.InnerText.Substring(0, minOrderSizePos).ConvertInvariant<decimal>();
147- int tickSizePos = tickSizeNode.InnerText.IndexOf(' ');
148- if (tickSizePos < 0)
149- {
150- throw new ArgumentException("Tick size text does not have a space after the number");
151- }
152- decimal tickSize = tickSizeNode.InnerText.Substring(0, tickSizePos).ConvertInvariant<decimal>();
153- int incrementSizePos = incrementNode.InnerText.IndexOf(' ');
154- if (incrementSizePos < 0)
155- {
156- throw new ArgumentException("Increment size text does not have a space after the number");
157- }
158- decimal incrementSize = incrementNode.InnerText.Substring(0, incrementSizePos).ConvertInvariant<decimal>();
159- market.MarketSymbol = symbol;
160- market.BaseCurrency = symbol.Substring(0, symbol.Length - 3);
161- market.QuoteCurrency = symbol.Substring(symbol.Length - 3);
162- market.MinTradeSize = minOrderSize;
163- market.QuantityStepSize = tickSize;
164- market.PriceStepSize = incrementSize;
165- markets.Add(market);
166- }
167- }
168- return markets;
169- }
149+ throw new ApplicationException("Gemini html for symbol metadata does not have 4 rows per entry anymore");
150+ }
151+
152+ ExchangeMarket market = new ExchangeMarket { IsActive = true };
153+ XmlNode symbolNode = tr.ChildNodes.Item(0);
154+ XmlNode minOrderSizeNode = tr.ChildNodes.Item(1);
155+ XmlNode tickSizeNode = tr.ChildNodes.Item(2);
156+ XmlNode incrementNode = tr.ChildNodes.Item(3);
157+ string symbol = symbolNode.InnerText;
158+ int minOrderSizePos = minOrderSizeNode.InnerText.IndexOf(' ');
159+ if (minOrderSizePos < 0)
160+ {
161+ throw new ArgumentException("Min order size text does not have a space after the number");
162+ }
163+ decimal minOrderSize = minOrderSizeNode.InnerText.Substring(0, minOrderSizePos).ConvertInvariant<decimal>();
164+ int tickSizePos = tickSizeNode.InnerText.IndexOf(' ');
165+ if (tickSizePos < 0)
166+ {
167+ throw new ArgumentException("Tick size text does not have a space after the number");
168+ }
169+ decimal tickSize = tickSizeNode.InnerText.Substring(0, tickSizePos).ConvertInvariant<decimal>();
170+ int incrementSizePos = incrementNode.InnerText.IndexOf(' ');
171+ if (incrementSizePos < 0)
172+ {
173+ throw new ArgumentException("Increment size text does not have a space after the number");
170174 }
175+ decimal incrementSize = incrementNode.InnerText.Substring(0, incrementSizePos).ConvertInvariant<decimal>();
176+ market.MarketSymbol = symbol;
177+ market.BaseCurrency = symbol.Substring(0, symbol.Length - 3);
178+ market.QuoteCurrency = symbol.Substring(symbol.Length - 3);
179+ market.MinTradeSize = minOrderSize;
180+ market.QuantityStepSize = tickSize;
181+ market.PriceStepSize = incrementSize;
182+ markets.Add(market);
171183 }
184+ return markets;
172185 }
173186 catch (Exception ex)
174187 {
0 commit comments