profile.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* Import modules. */
  2. import {
  3. randomBytes,
  4. sha256,
  5. } from '@nexajs/crypto'
  6. import { entropyToMnemonic } from '@nexajs/hdnode'
  7. import {
  8. binToHex,
  9. hexToBin,
  10. } from '@nexajs/utils'
  11. import { defineStore } from 'pinia'
  12. /* Set constants. */
  13. const ENTROPY_BYTES_LENGTH = 32
  14. /**
  15. * Profile Store
  16. */
  17. export const useProfileStore = defineStore('profile', {
  18. state: () => ({
  19. /* Initialize session. */
  20. _session: null,
  21. /* Initialize entropy (used for HD wallet). */
  22. // NOTE: This is a cryptographically-secure "random" 32-byte (256-bit) value. */
  23. _entropy: null,
  24. /**
  25. * Email
  26. *
  27. * This is a valid email address.
  28. */
  29. _email: null,
  30. /**
  31. * Master Seed
  32. *
  33. * A 32-byte seed, which can be generated randomly, or by importing
  34. * from an existing wallet.
  35. */
  36. _masterSeed: null,
  37. /**
  38. * Metadata
  39. *
  40. * Used to store (user-defined) data for:
  41. * 1. Individual accounts
  42. * 2. Individual unspent transaction outputs (UXTOs)
  43. *
  44. * NOTE: Metadata MUST be used sparingly, to avoid data storage bloat;
  45. * and should be deleted when no longer needed.
  46. *
  47. * TODO: Allow this data to be stored on-chain using:
  48. * 1. Bitcoin Files Protocol (BFP) (https://bitcoinfiles.com/)
  49. * 2. Telr Locker (https://locker.telr.io)
  50. */
  51. _meta: null,
  52. /**
  53. * Nickname
  54. *
  55. * This is a public alias.
  56. *
  57. * NOTE: Only alpha-numeric characters are accepted.
  58. * Both upper and lower-case characters are accepted.
  59. */
  60. _nickname: null,
  61. }),
  62. getters: {
  63. session(_state) {
  64. return _state._session
  65. },
  66. sessionid(_state) {
  67. return _state._session?.id
  68. },
  69. challenge(_state) {
  70. return _state._session?.challenge
  71. },
  72. mnemonic(_state) {
  73. if (!_state._entropy) return null
  74. return entropyToMnemonic(_state._entropy)
  75. },
  76. },
  77. actions: {
  78. async createWallet() {
  79. /* Return random bytes (as hex string). */
  80. const myBytes = binToHex(randomBytes(ENTROPY_BYTES_LENGTH))
  81. console.log('CREATE WALLET (myBytes):', myBytes)
  82. /* Generate (random) bytes from the hosting server. */
  83. // TODO Find an alternative for client-ONLY builds.
  84. const svrBytes = await $fetch('/api/entropy')
  85. .catch(err => console.error(err))
  86. console.log('SERVER BYTES', svrBytes)
  87. /* Create 32-bytes (256-bit) entropy.*/
  88. const entropy = myBytes.slice(0, 32) + svrBytes.slice(-32)
  89. console.log('FINAL ENTROPY', entropy)
  90. const hashed = sha256(hexToBin(entropy))
  91. console.log('HASHED ENTROPY', binToHex(hashed))
  92. /* Set entropy. */
  93. // NOTE: Serialize to a 16-byte (128-bit) Hex String.
  94. // NOTE: We use 16-bytes to remain compatible with popular HD wallets.
  95. this._entropy = binToHex(hashed).slice(0, 16) + binToHex(hashed).slice(-16)
  96. },
  97. deleteSession() {
  98. /* Set session. */
  99. this._setSession(null)
  100. },
  101. saveSession(_session) {
  102. console.log('PROFILE SAVING SESSION', _session)
  103. /* Set session. */
  104. this._setSession(_session)
  105. },
  106. /**
  107. * Set Session
  108. *
  109. * @param {Object} _session Save session details.
  110. */
  111. _setSession (_session) {
  112. /* Set session. */
  113. this._session = _session
  114. console.log('SET SESSION', this._session)
  115. },
  116. },
  117. persist: true,
  118. })