hi_lo.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Import modules. */
  2. import { getAddressBalance } from '@nexajs/rostrum'
  3. import { listUnspent } from '@nexajs/address'
  4. import moment from 'moment'
  5. import PouchDB from 'pouchdb'
  6. import { getHmac } from '@nexajs/crypto'
  7. /* Initialize databases. */
  8. const playsDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/plays`)
  9. const logsDb = new PouchDB(`http://${process.env.COUCHDB_USER}:${process.env.COUCHDB_PASSWORD}@127.0.0.1:5984/logs`)
  10. // TODO Replace with @nexajs/utils
  11. const jsonStringify = (_data, _transform = true) => {
  12. let data
  13. data = JSON.stringify(_data, (key, value) =>
  14. typeof value === 'bigint' ? value.toString() + 'n' : value
  15. )
  16. if (!_transform) {
  17. data = JSON.parse(data)
  18. }
  19. return data
  20. }
  21. export default async (_updatedInfo) => {
  22. // console.log('PLAY HANDLER', _updatedInfo)
  23. /* Initialize locals. */
  24. let playAddress
  25. let playData
  26. let playHash
  27. let playSatoshis
  28. let playerJoy
  29. let houseJoy
  30. let response
  31. let unspent
  32. /* Set play address. */
  33. playAddress = _updatedInfo[0]
  34. // console.log('GAMEPLAY ADDRESS', playAddress)
  35. // Fetch all unspent transaction outputs for the temporary in-browser wallet.
  36. unspent = await listUnspent(playAddress)
  37. // console.log('\n Unspent outputs:\n', unspent)
  38. if (unspent.length === 0) {
  39. // NOTE: Prevent replay.
  40. return
  41. }
  42. playSatoshis = await getAddressBalance(playAddress)
  43. // console.log('\n Play balance:\n', playSatoshis)
  44. if (playSatoshis === 0) {
  45. // NOTE: Prevent replay.
  46. return
  47. }
  48. response = await playsDb
  49. .query('api/byAddress', {
  50. key: playAddress,
  51. include_docs: true,
  52. })
  53. .catch(err => console.error(err))
  54. // console.log('RESPONSE', response)
  55. if (response?.rows.length > 0) {
  56. playData = response.rows[0].doc
  57. // console.log('PLAY DATA', playData)
  58. }
  59. playHash = getHmac(playData.entropy, playData.seed)
  60. // console.log('PLAY HASH', playHash)
  61. const playValueHex = playHash.slice(0, 8) // 32-bit value
  62. // console.log('PLAY VALUE (hex):', playValueHex)
  63. const playValueNum = parseInt(playValueHex, 16)
  64. // console.log('PLAY VALUE (number):', playValueNum)
  65. const MAX_PLAY_VALUE = parseInt('ffffffff', 16) // MAX 32-bit integer value
  66. // console.log('MAX_PLAY_VALUE', MAX_PLAY_VALUE)
  67. const playValue = (playValueNum / MAX_PLAY_VALUE) * 100.0
  68. // console.log('PLAY VALUE', playValue)
  69. // console.log('PLAY VALUE (formatted):', playValue.toFixed(2))
  70. /**
  71. * Calculate (1.2x) Play Outcome
  72. */
  73. if (playData.payout === 1.2) {
  74. if (playValue < 80.8 && playData.position === 0) {
  75. playerJoy = true
  76. houseJoy = false
  77. } else if (playValue > 19.2 && playData.position === 1) {
  78. playerJoy = true
  79. houseJoy = false
  80. } else {
  81. playerJoy = false
  82. houseJoy = true
  83. }
  84. }
  85. /**
  86. * Calculate (2x) Play Outcome
  87. */
  88. if (playData.payout === 2) {
  89. if (playValue < 48.5 && playData.position === 0) {
  90. playerJoy = true
  91. houseJoy = false
  92. } else if (playValue > 51.5 && playData.position === 1) {
  93. playerJoy = true
  94. houseJoy = false
  95. } else {
  96. playerJoy = false
  97. houseJoy = true
  98. }
  99. }
  100. /**
  101. * Calculate (5x) Play Outcome
  102. */
  103. if (playData.payout === 5) {
  104. if (playValue < 17.6 && playData.position === 0) {
  105. playerJoy = true
  106. houseJoy = false
  107. } else if (playValue > 82.4 && playData.position === 1) {
  108. playerJoy = true
  109. houseJoy = false
  110. } else {
  111. playerJoy = false
  112. houseJoy = true
  113. }
  114. }
  115. /* Initialize paid flag (used by Wallet daemon). */
  116. const txidem = null
  117. /* Build database update. */
  118. const updated = {
  119. ...playData,
  120. unspent: jsonStringify(unspent[0], false),
  121. satoshis: playSatoshis.confirmed + playSatoshis.unconfirmed,
  122. outcome: playValue,
  123. playerJoy,
  124. houseJoy,
  125. txidem,
  126. updatedAt: moment().valueOf()
  127. }
  128. console.log('UPDATED', updated)
  129. response = await playsDb
  130. .put(updated)
  131. .catch(err => console.error(err))
  132. console.log('UPDATED RESPONSE', response)
  133. }