Kaynağa Gözat

完成 增加starkNet页面,增加数据图表显示

million 1 yıl önce
ebeveyn
işleme
7310880206
51 değiştirilmiş dosya ile 2237 ekleme ve 73 silme
  1. 4 2
      index.html
  2. 5 0
      package.json
  3. 5 0
      src/assets/TVL.svg
  4. 22 18
      src/assets/base.css
  5. 5 0
      src/assets/exit.svg
  6. BIN
      src/assets/home/BG1.png
  7. BIN
      src/assets/home/BG2.png
  8. BIN
      src/assets/home/BG3.png
  9. BIN
      src/assets/navBg.png
  10. 14 0
      src/assets/starkNet/STARKNET.svg
  11. BIN
      src/assets/starkNet/starkNet.png
  12. 10 0
      src/assets/tag.svg
  13. 10 0
      src/assets/title.svg
  14. 5 0
      src/assets/viewMore.svg
  15. 4 2
      src/components/Footer.vue
  16. 35 31
      src/components/Nav.vue
  17. BIN
      src/project/aspect/BG.png
  18. BIN
      src/project/aspect/avatar.png
  19. BIN
      src/project/briq/BG.png
  20. BIN
      src/project/briq/avatar.png
  21. BIN
      src/project/fibrous/BG.png
  22. BIN
      src/project/fibrous/avatar.png
  23. BIN
      src/project/mySwap/BG.png
  24. BIN
      src/project/mySwap/avatar.png
  25. BIN
      src/project/realms/BG.png
  26. BIN
      src/project/realms/avatar.png
  27. BIN
      src/project/sithSwap/BG.png
  28. BIN
      src/project/sithSwap/avatar.png
  29. BIN
      src/project/starkGate/BG.png
  30. BIN
      src/project/starkGate/avatar.png
  31. BIN
      src/project/starknetId/BG.png
  32. BIN
      src/project/starknetId/avatar.png
  33. 6 1
      src/router/index.ts
  34. 3 2
      src/stores/sun.ts
  35. 21 0
      src/utils/indexedDB/deleteData.js
  36. 11 0
      src/utils/indexedDB/getDBTranscationsData.js
  37. 100 0
      src/utils/indexedDB/main.js
  38. 6 0
      src/utils/stark/getAccountInfo.js
  39. 55 0
      src/utils/stark/getActivity.js
  40. 53 0
      src/utils/stark/getBalance.js
  41. 37 0
      src/utils/stark/getBridge.js
  42. 92 0
      src/utils/stark/getTransactions.js
  43. 73 0
      src/utils/stark/getTransfers.js
  44. 31 0
      src/utils/stark/getTxAndFee.js
  45. 19 0
      src/utils/stark/getVol.js
  46. 47 0
      src/utils/stark/main.js
  47. 21 0
      src/utils/stark/utils.js
  48. 48 5
      src/views/HomeView.vue
  49. 10 7
      src/views/LayerZeroView.vue
  50. 1118 0
      src/views/StarkNet.vue
  51. 367 5
      src/views/ZksyncView.vue

+ 4 - 2
index.html

@@ -25,8 +25,10 @@
         gtag('config', 'G-CG3QTL7PXK');
     </script>
 </head>
-<body>
-<div id="app"></div>
+<body style="background: black">
+<div id="app">
+
+</div>
 <script type="module" src="/src/main.ts"></script>
 </body>
 </html>

+ 5 - 0
package.json

@@ -11,12 +11,17 @@
     "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false"
   },
   "dependencies": {
+    "@antv/g2plot": "^2.4.31",
     "axios": "^1.4.0",
     "echarts": "^5.4.2",
     "element-plus": "^2.3.6",
     "ethers": "^6.6.0",
+    "get-starknet": "^3.0.1",
+    "idb": "^7.1.1",
+    "moment": "^2.29.4",
     "pinia": "^2.1.3",
     "sass": "^1.63.4",
+    "starknet": "^5.17.0",
     "vue": "^3.3.4",
     "vue-router": "^4.2.2"
   },

Dosya farkı çok büyük olduğundan ihmal edildi
+ 5 - 0
src/assets/TVL.svg


+ 22 - 18
src/assets/base.css

@@ -20,15 +20,17 @@
   --vt-c-text-dark-1: var(--vt-c-white);
   --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
 
-  /*--vt-c-border: #555555;*/
-  --vt-c-border: #f1f1f1;
-
-  --vt-c-pure: #ffffff;
+  --vt-c-border: #555555;
+  --vt-c-pure: #000000;
+  /*--vt-c-border: #f1f1f1;*/
+  /*--vt-c-pure: #ffffff;*/
 }
 
 /* semantic color variables for this project */
 :root {
-  --color-background: #fcfffa;
+  /*--color-background: #fcfffa;*/
+  --color-background:#000000;
+  --color-text:#f2f2f2;
   --color-background-soft: var(--vt-c-white-soft);
   --color-background-mute: var(--vt-c-white-mute);
 
@@ -36,24 +38,25 @@
   --color-border-hover: var(--vt-c-divider-light-1);
 
   --color-heading: var(--vt-c-text-light-1);
-  --color-text: var(--vt-c-text-light-1);
+  /*--color-text: var(--vt-c-text-light-1);*/
 
   --section-gap: 160px;
 }
 
-@media (prefers-color-scheme: dark) {
-  :root {
-    --color-background: var(--vt-c-black);
-    --color-background-soft: var(--vt-c-black-soft);
-    --color-background-mute: var(--vt-c-black-mute);
+/*@media (prefers-color-scheme: dark) {*/
+/*  :root {*/
+/*    !*--color-background: var(--vt-c-black);*!*/
+/*    --color-background:#000000;*/
+/*    --color-background-soft: var(--vt-c-black-soft);*/
+/*    --color-background-mute: var(--vt-c-black-mute);*/
 
-    --color-border: var(--vt-c-divider-dark-2);
-    --color-border-hover: var(--vt-c-divider-dark-1);
+/*    --color-border: var(--vt-c-divider-dark-2);*/
+/*    --color-border-hover: var(--vt-c-divider-dark-1);*/
 
-    --color-heading: var(--vt-c-text-dark-1);
-    --color-text: var(--vt-c-text-dark-2);
-  }
-}
+/*    --color-heading: var(--vt-c-text-dark-1);*/
+/*    --color-text: var(--vt-c-text-dark-2);*/
+/*  }*/
+/*}*/
 
 *,
 *::before,
@@ -66,7 +69,8 @@
 body {
   min-height: 100vh;
   color: var(--color-text);
-  background: var(--color-background);
+  /*background: var(--color-background);*/
+  background: #000000;
   transition: color 0.5s, background-color 0.5s;
   line-height: 1.6;
   font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,

Dosya farkı çok büyük olduğundan ihmal edildi
+ 5 - 0
src/assets/exit.svg


BIN
src/assets/home/BG1.png


BIN
src/assets/home/BG2.png


BIN
src/assets/home/BG3.png


BIN
src/assets/navBg.png


Dosya farkı çok büyük olduğundan ihmal edildi
+ 14 - 0
src/assets/starkNet/STARKNET.svg


BIN
src/assets/starkNet/starkNet.png


+ 10 - 0
src/assets/tag.svg

@@ -0,0 +1,10 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g opacity="0.5">
+<mask id="mask0_1898_1496" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
+<rect width="20" height="20" fill="#D9D9D9"/>
+</mask>
+<g mask="url(#mask0_1898_1496)">
+<path d="M5 16.6668L5.83333 13.3335H2.5L2.91667 11.6668H6.25L7.08333 8.3335H3.75L4.16667 6.66683H7.5L8.33333 3.3335H10L9.16667 6.66683H12.5L13.3333 3.3335H15L14.1667 6.66683H17.5L17.0833 8.3335H13.75L12.9167 11.6668H16.25L15.8333 13.3335H12.5L11.6667 16.6668H10L10.8333 13.3335H7.5L6.66667 16.6668H5ZM7.91667 11.6668H11.25L12.0833 8.3335H8.75L7.91667 11.6668Z" fill="white"/>
+</g>
+</g>
+</svg>

+ 10 - 0
src/assets/title.svg

@@ -0,0 +1,10 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g opacity="0.5">
+<mask id="mask0_1899_1564" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
+<rect width="20" height="20" fill="#D9D9D9"/>
+</mask>
+<g mask="url(#mask0_1899_1564)">
+<path d="M6.66637 16.4581C6.48921 16.4581 6.3408 16.3982 6.22115 16.2784C6.10149 16.1587 6.04167 16.0102 6.04167 15.8332V14.7915H5.12819C4.91478 14.7915 4.7359 14.7193 4.59154 14.5749C4.44718 14.4306 4.375 14.2517 4.375 14.0383V5.96136C4.375 5.74796 4.44718 5.56907 4.59154 5.42471C4.7359 5.28035 4.91478 5.20817 5.12819 5.20817H6.04167V4.16648C6.04167 3.9894 6.10158 3.84096 6.22142 3.72117C6.34126 3.60139 6.48976 3.5415 6.66692 3.5415C6.84408 3.5415 6.99249 3.60139 7.11215 3.72117C7.2318 3.84096 7.29162 3.9894 7.29162 4.16648V5.20817H8.2051C8.41851 5.20817 8.59739 5.28035 8.74175 5.42471C8.88611 5.56907 8.95829 5.74796 8.95829 5.96136V14.0383C8.95829 14.2517 8.88611 14.4306 8.74175 14.5749C8.59739 14.7193 8.41851 14.7915 8.2051 14.7915H7.29162V15.8332C7.29162 16.0102 7.23171 16.1587 7.11188 16.2784C6.99203 16.3982 6.84353 16.4581 6.66637 16.4581ZM5.62496 13.5415H7.70833V6.45813H5.62496V13.5415ZM13.333 16.4581C13.1559 16.4581 13.0075 16.3982 12.8878 16.2784C12.7682 16.1587 12.7083 16.0102 12.7083 15.8332V12.2915H11.7949C11.5815 12.2915 11.4026 12.2193 11.2582 12.0749C11.1138 11.9306 11.0417 11.7517 11.0417 11.5383V7.62803C11.0417 7.41462 11.1138 7.23574 11.2582 7.09138C11.4026 6.94702 11.5815 6.87484 11.7949 6.87484H12.7083V4.16648C12.7083 3.9894 12.7683 3.84096 12.8881 3.72117C13.0079 3.60139 13.1564 3.5415 13.3336 3.5415C13.5107 3.5415 13.6592 3.60139 13.7788 3.72117C13.8985 3.84096 13.9583 3.9894 13.9583 4.16648V6.87484H14.8718C15.0852 6.87484 15.2641 6.94702 15.4084 7.09138C15.5528 7.23574 15.625 7.41462 15.625 7.62803V11.5383C15.625 11.7517 15.5528 11.9306 15.4084 12.0749C15.2641 12.2193 15.0852 12.2915 14.8718 12.2915H13.9583V15.8332C13.9583 16.0102 13.8984 16.1587 13.7785 16.2784C13.6587 16.3982 13.5102 16.4581 13.333 16.4581ZM12.2916 11.0415H14.375V8.1248H12.2916V11.0415Z" fill="white"/>
+</g>
+</g>
+</svg>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 5 - 0
src/assets/viewMore.svg


+ 4 - 2
src/components/Footer.vue

@@ -50,8 +50,8 @@ const toPage = (url:string) => {
   display: flex;
   .footer-left {
     width: 757px;
-    height: 275px;
     border-right: 1px solid var(--vt-c-border);
+    border-left: 1px solid var(--vt-c-border);
     margin-left: -60px;
 
     .logoBox {
@@ -77,8 +77,10 @@ const toPage = (url:string) => {
   }
 
   .footer-right{
-    width: 680px;
+    width: 682px;
+    border-right: 1px solid var(--vt-c-border);
     padding: 40px 60px;
+    margin-right: -60px;
     .descriptive{
       font-family: HONOR Sans CN;
       font-size: 12px;

+ 35 - 31
src/components/Nav.vue

@@ -16,7 +16,7 @@ const doSth = () => {
 
 onMounted(() => {
   pathname.value = window.location.pathname
-  console.log(window.location.pathname);
+  // console.log(window.location.pathname);
 })
 
 const sunAndMoon = () => {
@@ -70,31 +70,35 @@ const toNFT = () => {
 <template>
   <div class="topBar">
     <div class="left">
-      <div class="img">
-        <img v-show="!sunStore.sun" src="../assets/bitflower-white.svg" alt="bitflower">
-        <img v-show="sunStore.sun" src="../assets/bitflower.svg" alt="logo">
+      <div style="z-index: 1;" class="img">
+        <img  v-show="!sunStore.sun" src="../assets/bitflower-white.svg" alt="bitflower">
+        <img  v-show="sunStore.sun" src="../assets/bitflower.svg" alt="logo">
       </div>
-      <div class="nav" @click="toHome">
+      <div :class="pathname !== '/' ? 'nav':'nav1' " @click="toHome">
         Home
       </div>
-      <div class="nav" @click="toNFT">
+      <div :class="pathname !== '/' ? 'nav':'nav1' " @click="toNFT">
         NFT
       </div>
-      <div class="nav" @click="toAirdrop">
+      <div :class="pathname !== '/' ? 'nav':'nav1' " @click="toAirdrop">
         Airdrop
       </div>
     </div>
     <div class="right">
-      <img v-show="!sunStore.sun" @click="sunAndMoon" src="../assets/sun-fill.svg" alt="sun-fill">
-      <img v-show="sunStore.sun" @click="sunAndMoon" src="../assets/moon-clear-fill.svg" alt="moon-clear-fill">
+<!--      <img v-show="!sunStore.sun" @click="sunAndMoon" src="../assets/sun-fill.svg" alt="sun-fill">-->
+<!--      <img v-show="sunStore.sun" @click="sunAndMoon" src="../assets/moon-clear-fill.svg" alt="moon-clear-fill">-->
       <div v-show="pathname !== '/'">
-        <div class="button" v-show="!addressStore.address" @click="connectWallet">
+        <div class="button" v-show="(!addressStore.address && pathname !== '/starkNet') || (!addressStore.starkNetAddress && pathname === '/starkNet')" @click="connectWallet">
           <img src="../assets/git-commit-line.svg" alt="commit">
           Connect Wallet
         </div>
-        <div class="connect" v-if="addressStore.address">
+        <div class="connect" v-if="addressStore.address && pathname !== '/starkNet'">
           <img src="../assets/git-commit-line-black.svg" alt="commit">
-          {{ addressStore.address.slice(0, 8) }}...{{ addressStore.address.slice(-4) }}
+          {{  addressStore.address.slice(0, 8) }}...{{ addressStore.address.slice(-4) }}
+        </div>
+        <div class="connect" v-if="addressStore.starkNetAddress && pathname === '/starkNet'">
+          <img src="../assets/git-commit-line-black.svg" alt="commit">
+          {{ addressStore.starkNetAddress.slice(0, 8) }}...{{ addressStore.starkNetAddress.slice(-4) }}
         </div>
       </div>
 
@@ -109,7 +113,7 @@ const toNFT = () => {
   justify-content: space-between;
   padding: 0 60px 25px;
   margin: 0 -60px;
-  border-bottom: 1px solid var(--vt-c-border);
+  //border-bottom: 1px solid var(--vt-c-border);
 
   .left {
     display: flex;
@@ -128,6 +132,8 @@ const toNFT = () => {
       padding: 0 60px;
       height: 100px;
       display: flex;
+      width: 200px;
+      justify-content: center;
       align-items: center;
       margin-bottom: -25px;
       margin-top: -30px;
@@ -145,13 +151,7 @@ const toNFT = () => {
         bottom: 0;
       }
     }
-
-    .nav:hover{
-      background: rgba(255, 255, 255, 0.30);
-      backdrop-filter: blur(12px);
-    }
-
-    .navOne {
+    .nav1{
       font-family: HONOR Sans CN;
       font-size: 21px;
       font-style: normal;
@@ -160,24 +160,26 @@ const toNFT = () => {
       padding: 0 60px;
       height: 100px;
       display: flex;
+      width: 200px;
+      justify-content: center;
       align-items: center;
       margin-bottom: -25px;
       margin-top: -30px;
-      border-right: 1px solid var(--vt-c-border);
-      margin-left: 57px;
-      border-left: 1px solid var(--vt-c-border);
+      //border-right: 1px solid var(--vt-c-border);
+      //border-left: 1px solid var(--vt-c-border);
       position: relative;
       cursor: pointer;
+    }
 
-      .line {
-        position: absolute;
-        width: 100%;
-        height: 10px;
-        background: var(--color-text);
-        left: 0;
-        bottom: 0;
-      }
+    .nav:hover{
+      background: rgba(255, 255, 255, 0.30);
+      backdrop-filter: blur(12px);
+    }
+    .nav1:hover{
+      background: rgba(255, 255, 255, 0.30);
+      backdrop-filter: blur(12px);
     }
+
   }
 
   .mid {
@@ -207,6 +209,8 @@ const toNFT = () => {
       line-height: 20px;
       color: #FFFFFF;
       cursor: pointer;
+      border: 1px solid #4C4C4C;
+
     }
 
     .connect {

BIN
src/project/aspect/BG.png


BIN
src/project/aspect/avatar.png


BIN
src/project/briq/BG.png


BIN
src/project/briq/avatar.png


BIN
src/project/fibrous/BG.png


BIN
src/project/fibrous/avatar.png


BIN
src/project/mySwap/BG.png


BIN
src/project/mySwap/avatar.png


BIN
src/project/realms/BG.png


BIN
src/project/realms/avatar.png


BIN
src/project/sithSwap/BG.png


BIN
src/project/sithSwap/avatar.png


BIN
src/project/starkGate/BG.png


BIN
src/project/starkGate/avatar.png


BIN
src/project/starknetId/BG.png


BIN
src/project/starknetId/avatar.png


+ 6 - 1
src/router/index.ts

@@ -2,7 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
 import HomeView from '../views/HomeView.vue'
 import ZksyncView from '../views/ZksyncView.vue'
 import LayerZero from '../views/LayerZeroView.vue'
-
+import StarkNet from '../views/StarkNet.vue'
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
@@ -21,6 +21,11 @@ const router = createRouter({
       path: '/layerZero',
       name: 'layerZero',
       component: LayerZero
+    },
+    {
+      path: '/starkNet',
+      name: 'starkNet',
+      component: StarkNet
     }
   ]
 })

+ 3 - 2
src/stores/sun.ts

@@ -2,7 +2,7 @@ import { ref } from 'vue'
 import { defineStore } from 'pinia'
 
 export const useSunStore = defineStore('sun', () => {
-  const sun = ref(true)
+  const sun = ref(false)
   function change() {
     sun.value = !sun.value
   }
@@ -12,6 +12,7 @@ export const useSunStore = defineStore('sun', () => {
 
 export const useAddressStore = defineStore('address', () => {
   let address = ref('')
+  let starkNetAddress = ref('')
 
-  return { address }
+  return { address,starkNetAddress }
 })

+ 21 - 0
src/utils/indexedDB/deleteData.js

@@ -0,0 +1,21 @@
+import {dbConfig, get, initDB, remove} from "./main.js";
+
+const deleteData = async (storeName, keys) => {
+    try {
+        await initDB(dbConfig)
+        const promises = keys.map(async key => {
+            const result = await get(storeName, key)
+            console.log(result)
+            if (result) {
+                await remove(storeName, key)
+            }
+        });
+
+        await Promise.all(promises);
+    } catch (e) {
+        console.log(e)
+    }
+
+}
+
+export default deleteData

+ 11 - 0
src/utils/indexedDB/getDBTranscationsData.js

@@ -0,0 +1,11 @@
+import {dbConfig, getAllKeys, initDB} from "./main.js";
+
+const getDBTranscationsData = async (chain) => {
+    await initDB(dbConfig)
+    if (chain === 'zkSync') {
+        return await getAllKeys('zkTransactions')
+    } else if (chain === 'stark') {
+        return await getAllKeys('starkTransactions')
+    }
+}
+export default getDBTranscationsData

+ 100 - 0
src/utils/indexedDB/main.js

@@ -0,0 +1,100 @@
+import {openDB} from 'idb';
+
+let db = null;
+
+export const initDB = async (config) => {
+    try {
+        db = await openDB(config.name, config.version, {
+            upgrade(db) {
+                config.objectStoresMeta.forEach(meta => {
+                    if (!db.objectStoreNames.contains(meta.store)) {
+                        let store = db.createObjectStore(meta.store, meta.storeConfig);
+                        meta.storeSchema.forEach(schema => {
+                            store.createIndex(schema.key, schema.value);
+                        });
+                    }
+                });
+            },
+        });
+    } catch (err) {
+        console.error('Failed to open db:', err);
+    }
+};
+
+export const add = async (storeName, value) => {
+    try {
+        return db?.add(storeName, value);
+    } catch (err) {
+        console.error('Failed to add:', err);
+        return null;
+    }
+};
+
+export const get = async (storeName, key) => {
+    try {
+        return db?.get(storeName, key);
+    } catch (err) {
+        console.error('Failed to get:', err);
+        return null;
+    }
+};
+
+export const remove = async (storeName, key) => {
+    try {
+        return db?.delete(storeName, key);
+    } catch (err) {
+        console.error('Failed to remove:', err);
+        return null;
+    }
+};
+
+export const update = async (storeName, value) => {
+    try {
+        return db?.put(storeName, value);
+    } catch (err) {
+        console.error('Failed to update:', err);
+        return null;
+    }
+};
+export const getAllKeys = async (storeName) => {
+    try {
+        let tx = db.transaction(storeName, 'readonly'); // Corrected this line
+        let store = tx.objectStore(storeName);
+        return await store.getAllKeys();
+    } catch (err) {
+        console.error('Failed to get all keys:', err);
+        return null;
+    }
+}
+
+
+export const dbConfig = {
+    name: "BitBoxTools",
+    version: 2,
+    objectStoresMeta: [
+        {
+            store: "starkTransactions",
+            storeConfig: {keyPath: "address", autoIncrement: false},
+            storeSchema: [
+                {key: "address", value: "address"},
+                {key: "data", value: "data"},
+            ]
+        },
+        {
+            store: "zkTransactions",
+            storeConfig: {keyPath: "address", autoIncrement: false},
+            storeSchema: [
+                {key: "address", value: "address"},
+                {key: "data", value: "data"},
+            ]
+        },
+        {
+            store: "zkProtocol",
+            storeConfig: {keyPath: "address", autoIncrement: false},
+            storeSchema: [
+                {key: "address", value: "address"},
+                {key: "data", value: "data"},
+            ]
+        }
+    ],
+};

Dosya farkı çok büyük olduğundan ihmal edildi
+ 6 - 0
src/utils/stark/getAccountInfo.js


+ 55 - 0
src/utils/stark/getActivity.js

@@ -0,0 +1,55 @@
+const getWeekNumber = (date) => {
+    const year = date.getFullYear();
+    const oneJan = new Date(year, 0, 1);
+    const dayIndex = (date.getDay() + 6) % 7;
+    const daysSinceFirstDay = Math.floor((date.getTime() - oneJan.getTime()) / 86400000);
+    const weekIndex = Math.floor((daysSinceFirstDay + oneJan.getDay() - dayIndex) / 7);
+
+    return `${year}-${weekIndex}`;
+};
+const countAllTransactionPeriods = (address, transfers) => {
+    const uniqueDays = new Set();
+    const uniqueWeeks = new Set();
+    const uniqueMonths = new Set();
+    const uniqueContracts = new Set();
+    transfers.forEach((transfer) => {
+        if (transfer.transfer_from_address.toLowerCase() !== address.toLowerCase()) return;
+        const timestamp = new Date(transfer.timestamp * 1000);
+        const year = timestamp.getFullYear();
+        const month = timestamp.getMonth();
+        const day = timestamp.getDate();
+        const week = getWeekNumber(timestamp);
+
+        uniqueDays.add(`${year}-${month}-${day}`);
+        uniqueWeeks.add(`${year}-${week}`);
+        uniqueMonths.add(`${year}-${month}`);
+        uniqueContracts.add(transfer.transfer_to_address);
+    });
+    return {
+        dayActivity: uniqueDays.size,
+        weekActivity: uniqueWeeks.size,
+        monthActivity: uniqueMonths.size,
+        contractActivity: uniqueContracts.size,
+    };
+};
+
+export default function getActivity(address, transfers) {
+    if (transfers.length === 0) return {
+        dayActivity: 0,
+        weekActivity: 0,
+        monthActivity: 0,
+        contractActivity: 0,
+    }
+    const {
+        dayActivity,
+        weekActivity,
+        monthActivity,
+        contractActivity
+    } = countAllTransactionPeriods(address, transfers);
+    return {
+        dayActivity,
+        weekActivity,
+        monthActivity,
+        contractActivity,
+    }
+}

+ 53 - 0
src/utils/stark/getBalance.js

@@ -0,0 +1,53 @@
+import axios from 'axios';
+
+export default async function getBalance(address) {
+    try {
+        const url = "https://starkscan.stellate.sh/"
+        const data = {
+            'query': 'query ERC20BalancesByOwnerAddressTableQuery(\n  $input: ERC20BalancesByOwnerAddressInput!\n) {\n  erc20BalancesByOwnerAddress(input: $input) {\n    id\n    ...ERC20BalancesByOwnerAddressTableRowFragment_erc20Balance\n  }\n}\n\nfragment ERC20BalancesByOwnerAddressTableRowFragment_erc20Balance on ERC20Balance {\n  id\n  contract_address\n  contract_erc20_identifier\n  contract_erc20_contract {\n    symbol\n    is_social_verified\n    icon_url\n    id\n  }\n  balance_display\n}\n',
+            'variables': {
+                'input': {
+                    'owner_address': address,
+                }
+            }
+        }
+        const headers = {
+            'authority': 'starkscan.stellate.sh',
+            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
+        }
+        const response = await axios.post(url, data, {headers: headers});
+        let balance = {
+            'ETH': 0,
+            'USDT': 0,
+            'USDC': 0,
+            "DAI": 0,
+            "WBTC": 0,
+        }
+        response.data['data']['erc20BalancesByOwnerAddress'].forEach((token) => {
+            if (token['contract_address'] === '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7') {
+                balance['ETH'] = Number(parseFloat(token['balance_display'])).toFixed(3)
+            } else if (token['contract_address'] === '0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8') {
+                balance['USDT'] = Number(parseFloat(token['balance_display'])).toFixed(3)
+            } else if (token['contract_address'] === '0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8') {
+                balance['USDC'] = Number(parseFloat(token['balance_display'])).toFixed(3)
+            } else if (token['contract_address'] === '0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3') {
+                balance['DAI'] = Number(parseFloat(token['balance_display'])).toFixed(3)
+            } else if (token['contract_address'] === '0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3') {
+                balance['WBTC'] = Number(parseFloat(token['balance_display'])).toFixed(3)
+            }
+        })
+        return balance
+    } catch (e) {
+        console.log(e)
+        return {
+            'ETH': '-',
+            'USDT': '-',
+            'USDC': '-',
+            "DAI": '-',
+            "WBTC": '-',
+        }
+    }
+
+}
+
+

+ 37 - 0
src/utils/stark/getBridge.js

@@ -0,0 +1,37 @@
+export const getBridge = (transfers) => {
+    let DepositTx = 0, WithdrawTx = 0;
+    let DepositVolume = 0, WithdrawVolume = 0;
+    const Price = {
+        "StarkGate: ETH": 1800,
+        "StarkGate: USDT": 1,
+        "StarkGate: USDC": 1,
+        "StarkGate: DAI": 1,
+        "StarkGate: WBTC": 29000,
+    }
+    transfers.forEach((transfer) => {
+        const transfer_from_address = transfer.transfer_from_address;
+        const transfer_to_address = transfer.transfer_to_address;
+        const transfer_amount_display = transfer.transfer_amount_display;
+        const from_erc20_identifier = transfer['from_erc20_identifier']
+        if (transfer_from_address.toLowerCase() === "0x0000000000000000000000000000000000000000000000000000000000000000".toLowerCase()) {
+            const selector_identifier = transfer['main_call'] ? transfer['main_call']['selector_identifier'] : null
+            if (selector_identifier === "handle_deposit") {
+                DepositTx += 1;
+                DepositVolume += parseFloat(transfer_amount_display) * Price[from_erc20_identifier];
+            }
+        }
+        if (transfer_to_address.toLowerCase() === "0x0000000000000000000000000000000000000000000000000000000000000000".toLowerCase()) {
+            const selector_identifier = transfer['main_call'] ? transfer['main_call']['selector_identifier'] : null
+            if (selector_identifier === "initiate_withdraw") {
+                WithdrawTx += 1;
+                WithdrawVolume += parseFloat(transfer_amount_display) * Price[from_erc20_identifier];
+            }
+        }
+    })
+    return {
+        DepositTx,
+        WithdrawTx,
+        DepositVolume: Number(DepositVolume.toFixed(2)),
+        WithdrawVolume: Number(WithdrawVolume.toFixed(2)),
+    }
+}

+ 92 - 0
src/utils/stark/getTransactions.js

@@ -0,0 +1,92 @@
+import axios from "axios";
+import {getTransfers} from "./getTransfers.js";
+
+async function fetchTransactions(url, Json_data, headers) {
+    const response = await axios.post(url, Json_data, {headers: headers});
+    let transactions = [];
+    response.data.data['transactions']['edges'].forEach((item) => {
+        const {
+            actual_fee_display,
+            initiator_address,
+            initiator_identifier,
+            nonce,
+            timestamp,
+            transaction_hash,
+        } = item['node'];
+        transactions.push({
+            actual_fee_display,
+            initiator_address,
+            initiator_identifier,
+            nonce,
+            timestamp,
+            transaction_hash,
+            transfers: []
+        })
+    });
+    return {
+        transactions: transactions,
+        hasNextPage: response.data.data['transactions']['pageInfo']['hasNextPage'],
+        endCursor: response.data.data['transactions']['pageInfo']['endCursor'],
+    }
+}
+
+export default async function getTransactions(address) {
+    const url = "https://starkscan.stellate.sh/";
+    const headers = {
+        'authority': 'starkscan.stellate.sh',
+        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
+    }
+    const Json_data = {
+        'query': 'query TransactionsTableQuery(\n  $first: Int!\n  $after: String\n  $input: TransactionsInput!\n) {\n  ...TransactionsTablePaginationFragment_transactions_2DAjA4\n}\n\nfragment TransactionsTableExpandedItemFragment_transaction on Transaction {\n  entry_point_selector_name\n  calldata_decoded\n  entry_point_selector\n  calldata\n  initiator_address\n  initiator_identifier\n actual_fee\n  actual_fee_display\n main_calls {\n    selector\n    selector_name\n    calldata_decoded\n    selector_identifier\n    calldata\n    contract_address\n    contract_identifier\n    id\n  }\n}\n\nfragment TransactionsTablePaginationFragment_transactions_2DAjA4 on Query {\n  transactions(first: $first, after: $after, input: $input) {\n    edges {\n      node {\n        id\n        ...TransactionsTableRowFragment_transaction\n        __typename\n      }\n      cursor\n    }\n    pageInfo {\n      endCursor\n      hasNextPage\n    }\n  }\n}\n\nfragment TransactionsTableRowFragment_transaction on Transaction {\n  id\n  transaction_hash\n  block_number\n  transaction_status\n  transaction_type\n  timestamp\n  nonce\n contract_address\n  contract_identifier\n sender_address\n  sender_identifier\n initiator_address\n  initiator_identifier\n  initiator {\n    is_social_verified\n    id\n  }\n  main_calls {\n    selector_identifier\n    id\n  }\n  ...TransactionsTableExpandedItemFragment_transaction\n}\n',
+        'variables': {
+            'first': 100,
+            'after': null,
+            'input': {
+                'initiator_address': address,
+                'sort_by': 'timestamp',
+                'order_by': 'desc',
+                'min_block_number': null,
+                'max_block_number': null,
+                'min_timestamp': null,
+                'max_timestamp': null
+            }
+        }
+    };
+    let allTransactions = [];
+    let results = await fetchTransactions(url, Json_data, headers);
+    allTransactions.push(...results.transactions);
+    while (results.hasNextPage) {
+        Json_data['variables']['after'] = results.endCursor;
+        results = await fetchTransactions(url, Json_data, headers);
+        allTransactions.push(...results.transactions);
+    }
+    const transfers = await getTransfers(address)
+    transfers.forEach((transfer) => {
+        allTransactions.forEach((transaction) => {
+            if (transfer['transaction_hash'] === transaction['transaction_hash']) {
+                transaction['transfers'].push(transfer)
+            }
+        })
+    })
+    // const localTransactions = JSON.parse(localStorage.getItem('stark_transactions'));
+    // if (localTransactions === null) {
+    //     localStorage.setItem('stark_transactions', JSON.stringify([{
+    //         address: address,
+    //         transactions: allTransactions
+    //     }]))
+    //     return allTransactions;
+    // } else {
+    //     const index = localTransactions.findIndex((item) => item.address === address);
+    //     if (index === -1) {
+    //         localTransactions.push({
+    //             address: address,
+    //             transactions: allTransactions
+    //         })
+    //     } else {
+    //         localTransactions[index].transactions = allTransactions;
+    //     }
+    //     localStorage.setItem('stark_transactions', JSON.stringify(localTransactions));
+    // }
+    return {transfers, transactions: allTransactions}
+}
+

+ 73 - 0
src/utils/stark/getTransfers.js

@@ -0,0 +1,73 @@
+import axios from 'axios';
+
+async function fetchTransfers(url, Json_data, headers) {
+    const response = await axios.post(url, Json_data, {headers: headers});
+    let transfers = [];
+    const Price = {
+        "StarkGate: ETH": 1800,
+        "StarkGate: USDT": 1,
+        "StarkGate: USDC": 1,
+        "StarkGate: DAI": 1,
+        "StarkGate: WBTC": 29500,
+    }
+    response.data.data['erc20TransferEvents']['edges'].forEach((item) => {
+        const {
+            transaction_hash,
+            from_address,
+            transfer_amount_display,
+            transfer_from_address,
+            transfer_to_address,
+            from_erc20_identifier,
+            main_call,
+            timestamp,
+            __typename,
+        } = item['node'];
+        transfers.push({
+            transaction_hash,
+            from_address,
+            transfer_amount_display,
+            transfer_from_address,
+            transfer_to_address,
+            from_erc20_identifier,
+            timestamp,
+            main_call,
+            __typename,
+            total_value: Price.hasOwnProperty(from_erc20_identifier) ? transfer_amount_display * Price[from_erc20_identifier] : 0,
+        })
+    });
+    return {
+        transfers: transfers,
+        hasNextPage: response.data.data['erc20TransferEvents']['pageInfo']['hasNextPage'],
+        endCursor: response.data.data['erc20TransferEvents']['pageInfo']['endCursor'],
+    }
+}
+
+export async function getTransfers(address) {
+    const url = "https://starkscan.stellate.sh/";
+    const headers = {
+        'authority': 'starkscan.stellate.sh',
+        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
+    }
+    const Json_data = {
+        'query': 'query ERC20TransferEventsTableQuery(\n  $first: Int!\n  $after: String\n  $input: ERC20TransferEventsInput!\n) {\n  ...ERC20TransferEventsTablePaginationFragment_erc20TransferEvents_2DAjA4\n}\n\nfragment ERC20TransferEventsTablePaginationFragment_erc20TransferEvents_2DAjA4 on Query {\n  erc20TransferEvents(first: $first, after: $after, input: $input) {\n    edges {\n      node {\n        id\n        ...ERC20TransferEventsTableRowFragment_erc20TransferEvent\n        __typename\n      }\n      cursor\n    }\n    pageInfo {\n      endCursor\n      hasNextPage\n    }\n  }\n}\n\nfragment ERC20TransferEventsTableRowFragment_erc20TransferEvent on ERC20TransferEvent {\n  id\n  transaction_hash\n  from_address\n  from_erc20_identifier\n  from_contract {\n    is_social_verified\n    id\n  }\n  transfer_from_address\n  transfer_from_identifier\n  transfer_from_contract {\n    is_social_verified\n    id\n  }\n  transfer_to_address\n  transfer_to_identifier\n  transfer_to_contract {\n    is_social_verified\n    id\n  }\n  transfer_amount\n  transfer_amount_display\n  timestamp\n  main_call {\n    selector_identifier\n    id\n  }\n}\n',
+        'variables': {
+            'first': 100,
+            'after': null,
+            'input': {
+                'transfer_from_or_to_address': address,
+                'call_invocation_type': 'FUNCTION',
+                'sort_by': 'timestamp',
+                'order_by': 'desc'
+            }
+        }
+    }
+    let allTransfers = [];
+    let results = await fetchTransfers(url, Json_data, headers);
+    allTransfers.push(...results.transfers);
+    while (results.hasNextPage) {
+        Json_data['variables']['after'] = results.endCursor;
+        results = await fetchTransfers(url, Json_data, headers);
+        allTransfers.push(...results.transfers);
+    }
+    return allTransfers;
+}

+ 31 - 0
src/utils/stark/getTxAndFee.js

@@ -0,0 +1,31 @@
+import {getTimeAgo} from "./utils.js";
+
+const getTxAndFee = async (transcations) => {
+    try {
+        if (!transcations) return {
+            tx: 0,
+            lastTime: '无交易',
+            fee: 0
+        }
+        let fee = 0;
+        transcations.forEach((transaction) => {
+            fee += parseFloat(transaction['actual_fee_display']);
+        })
+        const tx = transcations.length
+        const lastTimeStamp = transcations[0]['timestamp']
+        const lastTime = getTimeAgo(lastTimeStamp) || '无交易'
+        return {
+            tx,
+            lastTime,
+            fee: Number(fee).toFixed(3)
+        }
+    } catch (e) {
+        return {
+            tx: '-',
+            lastTime: '-',
+            fee: '-'
+        }
+    }
+
+}
+export default getTxAndFee;

+ 19 - 0
src/utils/stark/getVol.js

@@ -0,0 +1,19 @@
+export default function getVol(transcations) {
+    try {
+        let Vol = 0;
+        transcations.forEach((transaction) => {
+            const transfers = transaction.transfers.sort(
+                (a, b) =>
+                    parseInt(b.total_value) - parseInt(a.total_value)
+            );
+            if (transfers.length === 0) return;
+            const tmpVol = parseFloat(transfers[0].total_value)
+            Vol += tmpVol;
+        })
+        return {Vol: Vol.toFixed(3)}
+    } catch (e) {
+        console.log(e)
+        return {Vol: '-'}
+    }
+
+}

+ 47 - 0
src/utils/stark/main.js

@@ -0,0 +1,47 @@
+import getTransactions from "./getTransactions.js";
+import getTxAndFee from "./getTxAndFee.js";
+import getBalance from "./getBalance.js";
+import getActivity from "./getActivity.js";
+import {getBridge} from "./getBridge.js";
+import {getAccountInfo} from "./getAccountInfo.js";
+import getVol from "./getVol.js";
+import {initDB, dbConfig, update} from "../indexedDB/main";
+
+export const getStark = async (address) => {
+    let data;
+    try {
+        await initDB(dbConfig);
+        const result = await getTransactions(address);
+        const transactions = result['transactions'];
+        const transfers = result['transfers'];
+        const activity = getActivity(address, transfers)
+        const {tx, lastTime, fee} = await getTxAndFee(transactions);
+        const balance = await getBalance(address);
+        const bridge = getBridge(transfers)
+        const accountInfo = await getAccountInfo(address)
+        const Vol = getVol(transactions)
+        data = {
+            accountInfo,
+            balance,
+            tx,
+            lastTime,
+            fee,
+            activity,
+            bridge,
+            transactions,
+            ...Vol,
+            result: "success"
+        }
+        await update("starkTransactions", {
+            address: address,
+            data: JSON.stringify(transactions)
+        })
+        return data
+    } catch (e) {
+        data = {
+            result: "error",
+            reason: e.message
+        }
+        return data
+    }
+}

+ 21 - 0
src/utils/stark/utils.js

@@ -0,0 +1,21 @@
+export const getTimeAgo = (timestamp) => {
+    const date = new Date(timestamp) * 1000;
+    const seconds = (new Date().getTime() - new Date(date).getTime()) / 1000;
+
+    if (seconds < 60) {
+        return Math.round(seconds) + ' 秒前';
+    }
+
+    const minutes = seconds / 60;
+    if (minutes < 60) {
+        return Math.round(minutes) + ' 分前';
+    }
+
+    const hours = minutes / 60;
+    if (hours < 24) {
+        return Math.round(hours) + ' 时前';
+    }
+
+    const days = hours / 24;
+    return Math.round(days) + ' 天前';
+};

+ 48 - 5
src/views/HomeView.vue

@@ -14,11 +14,20 @@ const toPage = (url:string) => {
 <template>
   <main class="main">
     <div class="mainBG">
-      <img src="../assets/BG.png" alt="BG">
+      <img src="../assets/navBg.png" alt="BG">
+    </div>
+    <div class="BG1">
+      <img src="../assets/home/BG1.png" alt="BG">
+    </div>
+    <div class="BG2">
+      <img src="../assets/home/BG2.png" alt="BG">
+    </div>
+    <div class="BG3">
+      <img src="../assets/home/BG3.png" alt="BG">
     </div>
     <Nav/>
     <div class="header">
-      <div class="left">
+      <div class="left" style="z-index: 2">
         <img class="left" v-show="!sunStore.sun" src="../assets/home/header-white.svg" alt="header">
         <img class="left" v-show="sunStore.sun" src="../assets/home/header.svg" alt="header">
       </div>
@@ -270,7 +279,7 @@ const toPage = (url:string) => {
   width: 1440px;
   height: 100%;
   margin: auto;
-  border: 1px solid var(--vt-c-border);
+  //border: 1px solid var(--vt-c-border);
   border-top: none;
   border-bottom: none;
   padding: 30px 60px 0;
@@ -287,9 +296,43 @@ const toPage = (url:string) => {
     position: absolute;
     top: 0;
     z-index: -1;
-    display: none;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: center;
+  }
+  .BG1 {
+    position: absolute;
+    top: -560px;
+    left: 210px;
+    display: flex;
+    justify-content: center;
+    animation: rotateAnimation 10s linear infinite;
+  }
+  .BG2 {
+    position: absolute;
+    top: -660px;
+    left: -370px;
+    display: flex;
+    justify-content: center;
+    animation: rotateAnimation 15s linear infinite;
+  }
+  .BG3 {
+    position: absolute;
+    top: 300px;
+    left: 700px;
+    display: flex;
+    justify-content: center;
+    animation: rotateAnimation 10s linear infinite;
+  }
+  @keyframes rotateAnimation {
+    0% {
+      transform: rotate(0deg);
+    }
+    100% {
+      transform: rotate(-360deg);
+    }
   }
-
   .header {
     display: flex;
     align-items: center;

+ 10 - 7
src/views/LayerZeroView.vue

@@ -158,8 +158,6 @@ const switchEthereumChain = () => {
 }
 //连接钱包按钮
 const connectWallet = async () => {
-  console.log('layer')
-
   let accounts: string[] = await MM.value.request({method: 'eth_requestAccounts'});
   addressStore.address = accounts[0]
   // getMainTx()
@@ -319,7 +317,7 @@ const initEcharts = () => {
     },
     series: [
       {
-        color: '#000000',
+        color: '#EC796B',
         data: showMonthNumberArr.value,
         type: 'bar'
       }
@@ -353,18 +351,18 @@ const toEmail = (email:string) => {
 <template>
   <main class="main">
     <div class="mainBG">
-      <img src="../assets/BG.png" alt="BG">
+      <img src="../assets/navBg.png" alt="BG">
     </div>
     <Nav @doSth="connectWallet"/>
     <div class="chainBox">
-      <div class="item" style="cursor: pointer" @click="toPage('/zksync')">
+      <div class="item" @click="toPage('/zksync')">
         zkSync
       </div>
-      <div class="item">
+      <div class="item" >
         Layer Zero
         <div class="line"></div>
       </div>
-      <div class="item">
+      <div class="item" @click="toPage('/starkNet')">
         StarkNet
       </div>
     </div>
@@ -550,6 +548,10 @@ const toEmail = (email:string) => {
     position: absolute;
     top: 0;
     z-index: -1;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: center;
   }
   .topBar {
     display: flex;
@@ -669,6 +671,7 @@ const toEmail = (email:string) => {
       font-weight: 700;
       line-height: normal;
       position: relative;
+      cursor: pointer;
       .line{
         position: absolute;
         width: 60px;

+ 1118 - 0
src/views/StarkNet.vue

@@ -0,0 +1,1118 @@
+<script setup lang="ts">
+//@ts-ignore
+import MetaMaskSDK from '../utils/metamask-sdk.js'
+//@ts-ignore
+import getZksEra from '../utils/getZksEra.js'
+//@ts-ignore
+import getZksLite from '../utils/getZksLite.js'
+//@ts-ignore
+import getZkSyncBridge from '../utils/getZkSyncBridge.js'
+import * as echarts from 'echarts';
+import {onMounted, ref} from 'vue';
+
+import mySwapAv from '../project/mySwap/avatar.png'
+import mySwapBg from '../project/mySwap/BG.png'
+import starknetIdAv from '../project/starknetId/avatar.png'
+import starknetIdBg from '../project/starknetId/BG.png'
+import starkGateAv from '../project/starkGate/avatar.png'
+import starkGateBg from '../project/starkGate/BG.png'
+import realmsAv from '../project/realms/avatar.png'
+import realmsBg from '../project/realms/BG.png'
+import aspectAv from '../project/aspect/avatar.png'
+import aspectBg from '../project/aspect/BG.png'
+import briqAv from '../project/briq/avatar.png'
+import briqBg from '../project/briq/BG.png'
+import sithSwapAv from '../project/sithSwap/avatar.png'
+import sithSwapBg from '../project/sithSwap/BG.png'
+import fibrousAv from '../project/fibrous/avatar.png'
+import fibrousBg from '../project/fibrous/BG.png'
+
+import router from "@/router";
+import {useSunStore,useAddressStore} from "@/stores/sun";
+import Nav from '@/components/Nav.vue'
+import Footer from '@/components/Footer.vue'
+//@ts-ignore
+import {getAllZksSyncData} from "@/utils/getZksyncData/index.js";
+import {getStark} from "@/utils/stark/main.js";
+import { connect, disconnect } from "get-starknet"
+import axios from 'axios';
+import {Area, Bar} from '@antv/g2plot';
+import moment from "moment";
+
+const sunStore = useSunStore()
+const addressStore = useAddressStore()
+
+type EChartsOption = echarts.EChartsOption;
+
+onMounted(() => {
+  fetchData()
+  fetchData2()
+  connectWallet2()
+})
+
+
+type dataArrType = {
+  name: string,
+  type: string[],
+  BG: string,
+  avatar: string,
+  url:string
+}[]
+let dataArr: dataArrType = [
+  {
+    name: 'mySwap',
+    type: ['DeFi'],
+    BG: mySwapBg,
+    avatar: mySwapAv,
+    url:'https://www.myswap.xyz/'
+  },
+  {
+    name:'Starknet.id',
+    type: ['Digitalid ID'],
+    BG:starknetIdBg,
+    avatar:starknetIdAv,
+    url:'https://app.starknet.id/'
+  },
+  {
+    name: 'StarkGate',
+    type: ['DEFI'],
+    BG: starkGateBg,
+    avatar: starkGateAv,
+    url:'https://starkgate.starknet.io/terms'
+  },
+  {
+    name: 'Realms',
+    type: ['GAMEFI', 'NFT'],
+    BG: realmsBg,
+    avatar: realmsAv,
+    url:'https://realms.world/'
+  },
+  {
+    name: 'ASPECT',
+    type: ['NFT'],
+    BG: aspectBg,
+    avatar: aspectAv,
+    url:'https://aspect.co/'
+  },
+
+  {
+    name: 'briq',
+    type: ['NFT'],
+    BG: briqBg,
+    avatar: briqAv,
+    url:'https://briq.construction/'
+  },
+  {
+    name:'SithSwap',
+    type: ['DEFI','BRIDGE'],
+    BG:sithSwapBg,
+    avatar:sithSwapAv,
+    url:'https://app.sithswap.com/'
+  },
+  {
+    name: 'Fibrous',
+    type: ['DEFI'],
+    BG: fibrousBg,
+    avatar: fibrousAv,
+    url:'https://app.fibrous.finance/'
+  }
+]
+
+//连接钱包按钮
+const connectWallet2 = async () => {
+  const starknet = await connect();
+  addressStore.starkNetAddress = starknet.account.address
+  getMoreInfo()
+}
+
+//获取更多信息
+let amount = ref('-')
+let fee = ref('-')
+let contract = ref('-')
+let tradingTimeArr = ref()
+let l1Tol2Tx = ref('-')
+let l2Tol1Tx = ref('-')
+let tx = ref('-')
+
+const getMoreInfo = () => {
+  getStark(addressStore.starkNetAddress).then((res:any)=>{
+    if(res.result === "error"){
+      return
+    }
+    amount.value = res.Vol
+    fee.value = res.fee
+    contract.value = res.activity.contractActivity
+    tradingTimeArr.value = res.transactions
+    l1Tol2Tx.value = res.bridge.DepositTx
+    l2Tol1Tx.value = res.bridge.WithdrawTx
+    tx.value = res.tx
+    processTime()
+  })
+}
+//处理时间数据
+const monthArr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+let showMonthNumberArr = ref([0,0,0,0,0,0,0,0,0,0,0,0])
+let showMonthArr = ref()
+const processTime = () => {
+  let nowDate = new Date().toString()
+  let nowDateArr = nowDate.split(' ')
+  let nowMonth = nowDateArr[1]
+  showMonthArr.value = []
+  showMonthArr.value.push(nowMonth)
+  let nowMonthIndex = monthArr.indexOf(nowMonth)
+  const forLoop = () => {
+    for (let i = 11; i !== nowMonthIndex ; i--) {
+      showMonthArr.value.unshift(monthArr[i])
+    }
+  }
+  for (let i = nowMonthIndex; i !== 0 ; i--) {
+    showMonthArr.value.unshift(monthArr[i-1])
+    if (i === 1) {
+      forLoop()
+    }
+  }
+  if (tradingTimeArr.value){
+    tradingTimeArr.value.forEach((item:any) => {
+      // if(item.balanceChanges[0].from && item.balanceChanges[0].from.toLowerCase() === addressStore.address.toLowerCase()){
+      let receivedAt = timestampToCtime(item.timestamp)
+      // console.log(receivedAt);
+      let strArr = receivedAt.split(' ')
+      let month = strArr[1]
+      let index = showMonthArr.value.indexOf(month)
+      showMonthNumberArr.value[index]++
+      // }
+    })
+  }
+
+  initEcharts()
+
+}
+function timestampToCtime(timestamp) {
+  const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+  const date = new Date(timestamp * 1000); // JavaScript使用毫秒为单位的时间戳,所以需要乘以1000
+  const day = days[date.getUTCDay()];
+  const month = months[date.getUTCMonth()];
+  const dayOfMonth = date.getUTCDate();
+  const time = date.getUTCHours() + ':' + ('0' + date.getUTCMinutes()).slice(-2) + ':' + ('0' + date.getUTCSeconds()).slice(-2);
+  const year = date.getUTCFullYear();
+
+  return `${day} ${month} ${dayOfMonth} ${time} UTC ${year}`;
+}
+//初始化echarts
+const initEcharts = () => {
+  let chartDom = document.getElementById('echartsBox1')!
+  let myChart = echarts.init(chartDom);
+  let option: EChartsOption;
+
+  option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    xAxis: {
+      type: 'category',
+      axisTick: {
+        alignWithLabel: true
+      },
+      data: showMonthArr.value
+    },
+    yAxis: {
+      type: 'value',
+    },
+    series: [
+      {
+        color: '#EC796B',
+        data: showMonthNumberArr.value,
+        type: 'bar'
+      }
+    ]
+  };
+
+  option && myChart.setOption(option);
+}
+
+//跳转网页
+const toLink = (url:string) => {
+  window.open(url)
+}
+
+const toPage = (url:string) => {
+  router.push(url)
+}
+const toEmail = (email:string) => {
+  const emailAddress = email; // 替换为你想发送邮件的收件人地址
+  const subject = 'Hello'; // 替换为你想在邮件中设置的主题
+  const body = 'This is the email body.'; // 替换为你想在邮件中设置的内容
+
+  const mailtoUrl = `mailto:${emailAddress}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
+
+  window.open(mailtoUrl);
+}
+
+let affix = ref(false)
+let chart = ref(false)
+
+const affixMouseenter = () => {
+  const slideDiv = document.getElementById("slideDiv");
+  slideDiv.style.bottom = "0";
+}
+
+const affixMouseleave = () => {
+  const slideDiv = document.getElementById("slideDiv");
+  slideDiv.style.bottom = "-608px";
+}
+
+
+const getStarkTvl = async () => {
+  const url = 'https://api.llama.fi/v2/historicalChainTvl/Starknet';
+  const response = await axios.get(url);
+  return response.data;
+}
+
+const getZkTvlDetail = async () => {
+  const url = "https://api.llama.fi/protocols";
+  const response = await axios.get(url);
+  let result = [];
+  response.data.forEach((item) => {
+    if (item['chains'].includes("Starknet") && item.category !== "CEX") {
+      result.push({
+        name: item.name,
+        tvl: item['chainTvls']['Starknet'] / 1000000,
+      });
+    }
+  });
+  result.sort((a, b) => b.tvl - a.tvl);
+  result = result.slice(0, 10);
+  return result;
+}
+
+let change = ref(0)
+let change24h = ref('-')
+let nowTvl = ref('-')
+
+const fetchData = async () => {
+  const result = await getStarkTvl();
+  change.value = ((result[result.length - 1].tvl - result[result.length - 2].tvl) / result[result.length - 2].tvl) * 100;
+  change24h.value = change.value.toFixed(2) + '%'
+  nowTvl.value = (result[result.length - 1].tvl / 1000000).toFixed(2) + 'M'
+
+  let VolData = [];
+  result.forEach(item => {
+    VolData.push({
+      date: new Date(item.date * 1000).toLocaleDateString(),
+      tvl: item.tvl / 1000000,
+    });
+  });
+  const max = Math.max(...VolData.map(item => item.tvl));
+  const chart = new Area('TVLBox',{
+    data: VolData,
+    xField: 'date',
+    yField: 'tvl',
+    smooth: true,
+    isStack: true,
+    padding:[60],
+    color: '#FFF',
+    // label: {
+    //   style:{
+    //     fill:'#FFF'
+    //   },
+    //   content: (originData) => {
+    //     return `${originData.tvl.toFixed(0)}`;
+    //   },
+    // },
+    slider: {
+      start: 0,
+      end: 1,
+      formatter: (v) => moment(v).format('YYYY-MM-DD'),
+      textStyle:{
+        fill:'#FFF'
+      }
+    },
+    meta: {
+      tvl: {
+        alias: 'TVL(M)',
+        min: 0,
+        max: max * 1.1,
+
+      }
+    }
+  });
+  chart.render();
+}
+
+let TVLTopData = ref()
+const fetchData2 = async () => {
+  let result = await getZkTvlDetail();
+  TVLTopData.value = result.slice(0,5)
+
+  const max = Math.max(...result.map(item => item.tvl));
+  const chart = new Bar('TVLTop', {
+    data:result,
+    xField: 'tvl',
+    yField: 'name',
+    color: '#FFF',
+    yAxis: {
+      label: {
+        formatter: (v) => `${v}`,
+      }
+    },
+    label: {
+      position: 'right',
+      style:{
+        fill:'#FFF'
+      },
+      formatter: (v) => `${v.tvl.toFixed(2)}`,
+    },
+    meta: {
+      tvl: {
+        alias: 'TVL(M)',
+        max: max * 1.1,
+      }
+    }
+  });
+  chart.render();
+}
+
+</script>
+
+<template>
+  <main class="main">
+    <div class="mainBG">
+      <img src="../assets/navBg.png" alt="BG">
+    </div>
+    <Nav @doSth="connectWallet2"/>
+
+    <div class="chainBox">
+      <div class="item" @click="toPage('/zkSync')">
+        zkSync
+      </div>
+      <div class="item" @click="toPage('/layerZero')">
+        Layer Zero
+      </div>
+      <div class="item">
+        StarkNet
+        <div class="line"></div>
+      </div>
+    </div>
+    <div class="dataBox">
+      <div class="left">
+        <div class="leftTop">
+          <div class="item">
+            <div class="top">
+              <div class="img">
+                <img src="../assets/starkNet/STARKNET.svg" alt="STARKNET">
+              </div>
+              <div class="title">
+                Protocols lnteraction
+                <el-popover
+                    placement="bottom"
+                    :width="230"
+                    trigger="hover"
+                    effect="dark"
+                >
+                  <template #reference>
+                    <img src="../assets/info.svg" alt="info">
+                  </template>
+                  <div class="popoverText">
+                    Number of protocolsinteracted
+                  </div>
+                  <div class="popoverText">
+                    with out of allavailable protocols
+                  </div>
+                </el-popover>
+              </div>
+            </div>
+            <div class="number">
+              {{ contract }}
+            </div>
+          </div>
+          <div class="item">
+            <div class="top">
+              <div class="img">
+                <img class="img" src="../assets/group4.svg" alt="group2">USDT
+              </div>
+              <div class="title">
+                <span style="width: 150px">vol</span>
+                <span>fee</span>
+              </div>
+            </div>
+            <div class="number">
+              <span class="number" style="width: 150px">
+                {{ amount }}
+              </span>
+              <span class="number">
+                {{fee}}
+              </span>
+            </div>
+          </div>
+          <img width="175" src="../assets/starkNet/starkNet.png" alt="starkNet">
+        </div>
+        <div class="leftBottom">
+          <div class="item">
+            <div class="top">
+              <div class="img">
+                <img src="../assets/starkNet/STARKNET.svg" alt="STARKNET">
+              </div>
+              <div class="title">
+                Total Transactions
+                <el-popover
+                    placement="bottom"
+                    :width="250"
+                    trigger="hover"
+                    effect="dark"
+                >
+                  <template #reference>
+                    <img src="../assets/info.svg" alt="info">
+                  </template>
+                  <div class="popoverText">
+                    Total StarkNet
+                  </div>
+                  <div class="popoverText">
+                    transactions issuedfrom the account
+                  </div>
+                </el-popover>
+              </div>
+            </div>
+            <div class="number">
+              {{ tx }}
+            </div>
+          </div>
+          <div class="item" style="height: 94px">
+            <div class="top">
+              <div class="img">
+                <img v-show="!sunStore.sun" class="img" src="../assets/official-bridge-white.svg" alt="group2">
+                <img v-show="sunStore.sun" class="img" src="../assets/official-bridge-black.svg" alt="group2">
+              </div>
+              <div style="display: flex;gap:40px">
+                <div style="display: flex;flex-direction: column;gap:20px">
+                  <img v-show="!sunStore.sun" src="../assets/L1-To-L2-white.svg" alt="To">
+                  <img v-show="sunStore.sun" src="../assets/L1-To-L2.svg" alt="To">
+                  <div class="number">
+                    {{ l1Tol2Tx }}
+                  </div>
+                </div>
+                <div style="display: flex;flex-direction: column;gap:20px">
+                  <img v-show="!sunStore.sun" src="../assets/L2-To-L1-white.svg" alt="To">
+                  <img v-show="sunStore.sun" src="../assets/L2-To-L1.svg" alt="To">
+                  <div class="number">
+                    {{ l2Tol1Tx }}
+                  </div>
+                </div>
+              </div>
+            </div>
+
+          </div>
+        </div>
+      </div>
+      <div style="position: relative">
+        <div style="display: flex;align-items: center;position: absolute;left: 40px;top:10px;z-index: 10;gap:4px">
+          Transactions Over Time
+          <el-popover
+              placement="right"
+              :width="240"
+              trigger="hover"
+              effect="dark"
+          >
+            <template #reference>
+              <img src="../assets/info.svg" alt="info">
+            </template>
+            <div class="popoverText">
+              Number of transactions permonth
+            </div>
+          </el-popover>
+        </div>
+        <div class="right" id="echartsBox1">
+
+        </div>
+      </div>
+
+    </div>
+    <div class="projectBox">
+      <div class="item" @click="toLink(item.url)" v-for="item in dataArr">
+        <div class="BG">
+          <img class="BG" :src="item.BG" alt="BG">
+        </div>
+        <div class="infoBox">
+          <div class="avatar">
+            <img class="avatar" :src="item.avatar" alt="avatar">
+          </div>
+          <div class="nameAndType">
+            <div class="name">
+              {{ item.name }}
+            </div>
+            <div class="typeBox">
+              <div class="type" v-for="item1 in item.type">
+                {{ item1 }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="dividingLine"/>
+    <Footer/>
+    <div class="dividingLine"/>
+    <div style="height: 61px;" @mouseenter="affixMouseenter" @mouseleave="affixMouseleave">
+      <div class="dataChart" id="slideDiv">
+        <div class="box">
+          <div class="titleBox">
+            <div class="title">
+              <img src="../assets/title.svg" alt="title">
+              starkNet info
+            </div>
+            <!--            <div class="exit" v-show="chart" @click="chart = false">-->
+            <!--              <img src="../assets/exit.svg" alt="exit">-->
+            <!--              Exit-->
+            <!--            </div>-->
+          </div>
+          <div class="data" >
+            <div class="dataGroup">
+              <div class="dataGroupTitle">
+                <img src="../assets/TVL.svg" alt="TVL">
+                TVL(M)
+              </div>
+              <div class="itemBox">
+                <div class="item">
+                  <div class="text1">
+                    {{nowTvl}}
+                  </div>
+
+                  <div class="text2">
+                    Now
+                  </div>
+                </div>
+                <div class="item">
+                  <div class="text3" v-show="change>=0">
+                    {{change24h}}
+                  </div>
+                  <div class="text3" style="color: red" v-show="change<0">
+                    {{change24h}}
+                  </div>
+                  <div class="text2">
+                    24h
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="verticalLine"/>
+            <div class="dataGroup">
+              <div class="dataGroupTitle">
+                <img src="../assets/tag.svg" alt="TVL">
+                Top 5 TVL(M)
+              </div>
+              <div class="itemBox">
+                <div class="item" v-for="(item,index) in TVLTopData">
+                  <div class="text1">
+                    {{ item.tvl.toFixed(2) }}M
+                  </div>
+                  <div class="text2">
+                    {{ item.name }}
+                  </div>
+                </div>
+
+              </div>
+            </div>
+          </div>
+          <!--          <div class="viewMore" v-show="affix" @click="chart = true">-->
+          <!--            <img src="../assets/viewMore.svg" alt="viewMore">-->
+          <!--            view more-->
+          <!--          </div>-->
+          <div class="chartBox">
+            <div class="TVLBox" id="TVLBox">
+
+            </div>
+            <div class="TVLTop" id="TVLTop">
+
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </main>
+</template>
+
+<style scoped lang="scss">
+.main {
+  width: 1440px;
+  height: 100%;
+  margin: auto;
+  border: 1px solid var(--vt-c-border);
+  border-top: none;
+  border-bottom: none;
+  padding: 30px 60px 0;
+  .dividingLine {
+    width: 100vw;
+    height: 1px;
+    border-bottom: 1px solid var(--vt-c-border);
+    position: absolute;
+    left: 0;
+  }
+  .mainBG{
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: center;
+    z-index: -1;
+  }
+  .topBar {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 60px 25px;
+    margin: 0 -60px;
+    border-bottom: 1px solid var(--vt-c-border);
+    .left{
+      display: flex;
+      align-items: center;
+      .nav{
+        font-family: HONOR Sans CN;
+        font-size: 21px;
+        font-style: normal;
+        font-weight: 700;
+        line-height: normal;
+        padding: 0 60px;
+        height: 100px;
+        display: flex;
+        align-items: center;
+        margin-bottom: -25px;
+        margin-top: -30px;
+        border-right: 1px solid var(--vt-c-border);
+        position: relative;
+        .line{
+          position: absolute;
+          width: 100%;
+          height: 10px;
+          background: var(--color-text);
+          left: 0;
+          bottom: 0;
+        }
+      }
+      .navOne{
+        font-family: HONOR Sans CN;
+        font-size: 21px;
+        font-style: normal;
+        font-weight: 700;
+        line-height: normal;
+        padding: 0 60px;
+        height: 100px;
+        display: flex;
+        align-items: center;
+        margin-bottom: -25px;
+        margin-top: -30px;
+        border-right: 1px solid var(--vt-c-border);
+        margin-left: 57px;
+        border-left: 1px solid var(--vt-c-border);
+        position: relative;
+        .line{
+          position: absolute;
+          width: 100%;
+          height: 10px;
+          background: var(--color-text);
+          left: 0;
+          bottom: 0;
+        }
+      }
+    }
+    .mid{
+      font-weight: 400;
+      font-size: 15px;
+      line-height: 21px;
+      font-family: 'Chillax';
+      text-transform: uppercase;
+    }
+    .right {
+      display: flex;
+      align-items: center;
+      gap:40px;
+      cursor: pointer;
+
+      .button {
+        width: fit-content;
+        height: 44px;
+        display: flex;
+        align-items: center;
+        gap: 6px;
+        background: #010101;
+        padding: 0 24px;
+        font-weight: 500;
+        font-size: 15px;
+        line-height: 20px;
+        color: #FFFFFF;
+        cursor: pointer;
+      }
+
+      .connect {
+        width: fit-content;
+        height: 44px;
+        display: flex;
+        align-items: center;
+        gap: 6px;
+        background: #FFFFFF;
+        border: 1px solid #010101;
+        border-radius: 30px;
+        padding: 0 24px;
+        font-weight: 500;
+        font-size: 15px;
+        line-height: 20px;
+        color: #010101;
+      }
+    }
+  }
+  .chainBox{
+    width: 100%;
+    display: flex;
+    align-items: center;
+    margin: 0 -60px;
+    .item{
+      padding: 24px 65px;
+      border-right: 1px solid var(--vt-c-border);
+      font-family: HONOR Sans CN;
+      font-size: 15px;
+      font-style: normal;
+      font-weight: 700;
+      line-height: normal;
+      position: relative;
+      cursor: pointer;
+      .line{
+        position: absolute;
+        width: 60px;
+        height: 4px;
+        background: var(--color-text);
+        left: 0;
+        right: 0;
+        margin: auto;
+        bottom: 0;
+      }
+    }
+  }
+  .dataBox {
+    height: 365px;
+    margin: 0 -60px;
+    border-bottom: 1px solid var(--vt-c-border);
+    border-top: 1px solid var(--vt-c-border);
+    display: flex;
+    align-items: center;
+    .left {
+      width: 845px;
+      height: 100%;
+      border-right: 1px solid var(--vt-c-border);
+      .item {
+        width: 260px;
+        display: flex;
+        flex-direction: column;
+        gap: 20px;
+
+        .top {
+          display: flex;
+          flex-direction: column;
+          gap: 6px;
+
+          .img {
+            height: 16px;
+          }
+        }
+        .publicChainBox{
+          display: flex;
+          align-items: center;
+          gap:40px;
+          .publicChainItem{
+            display: flex;
+            flex-direction: column;
+            gap:20px;
+          }
+        }
+        .title {
+          display: flex;
+          align-items: center;
+          gap: 8px;
+          font-weight: 400;
+          font-size: 14px;
+          line-height: 18px;
+          //color: #010101;
+          font-family: 'HONOR Sans CN';
+          .popoverText{
+            font-weight: 400;
+            font-size: 12px;
+            line-height: 24px;
+          }
+        }
+
+        .number {
+          display: flex;
+          align-items: center;
+          gap: 8px;
+          font-weight: 700;
+          font-size: 26px;
+          line-height: 34px;
+          //color: #010101;
+        }
+      }
+      .leftTop {
+        height: 175px;
+        width: 100%;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding-left: 60px;
+        padding-right: 60px;
+        border-bottom: 1px solid var(--vt-c-border);
+        .img{
+          display: flex;
+          align-items: center;
+          font-weight: 700;
+          gap:4px
+        }
+      }
+      .leftBottom {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        height: 175px;
+        padding-left: 60px;
+      }
+    }
+    .right {
+      height: 365px;
+      width: 596px;
+    }
+  }
+  .projectBox{
+    display: flex;
+    flex-wrap: wrap;
+    overflow:auto;
+    gap: 28px;
+    height: 585px;
+    margin: 0px -60px;
+    padding: 20px 0;
+    border-bottom: 1px solid var(--vt-c-border);
+
+    .item {
+      height: 256px;
+      width: 336px;
+      cursor: pointer;
+      .BG {
+        width: 100%;
+        height: 175px;
+      }
+
+      .infoBox {
+        display: flex;
+        align-items: center;
+        gap: 12px;
+        padding: 0 24px;
+        height: 80px;
+        //border: 1px solid #010101;
+        border-top: none;
+        background: #FFFFFF;
+
+        .avatar {
+          width: 40px;
+          height: 40px;
+          border-radius: 50%;
+        }
+
+        .nameAndType {
+          display: flex;
+          flex-direction: column;
+          gap: 2px;
+
+          .name {
+            font-weight: 700;
+            font-size: 17px;
+            line-height: 22px;
+            color: #010101;
+          }
+
+          .typeBox {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .type {
+              width: fit-content;
+              font-weight: 400;
+              font-size: 12px;
+              line-height: 16px;
+              color: #b3b3b3;
+              padding: 0 4px;
+            }
+
+            .type::before {
+              content: "\00B7";
+              margin-right: 5px;
+            }
+          }
+
+        }
+      }
+    }
+  }
+  .dataChart{
+    width: 100vw;
+    position: fixed;
+    bottom: -608px;
+    left: 0;
+    background: rgba(40, 40, 40, 0.96);
+    backdrop-filter: blur(34px);
+    display: flex;
+    justify-content: center;
+    transition: bottom 0.3s ease-in-out;
+    .box{
+      width: 1440px;
+      height: 100%;
+      .titleBox{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 20px 0;
+        .title{
+          display: flex;
+          color: #FFF;
+          font-family: HONOR Sans CN;
+          font-size: 15px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: normal;
+          gap:8px;
+          opacity: 0.5;
+        }
+
+        .exit{
+          color: #FFF73F;
+          font-family: Space Grotesk;
+          font-size: 15px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: normal;
+          display: flex;
+          gap:8px;
+          cursor: pointer;
+
+        }
+      }
+      .data{
+        display: flex;
+        gap:80px;
+        align-items: center;
+        padding: 24px 0;
+        border-bottom: 1px solid #4C4C4C;
+        border-top: 1px solid #4C4C4C;
+
+        .dataGroup{
+          display: flex;
+          flex-direction: column;
+          gap:16px;
+          .dataGroupTitle{
+            display: flex;
+            color: #FFF;
+            font-family: HONOR Sans CN;
+            font-size: 15px;
+            font-style: normal;
+            font-weight: 700;
+            line-height: normal;
+            gap:8px;
+            opacity: 0.5;
+
+          }
+          .itemBox{
+            display: flex;
+            align-items: center;
+            gap:80px;
+            .item{
+              display: flex;
+              flex-direction: column;
+              gap:8px;
+              .text1{
+                color: #FFF;
+                font-family: HONOR Sans CN;
+                font-size: 21px;
+                font-style: normal;
+                font-weight: 700;
+                line-height: normal;
+              }
+              .text2{
+                color: #FFF;
+                font-family: HONOR Sans CN;
+                font-size: 14px;
+                font-style: normal;
+                font-weight: 400;
+                line-height: normal;
+                opacity: 0.5;
+              }
+              .text3{
+                color: #57EB92;
+                font-family: HONOR Sans CN;
+                font-size: 21px;
+                font-style: normal;
+                font-weight: 700;
+                line-height: normal;
+              }
+            }
+          }
+        }
+        .verticalLine{
+          width: 1px;
+          height: 88px;
+          border-right: 1px solid #4c4c4c;
+        }
+      }
+      .viewMore{
+        width: 100%;
+        padding: 20px 0;
+        display: flex;
+        justify-content: center;
+        gap:8px;
+        color: #FFF73F;
+        font-family: Space Grotesk;
+        font-size: 15px;
+        font-style: normal;
+        font-weight: 700;
+        line-height: normal;
+        cursor: pointer;
+      }
+      .chartBox{
+        width: 100%;
+        height: 468px;
+        display: flex;
+        .TVLBox{
+          width: 840px;
+          height: 100%;
+          border-right: 1px solid #4c4c4c;
+          border-left: 1px solid #4c4c4c;
+        }
+        .TVLTop{
+          width: 600px;
+          height: 100%;
+          border-right: 1px solid #4c4c4c;
+          padding: 60px
+        }
+      }
+    }
+  }
+}
+
+::-webkit-scrollbar {
+  width: 4px; /* 滚动条宽度 */
+}
+
+// /* 滚动条轨道 */
+// ::-webkit-scrollbar-track {
+//   background: #f1f1f1; /* 轨道背景色 */
+// }
+
+/* 滚动条滑块 */
+::-webkit-scrollbar-thumb {
+  background: #888; /* 滑块背景色 */
+}
+
+/* 滚动条滑块悬停状态 */
+::-webkit-scrollbar-thumb:hover {
+  background: #555; /* 悬停状态下滑块背景色 */
+}
+</style>

+ 367 - 5
src/views/ZksyncView.vue

@@ -41,6 +41,10 @@ import Nav from '@/components/Nav.vue'
 import Footer from '@/components/Footer.vue'
 //@ts-ignore
 import {getAllZksSyncData} from "@/utils/getZksyncData/index.js";
+import { connect, disconnect } from "get-starknet"
+import axios from 'axios';
+import {Area, Bar} from '@antv/g2plot';
+import moment from "moment";
 
 const sunStore = useSunStore()
 const addressStore = useAddressStore()
@@ -50,6 +54,8 @@ type EChartsOption = echarts.EChartsOption;
 onMounted(() => {
   checkWalletAddress()
   listeningDisconnect()
+  fetchData()
+  fetchData2()
 })
 
 
@@ -184,7 +190,6 @@ const switchEthereumChain = () => {
 }
 //连接钱包按钮
 const connectWallet = async () => {
-  console.log('zks')
   let accounts: string[] = await MM.value.request({method: 'eth_requestAccounts'});
   addressStore.address = accounts[0]
   getMainTx()
@@ -193,6 +198,7 @@ const connectWallet = async () => {
   await addChain()
   await switchEthereumChain()
 }
+
 //获取主网交易次数
 let mainTx = ref('-')
 const getMainTx = () => {
@@ -309,7 +315,7 @@ const initEcharts = () => {
     },
     series: [
       {
-        color: '#000000',
+        color: '#EC796B',
         data: showMonthNumberArr.value,
         type: 'bar'
       }
@@ -337,12 +343,136 @@ const toEmail = (email:string) => {
   window.open(mailtoUrl);
 }
 
+let affix = ref(false)
+let chart = ref(false)
+
+const affixMouseenter = () => {
+  const slideDiv = document.getElementById("slideDiv");
+  slideDiv.style.bottom = "0";
+}
+
+const affixMouseleave = () => {
+  const slideDiv = document.getElementById("slideDiv");
+  slideDiv.style.bottom = "-608px";
+}
+
+
+const getStarkTvl = async () => {
+  const url = 'https://api.llama.fi/v2/historicalChainTvl/zkSync%20Era';
+  const response = await axios.get(url);
+  return response.data;
+}
+
+const getZkTvlDetail = async () => {
+  const url = "https://api.llama.fi/protocols";
+  const response = await axios.get(url);
+  let result = [];
+  response.data.forEach((item) => {
+    if (item['chains'].includes("zkSync Era") && item.category !== "CEX") {
+      result.push({
+        name: item.name,
+        tvl: item['chainTvls']['zkSync Era'] / 1000000,
+      });
+    }
+  });
+  result.sort((a, b) => b.tvl - a.tvl);
+  result = result.slice(0, 10);
+  return result;
+}
+
+let change = ref(0)
+let change24h = ref('-')
+let nowTvl = ref('-')
+
+const fetchData = async () => {
+  const result = await getStarkTvl();
+  change.value = ((result[result.length - 1].tvl - result[result.length - 2].tvl) / result[result.length - 2].tvl) * 100;
+  change24h.value = change.value.toFixed(2) + '%'
+  nowTvl.value = (result[result.length - 1].tvl / 1000000).toFixed(2) + 'M'
+
+  let VolData = [];
+  result.forEach(item => {
+    VolData.push({
+      date: new Date(item.date * 1000).toLocaleDateString(),
+      tvl: item.tvl / 1000000,
+    });
+  });
+  const max = Math.max(...VolData.map(item => item.tvl));
+  const chart = new Area('TVLBox',{
+    data: VolData,
+    xField: 'date',
+    yField: 'tvl',
+    smooth: true,
+    isStack: true,
+    padding:[60],
+    color: '#FFF',
+    // label: {
+    //   style:{
+    //     fill:'#FFF'
+    //   },
+    //   content: (originData) => {
+    //     return `${originData.tvl.toFixed(0)}`;
+    //   },
+    // },
+    slider: {
+      start: 0,
+      end: 1,
+      formatter: (v) => moment(v).format('YYYY-MM-DD'),
+      textStyle:{
+        fill:'#FFF'
+      }
+    },
+    meta: {
+      tvl: {
+        alias: 'TVL(M)',
+        min: 0,
+        max: max * 1.1,
+
+      }
+    }
+  });
+  chart.render();
+}
+
+let TVLTopData = ref()
+const fetchData2 = async () => {
+  let result = await getZkTvlDetail();
+  TVLTopData.value = result.slice(0,5)
+
+  const max = Math.max(...result.map(item => item.tvl));
+  const chart = new Bar('TVLTop', {
+    data:result,
+    xField: 'tvl',
+    yField: 'name',
+    color: '#FFF',
+    yAxis: {
+      label: {
+        formatter: (v) => `${v}`,
+      }
+    },
+    label: {
+      position: 'right',
+      style:{
+            fill:'#FFF'
+          },
+      formatter: (v) => `${v.tvl.toFixed(2)}`,
+    },
+    meta: {
+      tvl: {
+        alias: 'TVL(M)',
+        max: max * 1.1,
+      }
+    }
+  });
+  chart.render();
+}
+
 </script>
 
 <template>
   <main class="main">
     <div class="mainBG">
-      <img src="../assets/BG.png" alt="BG">
+      <img src="../assets/navBg.png" alt="BG">
     </div>
     <Nav @doSth="connectWallet"/>
 
@@ -351,10 +481,10 @@ const toEmail = (email:string) => {
         zkSync
         <div class="line"></div>
       </div>
-      <div class="item" style="cursor: pointer" @click="toPage('/layerZero')">
+      <div class="item" @click="toPage('/layerZero')">
         Layer Zero
       </div>
-      <div class="item">
+      <div class="item" @click="toPage('/starkNet')">
         StarkNet
       </div>
     </div>
@@ -547,7 +677,85 @@ const toEmail = (email:string) => {
         </div>
       </div>
     </div>
+    <div class="dividingLine"/>
     <Footer/>
+    <div class="dividingLine"/>
+    <div style="height: 61px;" @mouseenter="affixMouseenter" @mouseleave="affixMouseleave">
+      <div class="dataChart" id="slideDiv">
+        <div class="box">
+          <div class="titleBox">
+            <div class="title">
+              <img src="../assets/title.svg" alt="title">
+              zkSync info
+            </div>
+<!--            <div class="exit" v-show="chart" @click="chart = false">-->
+<!--              <img src="../assets/exit.svg" alt="exit">-->
+<!--              Exit-->
+<!--            </div>-->
+          </div>
+          <div class="data" >
+            <div class="dataGroup">
+              <div class="dataGroupTitle">
+                <img src="../assets/TVL.svg" alt="TVL">
+                TVL(M)
+              </div>
+              <div class="itemBox">
+                <div class="item">
+                  <div class="text1">
+                    {{nowTvl}}
+                  </div>
+
+                  <div class="text2">
+                    Now
+                  </div>
+                </div>
+                <div class="item">
+                  <div class="text3" v-show="change>=0">
+                    {{change24h}}
+                  </div>
+                  <div class="text3" style="color: red" v-show="change<0">
+                    {{change24h}}
+                  </div>
+                  <div class="text2">
+                    24h
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="verticalLine"/>
+            <div class="dataGroup">
+              <div class="dataGroupTitle">
+                <img src="../assets/tag.svg" alt="TVL">
+                Top 5 TVL(M)
+              </div>
+              <div class="itemBox">
+                <div class="item" v-for="(item,index) in TVLTopData">
+                  <div class="text1">
+                    {{ item.tvl.toFixed(2) }}M
+                  </div>
+                  <div class="text2">
+                    {{ item.name }}
+                  </div>
+                </div>
+
+              </div>
+            </div>
+          </div>
+<!--          <div class="viewMore" v-show="affix" @click="chart = true">-->
+<!--            <img src="../assets/viewMore.svg" alt="viewMore">-->
+<!--            view more-->
+<!--          </div>-->
+          <div class="chartBox">
+            <div class="TVLBox" id="TVLBox">
+
+            </div>
+            <div class="TVLTop" id="TVLTop">
+
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
   </main>
 </template>
 
@@ -560,9 +768,20 @@ const toEmail = (email:string) => {
   border-top: none;
   border-bottom: none;
   padding: 30px 60px 0;
+  .dividingLine {
+    width: 100vw;
+    height: 1px;
+    border-bottom: 1px solid var(--vt-c-border);
+    position: absolute;
+    left: 0;
+  }
   .mainBG{
     position: absolute;
     top: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    justify-content: center;
     z-index: -1;
   }
   .topBar {
@@ -683,6 +902,7 @@ const toEmail = (email:string) => {
       font-weight: 700;
       line-height: normal;
       position: relative;
+      cursor: pointer;
       .line{
         position: absolute;
         width: 60px;
@@ -856,6 +1076,148 @@ const toEmail = (email:string) => {
       }
     }
   }
+  .dataChart{
+    width: 100vw;
+    position: fixed;
+    bottom: -608px;
+    left: 0;
+    background: rgba(40, 40, 40, 0.96);
+    backdrop-filter: blur(34px);
+    display: flex;
+    justify-content: center;
+    transition: bottom 0.3s ease-in-out;
+    .box{
+      width: 1440px;
+      height: 100%;
+      .titleBox{
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 20px 0;
+        .title{
+          display: flex;
+          color: #FFF;
+          font-family: HONOR Sans CN;
+          font-size: 15px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: normal;
+          gap:8px;
+          opacity: 0.5;
+        }
+
+        .exit{
+          color: #FFF73F;
+          font-family: Space Grotesk;
+          font-size: 15px;
+          font-style: normal;
+          font-weight: 700;
+          line-height: normal;
+          display: flex;
+          gap:8px;
+          cursor: pointer;
+
+        }
+      }
+      .data{
+        display: flex;
+        gap:80px;
+        align-items: center;
+        padding: 24px 0;
+        border-bottom: 1px solid #4C4C4C;
+        border-top: 1px solid #4C4C4C;
+
+        .dataGroup{
+          display: flex;
+          flex-direction: column;
+          gap:16px;
+          .dataGroupTitle{
+            display: flex;
+            color: #FFF;
+            font-family: HONOR Sans CN;
+            font-size: 15px;
+            font-style: normal;
+            font-weight: 700;
+            line-height: normal;
+            gap:8px;
+            opacity: 0.5;
+
+          }
+          .itemBox{
+            display: flex;
+            align-items: center;
+            gap:80px;
+            .item{
+              display: flex;
+              flex-direction: column;
+              gap:8px;
+              .text1{
+                color: #FFF;
+                font-family: HONOR Sans CN;
+                font-size: 21px;
+                font-style: normal;
+                font-weight: 700;
+                line-height: normal;
+              }
+              .text2{
+                color: #FFF;
+                font-family: HONOR Sans CN;
+                font-size: 14px;
+                font-style: normal;
+                font-weight: 400;
+                line-height: normal;
+                opacity: 0.5;
+              }
+              .text3{
+                color: #57EB92;
+                font-family: HONOR Sans CN;
+                font-size: 21px;
+                font-style: normal;
+                font-weight: 700;
+                line-height: normal;
+              }
+            }
+          }
+        }
+        .verticalLine{
+          width: 1px;
+          height: 88px;
+          border-right: 1px solid #4c4c4c;
+        }
+      }
+      .viewMore{
+        width: 100%;
+        padding: 20px 0;
+        display: flex;
+        justify-content: center;
+        gap:8px;
+        color: #FFF73F;
+        font-family: Space Grotesk;
+        font-size: 15px;
+        font-style: normal;
+        font-weight: 700;
+        line-height: normal;
+        cursor: pointer;
+      }
+      .chartBox{
+        width: 100%;
+        height: 468px;
+        display: flex;
+        .TVLBox{
+          width: 840px;
+          height: 100%;
+          border-right: 1px solid #4c4c4c;
+          border-left: 1px solid #4c4c4c;
+        }
+        .TVLTop{
+          width: 600px;
+          height: 100%;
+          border-right: 1px solid #4c4c4c;
+          padding: 60px
+        }
+      }
+    }
+  }
 }
 
 ::-webkit-scrollbar {

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor