Professor Hantzen 1,276 Posted February 20, 2017 Share Posted February 20, 2017 I often have to check the balances on a few different accounts. To make that easier I wrote this node.js script that checks multiple Ripple account balances (XRP and IOU's) over websocket. Posting if it's useful to anyone. Hodor 1 Link to post Share on other sites
Duke67 1,911 Posted February 20, 2017 Share Posted February 20, 2017 (edited) 'use strict'; const RippleAPI = require('ripple-lib').RippleAPI; const api = new RippleAPI({server: 'wss://s1.ripple.com:443'}); const acntA = 'r**************1'; const acntB = 'r**************2'; const acntC = 'r**************3'; const acntD = 'r**************4'; const acntE = 'r**************5'; const acntF = 'r**************6'; var myStash = [acntF, acntA, acntB, acntC, acntD, acntE]; api.connect().then(() => { for (var i = 0; i < myStash.length; i++) { var acnt = myStash; api.getBalances(acnt).then(balances => { console.log(JSON.stringify(balances, null, 2)); }); } }); Edited February 20, 2017 by Duke67 T8493 1 Link to post Share on other sites
Professor Hantzen 1,276 Posted February 20, 2017 Author Share Posted February 20, 2017 1 hour ago, Duke67 said: 'use strict'; Sure, but I'm not a fan of ripple-lib/rippleAPI - it's changed so much it's been a nightmare to develop with, and ripple-lib in particular was very bloated (not sure on RippleAPI?). I run latency and memory sensitive applications mostly, so I tend to roll everything myself with the rippled websocket interface - it's about as fast and lean as you can get, hasn't changed in the past four years and requires only a single websocket. A little more coding is required, but I'm used to it. Hodor and Kakoyla 2 Link to post Share on other sites
Professor Hantzen 1,276 Posted February 20, 2017 Author Share Posted February 20, 2017 (edited) Also, the main purpose of my script was to format the output to be more readable than raw JSON. It can also output in CSV format for importing into spreadsheet. Out of interest - why do you define the accounts separately and then build an array from them? Couldn't you just: Quote 'use strict'; const RippleAPI = require('ripple-lib').RippleAPI; const api = new RippleAPI({server: 'wss://s1.ripple.com:443'}); var myStash = [ 'r**************1', // acntA 'r**************2', // acntB 'r**************3', // etc 'r**************4' ]; api.connect().then(() => { for (var index = 0; index < myStash.length; index++) { var acnt = myStash[index]; api.getBalances(acnt).then(balances => { console.log(JSON.stringify(balances, null, 2)); }); } }); And I believe you missed the [index] on myStash in the for loop (fixed above - had to change the variable name as the forum thinks i is a code for italics). It also doesn't close the connection, but I'll leave that fix for someone who loves nested asynchronous javascript promises... Edited February 20, 2017 by Professor Hantzen Link to post Share on other sites
jn_r 769 Posted February 20, 2017 Share Posted February 20, 2017 (edited) For tax purposes and to get a quick overview of my accounts and to get to learn the promisses stuff in nodejs I once created the following script. It makes use of the data-api to be able to also get historical data. You can use it as follows (if you name the script 'totals'): totals [date=<dd-mm-yyyy>] [time=<hh:mm:ss>] [account=<account_list>] Quote #! /usr/local/bin/node 'use strict' var accounts = [ "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "rGSRqpUQAschCY5rdoRAXnnCvoGpq5toZ1" ] const https = require('https') var emptyAccounts = new Set() var dd = new Date() try { process.argv.forEach(arg => { let [param, value] = arg.split("=") switch(param) { case 'date': let [D,M,Y] = value.split("-") dd.setFullYear(Y) dd.setMonth(M-1) dd.setDate(D) break case 'time': let [hh,mm,ss] = value.split(":") dd.setHours(hh) dd.setMinutes(mm) dd.setSeconds(ss) break case 'account': if (value !== 'all') { accounts = value.split(',') } break default: if ((process.argv[0] !== param) && (process.argv[1] !== param)) { throw(`Unknown keyword '${param}'`) } } }) } catch(e) { console.error(e) console.error(`Usage: ${process.argv[0]} ${process.argv[1]} [date=<dd-mm-yyyy>] [time=<hh:mm:ss>] [accounts=<file>]`) process.exit(1) } var dateTime = dd.toISOString().substring(0,19) + 'Z' function getURL(url) { return new Promise((resolve, reject) => { https.get(url, res => { var body = '' res.on('data', chunk => { body += chunk }) res.on('end', () => { try { resolve(JSON.parse(body)) } catch(e) { reject(Error(`Unable to parse to JSON: ${e}\n${body}`)) } }) }).on('error', err => { reject(Error(`Retrieving "${url}": ${err.message}`)) }) }) } function getLedger(date) { return getURL('https://data.ripple.com/v2/ledgers/' + date).then(response => { if (response.result === 'error') { throw(Error(`Getting ledger: ${response.message}`)) } else { return(response.ledger.seqNum) } }) } function getBalances(account, sequence, retry = 2) { return getURL('https://data.ripple.com/v2/accounts/' + account + '/balances?ledger_index=' + sequence).then(response => { if (response.result === 'error') { // no balances found, account does not exist yet? if (retry > 0) { // try again return getBalances(account, sequence, --retry) } else { emptyAccounts.add(account) return [] } } else { return response.balances } }) } function getValueInXRP(amount, currency, issuer, sequence, retry = 2) { if (currency === 'XRP') { var URL = 'https://data.ripple.com/v2/normalize?amount=' + amount + '¤cy=' + currency + '&sequence=' + sequence } else { var URL = 'https://data.ripple.com/v2/normalize?amount=' + amount + '¤cy=' + currency + '&sequence=' + sequence + '&issuer=' + issuer } return getURL(URL).then(response => { if (response.result === 'error') { // no value found, currency doesn't exit yet? if (retry > 0) { // try again return getValueInXRP(amount, currency, issuer, sequence, --retry) } else { console.log("huh?") return 0 } } else { return parseFloat(response.converted) } }) } function showResult(result, XRPresult, totalXRP, USDrate, EURrate) { console.log("----------------------------------") console.log(dd.toString().split('(')[0]) console.log("----------------------------------") accounts.sort().forEach(account => { if (emptyAccounts.has(account)) account = account + ' <== no balances returned' console.log(account) }) console.log("----------------------------------") Object.keys(result).sort().forEach(key => { console.log(`- ${key} : ${result[key].toPrecision(7)}`) }) console.log("----------------------------------") console.log(`Total in XRP: ${totalXRP.toFixed(0)}`) console.log(`Total in USD: ${(totalXRP / USDrate).toFixed(2)}`) console.log(`Total in EUR: ${(totalXRP / EURrate).toFixed(2)}`) console.log("----------------------------------") } getLedger(dateTime).then(sequence => { let result = {} let XRPresult = {} let totalXRP = 0 let getUSDrateURL = 'https://data.ripple.com/v2/exchange_rates/USD+rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B/XRP?date=' + dd.toISOString() let USDrate = 0 let getEURrateURL = 'https://data.ripple.com/v2/exchange_rates/EUR+rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq/XRP?date=' + dd.toISOString() let EURrate = 0 return Promise.all( accounts.map(account => { return getBalances(account, sequence).then(balances => { return Promise.all( balances.map(balance => { if (result[balance.currency] === undefined) { if (parseFloat(balance.value) != 0) { result[balance.currency] = parseFloat(balance.value) return getValueInXRP(balance.value, balance.currency, balance.counterparty, sequence).then(valueInXRP => { XRPresult[balance.currency] = valueInXRP totalXRP += valueInXRP }) } } else { result[balance.currency] += parseFloat(balance.value) return getValueInXRP(balance.value, balance.currency, balance.counterparty, sequence).then(valueInXRP => { XRPresult[balance.currency] += valueInXRP totalXRP += valueInXRP }) } }) ) }) }).concat( getURL(getUSDrateURL).then(response => { USDrate = parseFloat(response.rate) }), getURL(getEURrateURL).then(response => { EURrate = parseFloat(response.rate) }) ) ).then(() => { return showResult(result, XRPresult, totalXRP, USDrate, EURrate) }) }).catch(console.error) Edited February 20, 2017 by jn_r Professor Hantzen 1 Link to post Share on other sites
Professor Hantzen 1,276 Posted February 22, 2017 Author Share Posted February 22, 2017 Awesome script @jn_r! The date parameter makes it really easy to track account changes over time. Thanks for posting! jn_r 1 Link to post Share on other sites
canadrian1999 90 Posted July 24, 2018 Share Posted July 24, 2018 Hi all, found this, can anyone write a magicmirror module like xrp balances? Please. Thank you. https://forum.magicmirror.builders/topic/8461/xrp-balances Link to post Share on other sites
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now