|
@@ -0,0 +1,144 @@
|
|
|
+import Web3 from 'web3'
|
|
|
+import CryptoJS from 'crypto-js'
|
|
|
+
|
|
|
+export function useWalletAuth() {
|
|
|
+ // 登录状态
|
|
|
+ const authState = reactive({
|
|
|
+ isAuthenticated: false, // 登录状态
|
|
|
+ account: null, // 账户
|
|
|
+ privateKey: null, // 私钥
|
|
|
+ encryptedKey: null, // 加密后的密钥
|
|
|
+ loading: false, // 加载状态
|
|
|
+ error: null, // 错误信息
|
|
|
+ chainId: null, // 链ID
|
|
|
+ balance: '0', // 账户余额(ETH)
|
|
|
+ rpcUrl: 'https://api.angeltokens.io' // 您的私有链RPC
|
|
|
+ })
|
|
|
+
|
|
|
+ // Web3实例
|
|
|
+ const web3 = ref(null)
|
|
|
+
|
|
|
+ // 初始化Web3
|
|
|
+ const initWeb3 = () => {
|
|
|
+ try {
|
|
|
+ web3.value = new Web3(authState.rpcUrl)
|
|
|
+ return web3.value
|
|
|
+ } catch (err) {
|
|
|
+ authState.error = '初始化区块链连接失败'
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取账户余额
|
|
|
+ const getBalance = async () => {
|
|
|
+ if (!authState.account || !web3.value) return '0'
|
|
|
+
|
|
|
+ try {
|
|
|
+ const weiBalance = await web3.value.eth.getBalance(authState.account)
|
|
|
+ const ethBalance = web3.value.utils.fromWei(weiBalance, 'ether')
|
|
|
+ authState.balance = ethBalance
|
|
|
+ return ethBalance
|
|
|
+ } catch (err) {
|
|
|
+ authState.error = '获取余额失败: ' + err.message
|
|
|
+ return '0'
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通过私钥登录
|
|
|
+ const loginWithPrivateKey = async (privateKey, password = '') => {
|
|
|
+ authState.loading = true
|
|
|
+ authState.error = null
|
|
|
+
|
|
|
+ try {
|
|
|
+ const web3Instance = initWeb3()
|
|
|
+ if (!web3Instance) throw new Error('区块链连接失败')
|
|
|
+
|
|
|
+ // 验证私钥格式
|
|
|
+ if (!/^0x[0-9a-fA-F]{64}$/.test(privateKey)) {
|
|
|
+ throw new Error('私钥格式不正确')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加密存储私钥(如果提供了密码)
|
|
|
+ if (password) {
|
|
|
+ authState.encryptedKey = CryptoJS.AES.encrypt(
|
|
|
+ privateKey,
|
|
|
+ password
|
|
|
+ ).toString()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从私钥获取账户
|
|
|
+ const account = web3Instance.eth.accounts.privateKeyToAccount(privateKey)
|
|
|
+
|
|
|
+ // 验证账户有效性
|
|
|
+ const code = await web3Instance.eth.getCode(account.address)
|
|
|
+ if (code !== '0x') {
|
|
|
+ throw new Error('该地址是合约地址,不支持登录')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态
|
|
|
+ authState.account = account.address
|
|
|
+ authState.privateKey = privateKey
|
|
|
+ authState.isAuthenticated = true
|
|
|
+ authState.chainId = await web3Instance.eth.getChainId()
|
|
|
+
|
|
|
+ // 登录后自动获取余额
|
|
|
+ await getBalance()
|
|
|
+
|
|
|
+ return {
|
|
|
+ address: account.address,
|
|
|
+ chainId: authState.chainId,
|
|
|
+ balance: authState.balance
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ authState.error = err.message || '登录失败'
|
|
|
+ throw err
|
|
|
+ } finally {
|
|
|
+ authState.loading = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 通过加密存储登录(需密码)
|
|
|
+ const loginWithStorage = async (password) => {
|
|
|
+ if (!authState.encryptedKey) {
|
|
|
+ throw new Error('没有可用的加密钱包数据')
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 解密私钥
|
|
|
+ const bytes = CryptoJS.AES.decrypt(authState.encryptedKey, password)
|
|
|
+ const privateKey = bytes.toString(CryptoJS.enc.Utf8)
|
|
|
+
|
|
|
+ if (!privateKey) throw new Error('密码错误或数据损坏')
|
|
|
+
|
|
|
+ return await loginWithPrivateKey(privateKey)
|
|
|
+ } catch (err) {
|
|
|
+ authState.error = err.message || '解密失败'
|
|
|
+ throw err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 登出
|
|
|
+ const logout = () => {
|
|
|
+ authState.isAuthenticated = false
|
|
|
+ authState.account = null
|
|
|
+ authState.privateKey = null
|
|
|
+ authState.chainId = null
|
|
|
+ authState.balance = '0'
|
|
|
+ web3.value = null
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查本地是否有加密钱包数据
|
|
|
+ const hasStoredWallet = () => {
|
|
|
+ return !!authState.encryptedKey
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ authState,
|
|
|
+ web3,
|
|
|
+ loginWithPrivateKey,
|
|
|
+ loginWithStorage,
|
|
|
+ logout,
|
|
|
+ hasStoredWallet,
|
|
|
+ getBalance
|
|
|
+ }
|
|
|
+}
|