· 4 years ago · Jun 05, 2021, 07:14 PM
1// This library is for getting cryptocurrency market data from the CoinCap API 2.0 using Javascript - Fetch.
2// Check the documentation here under the RESTful API section for details on the control flow: https://docs.coincap.io/
3// Comments like this are used to divide this script into section. Each comment explains what each section is, how it works and how to use it, as well as any known bugs.
4// This script was designed for Google Sheets and uses the UrlFetchApp class from Google's API to get data from CoinCap. Therefore, this script will not work outside of Google Sheets.
5// I mainly made this to work like GOOGLEFINANCE() and I only intended to use it to get the current market price for cryptos.
6// It should be noted that all of the other functionality is an afterthought and there may be bugs beyond that main feature that I'm not super concerned about.
7// This is also a work in progress. I will be adding functionality from the rest of the CoinCap API soon enough.
8
9
10
11// Modular functions. These functions were not made specifically for this script and can be reused in any program.
12// These are meant to be used by utility and spreadsheet functions, but not meant to be imported and used in the spreadsheet.
13
14var modular = {
15 stringTo2dArray: function(str, d1, d2){
16 str = str.split(d1).map(function(x){ return x.split(d2) });
17 for(var a = 0; a < str.length; a++){
18 for(var b = 0; b < str[a].length; b++){
19 if(!isNaN(Number(str[a][b]))){
20 str[a][b] = Number(str[a][b]);
21 }
22 }
23 }
24 return str;
25 },
26
27 gsub: function(str, oldChar, newChar){
28 for(var a = 0; a < str.length; a++){
29 if(str.substring(a, a+oldChar.length) == oldChar){
30 str = str.substring(0, a) + newChar + str.substring(a+oldChar.length, str.length);
31 }
32 }
33 return str;
34 }
35}
36
37
38
39// Utility functions. These are meant to be used by spreadsheet functions, but not meant to be imported and used in the spreadsheet.
40
41var utility = {
42 separateKeys: function(str, newChar){
43 return modular.gsub(modular.gsub(str, "\":", newChar), "\"", "");
44 },
45
46 structTable: function(arr){
47 var header = ["Index"];
48 var newArr = [];
49 for(var a = 0; a < arr.length; a++){
50 var newDat = [a];
51 for(var b = 0; b < arr.length; b+=2){
52 if(a == 0){
53 header.push(arr[a][b]);
54 }
55 newDat.push(arr[a][b+1]);
56 }
57 newArr.push(newDat);
58 }
59 newArr.splice(0, 0, header);
60 return newArr;
61 },
62
63 requestOptions: function(){
64 return {
65 method: 'GET',
66 redirect: 'follow'
67 };
68 },
69
70 processArray: function(fetchData){
71 var returnData = JSON.stringify(fetchData);
72 return utility.structTable(modular.stringTo2dArray(utility.separateKeys(returnData.substring(2, returnData.length-2), ","), "},{", ","));
73 },
74
75 processObject: function(fetchData){
76 var returnData = JSON.stringify(fetchData);
77 return modular.stringTo2dArray(utility.separateKeys(returnData.substring(1, returnData.length-1), ";"), ",", ";");
78 },
79
80 processKey: function(fetchData){
81 var returnData = fetchData;
82 if(returnData == undefined){
83 throw new Error('Invalid Key.');
84 }else if(isNaN(Number(returnData))){
85 return returnData;
86 }else{
87 return Number(returnData);
88 }
89 }
90}
91
92
93
94// Spreadsheet functions. These are the functions meant to be imported and used in the spreadsheet.
95
96/** COINCAP() searches and returns current or historical data about a given crypto. Check the CoinCap API 2.0 documentation under the RESTful API section for details on the control flow: https://docs.coincap.io/
97 * @param {string} coinSymbol
98 * Required. A valid symbol, id or name of Crypto ("BTC", "bitcoin", "Bitcoin", etc.). This alone will return the current market price in USD.
99 * Example: =COINCAP("Bitcoin") -> Current average price of "Bitcoin".
100 *
101 * @param {string} searchType
102 * Required if 'index' is used. Otherwise optional. Default value is "". "history", "markets", or "". If your array returns a "Result too large" error, set 'startTime' and 'endTime'.
103 * Example: =COINCAP("bitcoin", "markets") -> Array containing all markets with "bitcoin".
104 *
105 * @param {number|string} index
106 * Required if 'key' is used. Otherwise optional. Default value is -1. Index of an array. Set to -1 to get whole array. Acts as 'key' if 'searchType' == "".
107 * Example: =COINCAP("BTC", "", "name") -> Name of "BTC".
108 *
109 * @param {string} key
110 * Required if 'interval' is used. Otherwise optional. Default value is "priceUsd". Property of an object. Set to "" to get all properties.
111 * Example: =COINCAP("BTC", "markets", 1, "exchangeId") -> Exchange ID of element 1 (the 2nd element) of the market list of "BTC".
112 *
113 * @param {string} interval
114 * Required if 'startTime' is used. Otherwise optional. Default value is "d1". String for history interval. Only used when 'searchType' == "history". Does nothing otherwise.
115 * Example: =COINCAP(B4, "history", 1, "", "m1") -> Object data of element 1 (the 2nd element) of the minutely history of the crypto in cell 'B4'.
116 *
117 * @param {Time|Date} startTime
118 * endTime is required if used. Otherwise optional. Time value. Timezone is UTC. Only used when 'searchType' == "history". Does nothing otherwise.
119 *
120 * @param {Time|Date} endTime
121 * Required if startTime is used. Otherwise optional. Time value. Timezone is UTC. Only used when 'searchType' == "history". Does nothing otherwise.
122 * Example: =COINCAP(B5, "history", -1, "", "d1", DATEVALUE(TODAY())-5, DATEVALUE(TODAY())) -> Array containing the daily history of the crypto in cell 'B5' between 5 days ago and today.
123 *
124 * @customfunction
125 */
126function COINCAP(coinSymbol, searchType, index, key, interval, startTime, endTime) {
127 if(searchType == "" || index == "timestamp"){ key = index; }
128
129 if(searchType == undefined){ searchType = ""; }
130 if(index == undefined){ index = -1; }
131 if(key == undefined){ key = "priceUsd"; }
132 if(interval == undefined){ interval = "d1"; }
133 if(startTime != undefined){
134 if(typeof(startTime) != "number" || typeof(endTime) != "number"){ throw new Error('Start and end date must be in number format.'); }
135 if(startTime >= endTime){ throw new Error('Start date must be before end date.'); }
136 startTime = (startTime - 25569) * 86400000;
137 endTime = (endTime - 25569) * 86400000;
138 }
139
140
141 var getData = UrlFetchApp.fetch("api.coincap.io/v2/assets?search=" + coinSymbol, utility.requestOptions());
142 var allData = JSON.parse(getData.getContentText());
143 if(allData.data.length == 0){ throw new Error('No cryptocurrency found.'); }
144
145 for(var a = 0; a < allData.data.length; a++){
146 if(allData.data[a].symbol == coinSymbol || allData.data[a].id == coinSymbol || allData.data[a].name == coinSymbol){
147 allData.data = allData.data[a];
148 foundIt = true;
149 }
150 }
151 if(allData.data.length > 0){ throw new Error('No cryptocurrency found.'); }
152
153
154 if(searchType == "history"){
155 if(startTime == undefined){
156 getData = "api.coincap.io/v2/assets/" + allData.data.id + "/history?interval=" + interval;
157 }else{
158 getData = "api.coincap.io/v2/assets/" + allData.data.id + "/history?interval=" + interval + "&start=" + startTime + "&end=" + endTime;
159 }
160 }else if(searchType == "markets"){
161 getData = "api.coincap.io/v2/assets/" + allData.data.id + "/markets";
162 }
163 if(searchType != ""){
164 allData = JSON.parse(UrlFetchApp.fetch(getData, utility.requestOptions()).getContentText());
165 }
166
167 if(key == "timestamp"){
168 return allData[key];
169 }else{
170 if(searchType == ""){
171 if(key != ""){
172 return utility.processKey(allData.data[key]);
173 }else{
174 return utility.processObject(allData.data);
175 }
176
177 }else{
178 if(index < 0){
179 return utility.processArray(allData.data);
180 }else{
181 if(key != ""){
182 return utility.processKey(allData.data[index][key]);
183 }else{
184 return utility.processObject(allData.data[index]);
185 }
186 }
187 }
188 }
189}
190
191//function COINCAPRATES(){}
192
193//function COINCAPEXCHANGES(){}
194
195//function COINCAPMARKETS(){}
196
197//function COINCAPCANDLES(){}