useWalletAuth.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import Web3 from 'web3'
  2. import CryptoJS from 'crypto-js'
  3. export function useWalletAuth() {
  4. // 登录状态
  5. const authState = reactive({
  6. isAuthenticated: false, // 登录状态
  7. account: null, // 账户
  8. privateKey: null, // 私钥
  9. encryptedKey: null, // 加密后的密钥
  10. loading: false, // 加载状态
  11. error: null, // 错误信息
  12. chainId: null, // 链ID
  13. balance: '0', // 账户余额(ETH)
  14. rpcUrl: 'https://api.angeltokens.io' // 您的私有链RPC
  15. })
  16. // Web3实例
  17. const web3 = ref(null)
  18. // 初始化Web3
  19. const initWeb3 = () => {
  20. try {
  21. web3.value = new Web3(authState.rpcUrl)
  22. return web3.value
  23. } catch (err) {
  24. authState.error = '初始化区块链连接失败'
  25. return null
  26. }
  27. }
  28. // 获取账户余额
  29. const getBalance = async () => {
  30. if (!authState.account || !web3.value) return '0'
  31. try {
  32. const weiBalance = await web3.value.eth.getBalance(authState.account)
  33. const ethBalance = web3.value.utils.fromWei(weiBalance, 'ether')
  34. authState.balance = ethBalance
  35. return ethBalance
  36. } catch (err) {
  37. authState.error = '获取余额失败: ' + err.message
  38. return '0'
  39. }
  40. }
  41. // 通过私钥登录
  42. const loginWithPrivateKey = async (privateKey, password = '') => {
  43. authState.loading = true
  44. authState.error = null
  45. try {
  46. const web3Instance = initWeb3()
  47. if (!web3Instance) throw new Error('区块链连接失败')
  48. // 验证私钥格式
  49. if (!/^0x[0-9a-fA-F]{64}$/.test(privateKey)) {
  50. throw new Error('私钥格式不正确')
  51. }
  52. // 加密存储私钥(如果提供了密码)
  53. if (password) {
  54. authState.encryptedKey = CryptoJS.AES.encrypt(
  55. privateKey,
  56. password
  57. ).toString()
  58. }
  59. // 从私钥获取账户
  60. const account = web3Instance.eth.accounts.privateKeyToAccount(privateKey)
  61. // 验证账户有效性
  62. const code = await web3Instance.eth.getCode(account.address)
  63. if (code !== '0x') {
  64. throw new Error('该地址是合约地址,不支持登录')
  65. }
  66. // 更新状态
  67. authState.account = account.address
  68. authState.privateKey = privateKey
  69. authState.isAuthenticated = true
  70. authState.chainId = await web3Instance.eth.getChainId()
  71. // 登录后自动获取余额
  72. await getBalance()
  73. return {
  74. address: account.address,
  75. chainId: authState.chainId,
  76. balance: authState.balance
  77. }
  78. } catch (err) {
  79. authState.error = err.message || '登录失败'
  80. throw err
  81. } finally {
  82. authState.loading = false
  83. }
  84. }
  85. // 通过加密存储登录(需密码)
  86. const loginWithStorage = async (password) => {
  87. if (!authState.encryptedKey) {
  88. throw new Error('没有可用的加密钱包数据')
  89. }
  90. try {
  91. // 解密私钥
  92. const bytes = CryptoJS.AES.decrypt(authState.encryptedKey, password)
  93. const privateKey = bytes.toString(CryptoJS.enc.Utf8)
  94. if (!privateKey) throw new Error('密码错误或数据损坏')
  95. return await loginWithPrivateKey(privateKey)
  96. } catch (err) {
  97. authState.error = err.message || '解密失败'
  98. throw err
  99. }
  100. }
  101. // 登出
  102. const logout = () => {
  103. authState.isAuthenticated = false
  104. authState.account = null
  105. authState.privateKey = null
  106. authState.chainId = null
  107. authState.balance = '0'
  108. web3.value = null
  109. }
  110. // 检查本地是否有加密钱包数据
  111. const hasStoredWallet = () => {
  112. return !!authState.encryptedKey
  113. }
  114. return {
  115. authState,
  116. web3,
  117. loginWithPrivateKey,
  118. loginWithStorage,
  119. logout,
  120. hasStoredWallet,
  121. getBalance
  122. }
  123. }