From 5f2ad5778491fa56aa05acf4eb728a79b355a22d Mon Sep 17 00:00:00 2001 From: cebgcontract <99630598+cebgcontract@users.noreply.github.com> Date: Fri, 4 Mar 2022 19:08:04 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4web3modal,=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=99=BB=E9=99=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- src/cebg.d.ts | 6 + src/components/core/ChainModal.vue | 193 +++++++++++++++++ src/components/index/DesktopFooter.vue | 4 + src/configs/allchain.ts | 274 +++++++++++++++++++++++++ src/configs/chains.ts | 59 ++++++ src/{utils => configs}/config_chain.ts | 0 src/main.ts | 3 +- src/utils/ChainManager.ts | 12 +- src/utils/blockchain.ts | 272 ++++++++++++++++-------- src/utils/chain.util.ts | 20 ++ src/utils/event-bus.ts | 8 + vue.config.js | 3 + 13 files changed, 761 insertions(+), 95 deletions(-) create mode 100644 src/cebg.d.ts create mode 100644 src/components/core/ChainModal.vue create mode 100644 src/configs/allchain.ts create mode 100644 src/configs/chains.ts rename src/{utils => configs}/config_chain.ts (100%) create mode 100644 src/utils/chain.util.ts diff --git a/.env.development b/.env.development index d037843..dd33e6a 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,5 @@ VUE_APP_WALLET_INFURAID='e7743d46923911fa8850619b7a7f6d9d' -VUE_APP_BASE_API='https://market-test.kingsome.cn' +VUE_APP_BASE_API='https://market.cebg.games' VUE_APP_CHAIN_ID=322 VUE_APP_CHAIN_RPC='https://rpc-testnet.kcc.network' VUE_APP_CHAIN_NAME='KCC-TESTNET' diff --git a/src/cebg.d.ts b/src/cebg.d.ts new file mode 100644 index 0000000..dba423d --- /dev/null +++ b/src/cebg.d.ts @@ -0,0 +1,6 @@ +interface Window { + ethereum: any + web3: any + celo: any +} +declare let window: Window diff --git a/src/components/core/ChainModal.vue b/src/components/core/ChainModal.vue new file mode 100644 index 0000000..c89acc7 --- /dev/null +++ b/src/components/core/ChainModal.vue @@ -0,0 +1,193 @@ + + + diff --git a/src/components/index/DesktopFooter.vue b/src/components/index/DesktopFooter.vue index f4b5017..d539398 100644 --- a/src/components/index/DesktopFooter.vue +++ b/src/components/index/DesktopFooter.vue @@ -44,20 +44,24 @@
Copyright © CEBG. All rights reserved. +
diff --git a/src/configs/allchain.ts b/src/configs/allchain.ts new file mode 100644 index 0000000..eed8f92 --- /dev/null +++ b/src/configs/allchain.ts @@ -0,0 +1,274 @@ +export const AllChains = [ + { + name: 'Ethereum Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ankr.com/eth', + id: '1', + symbol: 'ETH', + explorerurl: 'https://etherscan.io' + }, + { + name: 'Ethereum Ropsten Testnet RPC', + type: 'Testnet', + rpc: 'https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + id: '3', + symbol: 'ETH', + explorerurl: 'https://ropsten.etherscan.io' + }, + { + name: 'Ethereum Rinkeby Testnet RPC', + type: 'Testnet', + rpc: 'https://rinkey.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + id: '4', + symbol: 'ETH', + explorerurl: 'https://rinkey.etherscan.io' + }, + { + name: 'Ethereum Goerli Testnet RPC', + type: 'Testnet', + rpc: 'https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + id: '5', + symbol: 'ETH', + explorerurl: 'https://goerli.etherscan.io' + }, + { + name: 'Ethereum Kovan Testnet RPC', + type: 'Testnet', + rpc: 'https://kovan.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161', + id: '6', + symbol: 'ETH', + explorerurl: 'https://kovan.etherscan.io' + }, + { + name: 'Ubiq Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.octano.dev/', + id: '8', + symbol: 'UBQ', + explorerurl: 'https://ubiqscan.io/' + }, + { + name: 'Elastos ETH Mainnet RPC', + type: 'Mainnet', + rpc: 'https://api.elastos.io/eth', + id: '20', + symbol: 'ELA', + explorerurl: 'https://explorer.elaeth.io/' + }, + { + name: 'Cronos Mainnet RPC', + type: 'Mainnet', + rpc: 'https://evm-cronos.crypto.org', + id: '25', + symbol: 'CRO', + explorerurl: 'https://cronos.crypto.org/explorer/' + }, + { + name: 'Telos EVM Mainnet RPC', + type: 'Mainnet', + rpc: 'https://mainnet.telos.net/evm', + id: '40', + symbol: 'TLOS', + explorerurl: 'https://telos.net/' + }, + { + name: 'Binance Smart Chain Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ankr.com/bsc', + id: '56', + symbol: 'BNB', + explorerurl: 'https://bscscan.com' + }, + { + name: 'OKExChain Mainnet RPC', + type: 'Mainnet', + rpc: 'https://exchainrpc.okex.org', + id: '66', + symbol: 'OKT', + explorerurl: 'https://www.oklink.com/okexchain' + }, + { + name: 'Hoo Mainnet RPC', + type: 'Mainnet', + rpc: 'https://http-mainnet.hoosmartchain.com', + id: '70', + symbol: 'HOO', + explorerurl: 'https://hooscan.com' + }, + { + name: 'Binance Smart Chain Testnet RPC', + type: 'Testnet', + rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545/', + id: '97', + symbol: 'BNB', + explorerurl: 'https://testnet.bscscan.com' + }, + { + name: 'xDai Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.xdaichain.com/', + id: '100', + symbol: 'XDAI', + explorerurl: 'https://blockscout.com/xdai/mainnet/' + }, + { + name: 'Fuse Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.fuse.io', + id: '122', + symbol: 'FUSE', + explorerurl: 'https://explorer.fuse.io/' + }, + { + name: 'HECO Mainnet RPC', + type: 'Mainnet', + rpc: 'https://http-mainnet-node.huobichain.com/', + id: '128', + symbol: 'HT', + explorerurl: 'https://hecoinfo.com/' + }, + { + name: 'Matic Mainnet RPC', + type: 'Mainnet', + rpc: 'https://polygon-rpc.com', + id: '137', + symbol: 'MATIC', + explorerurl: 'https://explorer.matic.network/' + }, + { + name: 'Fantom Opera Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ftm.tools/', + id: '250', + symbol: 'FTM', + explorerurl: 'https://ftmscan.com' + }, + { + name: 'HECO Testnet RPC', + type: 'Testnet', + rpc: 'https://http-testnet.hecochain.com', + id: '256', + symbol: 'HT', + explorerurl: 'https://testnet.hecoinfo.com/' + }, + { + name: 'KCC Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc-mainnet.kcc.network', + id: '321', + symbol: 'KCS', + explorerurl: 'https://scan.kcc.network' + }, + { + name: 'KCC Testnet RPC', + type: 'Testnet', + rpc: 'https://scan-testnet.kcc.network', + id: '322', + symbol: 'tKCS', + explorerurl: 'https://scan-testnet.kcc.network' + }, + { + name: 'Moonriver Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.moonriver.moonbeam.network', + id: '1285', + symbol: 'MOVR', + explorerurl: 'https://blockscout.moonriver.moonbeam.network/' + }, + { + name: 'Fantom Testnet RPC', + type: 'Testnet', + rpc: 'https://rpc.testnet.fantom.network/', + id: '4002', + symbol: 'FTM', + explorerurl: 'https://testnet.ftmscan.com' + }, + { + name: 'IoTeX Mainnet RPC', + type: 'Mainnet', + rpc: 'https://babel-api.mainnet.iotex.io', + id: '4689', + symbol: 'IOTEX', + explorerurl: 'https://iotexscan.io/' + }, + { + name: 'Nahmii Mainnet RPC', + type: 'Mainnet', + rpc: 'https://l2.nahmii.io/', + id: '5551', + symbol: 'ETH', + explorerurl: 'https://explorer.nahmii.io/' + }, + { + name: 'Nahmii Testnet RPC', + type: 'Testnet', + rpc: 'https://l2.testnet.nahmii.io/', + id: '5553', + symbol: 'ETH', + explorerurl: 'https://explorer.testnet.nahmii.io/' + }, + { + name: 'Arbitrum Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ankr.com/arbitrum', + id: '42161', + symbol: 'ETH', + explorerurl: 'https://arbiscan.io/' + }, + { + name: 'Celo Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ankr.com/celo', + id: '42220', + symbol: 'CELO', + explorerurl: 'https://celoscan.com' + }, + { + name: 'Avalanche C Chain Local RPC', + type: 'Testnet', + rpc: 'https://localhost:9650/ext/bc/C/rpc', + id: '43112', + symbol: 'AVAX', + explorerurl: 'https://snowtrace.io' + }, + { + name: 'Avalanche FUJI Testnet RPC', + type: 'Testnet', + rpc: 'https://api.avax-test.network/ext/bc/C/rpc', + id: '43113', + symbol: 'AVAX', + explorerurl: 'https://testnet.explorer.avax.network/' + }, + { + name: 'Avalanche C Chain Mainnet RPC', + type: 'Mainnet', + rpc: 'https://rpc.ankr.com/avalanche', + id: '43114', + symbol: 'AVAX', + explorerurl: 'https://snowtrace.io' + }, + { + name: 'Matic Testnet RPC', + type: 'Testnet', + rpc: 'https://rpc-mumbai.maticvigil.com', + id: '80001', + symbol: 'MATIC', + explorerurl: 'https://mumbai.polygonscan.com/' + }, + { + name: 'Harmony Mainnet RPC', + type: 'Mainnet', + rpc: 'https://api.harmony.one/', + id: '1666600000', + symbol: 'ONE', + explorerurl: 'https://explorer.harmony.one' + }, + { + name: 'Harmony Testnet RPC', + type: 'Testnet', + rpc: 'https://api.s0.b.hmny.io/', + id: '1666700000', + symbol: 'ONE', + explorerurl: 'https://explorer.harmony.one' + } +] diff --git a/src/configs/chains.ts b/src/configs/chains.ts new file mode 100644 index 0000000..db292a9 --- /dev/null +++ b/src/configs/chains.ts @@ -0,0 +1,59 @@ +const env = process.env.NODE_ENV || 'development' +export interface IChainData{ + id: number + name: string + logo: string + rpc: string + explorerurl: string + symbol: string + decimals: number + type: string +} +export const chainMap: Map = new Map([ + ['development', [ + { + type: 'development', + id: 322, + name: 'KCC-TESTNET', + logo: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzIgMzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDA5M0REO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxNiIgY3k9IjE2IiByPSIxNiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTEzLjUsMTZsNS4yLDUuM0wyMiwxOGMwLjYtMC42LDEuNS0wLjYsMiwwYzAsMCwwLDAsMCwwYzAuNiwwLjYsMC42LDEuNiwwLDIuMmwtNC4zLDQuNAoJCWMtMC42LDAuNi0xLjUsMC42LTIuMSwwYzAsMCwwLDAsMCwwbC02LjItNi40VjIyYzAsMC44LTAuNywxLjUtMS41LDEuNWMtMC44LDAtMS41LTAuNy0xLjUtMS41VjEwYzAtMC44LDAuNy0xLjUsMS41LTEuNQoJCWMwLjgsMCwxLjUsMC43LDEuNSwxLjV2My44bDYuMi02LjRjMC42LTAuNiwxLjUtMC42LDIuMSwwYzAsMCwwLDAsMCwwbDQuMyw0LjRjMC42LDAuNiwwLjYsMS42LDAsMi4yYy0wLjYsMC42LTEuNSwwLjYtMiwwCgkJYzAsMCwwLDAsMCwwbC0zLjMtMy40TDEzLjUsMTZ6IE0xOC43LDE0LjVjMC44LDAsMS41LDAuNywxLjUsMS41cy0wLjcsMS41LTEuNSwxLjVzLTEuNS0wLjctMS41LTEuNQoJCUMxNy4yLDE1LjIsMTcuOSwxNC41LDE4LjcsMTQuNXoiLz4KPC9nPgo8L3N2Zz4K', + rpc: 'https://rpc-testnet.kcc.network', + explorerurl: 'https://scan-testnet.kcc.network', + symbol: 'KCS', + decimals: 18 + }, + { + type: 'development', + id: 97, + name: 'BSC Testnet', + logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAwIiBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgMCAyMDAwIDIwMDAiPjxnIGZpbGw9IiNmM2JhMmYiPjxwYXRoIGQ9Ik02MTEuNTkgODQwLjQybDM4OC40LTM4OC4zOSAzODguNiAzODguNTkgMjI2LTIyNkw5OTkuOTkgMCAzODUuNiA2MTQuNDJsMjI1Ljk5IDIyNk0uMDA2IDk5OS45NjlsMjI2LjAwNy0yMjYuMDA3IDIyNS45OTIgMjI1Ljk5M0wyMjYgMTIyNS45NnpNNjExLjU5IDExNTkuNThsMzg4LjQgMzg4LjM5IDM4OC41OS0zODguNTggMjI2LjEyIDIyNS44OC0uMTEuMTJMOTk5Ljk5IDIwMDBsLTYxNC40MS02MTQuNC0uMzItLjMyIDIyNi4zMy0yMjUuN00xNTQ4LjAxMyAxMDAwLjA5M2wyMjYuMDA3LTIyNi4wMDYgMjI1Ljk5MiAyMjUuOTkyLTIyNi4wMDYgMjI2LjAwN3oiLz48cGF0aCBkPSJNMTIyOS4yMiA5OTkuODhoLjFMOTk5Ljk5IDc3MC41NSA4MzAuNTEgOTQwLjAzaC0uMDFsLTE5LjQ3IDE5LjQ4LTQwLjE2IDQwLjE3LS4zMi4zMS4zMi4zMyAyMjkuMTIgMjI5LjEzIDIyOS4zMy0yMjkuMzMuMTEtLjEzLS4yMS0uMTEiLz48L2c+PC9zdmc+', + rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545/', + explorerurl: 'https://testnet.bscscan.com/', + symbol: 'BNB', + decimals: 18 + } + ]], + ['production', [ + { + type: 'production', + id: 321, + name: 'KCC-MAINNET', + logo: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzIgMzI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDA5M0REO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRkZGRkZGO30KPC9zdHlsZT4KPGc+Cgk8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxNiIgY3k9IjE2IiByPSIxNiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTEzLjUsMTZsNS4yLDUuM0wyMiwxOGMwLjYtMC42LDEuNS0wLjYsMiwwYzAsMCwwLDAsMCwwYzAuNiwwLjYsMC42LDEuNiwwLDIuMmwtNC4zLDQuNAoJCWMtMC42LDAuNi0xLjUsMC42LTIuMSwwYzAsMCwwLDAsMCwwbC02LjItNi40VjIyYzAsMC44LTAuNywxLjUtMS41LDEuNWMtMC44LDAtMS41LTAuNy0xLjUtMS41VjEwYzAtMC44LDAuNy0xLjUsMS41LTEuNQoJCWMwLjgsMCwxLjUsMC43LDEuNSwxLjV2My44bDYuMi02LjRjMC42LTAuNiwxLjUtMC42LDIuMSwwYzAsMCwwLDAsMCwwbDQuMyw0LjRjMC42LDAuNiwwLjYsMS42LDAsMi4yYy0wLjYsMC42LTEuNSwwLjYtMiwwCgkJYzAsMCwwLDAsMCwwbC0zLjMtMy40TDEzLjUsMTZ6IE0xOC43LDE0LjVjMC44LDAsMS41LDAuNywxLjUsMS41cy0wLjcsMS41LTEuNSwxLjVzLTEuNS0wLjctMS41LTEuNQoJCUMxNy4yLDE1LjIsMTcuOSwxNC41LDE4LjcsMTQuNXoiLz4KPC9nPgo8L3N2Zz4K', + rpc: 'https://rpc-mainnet.kcc.network', + explorerurl: 'https://explorer.kcc.io', + symbol: 'KCS', + decimals: 18 + }, + { + type: 'production', + id: 32, + name: 'BSC', + logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTAwIiBoZWlnaHQ9IjI1MDAiIHZpZXdCb3g9IjAgMCAyMDAwIDIwMDAiPjxnIGZpbGw9IiNmM2JhMmYiPjxwYXRoIGQ9Ik02MTEuNTkgODQwLjQybDM4OC40LTM4OC4zOSAzODguNiAzODguNTkgMjI2LTIyNkw5OTkuOTkgMCAzODUuNiA2MTQuNDJsMjI1Ljk5IDIyNk0uMDA2IDk5OS45NjlsMjI2LjAwNy0yMjYuMDA3IDIyNS45OTIgMjI1Ljk5M0wyMjYgMTIyNS45NnpNNjExLjU5IDExNTkuNThsMzg4LjQgMzg4LjM5IDM4OC41OS0zODguNTggMjI2LjEyIDIyNS44OC0uMTEuMTJMOTk5Ljk5IDIwMDBsLTYxNC40MS02MTQuNC0uMzItLjMyIDIyNi4zMy0yMjUuN00xNTQ4LjAxMyAxMDAwLjA5M2wyMjYuMDA3LTIyNi4wMDYgMjI1Ljk5MiAyMjUuOTkyLTIyNi4wMDYgMjI2LjAwN3oiLz48cGF0aCBkPSJNMTIyOS4yMiA5OTkuODhoLjFMOTk5Ljk5IDc3MC41NSA4MzAuNTEgOTQwLjAzaC0uMDFsLTE5LjQ3IDE5LjQ4LTQwLjE2IDQwLjE3LS4zMi4zMS4zMi4zMyAyMjkuMTIgMjI5LjEzIDIyOS4zMy0yMjkuMzMuMTEtLjEzLS4yMS0uMTEiLz48L2c+PC9zdmc+', + rpc: 'https://bsc-dataseed.binance.org', + explorerurl: 'https://www.bscscan.com', + symbol: 'BNB', + decimals: 18 + } + ]] +]) + +export const chains: () => IChainData[] = () => chainMap.get(env) || [] diff --git a/src/utils/config_chain.ts b/src/configs/config_chain.ts similarity index 100% rename from src/utils/config_chain.ts rename to src/configs/config_chain.ts diff --git a/src/main.ts b/src/main.ts index 9bbb50d..af02ffd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,12 +1,13 @@ import Vue from 'vue' import App from './App.vue' -import { Loading, Message, MessageBox, Notification, Slider } from 'element-ui' +import { Loading, Message, MessageBox, Notification, Slider, Tooltip } from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import router from './router' import store from './store' Vue.use(Loading.directive) Vue.use(Slider) +Vue.use(Tooltip) Vue.config.productionTip = false diff --git a/src/utils/ChainManager.ts b/src/utils/ChainManager.ts index f6adae9..a87257f 100644 --- a/src/utils/ChainManager.ts +++ b/src/utils/ChainManager.ts @@ -4,21 +4,20 @@ import { getNonce } from '@/api/User' import { AppModule } from '@/store/modules/app' import { UserModule } from '@/store/modules/user' import { Message } from 'element-ui' +import { EventBus, NEED_NONCE } from '@/utils/event-bus' @singleton export default class ChainManager { bc: BlockChain constructor() { this.bc = new BlockChain() + EventBus.$on(NEED_NONCE, this.checkNance.bind(this)) } public async init() { if (this.bc.isWalletConnect) { try { await this.bc.connect() - if (!AppModule.nonce && !AppModule.step) { - await this.getNance() - } } catch (err) { console.log('connect chain error: ', err) } @@ -36,17 +35,18 @@ export default class ChainManager { public async login() { if (!AppModule.accountId) { try { - await this.bc.connect() + await this.bc.connect(true) } catch (err) { Message({ message: err.message, type: 'error', duration: 5 * 1000 }) - return } } - console.log(`AppModule.accountId: ${AppModule.accountId}, chainId: ${AppModule.chainId}`) + } + + public async checkNance() { try { let nonce = AppModule.nonce if (!nonce) { diff --git a/src/utils/blockchain.ts b/src/utils/blockchain.ts index cecdb51..2e18e33 100644 --- a/src/utils/blockchain.ts +++ b/src/utils/blockchain.ts @@ -1,12 +1,22 @@ import { singleton } from '@/decorators/singleton.decorator' import WalletConnectProvider from '@walletconnect/web3-provider' -import Web3Modal, { isMobile } from 'web3modal' import { AppModule } from '@/store/modules/app' import Web3 from 'web3' -import { MessageBox } from 'element-ui' -import { ERC20ABI, MALL_ADDRESS } from '@/utils/config_chain' -import { ACCOUNT_CHANGE, EventBus, NEED_LOGIN, NEED_NONCE } from '@/utils/event-bus' +import { ERC20ABI, MALL_ADDRESS } from '@/configs/config_chain' +import { + ACCOUNT_CHANGE, + CHAIN_SELECTED, + EventBus, NEED_CHANGE_CHAIN, + NEED_LOGIN, + NEED_NONCE, + SHOW_CHAIN_MODAL, + WALLET_SELECTED +} from '@/utils/event-bus' import { UserModule } from '@/store/modules/user' +import { chains, IChainData } from '@/configs/chains' +import { isMobile } from '@/utils/resize' +import { hasMetamask } from '@/utils/chain.util' +import { AllChains } from '@/configs/allchain' const EIP721_DOMAIN_DATA = [ { name: 'name', type: 'string' }, @@ -15,41 +25,34 @@ const EIP721_DOMAIN_DATA = [ { name: 'verifyingContract', type: 'address' } ] +const CACHE_KEY = 'cebg_chain_cache_key' + @singleton export class BlockChain { provider:any web3: Web3 - web3Modal: Web3Modal + currentChain = 0 + // 0: null, 1: metamask, 2: walletconnect + walletType = 0 + dataCached = false coinInstanceMap: Map + public chainMap: Map = new Map() + public rpc: any = {} constructor() { - const chainId = parseInt(process.env.VUE_APP_CHAIN_ID!) - this.coinInstanceMap = new Map() - AppModule.updateChainID(chainId) - const rpc: any = { } - rpc[chainId] = process.env.VUE_APP_CHAIN_RPC! - const providerOptions = { - // binancechainwallet: { - // package: true - // }, - walletconnect: { - package: WalletConnectProvider, // required - options: { - infuraId: process.env.VUE_APP_WALLET_INFURAID, - chainId, - rpc - } - } + const chainDatas = chains() + for (const data of chainDatas) { + this.chainMap.set(data.id, data) } - const disableInjectedProvider = isMobile() - console.log('disableInjectedProvider: ', disableInjectedProvider) - this.web3Modal = new Web3Modal({ - cacheProvider: true, // optional - disableInjectedProvider, - providerOptions // required - }) - + for (const d of AllChains) { + this.rpc[parseInt(d.id)] = d.rpc + } + this.loadCachedProvider() + this.coinInstanceMap = new Map() + // AppModule.updateChainID(chainId) EventBus.$on(NEED_LOGIN, this.connect.bind(this)) + EventBus.$on(WALLET_SELECTED, this.walletSelected.bind(this)) + EventBus.$on(CHAIN_SELECTED, this.chainSelected.bind(this)) } loadJson(url: string) { @@ -58,43 +61,117 @@ export class BlockChain { } get isWalletConnect() { - return !!this.web3Modal.cachedProvider + return !!this.walletType && !!this.currentChain } - public async connect() { - try { - this.provider = await this.web3Modal.connect() - this.subscribeToEvents() - this.web3 = new Web3( this.provider) - const accounts = await this.web3.eth.getAccounts() - const chainId = await this.web3.eth.getChainId() - if (chainId !== AppModule.chainId) { - try { - await MessageBox.confirm( - 'You need to connect to supported network', - 'Wrong Network', - { - confirmButtonText: `Switch to ${process.env.VUE_APP_CHAIN_NAME} network`, - cancelButtonText: 'Cancel', - type: 'warning' - } - ) - await this.switchEthereumChain() - } catch (err) { - return this.disconnect() - } - } - if (accounts && accounts.length > 0) { - AppModule.updateAccount(accounts[0]) - } - AppModule.updateWalletStatus(true) - console.log('chainId: ', chainId) - console.log('accountsLogin: ', accounts, AppModule.accountId) + public get hexChainId() { + return '0x' + this.currentChain.toString(16) + } + + public async chainSelected(id: number) { + if (!this.chainMap.has(id)) { + return + } + this.currentChain = id + if (this.provider) { + await this.switchEthereumChain() + } else { + await this.connectWallet(true) + } + } + + public async walletSelected(type: number) { + this.walletType = type + await this.connectWallet(true) + } + + public async connectWallet(isManual: boolean) { + console.log('begin connect to wallet: ', this.walletType, this.currentChain) + if (this.walletType === 1) { + this.provider = await this.connectMetaMask() + } else if (this.walletType === 2) { + this.provider = await this.connectWalletConnect() + } + if (!this.provider) { + return + } + this.web3 = new Web3(this.provider) + this.subscribeToEvents() + const chainId = await this.web3.eth.getChainId() + if (!this.chainMap.has(chainId)) { + EventBus.$emit(NEED_CHANGE_CHAIN) + return + } + const accounts = await this.web3.eth.getAccounts() + if (accounts && accounts.length > 0) { + AppModule.updateAccount(accounts[0]) + } + this.saveProvider() + AppModule.updateChainID(chainId) + AppModule.updateWalletStatus(true) + console.log('current login chain: ', chainId) + console.log('accountsLogin: ', accounts, AppModule.accountId) + if (isManual) { EventBus.$emit(NEED_NONCE) - return { account: accounts[0], chainId } + } else { + AppModule.updateStep(1) + } + return { account: accounts[0], chainId } + } + + public async connect(isManual = false) { + if (isMobile()) { + this.walletType = 2 + } else { + if (hasMetamask()) { + if (isManual && !this.walletType) { + EventBus.$emit(SHOW_CHAIN_MODAL) + return + } + } else { + this.walletType = 2 + } + } + if (this.isWalletConnect) { + await this.connectWallet(false) + } else { + EventBus.$emit(NEED_CHANGE_CHAIN) + } + } + + public async connectMetaMask() { + let provider = null + if (typeof window.ethereum !== 'undefined') { + provider = window.ethereum + try { + await provider.request({ method: 'eth_requestAccounts' }) + } catch (error) { + throw new Error('User Rejected') + } + } else if (window.web3) { + provider = window.web3.currentProvider + } else if (window.celo) { + provider = window.celo + } else { + throw new Error('No Web3 Provider found') + } + return provider + } + + public async connectWalletConnect() { + const provider = new WalletConnectProvider({ + infuraId: process.env.VUE_APP_WALLET_INFURAID, + chainId: 97, + rpc: this.rpc + }) + try { + await provider.enable() } catch (err) { + console.log('connect to wallet connect error: ', err) await Promise.reject(err) } + + return provider } private async initInstance(abi: any, address: string, account: string) { @@ -115,15 +192,47 @@ export class BlockChain { } } + public clearCachedProvider() { + console.log('clear cached provider') + localStorage.removeItem(CACHE_KEY) + } + + public loadCachedProvider() { + const dataStr = localStorage.getItem(CACHE_KEY) + if (dataStr) { + try { + const data = JSON.parse(dataStr) + this.walletType = data.walletType + if (this.chainMap.has(data.chainId)) { + this.currentChain = data.chainId + } + } catch (err) { + console.log('err parse cached json') + this.clearCachedProvider() + } + } + } + + public saveProvider() { + const data = { + walletType: this.walletType, + chainId: this.currentChain + } + localStorage.setItem(CACHE_KEY, JSON.stringify(data)) + } + public async disconnect() { try { await UserModule.LogOut() await this.provider?.disconnect() + this.currentChain = 0 + this.walletType = 0 + this.clearCachedProvider() AppModule.updateStep(0) AppModule.updateNonce('') } catch (err) { } - this.web3Modal.clearCachedProvider() + this.clearCachedProvider() AppModule.updateAccount('') AppModule.updateWalletStatus(false) } @@ -146,20 +255,7 @@ export class BlockChain { console.log('chainChanged', chainId) const chainIdNum = parseInt(chainId) if (chainIdNum !== AppModule.chainId) { - try { - await MessageBox.confirm( - 'You need to connect to supported network', - 'Wrong Network', - { - confirmButtonText: `Switch to ${process.env.VUE_APP_CHAIN_NAME} network`, - cancelButtonText: 'Cancel', - type: 'warning' - } - ) - await this.switchEthereumChain() - } catch (err) { - return this.disconnect() - } + EventBus.$emit(NEED_CHANGE_CHAIN) } }) @@ -171,31 +267,33 @@ export class BlockChain { async switchEthereumChain() { try { - await window.ethereum.request({ + await this.provider.request({ method: 'wallet_switchEthereumChain', - params: [{ chainId: AppModule.hexChainId }] + params: [{ chainId: this.hexChainId }] }) } catch (e: any) { + console.log('switch chain error: ', e) if (e.code === 4902) { try { - await window.ethereum.request({ + const data = this.chainMap.get(this.currentChain)! + await this.provider.request({ method: 'wallet_addEthereumChain', params: [ { - chainId: AppModule.hexChainId, - chainName: process.env.VUE_APP_CHAIN_NAME, + chainId: this.hexChainId, + chainName: data.name, nativeCurrency: { - name: process.env.VUE_APP_CHAIN_CURRENCY_NAME, - symbol: process.env.VUE_APP_CHAIN_CURRENCY_SYMBOL, - decimals: parseInt(process.env.VUE_APP_CHAIN_CURRENCY_DECIMALS!) + name: data.symbol, + symbol: data.symbol, + decimals: data.decimals }, - blockExplorerUrls: [process.env.VUE_APP_CHAIN_EXPLORERURL], - rpcUrls: [process.env.VUE_APP_CHAIN_RPC] + blockExplorerUrls: [data.explorerurl], + rpcUrls: [data.rpc] } ] }) } catch (addError) { - console.error(addError) + console.error('add chain error: ', addError) } } // console.error(e) diff --git a/src/utils/chain.util.ts b/src/utils/chain.util.ts new file mode 100644 index 0000000..397c96a --- /dev/null +++ b/src/utils/chain.util.ts @@ -0,0 +1,20 @@ + +export function verifyInjectedProvider(check: string): boolean { + return window.ethereum + ? window.ethereum[check] + : window.web3 && + window.web3.currentProvider && + window.web3.currentProvider[check] +} + +/** + * check if there have metamask + * @return {boolean} + */ +export function hasMetamask(): boolean { + if (!!window.ethereum || !!window.web3) { + return verifyInjectedProvider('isMetaMask') + } else { + return false + } +} diff --git a/src/utils/event-bus.ts b/src/utils/event-bus.ts index a3c0c99..e693d97 100644 --- a/src/utils/event-bus.ts +++ b/src/utils/event-bus.ts @@ -14,3 +14,11 @@ export const NEED_LOGIN = 'need_login' export const NEED_NONCE = 'need_nonce' export const ACCOUNT_CHANGE = 'account_change' + +export const SHOW_CHAIN_MODAL = 'show_chain_modal' + +export const NEED_CHANGE_CHAIN = 'need_change_chain' + +export const WALLET_SELECTED = 'wallet_selected' + +export const CHAIN_SELECTED = 'chain_selected' diff --git a/vue.config.js b/vue.config.js index b7a3822..3b57371 100644 --- a/vue.config.js +++ b/vue.config.js @@ -11,6 +11,9 @@ module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/' : '/', lintOnSave: process.env.NODE_ENV === 'development', productionSourceMap: false, + devServer: { + https: true + }, pwa: { name: name },