HomeView.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. <script setup lang="ts">
  2. //@ts-ignore
  3. import MetaMaskSDK from '../utils/metamask-sdk.js'
  4. //@ts-ignore
  5. import getZksEra from '../utils/getZksEra.js'
  6. //@ts-ignore
  7. import getZksLite from '../utils/getZksLite.js'
  8. //@ts-ignore
  9. import getZkSyncBridge from '../utils/getZkSyncBridge.js'
  10. import * as echarts from 'echarts';
  11. import {onMounted, ref} from 'vue';
  12. import balancerBg from '../project/balancer/balancerBg.png'
  13. import balancerAv from '../project/balancer/balancerAv.png'
  14. import argentBg from '../project/argent/argentBg.png'
  15. import argentAv from '../project/argent/argentAv.png'
  16. import ontoBg from '../project/onto/ontoBg.png'
  17. import ontoAv from '../project/onto/ontoAv.png'
  18. import zerionBg from '../project/zerion/zerionBg.png'
  19. import zerionAv from '../project/zerion/zerionAv.png'
  20. import zksEraBridgeAv from '../project/zksEraBridge/zksEraBridgeAv.png'
  21. import zksEraBridgeBg from '../project/zksEraBridge/zksEraBridgeBg.png'
  22. import zksLiteBridgeBg from '../project/zksLiteBridge/zksLiteBridgeBg.png'
  23. import zksLiteBridgeAv from '../project/zksLiteBridge/zksLiteBridgeAv.png'
  24. import orbiterAv from '../project/orbiter/orbiterAv.png'
  25. import orbiterBg from '../project/orbiter/orbiterBg.png'
  26. import muteAv from '../project/mute/muteAv.png'
  27. import muteBg from '../project/mute/muteBg.png'
  28. import syncswapBg from '../project/syncswap/syncswapBg.png'
  29. import syncswapAv from '../project/syncswap/syncswapAv.png'
  30. import getcoinBg from '../project/getcoin/getcoinBg.png'
  31. import getcoinAv from '../project/getcoin/getcoinAv.png'
  32. type EChartsOption = echarts.EChartsOption;
  33. onMounted(() => {
  34. checkWalletAddress()
  35. })
  36. type dataArrType = {
  37. name: string,
  38. type: string[],
  39. BG: string,
  40. avatar: string,
  41. url:string
  42. }[]
  43. let dataArr: dataArrType = [
  44. {
  45. name: 'zks-era bridge',
  46. type: ['OFFICAL','BRIDGE'],
  47. BG: zksEraBridgeBg,
  48. avatar: zksEraBridgeAv,
  49. url:'https://bridge.zksync.io/'
  50. },
  51. {
  52. name: 'zks-lite bridge',
  53. type: ['OFFICAL','BRIDGE'],
  54. BG: zksLiteBridgeBg,
  55. avatar: zksLiteBridgeAv,
  56. url:'https://lite.zksync.io/transaction/deposit'
  57. },
  58. {
  59. name: 'Orbiter',
  60. type: ['ERA', 'SWAP'],
  61. BG: orbiterBg,
  62. avatar: orbiterAv,
  63. url:'https://www.orbiter.finance/'
  64. },
  65. {
  66. name: 'Mute',
  67. type: ['ERA', 'DEFI', 'SWAP'],
  68. BG: muteBg,
  69. avatar: muteAv,
  70. url:'https://app.mute.io/swap'
  71. },
  72. {
  73. name: 'Syncswap',
  74. type: ['ERA', 'SWAP'],
  75. BG: syncswapBg,
  76. avatar: syncswapAv,
  77. url:'https://syncswap.xyz/'
  78. },
  79. {
  80. name: 'Gitcoin',
  81. type: ['DEFI', 'SWAP'],
  82. BG: getcoinBg,
  83. avatar: getcoinAv,
  84. url:'https://bounties.gitcoin.co/'
  85. },
  86. ]
  87. let MM = ref()//MetaMaskSDK
  88. let address = ref('')//钱包地址
  89. let chainId = '0x144'
  90. const MMSDK = new MetaMaskSDK()
  91. MM.value = MMSDK.getProvider()
  92. //查询钱包地址
  93. const checkWalletAddress = async () => {
  94. let accounts: string[] = await MM.value.request({method: 'eth_accounts'});//不弹窗
  95. address.value = accounts[0]
  96. getMainTx()
  97. getLiteTx()
  98. getMoreInfo()
  99. await addChain()
  100. await switchEthereumChain()
  101. }
  102. //添加链
  103. const addChain = () => {
  104. MM.value.request({
  105. method: 'wallet_addEthereumChain',
  106. params: [{
  107. chainId: chainId,
  108. chainName: 'zkSync Era Mainnet',
  109. rpcUrls: ['https://mainnet.era.zksync.io'],
  110. blockExplorerUrls: ['https://explorer.zksync.io'],
  111. nativeCurrency: {
  112. name: 'ETH',
  113. symbol: 'ETH',
  114. decimals: 18,
  115. },
  116. }]
  117. })
  118. }
  119. //切换链
  120. const switchEthereumChain = () => {
  121. MM.value.request({
  122. method: 'wallet_switchEthereumChain',
  123. params: [{chainId: chainId}],
  124. }).then(() => {
  125. }).catch(() => {
  126. });
  127. }
  128. //连接钱包按钮
  129. const connectWallet = async () => {
  130. let accounts: string[] = await MM.value.request({method: 'eth_requestAccounts'});
  131. address.value = accounts[0]
  132. getMainTx()
  133. getLiteTx()
  134. getMoreInfo()
  135. await addChain()
  136. await switchEthereumChain()
  137. }
  138. //获取主网交易次数
  139. let mainTx = ref(0)
  140. const getMainTx = () => {
  141. getZksEra(address.value).then(({tx2}:{tx2:number}) => {
  142. mainTx.value = tx2
  143. })
  144. }
  145. //获取lite网交易次数
  146. let liteTx = ref(0)
  147. const getLiteTx = () => {
  148. getZksLite(address.value).then(({tx1}:{tx1:number}) => {
  149. liteTx.value = tx1
  150. })
  151. }
  152. //获取更多信息
  153. let amount = ref(0)
  154. let contract = ref(0)
  155. let tradingTimeArr = ref()
  156. const getMoreInfo = () => {
  157. getZkSyncBridge(address.value).then((
  158. {
  159. totalExchangeAmount,
  160. contractActivity,
  161. overTimeArr,
  162. }:{
  163. totalExchangeAmount:number
  164. contractActivity:number
  165. overTimeArr:any
  166. }) => {
  167. amount.value = totalExchangeAmount
  168. contract.value = contractActivity
  169. tradingTimeArr.value = overTimeArr
  170. processTime()
  171. })
  172. }
  173. //处理时间数据
  174. const monthArr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
  175. let showMonthNumberArr = ref([0,0,0,0,0,0,0,0,0,0,0,0])
  176. let showMonthArr = ref()
  177. const processTime = () => {
  178. let nowDate = new Date().toString()
  179. let nowDateArr = nowDate.split(' ')
  180. let nowMonth = nowDateArr[1]
  181. showMonthArr.value = []
  182. showMonthArr.value.push(nowMonth)
  183. let nowMonthIndex = monthArr.indexOf(nowMonth)
  184. const forLoop = () => {
  185. for (let i = 11; i !== nowMonthIndex ; i--) {
  186. showMonthArr.value.unshift(monthArr[i])
  187. }
  188. }
  189. for (let i = nowMonthIndex; i !== 0 ; i--) {
  190. showMonthArr.value.unshift(monthArr[i-1])
  191. if (i === 1) {
  192. forLoop()
  193. }
  194. }
  195. if (tradingTimeArr.value){
  196. tradingTimeArr.value.forEach((item:any) => {
  197. let receivedAt = new Date(Date.parse(item.receivedAt)).toString();
  198. let strArr = receivedAt.split(' ')
  199. let month = strArr[1]
  200. let index = showMonthArr.value.indexOf(month)
  201. showMonthNumberArr.value[index]++
  202. })
  203. }
  204. initEcharts()
  205. }
  206. //初始化echarts
  207. const initEcharts = () => {
  208. let chartDom = document.getElementById('echartsBox')!
  209. let myChart = echarts.init(chartDom);
  210. let option: EChartsOption;
  211. option = {
  212. tooltip: {
  213. trigger: 'axis',
  214. axisPointer: {
  215. type: 'shadow'
  216. }
  217. },
  218. xAxis: {
  219. type: 'category',
  220. axisTick: {
  221. alignWithLabel: true
  222. },
  223. data: showMonthArr.value
  224. },
  225. yAxis: {
  226. type: 'value',
  227. },
  228. series: [
  229. {
  230. color: '#000000',
  231. data: showMonthNumberArr.value,
  232. type: 'bar'
  233. }
  234. ]
  235. };
  236. option && myChart.setOption(option);
  237. }
  238. //跳转网页
  239. const toLink = (url:string) => {
  240. window.open(url)
  241. }
  242. const toEmail = (email:string) => {
  243. const emailAddress = email; // 替换为你想发送邮件的收件人地址
  244. const subject = 'Hello'; // 替换为你想在邮件中设置的主题
  245. const body = 'This is the email body.'; // 替换为你想在邮件中设置的内容
  246. const mailtoUrl = `mailto:${emailAddress}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
  247. window.open(mailtoUrl);
  248. }
  249. </script>
  250. <template>
  251. <main class="main">
  252. <div class="topBar">
  253. <div class="left">
  254. <img src="../assets/bitflower.svg" alt="logo">
  255. </div>
  256. <div class="mid">
  257. Blossom your Web3 Trip ✈
  258. </div>
  259. <div class="right">
  260. <div class="button" v-show="!address" @click="connectWallet">
  261. <img src="../assets/git-commit-line.svg" alt="commit">
  262. Connect Wallet
  263. </div>
  264. <div class="connect" v-if="address">
  265. <img src="../assets/git-commit-line-black.svg" alt="commit">
  266. {{ address.slice(0, 8) }}...{{ address.slice(-4) }}
  267. </div>
  268. </div>
  269. </div>
  270. <div class="dataColumn">
  271. <div class="item">
  272. <div class="top">
  273. <div class="img">
  274. <img src="../assets/group1.svg" alt="group1">
  275. </div>
  276. <div class="title">
  277. Protocols lnteraction
  278. <el-popover
  279. placement="bottom"
  280. :width="230"
  281. trigger="hover"
  282. effect="dark"
  283. >
  284. <template #reference>
  285. <img src="../assets/info.svg" alt="info">
  286. </template>
  287. <div class="popoverText">
  288. Number of protocolsinteracted
  289. </div>
  290. <div class="popoverText">
  291. with out of allavailable protocols
  292. </div>
  293. </el-popover>
  294. </div>
  295. </div>
  296. <div class="number">
  297. {{ contract }}
  298. </div>
  299. </div>
  300. <div class="item">
  301. <div class="top">
  302. <div class="img">
  303. <img class="img" src="../assets/group3.svg" alt="group2">
  304. </div>
  305. <div class="title">
  306. Total Transactions
  307. <el-popover
  308. placement="bottom"
  309. :width="250"
  310. trigger="hover"
  311. effect="dark"
  312. >
  313. <template #reference>
  314. <img src="../assets/info.svg" alt="info">
  315. </template>
  316. <div class="popoverText">
  317. Total zkSync lite
  318. </div>
  319. <div class="popoverText">
  320. transactions issuedfrom the account
  321. </div>
  322. </el-popover>
  323. </div>
  324. </div>
  325. <div class="number">
  326. {{ liteTx }}
  327. <img @click="toLink('https://zkscan.io/')" style="cursor: pointer" src="../assets/arrow-right-up-line.svg" alt="arrow">
  328. </div>
  329. </div>
  330. <div class="item">
  331. <div class="top">
  332. <div class="img">
  333. <img class="img" src="../assets/group2.svg" alt="group2">
  334. </div>
  335. <div class="title">
  336. Total Transactions
  337. <el-popover
  338. placement="bottom"
  339. :width="250"
  340. trigger="hover"
  341. effect="dark"
  342. >
  343. <template #reference>
  344. <img src="../assets/info.svg" alt="info">
  345. </template>
  346. <div class="popoverText">
  347. Total zkSync era
  348. </div>
  349. <div class="popoverText">
  350. transactions issuedfrom the account
  351. </div>
  352. </el-popover>
  353. </div>
  354. </div>
  355. <div class="number">
  356. {{ mainTx }}
  357. <img @click="toLink('https://explorer.zksync.io/')" style="cursor: pointer" src="../assets/arrow-right-up-line.svg" alt="arrow">
  358. </div>
  359. </div>
  360. <div class="item">
  361. <div class="top">
  362. <div class="img">
  363. <img class="img" src="../assets/group4.svg" alt="group2">
  364. </div>
  365. <div class="title">
  366. Total amount spent
  367. </div>
  368. </div>
  369. <div class="number">
  370. {{ amount }} USDT
  371. </div>
  372. </div>
  373. </div>
  374. <div class="primary">
  375. <div class="left">
  376. <div class="echarts">
  377. <div class="title">
  378. Transactions Over Time
  379. <el-popover
  380. placement="right"
  381. :width="240"
  382. trigger="hover"
  383. effect="dark"
  384. >
  385. <template #reference>
  386. <img src="../assets/info.svg" alt="info">
  387. </template>
  388. <div class="popoverText">
  389. Number of transactions permonth
  390. </div>
  391. </el-popover>
  392. </div>
  393. <div class="echartsBox" id="echartsBox">
  394. </div>
  395. </div>
  396. <div class="disclaimer">
  397. <img src="../assets/disclaimer.svg" alt="disclaimer">
  398. <div class="description">
  399. The list of dApps is for informational purposes only. It is not a testimony of the security or reliability
  400. of any dApp. Furthermore, most dApps are currently in alpha stage and their code is not audited. You are
  401. encouraged to do your own research (DYOR) before interacting with, or investing in any dApps. This should
  402. not be considered financial or investment advice.
  403. </div>
  404. <div class="contact">
  405. <div class="item" @click="toEmail('bitflower.web3@gmail.com')">
  406. <img src="../assets/mail-open-line.svg" alt="mail">
  407. E-mail
  408. </div>
  409. <div class="line"/>
  410. <div class="item" @click="toLink('https://t.me/bitflowersupport')">
  411. <img src="../assets/telegram-line.svg" alt="telegram">
  412. Telegram
  413. </div>
  414. </div>
  415. </div>
  416. </div>
  417. <div class="right">
  418. <div class="item" @click="toLink(item.url)" v-for="item in dataArr">
  419. <div class="BG">
  420. <img class="BG" :src="item.BG" alt="BG">
  421. </div>
  422. <div class="infoBox">
  423. <div class="avatar">
  424. <img class="avatar" :src="item.avatar" alt="avatar">
  425. </div>
  426. <div class="nameAndType">
  427. <div class="name">
  428. {{ item.name }}
  429. </div>
  430. <div class="typeBox">
  431. <div class="type" v-for="item1 in item.type">
  432. {{ item1 }}
  433. </div>
  434. </div>
  435. </div>
  436. </div>
  437. </div>
  438. </div>
  439. </div>
  440. </main>
  441. </template>
  442. <style lang="scss">
  443. .main {
  444. width: 1440px;
  445. height: 100vh;
  446. margin: auto;
  447. border: 1px solid #f7f7f7;
  448. padding: 30px 60px;
  449. .topBar {
  450. display: flex;
  451. align-items: center;
  452. justify-content: space-between;
  453. .mid{
  454. font-weight: 400;
  455. font-size: 15px;
  456. line-height: 21px;
  457. font-family: 'Chillax';
  458. text-transform: uppercase;
  459. }
  460. .right {
  461. .button {
  462. width: fit-content;
  463. height: 44px;
  464. display: flex;
  465. align-items: center;
  466. gap: 6px;
  467. background: #010101;
  468. padding: 0 24px;
  469. font-weight: 500;
  470. font-size: 15px;
  471. line-height: 20px;
  472. color: #FFFFFF;
  473. cursor: pointer;
  474. }
  475. .connect {
  476. width: fit-content;
  477. height: 44px;
  478. display: flex;
  479. align-items: center;
  480. gap: 6px;
  481. background: #FFFFFF;
  482. border: 1px solid #010101;
  483. border-radius: 30px;
  484. padding: 0 24px;
  485. font-weight: 500;
  486. font-size: 15px;
  487. line-height: 20px;
  488. color: #010101;
  489. }
  490. }
  491. }
  492. .dataColumn {
  493. display: flex;
  494. align-items: center;
  495. justify-content: space-between;
  496. padding: 75px 60px 60px 60px;
  497. border-bottom: 1px solid #f7f7f7;
  498. margin: 0 -60px;
  499. .item {
  500. width: 330px;
  501. display: flex;
  502. flex-direction: column;
  503. gap: 20px;
  504. .top {
  505. display: flex;
  506. flex-direction: column;
  507. gap: 6px;
  508. .img {
  509. height: 16px;
  510. }
  511. .title {
  512. display: flex;
  513. align-items: center;
  514. gap: 8px;
  515. font-weight: 400;
  516. font-size: 14px;
  517. line-height: 18px;
  518. color: #010101;
  519. .popoverText{
  520. font-weight: 400;
  521. font-size: 12px;
  522. line-height: 24px;
  523. }
  524. }
  525. }
  526. .number {
  527. display: flex;
  528. align-items: center;
  529. gap: 8px;
  530. font-weight: 700;
  531. font-size: 26px;
  532. line-height: 34px;
  533. color: #010101;
  534. }
  535. }
  536. }
  537. .primary {
  538. display: flex;
  539. gap: 60px;
  540. margin-top: 60px;
  541. .left {
  542. display: flex;
  543. flex-direction: column;
  544. .echarts {
  545. .title {
  546. display: flex;
  547. align-items: center;
  548. gap: 8px;
  549. font-weight: 700;
  550. font-size: 14px;
  551. line-height: 18px;
  552. color: #010101;
  553. }
  554. .echartsBox {
  555. height: 360px;
  556. width: 560px;
  557. }
  558. }
  559. .disclaimer {
  560. width: 558px;
  561. height: 246px;
  562. border: 1px solid #010101;
  563. padding: 24px;
  564. .description {
  565. margin-top: 8px;
  566. margin-bottom: 28px;
  567. font-weight: 400;
  568. font-size: 12px;
  569. line-height: 24px;
  570. color: #808080;
  571. }
  572. .contact {
  573. width: fit-content;
  574. height: 44px;
  575. display: flex;
  576. align-items: center;
  577. gap: 24px;
  578. font-weight: 500;
  579. font-size: 14px;
  580. line-height: 18px;
  581. color: #FFFFFF;
  582. background: #010101;
  583. padding: 0 24px;
  584. .item{
  585. display: flex;
  586. align-items: center;
  587. gap:6px;
  588. cursor: pointer;
  589. }
  590. .line{
  591. width: 1px;
  592. height: 16px;
  593. border-right: 1px solid #4C4C4C;
  594. }
  595. }
  596. }
  597. }
  598. .right {
  599. display: flex;
  600. flex-wrap: wrap;
  601. overflow: auto;
  602. gap: 26px;
  603. width: 100%;
  604. height: 620px;
  605. margin-right: -60px;
  606. .item {
  607. height: 256px;
  608. width: 336px;
  609. cursor: pointer;
  610. .BG {
  611. width: 100%;
  612. height: 175px;
  613. }
  614. .infoBox {
  615. display: flex;
  616. align-items: center;
  617. gap: 12px;
  618. padding: 0 24px;
  619. height: 80px;
  620. border: 1px solid #010101;
  621. border-top: none;
  622. .avatar {
  623. width: 40px;
  624. height: 40px;
  625. border-radius: 50%;
  626. }
  627. .nameAndType {
  628. display: flex;
  629. flex-direction: column;
  630. gap: 2px;
  631. .name {
  632. font-weight: 700;
  633. font-size: 17px;
  634. line-height: 22px;
  635. color: #010101;
  636. }
  637. .typeBox {
  638. display: flex;
  639. align-items: center;
  640. gap: 10px;
  641. .type {
  642. width: fit-content;
  643. height: 16px;
  644. border: 1px solid #b3b3b3;
  645. font-weight: 400;
  646. font-size: 12px;
  647. line-height: 16px;
  648. color: #b3b3b3;
  649. padding: 0 4px;
  650. }
  651. }
  652. }
  653. }
  654. }
  655. }
  656. }
  657. }
  658. ::-webkit-scrollbar {
  659. width: 4px; /* 滚动条宽度 */
  660. }
  661. // /* 滚动条轨道 */
  662. // ::-webkit-scrollbar-track {
  663. // background: #f1f1f1; /* 轨道背景色 */
  664. // }
  665. /* 滚动条滑块 */
  666. ::-webkit-scrollbar-thumb {
  667. background: #888; /* 滑块背景色 */
  668. }
  669. /* 滚动条滑块悬停状态 */
  670. ::-webkit-scrollbar-thumb:hover {
  671. background: #555; /* 悬停状态下滑块背景色 */
  672. }
  673. </style>