diff --git a/contribute.md b/CONTRIBUTING.md similarity index 100% rename from contribute.md rename to CONTRIBUTING.md diff --git a/README.md b/README.md index cf7c2e6..3a0d1db 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,127 @@ # Crypto Sheets -Google Sheets script editor code for managing a cryptocurrency tracking spreadsheet -## Instructions +This is a (javascript-based) tool to aid in creating your own crypto tracking spreadsheet. It can automagically pull in current cryptocurrency rates, as well as your wallet balances. It requires the use of Google Sheets and its built-in script editor. -This is a template for creating your own spreadsheet to track your cryptocurrency balances and current prices. It assumes the use of Google Sheets and the built in script editor (Tools > Script editor...). +If you want a better understanding of how it works and have no programming experience, it's never too late to learn. Take a free course at **Codecademy** and flex your brain :muscle::fireworks:. [Programming can open doors for you, no matter your occupation](https://www.forbes.com/sites/laurencebradford/2016/06/20/why-every-millennial-should-learn-some-code/#1231c1e270f2). +https://www.codecademy.com/learn/introduction-to-javascript + +# Instructions + +## Populating `Rates` sheet with currency data + +1. Create [a new Google Sheets spreadsheet](docs.google.com/spreadsheets) and name it something, or open an existing one + + 1. ![Create new spreadsheet](https://i.imgur.com/ARb3B0Dm.png) + + 1. ![Name your spreadsheet](https://i.imgur.com/uJ6h43nm.png) + +1. Create two new sheets called `Rates` and `Wallets` + + 1. ![Rates and Wallets sheets](https://i.imgur.com/WHO747jm.png) + +1. Click "Tools > Script editor..." on the menu bar, and name your script project something + + 1. ![Script Editor](https://i.imgur.com/hjhZlaAm.png) + + 1. ![Project Name](https://i.imgur.com/tUXLp1Pm.png) + +1. Select all of the text in the right-side pane and delete it + + 1. ![Delete existing code](https://i.imgur.com/RVyXaUzm.png) + +1. Paste [the contents of scripteditor.js](scripteditor.js) into the right-side pane + + 1. ![Paste script](https://i.imgur.com/5ktIBNom.png) -1. Click "Tools > Script editor..." on the menu bar -1. Select all of the text in the right pane and delete it (unless you have already written your own functions) -1. Paste the contents of scripteditor.js into the pane on the right 1. Add in as many currencies that you want to track -1. Add triggers "Edit > Current project's triggers..." - 1. Click "Add a new trigger" + + 1. ![Add currencies to track](https://i.imgur.com/SyBS19j.png) + +1. Add triggers to your project ("Edit > Current project's triggers..."). This is how your spreadsheet will update automatically. + + 1. ![Add triggers](https://i.imgur.com/d7MIO7Km.png) + + 1. Set up a new trigger + + 1. ![New trigger](https://i.imgur.com/AzDXGQvm.png) + 1. In the "Run" dropdown, choose "getData" and choose which triggers you'd like. I use "Time-driven/Minutes/Every 15", and "From spreadsheet/On open". + + 1. ![Trigger definition](https://i.imgur.com/SyEoEVv.png) + +You can manually execute the script to test it by clicking the `Select function`, selecting `getData`, and clicking the run button (looks like the play symbol) + + ![Manually execute script](https://i.imgur.com/TP5BMTAm.png) + +## Populating `Wallets` sheet with account balances +*Note: Currently only supports BCH, BTC, ETH, and VTC. Update other wallet balances manually in your spreadsheet for the time being. Feel free to [submit an issue](https://github.com/saitei/crypto-sheets/issues) for other currencies.* + +1. Make sure you have created a `Wallets` sheet + + 1. ![Rates and Wallets sheets](https://i.imgur.com/WHO747jm.png) + +1. In the script editor, uncomment (delete the `//` before) `var ssWallets = ss.getSheetByName('Wallets')` + + 1. ![uncomment wallets sheet](https://i.imgur.com/RUysbr9m.png) + + 1. It should look like this + + 1. ![uncommented code](https://i.imgur.com/iPO8UIlm.png) + +1. Scroll down to the `WALLET BALANCE CONFIGURATION` section (around line 130) + + 1. ![wallet section](https://i.imgur.com/0ODMumfm.png) + +1. Follow the instructions for each currency to add your address. You can change the value in `getRange` to output the balance to a different cell in the `Wallets` sheet. + 1. Before configuration + + 1. ![before wallet config](https://i.imgur.com/iZkSemq.png) + + 1. After configuration + + 1. ![after wallet config](https://i.imgur.com/dTLu4cC.png) + + +## Advanced + +There are comments in the code for anything that's not covered here. If you had to use these instructions, the safe bet is to not modify anything else. + +## How to Contribute + +* Help others in the cryptosheets subreddit (https://www.reddit.com/r/cryptosheets/). You don't need to write any code to help others out. +* Hop in the gitter.im chat rooms + * [Lobby](https://gitter.im/cryptosheets/Lobby) + * [Development](https://gitter.im/cryptosheets/development) +* Check out the [contributing page](CONTRIBUTING.md) and become involved on GitHub +* If all else fails, give a stranger a compliment and brighten their day -There are comments in the code, and I'll add better instructions here in the future. +### Powered By -*More instructions to follow. +[CoinMarketCap](https://coinmarketcap.com/) +[Block Explorer](https://blockexplorer.com) +[Etherscan](https://etherscan.io) +explorer.vertcoin.info -## To Do +### Acknowledgements -1. Add detailed instructions for configuring your own Google Sheets crypto tracker -1. Templatize the script to pull in lists of cryptos to track, and account balances to track -1. Historical data +apiontek +iKrazy +solifugo +yukihirai0505 +Christopher Walken -## Donations +### Donations -They are appreciated but not expected -* XRB - xrb_3ix8dfgn7hkz3choqi1qr6jgopoodh1jr1giwixzqaohks7d1f98dau45c11 -* ETH - 0x7E9DDB5343a583705Ed9ADE065C0595EFB55D681 -* VTC - Vo8EXgAtxCVUtMaTQECuzLD2tZU1HqLbhT +* XRB + * **xrb_3ix8dfgn7hkz3choqi1qr6jgopoodh1jr1giwixzqaohks7d1f98dau45c11** +* ETH + * **0x7E9DDB5343a583705Ed9ADE065C0595EFB55D681** +* VTC + * **Vo8EXgAtxCVUtMaTQECuzLD2tZU1HqLbhT** +* BCH + * **1Gzs8uKoUY23R7kTRE8NwAucAArAk8mdCg** -## License +### License This project is licensed under the GNU General Public License v3.0 diff --git a/scripteditor.js b/scripteditor.js index c64ab98..9ab246a 100644 --- a/scripteditor.js +++ b/scripteditor.js @@ -1,32 +1,47 @@ +// XXXXXXXXX DONT TOUCH XXXXXXXXXXXXX var queryString = Math.random(); var ss = SpreadsheetApp.getActiveSpreadsheet(); +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // ====== // !!! -// IMPORTANT: Create a sheet called 'Rates'. This is where the values will be written +// IMPORTANT: Create a sheet called 'Rates'. This is where the values will be written. // !!! // ====== + var ssRates = ss.getSheetByName('Rates'); -// ====== Set the target currency ======= +// ====== +// !!! +// IMPORTANT: If tracking wallet balances, create a sheet called 'Wallets'. This is where the values will be written. +// !!! +// ====== + +//var ssWallets = ss.getSheetByName('Wallets'); + +// =+=+= Set the target currency =+=+=+=+ // Don't change if using USD // Possible values: // "aud", "brl", "cad", "chf", "clp", "cny", "czk", "dkk", "eur", "gbp", "hkd", "huf", // "idr", "ils", "inr", "jpy", "krw", "mxn", "myr", "nok", "nzd", "php", "pkr", "pln", // "rub", "sek", "sgd", "thb", "try", "twd", "usd", "zar" -// ====================================== +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ var targetCurrency = 'usd' +// XXXXXXXX DONT TOUCH XXXXXXXXXX // Grabs all CoinMarketCap data if (typeof targetCurrency == 'undefined' || targetCurrency == '') {targetCurrency = 'usd'}; var coins = getCoins(); +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX function getData() { - // ===== Coins to Track ====== - // Enter the coins you want tracked, each one on a new line, in single quotes, followed by a comma + // =+=+=+ Coins to Track =+=+=+ + // Enter the coins you want tracked, one per line, in single quotes, followed by a comma // Use the value in the 'id' field here: https://api.coinmarketcap.com/v1/ticker/?limit=0 - // =========================== + // If you're getting errors, you may be using the wrong 'id'. Double-check the values. + // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + var myCoins = [ 'ark', 'bitcoin', @@ -36,9 +51,13 @@ function getData() { 'monero', ] + // XXXXXXXX DONT TOUCH UNLESS WIZARD XXXXXXXXXXX + // // Creates column headers. Don't change unless you know what you're doing. - // If there is data you don't want, just hide the column in your spreadsheet, or simply don't reference it - // DO NOT TOUCH + // If there is data you don't want, just hide the column in your spreadsheet + // ...or simply don't reference it + // \/ \/ \/ \/ \/ \/ \/ + ssRates.getRange('A1').setValue("ID"); ssRates.getRange('B1').setValue("Name"); ssRates.getRange('C1').setValue("Symbol"); @@ -55,18 +74,26 @@ function getData() { ssRates.getRange('N1').setValue("Percent Change 7D"); ssRates.getRange('O1').setValue("Last Updated"); // Adds in extra column headers if non-USD currency was chosen - if (typeof targetCurrency !== 'usd') { + if (targetCurrency !== 'usd') { ssRates.getRange('P1').setValue("Price " + targetCurrency.toUpperCase()); ssRates.getRange('Q1').setValue("24H Volume " + targetCurrency.toUpperCase()); ssRates.getRange('R1').setValue("Market Cap " + targetCurrency.toUpperCase()); }; + // /\ /\ /\ /\ /\ + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + // XXXXXXXX DONT TOUCH UNLESS WIZARD XXXXXXXXXX + // // Creating new Object with our coins for later use. // Each Object's key is the coin symbol + // + // \/ \/ \/ \/ \/ + var myCoinsObj = {}; var myCoinsCount = myCoins.length; for (var i = 0; i < myCoinsCount; i++) { + var c = i+2; var n = 0; while (coins[n]['id'] !== myCoins[i]) { n++; @@ -74,45 +101,71 @@ function getData() { myCoinsObj[coins[n]['id']] = coins[n]; - ssRates.getRange('A'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['id']); - ssRates.getRange('B'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['name']); - ssRates.getRange('C'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['symbol']); - ssRates.getRange('D'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['rank']); - ssRates.getRange('E'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['price_usd']); - ssRates.getRange('F'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['price_btc']); - ssRates.getRange('G'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['24h_volume_usd']); - ssRates.getRange('H'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['market_cap_usd']); - ssRates.getRange('I'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['available_supply']); - ssRates.getRange('J'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['total_supply']); - ssRates.getRange('K'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['max_supply']); - ssRates.getRange('L'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_1h']); - ssRates.getRange('M'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_24h']); - ssRates.getRange('N'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_7d']); - ssRates.getRange('O'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['last_updated']); - if (typeof targetCurrency !== 'usd') { - ssRates.getRange('P'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['price_' + targetCurrency]); - ssRates.getRange('Q'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['24h_volume_' + targetCurrency]); - ssRates.getRange('R'+(i+2).toString()).setValue(myCoinsObj[myCoins[i]]['market_cap_' + targetCurrency]); + ssRates.getRange('A'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['id']); + ssRates.getRange('B'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['name']); + ssRates.getRange('C'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['symbol']); + ssRates.getRange('D'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['rank']); + ssRates.getRange('E'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['price_usd']); + ssRates.getRange('F'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['price_btc']); + ssRates.getRange('G'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['24h_volume_usd']); + ssRates.getRange('H'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['market_cap_usd']); + ssRates.getRange('I'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['available_supply']); + ssRates.getRange('J'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['total_supply']); + ssRates.getRange('K'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['max_supply']); + ssRates.getRange('L'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_1h']); + ssRates.getRange('M'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_24h']); + ssRates.getRange('N'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['percent_change_7d']); + ssRates.getRange('O'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['last_updated']); + if (targetCurrency !== 'usd') { + ssRates.getRange('P'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['price_' + targetCurrency]); + ssRates.getRange('Q'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['24h_volume_' + targetCurrency]); + ssRates.getRange('R'+(c).toString()).setValue(myCoinsObj[myCoins[i]]['market_cap_' + targetCurrency]); + + // /\ /\ /\ /\ /\ /\ + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX }; } - // ===== VTC wallet balances ======= + // + // ================================= + // + // WALLET BALANCE CONFIGURATION + // + // ================================= + + // + // ===== BCH Wallet Balances ======= // Add more as needed with different variable names // Change the value in getRange() to match the cell in spreadsheet - // Change the value in setValue() to match the variable above + // Change the value in setValue() to match the wallet variable used (e.g. bchWallet) // ================================= // // Uncomment variables to use // - //var VtcWallet = getVtcBalance("yourAddressHere"); - //ssRates.getRange('E3').setValue(VtcWallet); + //var bchWallet = getBchBalance("Your BCH Address"); + //ssWallets.getRange('B2').setValue(bchWallet); + + // + // ===== BTC Wallet Balances ======= + // Add more as needed with different variable names + // Change the value in getRange() to match the cell in spreadsheet + // Change the value in setValue() to match the wallet variable used (e.g. btcWallet) + // ================================= + + // + // Uncomment variables to use + // + //var btcWallet = getBtcBalance("Your BTC Address"); + //ssWallets.getRange('B3').setValue(btcWallet); + + // // ===== Ethereum Wallet Balances ===== - //Create an account on Etherscan.io + // Create an account on Etherscan.io // Create an API key at https://etherscan.io/myapikey - // Put your API key in below, replacing yourEtherscanApiKey + // Add your API key in below // Add Ethereum address, replacing yourEthAddress // Change the value in setValue() to match the variable above // ==================================== @@ -121,44 +174,91 @@ function getData() { // Uncomment variables and follow instructions above to use // - //var EthApiKey = "yourEtherscanApiKey"; - //var EthWallet = getEthBalance(EthApiKey,"yourEthAddress"); - //ssRates.getRange('E1').setValue(EthWallet); -} - + //var ethApiKey = "Your Etherscan API Key"; + //var ethWallet = getEthBalance(ethApiKey,"Your ETH Address"); + //ssWallets.getRange('B4').setValue(ethWallet); + + // ===== VTC wallet balances ======= + // Add more as needed with different variable names + // Change the value in getRange() to match the cell in spreadsheet + // Change the value in setValue() to match the variable above + // ================================= + // - // DON'T TOUCH ANYTHING BELOW - // IT MAKES THE MAGIC HAPPEN + // Uncomment variables to use // + //var vtcWallet = getVtcBalance("Your VTC Address"); + //ssRates.getRange('B5').setValue(vtcWallet); +} + +// XXXXXXXXXX DONT TOUCH UNLESS WIZARD XXXXXXXXXXXXX +// +// DON'T TOUCH ANYTHING BELOW UNLESS WIZARD +// IT MAKES THE MAGIC HAPPEN +// +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + function getCoins() { - var url = 'https://api.coinmarketcap.com/v1/ticker/?limit=0&convert=' + targetCurrency; + var url = 'https://api.coinmarketcap.com/v1/ticker/?limit=0&convert='+targetCurrency; var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); var json = response.getContentText(); var data = JSON.parse(json); - + return data; } - + +function getBchBalance(bchAddress) { + + var url = 'https://bitcoincash.blockexplorer.com/api/addr/'+bchAddress+'/balance'; + var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); + var balance = response.getContentText(); + //Pause to not trigger API limit for multiple wallets + Utilities.sleep(300); + + return balance * Math.pow(10,-8); +} + +function getBtcBalance(btcAddress) { + + var url = 'https://blockexplorer.com/api/addr/'+btcAddress+'/balance'; + var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); + var balance = response.getContentText(); + //Pause to not trigger API limit for multiple wallets + Utilities.sleep(300); + + return balance * Math.pow(10,-8); +} + function getEthBalance(ethApiKey,ethAddress) { - - var obj = JSON.parse (UrlFetchApp.fetch("https://api.etherscan.io/api?module=account&action=balance&address="+ethAddress+"&tag=latest&apikey="+ethApiKey)); - var data = (obj.result); - return data * Math.pow(10,-18); + var url = 'https://api.etherscan.io/api?module=account&action=balance&address='+ethAddress+'&tag=latest&apikey='+ethApiKey; + var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); + var json = response.getContentText(); + var obj = JSON.parse(json); + var balance = obj.result; + //Pause to not trigger API limit for multiple wallets + Utilities.sleep(300); + + return balance * Math.pow(10,-18); } - + function getVtcBalance(vtcAddress) { - - var obj = UrlFetchApp.fetch("http://explorer.vertcoin.info/ext/getbalance/"+vtcAddress); - return obj; + var url = 'http://explorer.vertcoin.info/ext/getbalance/'+vtcAddress; + var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); + var balance = response.getContentText(); + //Pause to not trigger API limit for multiple wallets + Utilities.sleep(300); + + return balance; } - -// + +// XXXXXXXXXXXXXXXXXXXXXXX // !!! DEPRECATED !!! -// +// USE AT YOUR OWN RISK +// XXXXXXXXXXXXXXXXXXXXXXX function getRate(currencyId) { @@ -182,3 +282,13 @@ function getWebRate(currencyId) { return coinScrape1 + currencyId + '?' + queryString + coinScrape2; } + +function getCurrencyConversion(currencyOne, currencyTwo) { + + var url = 'https://api.fixer.io/latest?symbols='+currencyOne.toUpperCase()+','+currencyTwo.toUpperCase(); + var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true}); + var json = response.getContentText(); + var data = JSON.parse(json); + + return parseFloat(data['rates'][currencyTwo]); +}