Guest User

Untitled

a guest
May 23rd, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.02 KB | None | 0 0
  1. const express = require('express')
  2. const app = express()
  3.  
  4. const etherscan = require('etherscan-api').init('(my api key redacted)')
  5.  
  6. const { Client } = require('pg')
  7. const postgres = new Client()
  8. postgres.connect().catch((error) => { console.log('connecting to postgres: ' + error) })
  9.  
  10. const functions = require('./functions.js')
  11.  
  12. app.put('/ethtrancache/:address(0x[0-9a-fA-F]{40})/', handleAddAddress)
  13. app.get('/ethtrancache/:address(0x[0-9a-fA-F]{40})/', handleGetBalance)
  14. app.delete('/ethtrancache/:address(0x[0-9a-fA-F]{40})/', handleDeleteAddress)
  15. app.get('/ethtrancache/:address(0x[0-9a-fA-F]{40})/transactions', handleGetTransactions)
  16.  
  17. async function handleDeleteAddress (request, response) {
  18. try {
  19. await functions.deleteAddress(postgres, request.params['address'])
  20. } catch (err) {
  21. response.send(
  22. { result: 'failure', msg: 'error deleting existing address: ' + err })
  23. return
  24. }
  25. response.send({result: 'success'})
  26. }
  27.  
  28. async function handleAddAddress (request, response) {
  29. try {
  30. await functions.addAddress(postgres, etherscan, request.params['address'])
  31. } catch (err) {
  32. response.send({ result: 'failure', msg: 'error adding address: ' + err })
  33. return
  34. }
  35. response.send({ result: 'success' })
  36. }
  37.  
  38. async function handleGetBalance (request, response) {
  39. var balance
  40. try {
  41. balance = await functions.getBalance(postgres, request.params['address'])
  42. } catch (err) {
  43. response.send({ result: 'failure', msg: 'error getting balance: ' + err })
  44. return
  45. }
  46. response.send({ result: 'success', balance: balance })
  47. }
  48.  
  49. async function handleGetTransactions (request, response) {
  50. var transactions
  51. try {
  52. transactions = await functions.getTransactions(postgres, request.params['address'], request.query.other_address)
  53. } catch (err) {
  54. response.send({ result: 'failure', msg: 'error getting transactions: ' + err })
  55. return
  56. }
  57. response.send({ result: 'success', transactions: transactions })
  58. }
  59.  
  60. app.listen(3000, () => console.log('listening on port 3000'))
  61.  
  62. async function addAddress (postgres, etherscan, address) {
  63. /*
  64. "Accept an Ethereum address as input, and then:
  65. 1. query https://etherscan.io/apis and collects all transactions
  66. associated with that address.
  67. 1. store the transactions in the DB.
  68. 2. store the address balance in the DB."
  69. */
  70.  
  71. // clear out existing balance and transactions
  72. try {
  73. await deleteAddress(postgres, address)
  74. } catch (err) { throw new Error('error deleting existing address: ' + err) }
  75.  
  76. /* scrape and store eth balance */
  77.  
  78. var balance
  79.  
  80. try {
  81. balance = await etherscan.account.balance(address)
  82. } catch (err) { throw new Error('err getting eth balance: ' + err) }
  83.  
  84. try {
  85. await postgres.query(
  86. 'INSERT INTO eth_balances(address, balance) VALUES(LOWER($1), $2)',
  87. [address, balance['result']])
  88. } catch (err) { throw new Error('error storing eth balance: ' + err) }
  89.  
  90. /* scrape and store transactions */
  91.  
  92. var txlist
  93.  
  94. try {
  95. txlist = await etherscan.account.txlist(address)
  96. } catch (err) { throw new Error('error getting transactions: ' + err) }
  97.  
  98. try {
  99. for (var i = 0; i < txlist.result.length; i++) {
  100. await postgres.query(
  101. 'INSERT INTO transactions(to_address, txn_id, from_address, value)' +
  102. ' VALUES(LOWER($1), LOWER($2), LOWER($3), $4)',
  103. [ txlist.result[i].to,
  104. txlist.result[i].hash,
  105. txlist.result[i].from,
  106. txlist.result[i].value ])
  107. }
  108. } catch (err) { throw new Error('error storing transactions: ' + err) }
  109. }
  110.  
  111. async function deleteAddress (postgres, address) {
  112. try {
  113. await postgres.query(
  114. 'DELETE FROM eth_balances WHERE address = LOWER($1)',
  115. [address])
  116. await postgres.query(
  117. 'DELETE FROM transactions WHERE from_address = LOWER($1) OR to_address = LOWER($1)',
  118. [address])
  119. } catch (err) { throw new Error('PostgreSQL error: ' + err) }
  120. }
  121.  
  122. async function getBalance (postgres, address) {
  123. /*
  124. Return stored address balance by ETH address
  125. */
  126. try {
  127. var result = await postgres.query(
  128. 'SELECT balance FROM eth_balances WHERE address = LOWER($1)',
  129. [address])
  130.  
  131. if (result.rows.length === 0) { throw new Error('no such address') }
  132.  
  133. return result.rows[0].balance
  134. } catch (err) { throw new Error('error getting eth_balance: ' + err) }
  135. }
  136.  
  137. async function getTransactions (postgres, address, otherAddress) {
  138. /*
  139. Return transactions of stored ETH address, and accept some form of search
  140. params (which params are up to you).
  141. */
  142.  
  143. var query =
  144. 'SELECT * FROM transactions WHERE ' +
  145. 'from_address = LOWER($1) OR to_address = LOWER($1)'
  146.  
  147. var values = [address]
  148.  
  149. if (otherAddress !== undefined) {
  150. query += ' AND ( from_address = LOWER($2) OR to_address = LOWER($2) )'
  151. values.push(otherAddress)
  152. }
  153.  
  154. query += ';'
  155.  
  156. try {
  157. var result = await postgres.query(query, values)
  158. } catch (err) { throw new Error('error getting transactions: ' + err) }
  159.  
  160. return result.rows
  161. }
  162.  
  163. module.exports = {
  164. addAddress: addAddress,
  165. deleteAddress: deleteAddress,
  166. getBalance: getBalance,
  167. getTransactions: getTransactions
  168. }
  169.  
  170. {
  171. "name": "assignment",
  172. "version": "1.0.0",
  173. "description": "",
  174. "main": "index.js",
  175. "scripts": {
  176. "lint": "node_modules/.bin/eslint *.js"
  177. },
  178. "author": "",
  179. "license": "ISC",
  180. "dependencies": {
  181. "etherscan-api": "^8.0.4",
  182. "express": "^4.16.3",
  183. "pg": "^7.4.3"
  184. },
  185. "devDependencies": {
  186. "eslint": "^4.19.1",
  187. "eslint-config-standard": "^11.0.0",
  188. "eslint-plugin-import": "^2.11.0",
  189. "eslint-plugin-node": "^6.0.1",
  190. "eslint-plugin-promise": "^3.7.0",
  191. "eslint-plugin-standard": "^3.1.0"
  192. }
  193. }
  194.  
  195. #!/bin/sh
  196.  
  197. # tested with PostgreSQL version 9.3.22
  198.  
  199. . ./pgenv
  200. dropdb -h $PGHOST -U $PGUSER $PGDATABASE || exit 1
  201. createdb -h $PGHOST -U $PGUSER $PGDATABASE || exit 1
  202. psql -h $PGHOST -U $PGUSER $PGDATABASE -f createTables.psql
  203.  
  204. export PGHOST=
  205. export PGUSER=
  206. export PGPASSWORD=
  207. export PGDATABASE=assignment
  208.  
  209. create table eth_balances(address text PRIMARY KEY, balance bigint);
  210. create table transactions(to_address text, txn_id text UNIQUE, from_address text, value bigint);
Add Comment
Please, Sign In to add comment