daemon.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* Import modules. */
  2. import moment from 'moment'
  3. import PouchDB from 'pouchdb'
  4. import { v4 as uuidv4 } from 'uuid'
  5. /* Import handlers. */
  6. import handlePlays from './handlers/plays.js'
  7. import handleWallet from './handlers/wallet.js'
  8. /* Initialize databases. */
  9. const errorsDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/errors`)
  10. const logsDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/logs`)
  11. const playsDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/plays`)
  12. const walletDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/wallet`)
  13. /* Set constants. */
  14. const PLAYS_INTERVAL = 5000
  15. const WALLET_INTERVAL = 15000
  16. // TODO Replace with @nexajs/utils
  17. const jsonParse = (_data, _transform = true) => {
  18. let data
  19. if (_transform) {
  20. data = _data
  21. } else {
  22. // NOTE: We actually (de-)transform before decoding.
  23. data = JSON.stringify(_data)
  24. }
  25. try {
  26. return JSON.parse(data, (key, value) => {
  27. if (typeof value === 'string' && /^\d+n$/.test(value)) {
  28. return BigInt(value.slice(0, value.length - 1))
  29. }
  30. return value
  31. })
  32. } catch (err) {
  33. console.log('JSON PARSE ERROR!');
  34. console.log('ERROR', err)
  35. }
  36. }
  37. console.info('\n Starting Nexa Games daemon...\n')
  38. /**
  39. * Plays Queue
  40. *
  41. * Performs a check to validate ALL (unpaid) plays and
  42. * calculate payouts for entry to the Wallet.
  43. */
  44. const handlePlaysQueue = async () => {
  45. console.info('\n Checking Plays queue...\n')
  46. const playQueue = {}
  47. let response
  48. let rows
  49. /* Request pending transactions. */
  50. response = await playsDb
  51. .query('api/isUnpaid', {
  52. include_docs: true,
  53. })
  54. .catch(err => console.error(err))
  55. // console.log('RESPONSE', response)
  56. /* Validate response. */
  57. if (response?.rows?.length > 0) {
  58. rows = response.rows
  59. // console.log('ROWS', rows)
  60. }
  61. /* Validate rows. */
  62. if (rows) {
  63. rows.forEach(_item => {
  64. const play = _item.doc
  65. // console.log('PLAY', play)
  66. if (!playQueue[play._id]) {
  67. playQueue[play._id] = play
  68. }
  69. })
  70. }
  71. // console.log('PLAY QUEUE', playQueue)
  72. const pending = Object.keys(playQueue).filter(_playid => {
  73. /* Set play. */
  74. const play = jsonParse(playQueue[_playid], false)
  75. console.log('PLAY', play);
  76. /* Return unprocessed .*/
  77. return play.txidem === null
  78. })
  79. // console.log('PENDING', pending)
  80. /* Handle queue. */
  81. handlePlays(playQueue, pending)
  82. }
  83. /**
  84. * Wallet Queue
  85. *
  86. * Performs a check to make sure we have transacted all pending
  87. * transactions queued in the wallet.
  88. */
  89. const handleWalletQueue = async () => {
  90. console.info('\n Checking Wallet queue...\n')
  91. const walletQueue = {}
  92. let response
  93. let rows
  94. /* Request pending transactions. */
  95. response = await walletDb
  96. .query('api/isPending', {
  97. include_docs: true,
  98. })
  99. .catch(err => console.error(err))
  100. // console.log('RESPONSE', response)
  101. /* Validate response. */
  102. if (response?.rows?.length > 0) {
  103. rows = response.rows
  104. // console.log('ROWS', rows)
  105. }
  106. /* Validate rows. */
  107. if (rows) {
  108. rows.forEach(_item => {
  109. const payment = jsonParse(_item.doc, false)
  110. console.log('PAYMENT', payment)
  111. if (!walletQueue[payment._id]) {
  112. walletQueue[payment._id] = {
  113. id: payment._id,
  114. entropy: payment.entropy,
  115. unspent: payment.unspent,
  116. receivers: payment.receivers,
  117. txidem: payment.txidem,
  118. createdAt: payment.createdAt,
  119. }
  120. }
  121. })
  122. }
  123. console.log('WALLET QUEUE', walletQueue)
  124. const pending = Object.keys(walletQueue).filter(_paymentid => {
  125. /* Set payment. */
  126. const payment = walletQueue[_paymentid]
  127. /* Return unprocessed .*/
  128. return payment.txidem === null
  129. })
  130. console.log('PENDING', pending)
  131. /* Handle queue. */
  132. handleWallet(walletQueue, pending)
  133. }
  134. ;(async () => {
  135. // handlePlaysQueue()
  136. // handleWalletQueue()
  137. // return
  138. setInterval(() => {
  139. console.log('Managing Plays queue...')
  140. handlePlaysQueue()
  141. }, PLAYS_INTERVAL)
  142. setInterval(() => {
  143. console.log('Managing Wallet queue...')
  144. handleWalletQueue()
  145. }, WALLET_INTERVAL)
  146. })()