From ae6e2e334196d3f7dff36d14dfd2c83800f1319d Mon Sep 17 00:00:00 2001 From: ercanakalar Date: Sat, 31 Aug 2024 12:40:57 +0300 Subject: [PATCH 1/3] feat: :sparkles: first part implemented --- .gitignore | 3 + .vscode/extensions.json | 3 + ERC20.ts | 578 ++++++++++++++--------------- README.md | 33 ++ index.html | 13 + package.json | 30 ++ public/favicon.ico | Bin 0 -> 4286 bytes src/App.vue | 33 ++ src/assets/base.css | 86 +++++ src/assets/logo.svg | 1 + src/assets/main.css | 35 ++ src/components/NetworkDropdown.vue | 87 +++++ src/components/TokenTable.vue | 131 +++++++ src/env.d.ts | 13 + src/main.ts | 10 + src/router/index.ts | 23 ++ src/shims-vue.d.ts | 7 + src/store/index.ts | 77 ++++ src/types/fetch.ts | 16 + src/views/AboutView.vue | 7 + src/views/HomeView.vue | 14 + tsconfig.json | 18 + vite.config.ts | 22 ++ 23 files changed, 951 insertions(+), 289 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 README.md create mode 100644 index.html create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 src/App.vue create mode 100644 src/assets/base.css create mode 100644 src/assets/logo.svg create mode 100644 src/assets/main.css create mode 100644 src/components/NetworkDropdown.vue create mode 100644 src/components/TokenTable.vue create mode 100644 src/env.d.ts create mode 100644 src/main.ts create mode 100644 src/router/index.ts create mode 100644 src/shims-vue.d.ts create mode 100644 src/store/index.ts create mode 100644 src/types/fetch.ts create mode 100644 src/views/AboutView.vue create mode 100644 src/views/HomeView.vue create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dba87bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/node_modules + +/package-lock.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/ERC20.ts b/ERC20.ts index 3ce8032..17de1ab 100644 --- a/ERC20.ts +++ b/ERC20.ts @@ -1,290 +1,290 @@ export default { - abi: [ - { - inputs: [ - { - internalType: 'string', - name: 'name_', - type: 'string', - }, - { - internalType: 'string', - name: 'symbol_', - type: 'string', - }, - ], - stateMutability: 'nonpayable', - type: 'constructor', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'owner', - type: 'address', - }, - { - indexed: true, - internalType: 'address', - name: 'spender', - type: 'address', - }, - { - indexed: false, - internalType: 'uint256', - name: 'value', - type: 'uint256', - }, - ], - name: 'Approval', - type: 'event', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'address', - name: 'from', - type: 'address', - }, - { - indexed: true, - internalType: 'address', - name: 'to', - type: 'address', - }, - { - indexed: false, - internalType: 'uint256', - name: 'value', - type: 'uint256', - }, - ], - name: 'Transfer', - type: 'event', - }, - { - inputs: [ - { - internalType: 'address', - name: 'owner', - type: 'address', - }, - { - internalType: 'address', - name: 'spender', - type: 'address', - }, - ], - name: 'allowance', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'spender', - type: 'address', - }, - { - internalType: 'uint256', - name: 'amount', - type: 'uint256', - }, - ], - name: 'approve', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'account', - type: 'address', - }, - ], - name: 'balanceOf', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'decimals', - outputs: [ - { - internalType: 'uint8', - name: '', - type: 'uint8', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'spender', - type: 'address', - }, - { - internalType: 'uint256', - name: 'subtractedValue', - type: 'uint256', - }, - ], - name: 'decreaseAllowance', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'spender', - type: 'address', - }, - { - internalType: 'uint256', - name: 'addedValue', - type: 'uint256', - }, - ], - name: 'increaseAllowance', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [], - name: 'name', - outputs: [ - { - internalType: 'string', - name: '', - type: 'string', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'symbol', - outputs: [ - { - internalType: 'string', - name: '', - type: 'string', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [], - name: 'totalSupply', - outputs: [ - { - internalType: 'uint256', - name: '', - type: 'uint256', - }, - ], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'to', - type: 'address', - }, - { - internalType: 'uint256', - name: 'amount', - type: 'uint256', - }, - ], - name: 'transfer', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'from', - type: 'address', - }, - { - internalType: 'address', - name: 'to', - type: 'address', - }, - { - internalType: 'uint256', - name: 'amount', - type: 'uint256', - }, - ], - name: 'transferFrom', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - ], -} + abi: [ + { + inputs: [ + { + internalType: 'string', + name: 'name_', + type: 'string', + }, + { + internalType: 'string', + name: 'symbol_', + type: 'string', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + inputs: [ + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + ], + name: 'allowance', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'approve', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + internalType: 'uint256', + name: 'subtractedValue', + type: 'uint256', + }, + ], + name: 'decreaseAllowance', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + internalType: 'uint256', + name: 'addedValue', + type: 'uint256', + }, + ], + name: 'increaseAllowance', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'transferFrom', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + ], +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000..53d6bc5 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Frontend-Coding-Challenge + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` diff --git a/index.html b/index.html new file mode 100644 index 0000000..a888544 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..2499df6 --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "Frontend-Coding-Challenge", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "axios": "^1.7.5", + "ethers": "^5.7.2", + "vue": "^3.4.29", + "vue-router": "^4.4.3", + "vuex": "^4.0.2" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.2.0", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..8971390 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/assets/base.css b/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --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); + + --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); + + --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); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/main.css b/src/assets/main.css new file mode 100644 index 0000000..36fb845 --- /dev/null +++ b/src/assets/main.css @@ -0,0 +1,35 @@ +@import './base.css'; + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + font-weight: normal; +} + +a, +.green { + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} + +@media (min-width: 1024px) { + body { + display: flex; + place-items: center; + } + + #app { + display: grid; + grid-template-columns: 1fr 1fr; + padding: 0 2rem; + } +} diff --git a/src/components/NetworkDropdown.vue b/src/components/NetworkDropdown.vue new file mode 100644 index 0000000..1a2e5c1 --- /dev/null +++ b/src/components/NetworkDropdown.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/components/TokenTable.vue b/src/components/TokenTable.vue new file mode 100644 index 0000000..5f5380b --- /dev/null +++ b/src/components/TokenTable.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..b3a7a33 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,13 @@ +// src/env.d.ts + +/// + +interface ImportMetaEnv { + readonly VITE_APP_TITLE: 'DEneme'; // Example custom environment variable + readonly VITE_API_URL: 'http://localhost:5173/'; // Your API URL or other env variables + // Add more environment variables as needed... +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..d5fd1ff --- /dev/null +++ b/src/main.ts @@ -0,0 +1,10 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import router from './router'; // Import your router configuration +import store from './store/index'; // Import Vuex store + +const app = createApp(App); + +app.use(store); // Use Vuex store +app.use(router); +app.mount('#app'); diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..1874989 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router'; +import HomeView from '../views/HomeView.vue'; +import AboutView from '../views/AboutView.vue'; + +const routes = [ + { + path: '/', + name: 'home', + component: HomeView, + }, + { + path: '/about', + name: 'about', + component: AboutView, + }, +]; + +const router = createRouter({ + history: createWebHistory(import.meta.env.VITE_API_URL), + routes, +}); + +export default router; diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts new file mode 100644 index 0000000..0845e2c --- /dev/null +++ b/src/shims-vue.d.ts @@ -0,0 +1,7 @@ +// src/shims-vue.d.ts + +declare module '*.vue' { + import { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..c25312e --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,77 @@ +import { createStore } from 'vuex'; +import axios from 'axios'; + +import { Tokens } from '@/types/fetch'; + +const store = createStore({ + state: { + selectedNetwork: 0, + networks: [], + isLoading: false, + error: null, + tokens: [], + }, + mutations: { + setSelectedNetwork(state, network) { + state.selectedNetwork = network; + }, + setLoading(state, loading) { + state.isLoading = loading; + }, + setError(state, error) { + state.error = error; + }, + setNetworks(state, networks) { + state.networks = networks; + }, + setTokens(state, tokens) { + state.tokens = tokens; + }, + }, + actions: { + async fetchNetworks({ commit, state }) { + if (state.networks.length === 0) { + commit('setLoading', true); + commit('setError', null); + try { + const response = await axios.get('/api/privapi/trading/environments', { + headers: { + Accept: 'application/json', + }, + }); + commit('setNetworks', response.data); + } catch (error) { + commit('setError', 'Error fetching networks. Please try again.'); + } finally { + commit('setLoading', false); + } + } + }, + async fetchTokens({ commit }, networkId) { + commit('setLoading', true); + commit('setError', null); + try { + const response = await axios.get('/api/privapi/trading/tokens', { + headers: { + Accept: 'application/json', + }, + }); + const filteredTokens = response.data.filter((token: Tokens) => token.chain_id === networkId); + commit('setTokens', filteredTokens); + } catch (error) { + commit('setError', 'Error fetching tokens. Please try again.'); + } finally { + commit('setLoading', false); + } + }, + }, + getters: { + selectedNetwork: (state) => state.selectedNetwork, + networks: (state) => state.networks, + isLoading: (state) => state.isLoading, + error: (state) => state.error, + tokens: (state) => state.tokens, + }, +}); + +export default store; diff --git a/src/types/fetch.ts b/src/types/fetch.ts new file mode 100644 index 0000000..c89f4d0 --- /dev/null +++ b/src/types/fetch.ts @@ -0,0 +1,16 @@ +export type Tokens = { + address: string; + auctionendtime: number | null; + auctionmode: number; + chain_id: number; + env: string; + evmdecimals: number; + isnative: boolean; + isvirtual: boolean; + min_depositamnt: string; + name: string; + old_symbol: string | null; + status: string; + subnet_symbol: string; + symbol: string; +}; diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue new file mode 100644 index 0000000..80fccb3 --- /dev/null +++ b/src/views/AboutView.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..1391090 --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e922678 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "esnext", // Use 'esnext' to support modern JavaScript features + "module": "esnext", // Compatible module setting for 'import.meta' + "strict": true, + "jsx": "preserve", + "moduleResolution": "node", + "skipLibCheck": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "exclude": ["node_modules"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..2cc4a2a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import path from 'path'; + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + server: { + proxy: { + '/api': { + target: 'https://api.dexalot-test.com', + changeOrigin: true, + secure: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, + }, +}); From b41f1768dce89d6b1cab7ecabbc662101f8bebfb Mon Sep 17 00:00:00 2001 From: ercanakalar Date: Sun, 1 Sep 2024 16:57:15 +0300 Subject: [PATCH 2/3] feat: :sparkles: Part 2 is implemented --- src/App.vue | 8 +-- src/components/NetworkDropdown.vue | 14 ++--- src/components/TokenTable.vue | 50 +++++++++++++++-- src/store/index.ts | 88 ++++++++++++++++++++++++++---- src/types/fetch.ts | 18 ++++++ 5 files changed, 151 insertions(+), 27 deletions(-) diff --git a/src/App.vue b/src/App.vue index 8971390..11ae674 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,4 @@ @@ -37,13 +36,12 @@ const store = useStore(); const tokens = computed(() => store.getters.tokens || store.state.tokens || []); const selectedNetworkId = computed(() => store.getters.selectedNetworkId); const isLoading = computed(() => store.getters.isLoading); -const isLoadingBalance = computed(() => store.getters.isLoadingBalance); -const error = computed(() => store.getters.error); const balances = computed(() => store.getters.balances); const walletAddress = '0x0B1d5f23d1c10708ac0e63AD1e4F104a912eeF6d'; const fetchTokensAndBalances = async (networkId) => { + store.commit('setTokenBalances', []); await store.dispatch('fetchTokens', networkId); await store.dispatch('fetchTokenBalances', walletAddress); }; @@ -98,7 +96,6 @@ onMounted(() => { .no-data { font-size: 16px; color: #888; - margin-top: 10px; } .spinner-container { @@ -116,12 +113,6 @@ onMounted(() => { background-color: gray; } -.error-message { - color: red; - margin-bottom: 16px; - font-size: 14px; -} - .spinner { border: 4px solid #f3f3f3; border-top: 4px solid blue; @@ -131,30 +122,34 @@ onMounted(() => { animation: spin 1s linear infinite; } -@media screen and (max-width: 375px) { +@media screen and (max-width: 400px) { + .table-container { + padding: 0; + } .token-table td { border: 1px solid #ddd; text-align: left; - font-size: smaller; - padding: 1px; + font-size: 10px; + padding: 5px; } .token-table th { - font-size: x-small; - padding: 1px; + font-size: 10px; + padding: 5px; } } -@media screen and (max-width: 475px) { +@media screen and (min-width: 400px) and (max-width: 475px) { .table-container { padding: 0; } .token-table td { border: 1px solid #ddd; text-align: left; - font-size: small; + font-size: 12px; } .token-table th { - font-size: small; + font-size: 12px; + padding: 5px; } } diff --git a/src/router/index.ts b/src/router/index.ts index 1874989..791e622 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,6 +1,5 @@ import { createRouter, createWebHistory } from 'vue-router'; import HomeView from '../views/HomeView.vue'; -import AboutView from '../views/AboutView.vue'; const routes = [ { @@ -8,11 +7,6 @@ const routes = [ name: 'home', component: HomeView, }, - { - path: '/about', - name: 'about', - component: AboutView, - }, ]; const router = createRouter({ diff --git a/src/store/index.ts b/src/store/index.ts index 104b59f..39bb855 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,21 +2,12 @@ import { createStore } from 'vuex'; import axios from 'axios'; import { BigNumber, ethers } from 'ethers'; -import { Environments, Tokens } from '@/types/fetch'; import ERC20 from '../../ERC20'; -interface State { - selectedNetworkId: number; - network: Environments; - networks: Environments[]; - isLoading: boolean; - isLoadingBalance: boolean; - error: string | null; - tokens: Tokens[]; - balances: Record; -} +import { NetworkStoreState } from '@/types/store-type'; +import { Environments, Tokens } from '@/types/fetch-type'; -const store = createStore({ +const store = createStore({ state: { selectedNetworkId: 0, network: { @@ -37,9 +28,7 @@ const store = createStore({ token_url: '', }, networks: [], - isLoadingBalance: false, isLoading: false, - error: null, tokens: [], balances: {}, }, @@ -51,12 +40,6 @@ const store = createStore({ setLoading(state, loading: boolean) { state.isLoading = loading; }, - setLoadingBalance(state, loading: boolean) { - state.isLoadingBalance = loading; - }, - setError(state, error: string | null) { - state.error = error; - }, setNetworks(state, networks: Environments[]) { state.networks = networks; }, @@ -71,7 +54,6 @@ const store = createStore({ async fetchNetworks({ commit, state }) { if (state.networks.length === 0) { commit('setLoading', true); - commit('setError', null); try { const response = await axios.get('/api/privapi/trading/environments', { headers: { @@ -79,8 +61,6 @@ const store = createStore({ }, }); commit('setNetworks', response.data); - } catch (error) { - commit('setError', 'Error fetching networks. Please try again.'); } finally { commit('setLoading', false); } @@ -88,7 +68,6 @@ const store = createStore({ }, async fetchTokens({ commit }, networkId) { commit('setLoading', true); - commit('setError', null); try { const response = await axios.get('/api/privapi/trading/tokens', { headers: { @@ -97,22 +76,21 @@ const store = createStore({ }); const filteredTokens = response.data.filter((token: Tokens) => token.chain_id === networkId); commit('setTokens', filteredTokens); - } catch (error) { - commit('setError', 'Error fetching tokens. Please try again.'); } finally { commit('setLoading', false); } }, async fetchTokenBalances({ commit, state }, walletAddress: string) { - commit('setLoadingBalance', true); const balances: Record = { ...state.balances }; - try { - for (const token of state.tokens) { - const chainReaderUrl = state.network.chain_instance; - const provider = new ethers.providers.JsonRpcProvider(chainReaderUrl); + for (const token of state.tokens) { + const chainReaderUrl = state.network.chain_instance; + const provider = new ethers.providers.JsonRpcProvider(chainReaderUrl); + + let balance: BigNumber; + let symbol = token.symbol; - let balance: BigNumber; + try { if (token.isnative) { balance = await provider.getBalance(walletAddress); } else { @@ -121,14 +99,12 @@ const store = createStore({ } const displayValue = ethers.utils.formatUnits(balance, token.evmdecimals); - balances[token.symbol] = displayValue; - - commit('setTokenBalances', { ...balances }); + balances[symbol] = displayValue; + } catch (balanceError) { + balances[symbol] = `Error fetching balance`; } - } catch (error) { - commit('setError', `Error fetching token balances. Please try again.`); - } finally { - commit('setLoadingBalance', false); + + commit('setTokenBalances', { ...balances }); } }, }, @@ -136,7 +112,6 @@ const store = createStore({ selectedNetworkId: (state) => state.selectedNetworkId, networks: (state) => state.networks, isLoading: (state) => state.isLoading, - error: (state) => state.error, tokens: (state) => state.tokens, balances: (state) => state.balances, }, diff --git a/src/types/fetch.ts b/src/types/fetch-type.ts similarity index 100% rename from src/types/fetch.ts rename to src/types/fetch-type.ts diff --git a/src/types/store-type.ts b/src/types/store-type.ts new file mode 100644 index 0000000..bdc9cba --- /dev/null +++ b/src/types/store-type.ts @@ -0,0 +1,10 @@ +import { Environments, Tokens } from './fetch-type'; + +export type NetworkStoreState = { + selectedNetworkId: number; + network: Environments; + networks: Environments[]; + isLoading: boolean; + tokens: Tokens[]; + balances: Record; +}; diff --git a/src/views/AboutView.vue b/src/views/AboutView.vue deleted file mode 100644 index 80fccb3..0000000 --- a/src/views/AboutView.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 1391090..ead6360 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -10,5 +10,4 @@ import NetworkDropdown from '@/components/NetworkDropdown.vue'; import TokenTable from '@/components/TokenTable.vue'; - +