diff --git a/.env.dev b/.env.dev index 40f51db..fbf9c74 100644 --- a/.env.dev +++ b/.env.dev @@ -6,8 +6,8 @@ VUE_APP_GPAL_API='https://game2006api.cebggame.com/' VUE_APP_PASSPORT_PUBLISHABLE_KEY=pk_imapik-test-eRr-kyOKaZ0jIdrvrPCn VUE_APP_PASSPORT_REDIRECT_URI=http://localhost:4000/marketplace VUE_APP_PASSPORT_LOGOUT_URI=http://localhost:4000/ -# VUE_APP_PASSPORT_CLIENT_ID=eTmUah69p7ZdRhRYzBta6lZRKXXeXDYj -VUE_APP_PASSPORT_CLIENT_ID=0FNfXxQywm7wjdbyLTDzWt4txc53yRrT +VUE_APP_PASSPORT_CLIENT_ID=eTmUah69p7ZdRhRYzBta6lZRKXXeXDYj +#VUE_APP_PASSPORT_CLIENT_ID=0FNfXxQywm7wjdbyLTDzWt4txc53yRrT VUE_APP_PASSPORT_MARKET_ADDRESS=0x7d117aA8BD6D31c4fa91722f246388f38ab1942c VUE_APP_MKT_API='https://market-test.kingsome.cn' VUE_APP_NET_ID='13473' diff --git a/src/components/chain/BlockChain.js b/src/components/chain/BlockChain.js index 2dfd288..646778a 100644 --- a/src/components/chain/BlockChain.js +++ b/src/components/chain/BlockChain.js @@ -43,40 +43,45 @@ export class BlockChain { new PassportWallet(); } - async restoreWallet(walletType) { - this.wallet = new allProviders[walletType](); - const { provider, token } = await this.wallet.web3Provider(); + async updateInfo({provider, accounts, token}) { this.provider = provider + if (!token && !this.store.token) { + token = await this.wallet.getAccessToken(); + } else if (!token && this.store.token){ + token = this.store.token; + } + this.store.address = accounts[0]; this.token = token + this.store.token = token; this.store.$persist(); this.market.updateProvider(provider); return provider; } + async restoreWallet(walletType) { + this.wallet = new allProviders[walletType](); + let { provider, accounts, token } = await this.wallet.web3Provider(); + await this.updateInfo({provider, accounts, token}) + return provider; + } + async connect() { // if this only one provider configed, use it directly if (ALL_PROVIDERS.length === 1) { const walletType = ALL_PROVIDERS[0].id this.wallet = new allProviders[walletType](); - const { provider, accounts, token } = await this.wallet.web3Provider(); - this.provider = provider - this.market.updateProvider(provider); this.store.walletType = walletType; - this.store.address = accounts[0]; - this.token = token - this.store.$persist(); - return + const { provider, accounts, token } = await this.wallet.web3Provider(); + await this.updateInfo({ provider, accounts, token }) + return provider; } const rewardModal = createModal(WalletSelectModel, {}); - let result = await rewardModal.show(); + const result = await rewardModal.show(); if (!result.errcode) { - this.provider = result.provider; - this.market.updateProvider(this.provider); - this.wallet = new allProviders[result.wallet](); this.store.walletType = result.wallet; - this.store.address = result.accounts[0]; - this.token = token - this.store.$persist(); + this.wallet = new allProviders[result.wallet](); + await this.updateInfo(result) + return result.provider } else { console.log(`select result : ${result.errmsg}`); throw new Error(result.errmsg); diff --git a/src/components/chain/common/SiweMessage.js b/src/components/chain/common/SiweMessage.js new file mode 100644 index 0000000..3670db5 --- /dev/null +++ b/src/components/chain/common/SiweMessage.js @@ -0,0 +1,49 @@ +export class SiweMessage { + constructor(param) { + Object.assign(this, param); + } + + toMessage() { + const header = `${this.domain} wants you to sign in with your Ethereum account:`; + const uriField = `URI: ${this.uri}`; + let prefix = [header, this.address].join('\n'); + const versionField = `Version: ${this.version}`; + + const chainField = `Chain ID: ` + this.chainId || '1'; + + const nonceField = `Nonce: ${this.nonce}`; + + const suffixArray = [uriField, versionField, chainField, nonceField]; + + this.issuedAt = this.issuedAt || new Date().toISOString(); + + suffixArray.push(`Issued At: ${this.issuedAt}`); + + if (this.expirationTime) { + const expiryField = `Expiration Time: ${this.expirationTime}`; + + suffixArray.push(expiryField); + } + + if (this.notBefore) { + suffixArray.push(`Not Before: ${this.notBefore}`); + } + + if (this.requestId) { + suffixArray.push(`Request ID: ${this.requestId}`); + } + + if (this.resources) { + suffixArray.push( + [`Resources:`, ...this.resources.map(x => `- ${x}`)].join('\n') + ); + } + + const suffix = suffixArray.join('\n'); + prefix = [prefix, this.statement].join('\n\n'); + if (this.statement) { + prefix += '\n'; + } + return [prefix, suffix].join('\n'); + } +} diff --git a/src/components/chain/utils.js b/src/components/chain/utils.js new file mode 100644 index 0000000..7146039 --- /dev/null +++ b/src/components/chain/utils.js @@ -0,0 +1,59 @@ +export const WALLET_API_HOST_TEST = 'https://oauth-svr.cebggame.com/test'; +export const WALLET_API_HOST_RELEASE = 'https://wallet.cebggame.com'; +const apiBase = process.env.NODE_ENV === 'production' ? WALLET_API_HOST_RELEASE : WALLET_API_HOST_TEST; +import { SiweMessage } from './common/SiweMessage'; +import { ethers } from 'ethers'; + +const loginWithSignature = async(message, signature) => { + const url = `${apiBase}/wallet/login/general`; + const data = { + channel: 13, + code: signature, + message + } + let headers = { + 'Content-Type': 'application/json', + 'api_version': 2, + 'api_platform': 'marketplace', + 'api_env': process.env.NODE_ENV === 'production' ? 'release' : 'dev' + }; + return fetch(url, { + method: "POST", + body: JSON.stringify(data), + headers + }).then(res => res.json()); +} + +const utf8ToHex = (str) => { + return '0x' + Buffer.from(str).toString('hex'); +} + + +export const signLogin = async (provider, address) => { + const nonce = Date.now()+''; + address = ethers.utils.getAddress(address); + let chainId = await provider.request({ method: "eth_chainId" }); + chainId = parseInt(chainId); + const message = new SiweMessage({ + domain: document.location.host, + address, + chainId, + uri: document.location.origin, + version: "1", + statement: "CF MarketPlace", + nonce, + }); + const msgSign = message.toMessage(); + const signature = await provider.request({ + "method": "personal_sign", + "params": [ + utf8ToHex(msgSign), + address + ] + }); + const res = await loginWithSignature(message, signature); + if (res.errcode) { + throw new Error(res.errmsg); + } + return res.data?.token; +} \ No newline at end of file diff --git a/src/components/chain/wallet/MetaMaskWallet.js b/src/components/chain/wallet/MetaMaskWallet.js index 30cf2d0..e03cedd 100644 --- a/src/components/chain/wallet/MetaMaskWallet.js +++ b/src/components/chain/wallet/MetaMaskWallet.js @@ -1,4 +1,5 @@ import { providers } from "ethers" +import { signLogin } from '@/components/chain/utils.js' export class MetaMaskWallet{ constructor() { @@ -18,6 +19,12 @@ export class MetaMaskWallet{ return { provider, accounts }; } + async getAccessToken() { + const accounts = await this.nativeProvider.request({ method: "eth_requestAccounts" }); + const token = await signLogin(this.nativeProvider, accounts[0]); + return token + } + async logout() { await this.nativeProvider.request({ "method": "wallet_revokePermissions", diff --git a/src/components/chain/wallet/OkxWallet.js b/src/components/chain/wallet/OkxWallet.js index 985cad5..e390c8c 100644 --- a/src/components/chain/wallet/OkxWallet.js +++ b/src/components/chain/wallet/OkxWallet.js @@ -19,6 +19,12 @@ export class OkxWallet{ return { provider, accounts }; } + async getAccessToken() { + const accounts = await this.nativeProvider.request({ method: "eth_requestAccounts" }); + const token = await signLogin(this.nativeProvider, accounts[0]); + return token + } + async logout() { await this.nativeProvider.request({ method: 'wallet_disconnect' }); } diff --git a/src/components/chain/wallet/PassportWallet.js b/src/components/chain/wallet/PassportWallet.js index e945cd2..29f3b4e 100644 --- a/src/components/chain/wallet/PassportWallet.js +++ b/src/components/chain/wallet/PassportWallet.js @@ -20,6 +20,7 @@ export class PassportWallet { clientId, // replace with your client ID from Hub redirectUri, // replace with one of your redirect URIs from Hub logoutRedirectUri, // replace with one of your logout URIs from Hub + logoutMode: 'silent', audience: 'platform_api', scope: 'openid offline_access email transact', popupOverlayOptions: { @@ -63,7 +64,6 @@ export class PassportWallet { const accounts = await passportProvider.request({ method: "eth_requestAccounts" }); const provider = new providers.Web3Provider(passportProvider); const token = await this.passportInstance.getAccessToken() - console.log(`accesstoken`, token) return { provider, accounts, token }; } @@ -74,6 +74,7 @@ export class PassportWallet { async logout() { await this.passportInstance.logout(); + await this.passportInstance.logoutSilentCallback(logoutRedirectUri); } } diff --git a/src/store/wallet.js b/src/store/wallet.js index cea342e..9eec881 100644 --- a/src/store/wallet.js +++ b/src/store/wallet.js @@ -7,6 +7,7 @@ export const walletStore = defineStore( const walletType = ref(); const address = ref(); const chainId = ref(); + const token = ref(); const showAddress = computed(() => { if (address.value.length > 10) { @@ -19,11 +20,13 @@ export const walletStore = defineStore( walletType.value = ''; address.value = ''; chainId.value = ''; + token.value = ''; } return { walletType, address, chainId, + token, showAddress, reset, };