├── .gitignore ├── Brewfile ├── README.md ├── img ├── edit.png ├── file.png ├── group.png ├── intro.png ├── invite.png └── transaction.png ├── index.html ├── package.json ├── public ├── favicon.ico └── intro │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ ├── 9.png │ └── intro.md ├── src ├── App.vue ├── assets │ ├── css │ │ ├── main.scss │ │ └── reset.scss │ ├── fonts │ │ ├── Montserrat-Black.otf │ │ ├── Montserrat-Bold.otf │ │ ├── Montserrat-ExtraBold.otf │ │ ├── Montserrat-ExtraLight.otf │ │ ├── Montserrat-Light.otf │ │ ├── Montserrat-Medium.otf │ │ ├── Montserrat-Regular.otf │ │ ├── Montserrat-SemiBold.otf │ │ └── Montserrat-Thin.otf │ ├── images │ │ ├── add.svg │ │ ├── add_file.svg │ │ ├── add_folder.svg │ │ ├── arrow.svg │ │ ├── arrow_reload.svg │ │ ├── avatar │ │ │ ├── 0.png │ │ │ ├── 1.png │ │ │ ├── 2.png │ │ │ ├── 3.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 7.png │ │ │ ├── 8.png │ │ │ └── 9.png │ │ ├── close.svg │ │ ├── code.svg │ │ ├── conversion.svg │ │ ├── copy.svg │ │ ├── decode.svg │ │ ├── del.svg │ │ ├── discord.svg │ │ ├── edit.svg │ │ ├── file.svg │ │ ├── flower.svg │ │ ├── folder.svg │ │ ├── folder_open.svg │ │ ├── gas.gif │ │ ├── group.png │ │ ├── groupQRCode.jpg │ │ ├── groupQRCode.png │ │ ├── hint.png │ │ ├── json.svg │ │ ├── left.png │ │ ├── logo.svg │ │ ├── nft_bg.svg │ │ ├── note_edit.svg │ │ ├── read.svg │ │ ├── regist_bg.png │ │ ├── share.svg │ │ ├── show.svg │ │ ├── success.svg │ │ ├── table.svg │ │ ├── time.svg │ │ ├── time_icon.svg │ │ ├── top.svg │ │ ├── trash.svg │ │ ├── update.svg │ │ ├── user.svg │ │ └── write.svg │ └── logo.png ├── components │ ├── AddChainModal.vue │ ├── AddFolder.vue │ ├── AddTeamModal.vue │ ├── Avatar.vue │ ├── Contract.vue │ ├── ContractHd.vue │ ├── ContractInfo.vue │ ├── ContractMsg.vue │ ├── ConversionModal.vue │ ├── CreateContract.vue │ ├── DecodeModal.vue │ ├── EditModal.vue │ ├── GetContractModal.vue │ ├── Item.vue │ ├── LoginModal.vue │ ├── Main.vue │ ├── Menu.vue │ ├── Nav.vue │ ├── NetworkErrorModal.vue │ ├── ParameItem.vue │ ├── RegistModal.vue │ ├── SelectNftModal.vue │ ├── SelectSearch.vue │ ├── ShareModal.vue │ ├── SourceCodeModal.vue │ └── TeamModal.vue ├── hooks │ ├── useContract.js │ ├── useIsActivating.js │ ├── useNetwork.js │ └── useUtils.js ├── http │ ├── abi.js │ └── axios.js ├── libs │ ├── abi.js │ ├── chains.js │ ├── chainsOptions.js │ ├── connectWallet.js │ ├── defaultChain.js │ ├── demo.js │ ├── rem.js │ ├── rpcs.js │ ├── utils.js │ └── walletSwitchChain.js ├── main.js ├── router │ └── index.js ├── service │ └── service.js ├── store │ └── index.js └── views │ ├── About.vue │ └── Home.vue ├── vite.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | tap "homebrew/bundle" 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DappReader 2 | 3 | 4 | 5 | ![cover](./img/intro.png) 6 | 7 | ### **DappReader是一款令我们自豪的产品,一款全面面向EVM生态开发者服务的免费工具** 8 | 9 | DappReader旨在为开发者提供已发布的多链合约的管理和快速前端-合约调试。这款工具将帮助开发者更加高效地开发、测试和部署合约项目,提升项目的开发质量和效率。 10 | 11 | > 你可以简单理解为对标web2时代的的 **Postman** ! 12 | 13 | ### 你是否也有相同烦恼: 14 | 15 | 1. 使用Remix和Etherscan.io等工具处理已有合约或调试新合约非常不友好,并且需要频繁地更新和验证代码。 16 | 2. 写过的合约很久后忘记在哪里,需要翻交互记录才能找到 17 | 18 | 3. 与团队成员或其他前端工程师进行远程协作时也很繁琐。 19 | 20 | 4. 另外,让非开发人员使用智能合约需要写复杂的UI并部署到中心化服务器上。 21 | 22 | ### DappReader的主要功能: 23 | 1. 多种方式方便添加与管理所有EVM链智能合约 24 | 2. 快速检索与管理已发布的合约 25 | 3. 无代码快速生成智能合约操作界面 26 | 4. 对智能合约整体以及每一个函数单独进行注释 27 | 5. 与开发者或非开发者快速分享开发中的智能合约(包含注释),方便合约工程师与前端工程师联调 28 | 6. 提供完全免费的团队分享功能,非常适合小团队使用 29 | 7. 提供一系列类型转换工具,减少开发者工作量 30 | 31 | 32 | 33 | ### DappReader当前的开发进度: 34 | 35 | - [x] UI完全重新设计开发,使用而更加方便舒适 36 | - [x] 重新设计返回的展示方案 37 | - [x] 重新设计且开发动态侧边栏,让开发者更专注于合约本身 38 | - [x] 开发完整的团队分享功能 39 | - [ ] 加入更多AI功能 40 | - [ ] 基于多个智能合约流程执行功能 41 | - [ ] 基于外部变化自动执行合约的Trigger功能 42 | - [ ] 用户无代码生成简单前端页面并分享功能 43 | - [ ] 集成Remix完成一站式开发测试分享功能 44 | - [ ] 深度结合web2与web3,完成**web3os** 45 | 46 | ### DappReader功能介绍: 47 | 48 | 49 | 快速与团队成员分享智能合约 50 | 51 | 52 | 53 | 快速管理个人与公司的多个链上智能合约 54 | 55 | 56 | 57 | 轻松标注智能合约函数,与队友共享 58 | 59 | 60 | 61 | 更方便,更智能的输入纠错,自动数据decimal转换 62 | 63 | ### 加入我们的中文社区 64 | 65 | 66 | ### Do you have the same frustrations as well: 67 | 68 | 1. It is very unfriendly to use tools like Remix and Etherscan.io to handle existing contracts or debug new contracts, and the code needs to be updated and verified frequently. 69 | 2. After a long time, you forget where you wrote the contract and need to search through communication records to find it. 70 | 3. It is also cumbersome to collaborate with team members or other front-end engineers remotely. 71 | 4. Additionally, making non-developers use smart contracts requires writing complex UI and deploying them to centralized servers. 72 | 73 | ### Main Features of DappReader: 74 | 75 | 1. Conveniently add and manage all EVM chain smart contracts in various ways. 76 | 2. Quickly search and manage published contracts. 77 | 3. Quickly generate smart contract operation interfaces without code. 78 | 4. Add comments to the entire smart contract or each individual function. 79 | 5. Quickly share developing smart contracts (with comments) with developers or non-developers, making it easy for contract engineers to collaborate with front-end engineers. 80 | 6. Provides completely free team-sharing function that is ideal for small teams. 81 | 7. Provides a series of type conversion tools to reduce the workload for developers. 82 | 83 | DappReader Development Progress: 84 | 85 | - [x] Completely redesigned UI for a more convenient and comfortable experience. 86 | - [x] Redesigned the display of returned data. 87 | - [x] Developed a dynamic sidebar to allow developers to focus more on the contract itself. 88 | - [x] Developed a complete team sharing feature. 89 | - [ ] Adding more AI functionality. 90 | - [ ] Functionality for executing multiple smart contract processes. 91 | - [ ] Trigger functionality for automatically executing contracts based on external changes. 92 | - [ ] Functionality for users to generate simple front-end pages without code and share them. 93 | - [ ] Integration with Remix to provide one-stop development, testing, and sharing features. 94 | - [ ] Deep integration of web2 and web3 to complete web3os. 95 | 96 | 97 | ## 快速安装 98 | 99 | 下载本项目到本地后 100 | 101 | ``` 102 | yarn install 103 | ``` 104 | 105 | ### 在本地运行 106 | ``` 107 | yarn run dev 108 | ``` 109 | 110 | ### 编译本项目 111 | ``` 112 | yarn run build 113 | ``` 114 | -------------------------------------------------------------------------------- /img/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/edit.png -------------------------------------------------------------------------------- /img/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/file.png -------------------------------------------------------------------------------- /img/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/group.png -------------------------------------------------------------------------------- /img/intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/intro.png -------------------------------------------------------------------------------- /img/invite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/invite.png -------------------------------------------------------------------------------- /img/transaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/img/transaction.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dappreader 8 | 9 | 10 |
11 | 12 | 13 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-project", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@codemirror/lang-javascript": "^6.1.8", 13 | "@codemirror/lang-rust": "^6.0.1", 14 | "@codemirror/theme-one-dark": "^6.1.2", 15 | "@imengyu/vue3-context-menu": "^1.2.5", 16 | "@replit/codemirror-lang-solidity": "^6.0.1", 17 | "@types/node": "^20.12.6", 18 | "@uiw/codemirror-theme-vscode": "^4.20.2", 19 | "@vitejs/plugin-vue-jsx": "^3.1.0", 20 | "axios": "^1.2.0", 21 | "codemirror": "^6.0.1", 22 | "core-js": "^3.6.5", 23 | "ethereum-blockies-base64": "^1.0.2", 24 | "ethers": "^5.7.2", 25 | "fundebug-javascript": "^2.8.8", 26 | "fundebug-revideo": "^0.8.0", 27 | "fundebug-vue": "^0.3.6", 28 | "localforage": "^1.10.0", 29 | "markdown-it": "^14.1.0", 30 | "naive-ui": "^2.38.1", 31 | "sass": "^1.74.1", 32 | "terser": "^5.30.3", 33 | "terser-webpack-plugin": "^5.3.6", 34 | "vite-plugin-md": "^0.21.5", 35 | "vue": "^3.4.21", 36 | "vue-boring-avatars": "^1.3.0", 37 | "vue-codemirror": "^6.1.1", 38 | "vue-router": "^4.0.0-0", 39 | "vue3-highlightjs": "^1.0.5", 40 | "vue3-jazzicon": "^0.1.4", 41 | "vue3-json-viewer": "^2.2.2", 42 | "vue3-smooth-dnd": "^0.0.2", 43 | "vuex": "^4.0.0-0" 44 | }, 45 | "devDependencies": { 46 | "@vitejs/plugin-vue": "^5.0.4", 47 | "vite": "^5.2.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/favicon.ico -------------------------------------------------------------------------------- /public/intro/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/1.png -------------------------------------------------------------------------------- /public/intro/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/2.png -------------------------------------------------------------------------------- /public/intro/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/3.png -------------------------------------------------------------------------------- /public/intro/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/4.png -------------------------------------------------------------------------------- /public/intro/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/5.png -------------------------------------------------------------------------------- /public/intro/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/6.png -------------------------------------------------------------------------------- /public/intro/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/7.png -------------------------------------------------------------------------------- /public/intro/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/8.png -------------------------------------------------------------------------------- /public/intro/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/public/intro/9.png -------------------------------------------------------------------------------- /public/intro/intro.md: -------------------------------------------------------------------------------- 1 | ![image](/intro/1.png) 2 | 3 | ### What is DappReader 4 | **DappReader is a product we are proud to offer, a free tool for developers in the EVM ecosystem.** 5 | 6 | DappReader is designed to provide developers with the management of published multi-chain contracts and fast front-end-contract debugging. This tool will help developers to develop, test and deploy contract projects more efficiently, and improve the quality and efficiency of project development. 7 | 8 | You can simply understand it as the Postman of web2 era ! 9 | 10 | ### Do you have the same problem: 11 | Using tools such as Remix and Etherscan.io to handle existing contracts or debug new contracts is very unfriendly and requires frequent code updates and validation. 12 | 13 | Writing contracts and forgetting where they are after a long time, and having to dig through interaction logs to find them. 14 | 15 | Remote collaboration with team members or other Front-End Engineers is also cumbersome. 16 | 17 | In addition, making smart contracts available to non-developers requires writing complex UI and deploying it to a centralized server. It's not cool! 18 | 19 | ### Key features of DappReader: 20 | Multiple ways to easily add and manage all EVM chain smart contracts. 21 | 22 | Quickly retrieve and manage published contracts 23 | 24 | 25 | Quickly generate smart contract UI without code 26 | 27 | ![image](/intro/2.png) 28 | 29 | 30 | Annotate the whole smart contract and each function individually. 31 | 32 | 33 | 34 | ![image](/intro/3.png) 35 | 36 | 37 | Quickly share smart contracts under development (including annotations) with developers or non-developers, so that contract engineers can easily coordinate with front-end engineers. 38 | 39 | ![image](/intro/4.png) 40 | 41 | Provide completely free team sharing function, ideal for small teams to use 42 | 43 | Provide a series of type conversion tools to reduce the workload of developers. 44 | 45 | ![image](/intro/5.png) 46 | 47 | ### What's new 48 | 49 | Now add a more powerful AI smart contract auto-auditing tools 50 | 51 | ![image](/intro/6.png) 52 | ![image](/intro/7.png) 53 | 54 | 55 | Now you are free to insert DappReader directly into Mirror.xyz, and call smart contracts directly in your smart contract tutorials! 56 | 57 | ![image](/intro/8.png) 58 | 59 | 60 | ![image](/intro/9.png) -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 12 | 109 | 115 | -------------------------------------------------------------------------------- /src/assets/css/main.scss: -------------------------------------------------------------------------------- 1 | // variables 2 | $bgColor: #101013; 3 | $textColor: #989697; 4 | $borderBottom: 1px solid #252429; 5 | $mainColor: #1C42FF; 6 | 7 | // mixin 8 | @mixin main-content { 9 | width: 1280px; 10 | margin: auto; 11 | } 12 | 13 | @mixin flex-center-sb { 14 | display: flex; 15 | align-items: center; 16 | justify-content: space-between; 17 | } 18 | 19 | @mixin flex-center { 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | @mixin flex-start { 25 | display: flex; 26 | align-items: flex-start; 27 | } 28 | 29 | @mixin flex-end { 30 | display: flex; 31 | align-items: flex-end; 32 | } 33 | 34 | @mixin flex-center-center { 35 | display: flex; 36 | align-items: center; 37 | justify-content: center; 38 | } 39 | 40 | @mixin absolute-0 { 41 | position: absolute; 42 | left: 0; 43 | top: 0; 44 | bottom: 0; 45 | right: 0; 46 | } 47 | 48 | // class 49 | .main-content { 50 | @include main-content; 51 | } 52 | 53 | .flex-center-center { 54 | @include flex-center-center; 55 | } 56 | 57 | .flex-center { 58 | @include flex-center; 59 | } 60 | 61 | .flex-center-sb { 62 | @include flex-center-sb; 63 | } 64 | 65 | .flex-start { 66 | @include flex-start; 67 | } 68 | 69 | .flex-start-center { 70 | @include flex-start; 71 | justify-content: center 72 | } 73 | 74 | .flex-end { 75 | @include flex-end; 76 | } 77 | 78 | .flex-end-center { 79 | @include flex-end; 80 | justify-content: center 81 | } 82 | 83 | .flex-end-sb { 84 | @include flex-end; 85 | justify-content: space-between 86 | } 87 | 88 | .shade { 89 | @include absolute-0; 90 | background: rgba($color: $bgColor, $alpha: .9); 91 | z-index: 1; 92 | } 93 | 94 | .flex-column { 95 | flex-direction: column; 96 | } 97 | 98 | .btn { 99 | &:hover { 100 | background: #375CFF !important; 101 | } 102 | } 103 | 104 | .n-modal-mask { 105 | backdrop-filter: blur(5px) !important; 106 | } 107 | .n-dialog.n-modal { 108 | width: 500px; 109 | } 110 | 111 | 112 | 113 | 114 | .form-input { 115 | margin-top: 2px; 116 | height: 40px; 117 | background: #17171A; 118 | border: 1px solid rgba(133, 141, 153, 0.1); 119 | border-radius: 10px; 120 | --n-border-hover: none !important; 121 | --n-border-active: 1px solid #375CFF !important; 122 | --n-border-focus: 1px solid #375CFF !important; 123 | --n-box-shadow-active: none !important; 124 | --n-box-shadow-focus: none !important; 125 | --n-color-focus: none !important; 126 | --n-height: 38px !important; 127 | transition: all .01s !important; 128 | &.popover-input-item { 129 | border-radius: 6px; 130 | } 131 | } 132 | 133 | .form-textarea { 134 | height: auto !important; 135 | } 136 | 137 | .form-select { 138 | .n-base-selection { 139 | background: #17171A; 140 | border: 1px solid rgba(133, 141, 153, 0.1); 141 | border-radius: 10px; 142 | margin-top: 2px; 143 | height: 40px; 144 | --n-border-hover: none !important; 145 | --n-border-active: 1px solid #375CFF !important; 146 | --n-border-focus: 1px solid #375CFF !important; 147 | --n-box-shadow-active: none !important; 148 | --n-box-shadow-focus: none !important; 149 | --n-color-focus: none !important; 150 | --n-height: 40px !important; 151 | --n-color: #17171A !important; 152 | } 153 | } 154 | 155 | .input-group-select { 156 | .n-base-selection { 157 | --n-border-hover: none !important; 158 | --n-border-active: none !important; 159 | --n-border-focus: none !important; 160 | --n-box-shadow-active: none !important; 161 | --n-box-shadow-focus: none !important; 162 | --n-color-focus: none !important; 163 | --n-color: #0A0A0C !important; 164 | } 165 | } 166 | 167 | .n-base-selection { 168 | --n-border-hover: none !important; 169 | --n-border-active: 1px solid #375CFF !important; 170 | --n-border-focus: none !important; 171 | --n-box-shadow-active: none !important; 172 | --n-box-shadow-focus: none !important; 173 | --n-color-focus: none !important; 174 | --n-color: #0A0A0C !important; 175 | } 176 | 177 | .n-card__content { 178 | padding: 20px !important; 179 | padding-top: 0 !important; 180 | } 181 | 182 | .n-form-item-feedback-wrapper { 183 | min-height: 16px !important; 184 | } 185 | 186 | .form { 187 | box-sizing: border-box; 188 | } 189 | 190 | .form-btns { 191 | margin-top: 8px; 192 | .btn-item { 193 | flex: 1; 194 | height: 50px; 195 | border-radius: 10px; 196 | font-weight: 400; 197 | font-size: 16px; 198 | line-height: 22px; 199 | text-transform: capitalize; 200 | background: rgba(133, 141, 153, 0.2); 201 | color: #858D99; 202 | cursor: not-allowed; 203 | &.btn-item-activated { 204 | background: #375CFF; 205 | color: #FFFFFF; 206 | cursor: pointer; 207 | } 208 | } 209 | } 210 | 211 | .custom-card { 212 | --n-padding-top: 20px !important; 213 | --n-padding-bottom: 20px !important; 214 | --n-padding-left: 20px !important; 215 | --n-padding-right: 20px !important; 216 | .n-card-header { 217 | padding: 20px !important; 218 | } 219 | .n-card__content { 220 | padding: 0 !important; 221 | padding-bottom: 20px !important; 222 | } 223 | } 224 | 225 | .right-menu-popconfirm { 226 | .n-button { 227 | --n-text-color-hover: #fff !important; 228 | --n-text-color: #fff !important; 229 | --n-text-color-pressed: #fff !important; 230 | --n-text-color-focus: #fff !important; 231 | --n-text-color-disabled: #fff !important; 232 | --n-color-hover: #4B6CFF !important; 233 | --n-color-pressed: #375CFF !important; 234 | --n-color-focus: #375CFF !important; 235 | --n-border-hover: 1px solid #375CFF !important; 236 | --n-border-pressed: 1px solid #375CFF !important; 237 | --n-border-focus: 1px solid #375CFF !important; 238 | } 239 | } 240 | 241 | // .n-tabs-wrapper { 242 | // background: #0A0A0C !important; 243 | // border-radius: 10px; 244 | // } 245 | 246 | .v-x-scroll { 247 | width: 50%; 248 | border-radius: 0px 10px 0px 0px; 249 | } 250 | 251 | .jv-container.jv-dark { 252 | background: rgba(133, 141, 153, 0) !important; 253 | } 254 | 255 | .jv-container .jv-code { 256 | padding: 15px !important; 257 | } 258 | 259 | .jv-container .jv-more:after { 260 | background: linear-gradient(to bottom, rgba(13, 13, 14, .3),rgba(13, 13, 14, 1)); 261 | } 262 | 263 | .jv-container .jv-more:hover:after { 264 | background: linear-gradient(to bottom, rgba(21, 20, 27, .3),rgba(21, 20, 27, 1)); 265 | } 266 | 267 | .n-base-select-menu.n-select-menu { 268 | background: #15141B !important; 269 | border: 1px solid rgba(133, 141, 153, 0.15) !important; 270 | box-shadow: 0px 12px 30px rgba(10, 10, 12, 0.3) !important; 271 | backdrop-filter: blur(10px) !important; 272 | border-radius: 10px !important; 273 | } 274 | 275 | .n-base-select-menu .n-base-select-option.n-base-select-option--pending::before { 276 | background: rgba(55, 92, 255, 0.15) !important; 277 | border-radius: 6px !important; 278 | } 279 | 280 | .n-base-select-menu .n-base-select-option.n-base-select-option--selected { 281 | color: #375CFF !important; 282 | } 283 | 284 | .n-tabs .n-tabs-nav.n-tabs-nav--card-type .n-tabs-tab.n-tabs-tab--active { 285 | color: #ffffff !important; 286 | } 287 | 288 | .jv-container.boxed { 289 | border: 1px solid rgba(133, 141, 153, 0.2) !important; 290 | background: #0A0A0C !important; 291 | border-radius: 9px !important; 292 | } 293 | 294 | .result-params .jv-container.boxed { 295 | border: none !important; 296 | } 297 | 298 | .jv-more { 299 | display: none !important; 300 | } 301 | 302 | .hljs { 303 | padding: 15px !important; 304 | box-sizing: border-box; 305 | } 306 | 307 | .n-button { 308 | --n-border: none !important; 309 | --n-border-hover: none !important; 310 | --n-border-pressed: none !important; 311 | --n-border-focus: none !important; 312 | } 313 | 314 | .n-spin-content { 315 | border: none !important; 316 | } 317 | 318 | .modal-style { 319 | background: #23242A !important; 320 | border-radius: 10px; 321 | width: 564px; 322 | border: 1px solid rgba(133, 141, 153, 0.1); 323 | } 324 | 325 | .n-base-select-menu .n-base-select-menu__action { 326 | padding: 5px !important; 327 | border: none !important; 328 | } 329 | 330 | .n-date-panel .n-date-panel-dates .n-date-panel-date.n-date-panel-date--selected { 331 | color: #FFFFFF !important; 332 | } 333 | 334 | .n-date-panel .n-date-panel-actions .n-button .n-button__content { 335 | color: #FFFFFF !important; 336 | } 337 | 338 | .n-date-panel .n-date-panel-actions .n-button:not(.n-button--disabled):hover { 339 | background-color: #4B6CFF !important; 340 | } 341 | 342 | .search-modal { 343 | position: relative; 344 | .n-card-header { 345 | position: relative; 346 | z-index: 2; 347 | } 348 | .form { 349 | box-sizing: border-box; 350 | position: relative; 351 | z-index: 1; 352 | &::after { 353 | content: ''; 354 | position: absolute; 355 | z-index: -1; 356 | top: -69px; 357 | left: 0; 358 | width: 100%; 359 | height: 119px; 360 | background: #2D2E35; 361 | display: block; 362 | border-radius: 10px 10px 0 0; 363 | } 364 | } 365 | } 366 | 367 | .modal-content { 368 | padding-left: 20px; 369 | padding-right: 20px; 370 | box-sizing: border-box; 371 | } -------------------------------------------------------------------------------- /src/assets/css/reset.scss: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v5.0.1 | 20191019 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, menu, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | main, menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | vertical-align: baseline; 24 | } 25 | 26 | a { 27 | text-decoration: none; 28 | color: inherit; 29 | } 30 | 31 | /* HTML5 display-role reset for older browsers */ 32 | article, aside, details, figcaption, figure, 33 | footer, header, hgroup, main, menu, nav, section { 34 | display: block; 35 | } 36 | /* HTML5 hidden-attribute fix for newer browsers */ 37 | *[hidden] { 38 | display: none; 39 | } 40 | body { 41 | line-height: 1; 42 | // overflow-x: auto !important; 43 | } 44 | menu, ol, ul { 45 | list-style: none; 46 | } 47 | blockquote, q { 48 | quotes: none; 49 | } 50 | blockquote:before, blockquote:after, 51 | q:before, q:after { 52 | content: ''; 53 | content: none; 54 | } 55 | table { 56 | border-collapse: collapse; 57 | border-spacing: 0; 58 | } 59 | 60 | @font-face { 61 | font-family: 'Montserrat'; 62 | src: url(../fonts/Montserrat-Regular.otf); 63 | } 64 | 65 | @font-face { 66 | font-family: 'Montserrat-Bold'; 67 | src: url(../fonts/Montserrat-Bold.otf); 68 | } 69 | 70 | @font-face { 71 | font-family: 'Montserrat-Medium'; 72 | src: url(../fonts/Montserrat-Medium.otf); 73 | } 74 | 75 | * { 76 | font-family: 'Montserrat'; 77 | } -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Black.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Bold.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-ExtraBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-ExtraBold.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-ExtraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-ExtraLight.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Light.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Medium.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Regular.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-SemiBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-SemiBold.otf -------------------------------------------------------------------------------- /src/assets/fonts/Montserrat-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/fonts/Montserrat-Thin.otf -------------------------------------------------------------------------------- /src/assets/images/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/add_file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/add_folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/images/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/arrow_reload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/avatar/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/0.png -------------------------------------------------------------------------------- /src/assets/images/avatar/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/1.png -------------------------------------------------------------------------------- /src/assets/images/avatar/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/2.png -------------------------------------------------------------------------------- /src/assets/images/avatar/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/3.png -------------------------------------------------------------------------------- /src/assets/images/avatar/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/4.png -------------------------------------------------------------------------------- /src/assets/images/avatar/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/5.png -------------------------------------------------------------------------------- /src/assets/images/avatar/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/6.png -------------------------------------------------------------------------------- /src/assets/images/avatar/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/7.png -------------------------------------------------------------------------------- /src/assets/images/avatar/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/8.png -------------------------------------------------------------------------------- /src/assets/images/avatar/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/avatar/9.png -------------------------------------------------------------------------------- /src/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/images/conversion.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/decode.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/del.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/discord.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/flower.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/images/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/folder_open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/gas.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/gas.gif -------------------------------------------------------------------------------- /src/assets/images/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/group.png -------------------------------------------------------------------------------- /src/assets/images/groupQRCode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/groupQRCode.jpg -------------------------------------------------------------------------------- /src/assets/images/groupQRCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/groupQRCode.png -------------------------------------------------------------------------------- /src/assets/images/hint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/hint.png -------------------------------------------------------------------------------- /src/assets/images/json.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/left.png -------------------------------------------------------------------------------- /src/assets/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/images/nft_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/images/note_edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/read.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/images/regist_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/images/regist_bg.png -------------------------------------------------------------------------------- /src/assets/images/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/images/show.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/assets/images/success.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/time.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/time_icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/top.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/update.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/assets/images/write.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/AddChainModal.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 83 | 84 | 162 | -------------------------------------------------------------------------------- /src/components/AddFolder.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 92 | 93 | 102 | -------------------------------------------------------------------------------- /src/components/AddTeamModal.vue: -------------------------------------------------------------------------------- 1 | 45 | 124 | -------------------------------------------------------------------------------- /src/components/Avatar.vue: -------------------------------------------------------------------------------- 1 | 20 | 43 | -------------------------------------------------------------------------------- /src/components/ContractInfo.vue: -------------------------------------------------------------------------------- 1 | 24 | 67 | -------------------------------------------------------------------------------- /src/components/ConversionModal.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 74 | 75 | 84 | -------------------------------------------------------------------------------- /src/components/DecodeModal.vue: -------------------------------------------------------------------------------- 1 | 42 | 99 | 100 | 183 | 184 | -------------------------------------------------------------------------------- /src/components/EditModal.vue: -------------------------------------------------------------------------------- 1 | 69 | 144 | 145 | -------------------------------------------------------------------------------- /src/components/GetContractModal.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 50 | 51 | 87 | 88 | -------------------------------------------------------------------------------- /src/components/Item.vue: -------------------------------------------------------------------------------- 1 | 23 | 38 | -------------------------------------------------------------------------------- /src/components/LoginModal.vue: -------------------------------------------------------------------------------- 1 | 21 | 76 | 77 | -------------------------------------------------------------------------------- /src/components/Main.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 30 | 31 | 193 | -------------------------------------------------------------------------------- /src/components/NetworkErrorModal.vue: -------------------------------------------------------------------------------- 1 | 20 | 38 | -------------------------------------------------------------------------------- /src/components/ParameItem.vue: -------------------------------------------------------------------------------- 1 | 41 | 139 | 214 | -------------------------------------------------------------------------------- /src/components/RegistModal.vue: -------------------------------------------------------------------------------- 1 | 69 | 137 | 138 | -------------------------------------------------------------------------------- /src/components/SelectNftModal.vue: -------------------------------------------------------------------------------- 1 | 22 | 47 | 48 | -------------------------------------------------------------------------------- /src/components/SelectSearch.vue: -------------------------------------------------------------------------------- 1 | 30 | 74 | -------------------------------------------------------------------------------- /src/components/SourceCodeModal.vue: -------------------------------------------------------------------------------- 1 | 40 | 137 | 138 | 238 | 244 | -------------------------------------------------------------------------------- /src/components/TeamModal.vue: -------------------------------------------------------------------------------- 1 | 27 | 127 | -------------------------------------------------------------------------------- /src/hooks/useContract.js: -------------------------------------------------------------------------------- 1 | import { toRaw, computed } from "vue"; 2 | import { connectContract } from "../libs/connectWallet"; 3 | import { useStore } from 'vuex' 4 | // import { ethers } from 'ethers' 5 | export const useContract = (contractData) => { 6 | let C = null 7 | const store = useStore() 8 | const address = computed(() => { 9 | return store.state.address 10 | }) 11 | 12 | const network = computed(() => { 13 | return store.state.network 14 | }) 15 | 16 | const setContract = async(provider) => { 17 | if (contractChainId.value != network.value.chainId) return 18 | let user = toRaw(provider).getSigner() 19 | C = await connectContract(contractData.contractAddress, contractData.abi, user) 20 | console.log(C) 21 | } 22 | return { 23 | setContract, 24 | address 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/hooks/useIsActivating.js: -------------------------------------------------------------------------------- 1 | 2 | import { useStore } from 'vuex' 3 | import { connectWallet } from '../libs/connectWallet' 4 | import {chains} from '../libs/chains' 5 | import { toRaw } from 'vue' 6 | import { ethers } from 'ethers' 7 | export const useIsActivating = () => { 8 | const store = useStore() 9 | let provider = null 10 | const getProvider = async(init) => { 11 | try { 12 | provider = await connectWallet(init) 13 | store.commit('setProvider', toRaw(provider)) 14 | getWallet() 15 | getNetwork() 16 | } catch (error) { 17 | console.error(error) 18 | } 19 | } 20 | 21 | const getNetwork = async() => { 22 | if (!provider) return 23 | let network = await provider.getNetwork() 24 | let networkData = chains.filter(e => network.chainId == e.chainId)[0] 25 | network.name = networkData.name 26 | store.commit('setNetwork', toRaw(network)) 27 | } 28 | 29 | const getWallet = async() => { 30 | if (!provider) return 31 | let accounts = await provider.listAccounts() 32 | if (accounts.length) { 33 | let address = accounts[0] 34 | store.commit('setAddress', address) 35 | try { 36 | provider.getBalance(address).then(res => { 37 | let balance = res 38 | let balanceInEth = ethers.utils.formatEther(balance) 39 | store.commit('setBalance', toRaw(balanceInEth)) 40 | }) 41 | } catch (error) { 42 | console.error(error) 43 | } 44 | } 45 | } 46 | 47 | return { 48 | getProvider, 49 | getWallet, 50 | getNetwork 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/hooks/useNetwork.js: -------------------------------------------------------------------------------- 1 | import { walletSwitchChain } from "../libs/walletSwitchChain"; 2 | import { useIsActivating } from '../hooks/useIsActivating' 3 | 4 | export const useNetwork = () => { 5 | const { getProvider } = useIsActivating() 6 | const switchChain = (chainId) => { 7 | walletSwitchChain(chainId).then(res => { 8 | console.log(res) 9 | }).catch(err => { 10 | console.error(err) 11 | getProvider() 12 | }) 13 | } 14 | return { 15 | switchChain 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/hooks/useUtils.js: -------------------------------------------------------------------------------- 1 | import { useMessage } from 'naive-ui' 2 | import { getLs, setLs } from "../service/service" 3 | import { useStore } from 'vuex' 4 | import { chains } from '../libs/chains' 5 | 6 | export const useUtils = () => { 7 | const store = useStore() 8 | const message = useMessage() 9 | const copy = (value, type) => { 10 | if (type == 'abi') { 11 | value = JSON.parse(JSON.stringify(value)) 12 | value = value.map(e => { 13 | delete e.otherName 14 | delete e.tempName 15 | return e 16 | }) 17 | value = JSON.stringify(value) 18 | } else if (type == 'iframe') { 19 | value = JSON.parse(JSON.stringify(value)) 20 | } else { 21 | value = JSON.stringify(value) 22 | let reg = /^["|'](.*)["|']$/g 23 | value = value.replace(reg,"$1") 24 | } 25 | if (!navigator.clipboard || window.top != window.self) { 26 | let textarea = document.createElement('textarea') 27 | document.body.appendChild(textarea) 28 | textarea.style.position = 'fixed' 29 | textarea.style.clip = 'rect(0 0 0 0)' 30 | textarea.style.top = '10px' 31 | textarea.value = value 32 | textarea.select() 33 | document.execCommand('copy', true) 34 | document.body.removeChild(textarea) 35 | message.success('Copy successful') 36 | } else { 37 | navigator.clipboard.writeText(value) 38 | message.success('Copy successful') 39 | } 40 | 41 | } 42 | 43 | const toEtherscanAddress = (address, chain, type) => { 44 | let network = chains.filter(e => e.chainId == chain.chainId)[0] 45 | let host = network.explorers[0]?.url 46 | if (host) { 47 | let url = `${host}/address/${address}` 48 | if (type == 'tx') { 49 | url = `${host}/tx/${address}` 50 | } 51 | window.open(url) 52 | } 53 | } 54 | 55 | const hasContrace = (data, menuList, contractList) => { 56 | let {address, chain} = data 57 | address = address.toString() 58 | let contrace = null 59 | for (let i = 0; i < menuList.length; i++) { 60 | let son = menuList[i].son 61 | son.forEach((e) => { 62 | console.log(e.address) 63 | if (e.address == address && e.chain.chainId == chain.chainId) { 64 | contrace = e 65 | } 66 | }) 67 | } 68 | console.log(address) 69 | contractList.forEach((e) => { 70 | if (e.address == address && e.chain.chainId == chain.chainId) { 71 | contrace = e 72 | } 73 | }) 74 | return contrace 75 | } 76 | 77 | const open = (data) => { 78 | setLs('activeId', data.id).then(rep => { 79 | store.commit('setActiveId', rep) 80 | }) 81 | } 82 | 83 | const setData = async (info, folderIndex) => { 84 | let {id} = info 85 | let menuList = await getLs('menuList') || [] 86 | let contractList = await getLs('contractList') || [] 87 | if (id) { 88 | for (let i = 0; i < menuList.length; i++) { 89 | let son = menuList[i].son 90 | son.forEach((e, index) => { 91 | if (e.id == id) { 92 | son[index] = info 93 | } 94 | }) 95 | menuList[i].son = son 96 | } 97 | contractList.forEach((e, index) => { 98 | if (e.id == id) { 99 | contractList[index] = info 100 | } 101 | }) 102 | setLs('contractList', JSON.parse(JSON.stringify(contractList))).then(res => { 103 | console.log(res) 104 | store.commit("setContractList", res) 105 | }) 106 | setLs('menuList', JSON.parse(JSON.stringify(menuList))).then(res => { 107 | console.log(res) 108 | store.commit("setMenuList", res) 109 | }) 110 | } else { 111 | let data = info 112 | let has = await hasContrace(data, menuList, contractList) 113 | if (has) { 114 | // message.info('Contract already exists') 115 | await open(has) 116 | return 117 | } 118 | data.id = crypto.randomUUID() 119 | data.createAt = new Date().getTime() 120 | if (folderIndex && folderIndex >= 0) { 121 | let folderItem = menuList[folderIndex] 122 | let son = folderItem.son || [] 123 | son.push(data) 124 | menuList[folderIndex].son = son 125 | let res = await setLs('menuList', JSON.parse(JSON.stringify(menuList))) 126 | store.commit("setMenuList", res) 127 | } else { 128 | contractList.push(data) 129 | let res = await setLs('contractList', JSON.parse(JSON.stringify(contractList))) 130 | store.commit("setContractList", res) 131 | } 132 | await open(data) 133 | } 134 | } 135 | 136 | return { 137 | toEtherscanAddress, 138 | copy, 139 | setData 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/http/abi.js: -------------------------------------------------------------------------------- 1 | import { post, get } from './axios' 2 | 3 | export const publishContract = (data = {}) => post('/v1/publish_contract', data) 4 | export const updateContract = (data = {}) => post('/v1/update_contract', data) 5 | export const getContract = (data = {}) => get('/v1/get_contract', data) 6 | export const checkContractInfo = (data = {}) => get('/v1/check_contract_info', data) 7 | export const checkUserRegist = (data = {}) => get('/v1/check_user_regist', data) 8 | export const getUserInfo = (data = {}) => get('/v1/get_user_info', data) 9 | export const getTeamFriendList = (data = {}) => get('/v1/get_team_friend_list', data) 10 | export const login = (data = {}) => post('/v1/login', data) 11 | export const regist = (data = {}) => post('/v1/regist', data) 12 | export const updateUserInfo = (data = {}) => post('/v1/update_user_info', data) 13 | export const updateTeamInfo = (data = {}) => post('/v1/update_team_info', data) 14 | export const getNftList = (data = {}) => get('/get_nft_list', data, 'https://worker.dappreader.com') 15 | export const getChains = (data = {}) => get('/chains.json', data, 'https://chainid.network') 16 | export const getReport = (data = {}) => post('/v1/get_report', data) 17 | -------------------------------------------------------------------------------- /src/http/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import store from '../store' 3 | let baseURL = 'https://api.dappreader.com' 4 | axios.defaults.timeout = 100000; 5 | 6 | 7 | //http request 拦截器 8 | axios.interceptors.request.use( 9 | config => { 10 | let token = localStorage.getItem('token') || ''; 11 | config.headers = { 12 | 'content-type': 'application/json;charset=UTF-8' 13 | } 14 | if (token && (config.method == 'post' || config.url.indexOf('/v1/get_contract') > -1 || config.url.indexOf('/v1/get_team_friend_list') > -1)) { 15 | config.headers['Authorization'] = `Bearer ${token}` 16 | } 17 | return config; 18 | }, 19 | error => { 20 | return Promise.reject(error); 21 | } 22 | ) 23 | 24 | //响应拦截器即异常处理 25 | axios.interceptors.response.use(response => { 26 | return response 27 | }, err => { 28 | console.log('err', err) 29 | if (err && err.response) { 30 | switch (err.response.status) { 31 | case 400: 32 | console.log('错误请求') 33 | break; 34 | case 401: 35 | var userInfo = localStorage.getItem('userInfo') || null 36 | if (userInfo) { 37 | window.$message.error('Please login again') 38 | } else { 39 | window.$message.error('Please login') 40 | } 41 | store.commit('login') 42 | break; 43 | case 403: 44 | console.log('拒绝访问') 45 | break; 46 | case 404: 47 | console.log('请求错误,未找到该资源') 48 | break; 49 | case 405: 50 | console.log('请求方法未允许') 51 | break; 52 | case 408: 53 | console.log('请求超时') 54 | break; 55 | case 422: 56 | console.log('请求超时') 57 | break; 58 | case 500: 59 | console.log('服务器端出错') 60 | break; 61 | case 501: 62 | console.log('网络未实现') 63 | break; 64 | case 502: 65 | console.log('网络错误') 66 | break; 67 | case 503: 68 | console.log('服务不可用') 69 | break; 70 | case 504: 71 | console.log('网络超时') 72 | break; 73 | case 505: 74 | console.log('http版本不支持该请求') 75 | break; 76 | default: 77 | console.log(`连接错误${err.response.status}`) 78 | } 79 | } else { 80 | console.log('连接到服务器失败') 81 | } 82 | console.log(err.response.status) 83 | // store.commit('login') 84 | return Promise.reject(err.response) 85 | }) 86 | 87 | 88 | /** 89 | * 封装post请求 90 | * @param url 91 | * @param data 92 | * @returns {Promise} 93 | */ 94 | 95 | export const post = (url, data = {}, host) => { 96 | url = host ? `${host}${url}` : `${baseURL}${url}` 97 | return new Promise((resolve,reject) => { 98 | axios.post(url, data).then(response => { 99 | resolve(response.data) 100 | }, err => { 101 | reject(err) 102 | }) 103 | }) 104 | } 105 | 106 | 107 | export const get = (url, params = {}, host) => { 108 | url = host ? `${host}${url}` : `${baseURL}${url}` 109 | return new Promise((resolve,reject) => { 110 | axios.get(url, {params}).then(response => { 111 | resolve(response.data) 112 | }).catch(err => { 113 | reject(err) 114 | }) 115 | }) 116 | } -------------------------------------------------------------------------------- /src/libs/chainsOptions.js: -------------------------------------------------------------------------------- 1 | export const chainsOptions = [ 2 | { 3 | "endpointURL": "https://api.etherscan.io", 4 | "chainId": 1, 5 | }, { 6 | "endpointURL": "https://api-goerli.etherscan.io", 7 | "chainId": 5, 8 | }, { 9 | "endpointURL": "https://api-kovan.etherscan.io", 10 | "chainId": 42, 11 | }, { 12 | "endpointURL": "https://api-ropsten.etherscan.io", 13 | "chainId": 3, 14 | }, { 15 | "endpointURL": "https://api-sepolia.etherscan.io", 16 | "chainId": 11155111, 17 | }, 18 | ] -------------------------------------------------------------------------------- /src/libs/connectWallet.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { ethers } from 'ethers' 3 | export const connectWallet = (init) => { 4 | let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) 5 | return new Promise(async (resolve, reject) => { 6 | if (window.ethereum) { 7 | let web3Provider = window.ethereum; 8 | try { 9 | let accounts = await web3Provider.request({ method: 'eth_accounts' }) 10 | if (!init || (accounts && accounts.length)) { 11 | await window.ethereum.request({ method: 'eth_requestAccounts' }) 12 | let web3 = new ethers.providers.Web3Provider(web3Provider, "any"); 13 | resolve(web3); 14 | } 15 | // await window.ethereum.enable(); 16 | } catch (error) { 17 | console.log('连接失败', error) 18 | reject(error); 19 | } 20 | } else if (window.web3) { 21 | let web3Provider = window.web3.currentProvider; 22 | let web3 = new ethers.providers.Web3Provider(web3Provider); 23 | resolve(web3); 24 | } else { 25 | // 处理用户没有metamask的逻辑 26 | alert('Please install MetaMask!') 27 | window.open('https://metamask.io/') 28 | reject('') 29 | } 30 | }) 31 | } 32 | 33 | export const connectContract = (contractAddress, abi, provider) => { 34 | return new ethers.Contract(contractAddress, abi, provider) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/libs/defaultChain.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DappReader/DappReader-v2/af89256d707e87b87ee6394c17b2bda8cd5b4d35/src/libs/defaultChain.js -------------------------------------------------------------------------------- /src/libs/demo.js: -------------------------------------------------------------------------------- 1 | export const demo = { 2 | address: "0x89de39F47236522D6552131b81aD14bABDBCBf67", 3 | remark: "这是一个测试合约,由DappReader团队提供", 4 | name: "测试通用合约", 5 | chainId: 5, 6 | abi: [ 7 | { 8 | "inputs": [], 9 | "stateMutability": "nonpayable", 10 | "type": "constructor" 11 | }, 12 | { 13 | "anonymous": false, 14 | "inputs": [ 15 | { 16 | "indexed": true, 17 | "internalType": "address", 18 | "name": "owner", 19 | "type": "address" 20 | }, 21 | { 22 | "indexed": true, 23 | "internalType": "address", 24 | "name": "spender", 25 | "type": "address" 26 | }, 27 | { 28 | "indexed": false, 29 | "internalType": "uint256", 30 | "name": "value", 31 | "type": "uint256" 32 | } 33 | ], 34 | "name": "Approval", 35 | "type": "event" 36 | }, 37 | { 38 | "anonymous": false, 39 | "inputs": [ 40 | { 41 | "indexed": true, 42 | "internalType": "address", 43 | "name": "from", 44 | "type": "address" 45 | }, 46 | { 47 | "indexed": true, 48 | "internalType": "address", 49 | "name": "to", 50 | "type": "address" 51 | }, 52 | { 53 | "indexed": false, 54 | "internalType": "uint256", 55 | "name": "value", 56 | "type": "uint256" 57 | } 58 | ], 59 | "name": "Transfer", 60 | "type": "event" 61 | }, 62 | { 63 | "inputs": [], 64 | "name": "ReadInfo", 65 | "otherName": "读取合约留言", 66 | "outputs": [ 67 | { 68 | "internalType": "string", 69 | "name": "", 70 | "type": "string" 71 | } 72 | ], 73 | "stateMutability": "view", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [ 78 | { 79 | "internalType": "string", 80 | "name": "info", 81 | "type": "string" 82 | } 83 | ], 84 | "name": "WriteInfo", 85 | "otherName": "在合约内留言", 86 | "outputs": [], 87 | "stateMutability": "nonpayable", 88 | "type": "function" 89 | }, 90 | { 91 | "inputs": [ 92 | { 93 | "internalType": "address", 94 | "name": "owner", 95 | "type": "address" 96 | }, 97 | { 98 | "internalType": "address", 99 | "name": "spender", 100 | "type": "address" 101 | } 102 | ], 103 | "name": "allowance", 104 | "outputs": [ 105 | { 106 | "internalType": "uint256", 107 | "name": "", 108 | "type": "uint256" 109 | } 110 | ], 111 | "stateMutability": "view", 112 | "type": "function" 113 | }, 114 | { 115 | "inputs": [ 116 | { 117 | "internalType": "address", 118 | "name": "spender", 119 | "type": "address" 120 | }, 121 | { 122 | "internalType": "uint256", 123 | "name": "amount", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "approve", 128 | "outputs": [ 129 | { 130 | "internalType": "bool", 131 | "name": "", 132 | "type": "bool" 133 | } 134 | ], 135 | "stateMutability": "nonpayable", 136 | "type": "function" 137 | }, 138 | { 139 | "inputs": [ 140 | { 141 | "internalType": "address", 142 | "name": "account", 143 | "type": "address" 144 | } 145 | ], 146 | "name": "balanceOf", 147 | "otherName": "获取输入钱包内ORTT数量", 148 | "outputs": [ 149 | { 150 | "internalType": "uint256", 151 | "name": "", 152 | "type": "uint256" 153 | } 154 | ], 155 | "stateMutability": "view", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [], 160 | "name": "claimTestToken", 161 | "otherName": "claim合约测试代币DRTT", 162 | "outputs": [], 163 | "stateMutability": "nonpayable", 164 | "type": "function" 165 | }, 166 | { 167 | "inputs": [], 168 | "name": "decimals", 169 | "otherName": "合约自带代币精度", 170 | "outputs": [ 171 | { 172 | "internalType": "uint8", 173 | "name": "", 174 | "type": "uint8" 175 | } 176 | ], 177 | "stateMutability": "view", 178 | "type": "function" 179 | }, 180 | { 181 | "inputs": [ 182 | { 183 | "internalType": "address", 184 | "name": "spender", 185 | "type": "address" 186 | }, 187 | { 188 | "internalType": "uint256", 189 | "name": "subtractedValue", 190 | "type": "uint256" 191 | } 192 | ], 193 | "name": "decreaseAllowance", 194 | "outputs": [ 195 | { 196 | "internalType": "bool", 197 | "name": "", 198 | "type": "bool" 199 | } 200 | ], 201 | "stateMutability": "nonpayable", 202 | "type": "function" 203 | }, 204 | { 205 | "inputs": [], 206 | "name": "donate", 207 | "otherName": "向合约打赏ETH", 208 | "outputs": [], 209 | "stateMutability": "payable", 210 | "type": "function" 211 | }, 212 | { 213 | "inputs": [], 214 | "name": "getBalance", 215 | "otherName": "合约当前被打赏总数", 216 | "outputs": [ 217 | { 218 | "internalType": "uint256", 219 | "name": "", 220 | "type": "uint256" 221 | } 222 | ], 223 | "stateMutability": "view", 224 | "type": "function" 225 | }, 226 | { 227 | "inputs": [ 228 | { 229 | "internalType": "address", 230 | "name": "spender", 231 | "type": "address" 232 | }, 233 | { 234 | "internalType": "uint256", 235 | "name": "addedValue", 236 | "type": "uint256" 237 | } 238 | ], 239 | "name": "increaseAllowance", 240 | "outputs": [ 241 | { 242 | "internalType": "bool", 243 | "name": "", 244 | "type": "bool" 245 | } 246 | ], 247 | "stateMutability": "nonpayable", 248 | "type": "function" 249 | }, 250 | { 251 | "inputs": [], 252 | "name": "myDonation", 253 | "otherName": "当前账户打赏数量", 254 | "outputs": [ 255 | { 256 | "internalType": "uint256", 257 | "name": "", 258 | "type": "uint256" 259 | } 260 | ], 261 | "stateMutability": "view", 262 | "type": "function" 263 | }, 264 | { 265 | "inputs": [], 266 | "name": "name", 267 | "otherName": "合约自带测试代币名称", 268 | "outputs": [ 269 | { 270 | "internalType": "string", 271 | "name": "", 272 | "type": "string" 273 | } 274 | ], 275 | "stateMutability": "view", 276 | "type": "function" 277 | }, 278 | { 279 | "inputs": [ 280 | { 281 | "internalType": "uint256", 282 | "name": "a", 283 | "type": "uint256" 284 | }, 285 | { 286 | "internalType": "uint256", 287 | "name": "b", 288 | "type": "uint256" 289 | } 290 | ], 291 | "name": "plus", 292 | "otherName": "一个加法计算器", 293 | "outputs": [ 294 | { 295 | "internalType": "uint256", 296 | "name": "", 297 | "type": "uint256" 298 | } 299 | ], 300 | "stateMutability": "pure", 301 | "type": "function" 302 | }, 303 | { 304 | "inputs": [], 305 | "name": "symbol", 306 | "otherName": "合约自带代币符号", 307 | "outputs": [ 308 | { 309 | "internalType": "string", 310 | "name": "", 311 | "type": "string" 312 | } 313 | ], 314 | "stateMutability": "view", 315 | "type": "function" 316 | }, 317 | { 318 | "inputs": [], 319 | "name": "totalSupply", 320 | "outputs": [ 321 | { 322 | "internalType": "uint256", 323 | "name": "", 324 | "type": "uint256" 325 | } 326 | ], 327 | "stateMutability": "view", 328 | "type": "function" 329 | }, 330 | { 331 | "inputs": [ 332 | { 333 | "internalType": "address", 334 | "name": "to", 335 | "type": "address" 336 | }, 337 | { 338 | "internalType": "uint256", 339 | "name": "amount", 340 | "type": "uint256" 341 | } 342 | ], 343 | "name": "transfer", 344 | "outputs": [ 345 | { 346 | "internalType": "bool", 347 | "name": "", 348 | "type": "bool" 349 | } 350 | ], 351 | "stateMutability": "nonpayable", 352 | "type": "function" 353 | }, 354 | { 355 | "inputs": [ 356 | { 357 | "internalType": "address", 358 | "name": "from", 359 | "type": "address" 360 | }, 361 | { 362 | "internalType": "address", 363 | "name": "to", 364 | "type": "address" 365 | }, 366 | { 367 | "internalType": "uint256", 368 | "name": "amount", 369 | "type": "uint256" 370 | } 371 | ], 372 | "name": "transferFrom", 373 | "outputs": [ 374 | { 375 | "internalType": "bool", 376 | "name": "", 377 | "type": "bool" 378 | } 379 | ], 380 | "stateMutability": "nonpayable", 381 | "type": "function" 382 | }, 383 | { 384 | "inputs": [ 385 | { 386 | "internalType": "address", 387 | "name": "to", 388 | "type": "address" 389 | } 390 | ], 391 | "name": "withdraw", 392 | "otherName": "合约创建人提现打赏", 393 | "outputs": [], 394 | "stateMutability": "nonpayable", 395 | "type": "function" 396 | } 397 | ] 398 | } -------------------------------------------------------------------------------- /src/libs/rem.js: -------------------------------------------------------------------------------- 1 | (function (doc, win) { 2 | var docEl = doc.documentElement 3 | var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize' 4 | var recalc = function () { 5 | var clientWidth = docEl.clientWidth 6 | if (!clientWidth) return 7 | if (clientWidth >= 750) { 8 | docEl.style.fontSize = '100px' 9 | } else { 10 | docEl.style.fontSize = 100 * (clientWidth / 750) + 'px' 11 | } 12 | } 13 | if (!doc.addEventListener) return 14 | win.addEventListener(resizeEvt, recalc, false) 15 | doc.addEventListener('DOMContentLoaded', recalc, false) 16 | })(document, window) -------------------------------------------------------------------------------- /src/libs/utils.js: -------------------------------------------------------------------------------- 1 | import { ethers } from 'ethers' 2 | import { chainsRpc } from './chains' 3 | const fetcher = (...args) => fetch(...args).then((res) => res.json()) 4 | 5 | const admin_slot = ethers.BigNumber.from("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103") 6 | const impl_slot = ethers.BigNumber.from("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc") 7 | const eip1822_slot = ethers.BigNumber.from('0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7') 8 | 9 | let provider = null 10 | const get_address = async (proxy_address, solt_address) => { 11 | const info = await provider.getStorageAt(proxy_address , solt_address) 12 | const address = ethers.utils.getAddress("0x" + info.substring(26)) 13 | return address 14 | } 15 | /* eslint-disable */ 16 | export const throttle = (fn, wait) => { 17 | let callback = fn 18 | let timerId = null 19 | let firstInvoke = true 20 | const throttled = () => { 21 | let context = this 22 | let args = arguments 23 | if (firstInvoke) { 24 | callback.apply(context, args) 25 | firstInvoke = false 26 | return 27 | } 28 | if (timerId) { 29 | return 30 | } 31 | timerId = setTimeout(() => { 32 | clearTimeout(timerId) 33 | timerId = null 34 | callback.apply(context, args) 35 | }, wait) 36 | } 37 | return throttled 38 | } 39 | 40 | export const formatDate = (fmt, date) => { 41 | let ret 42 | date = new Date(date) 43 | let opt = { 44 | 'Y+': date.getFullYear().toString(), 45 | 'm+': (date.getMonth() + 1).toString(), 46 | 'd+': date.getDate().toString(), 47 | 'H+': date.getHours().toString(), 48 | 'M+': date.getMinutes().toString(), 49 | 'S+': date.getSeconds().toString() 50 | }; 51 | for (let k in opt) { 52 | ret = new RegExp('(' + k + ')').exec(fmt) 53 | if (ret) { 54 | fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, '0'))) 55 | } 56 | } 57 | return fmt 58 | } 59 | 60 | export const formatAddress = (address, num) => { 61 | if (num) { 62 | return address ? `${address.slice(0, num - 2)}...${address.slice(-num)}` : '' 63 | } else { 64 | return address ? `${address.slice(0, 6)}...${address.slice(-4)}` : '' 65 | } 66 | } 67 | 68 | export const getCreatorAddress = async (item) => { 69 | let chain = item.chain 70 | let address = item.address 71 | let response = null 72 | if ((chain.chainId == 1 || chain.chainId == 42 || chain.chainId == 3 || chain.chainId == 5 || chain.chainId == 11155111)) { 73 | let apiKey = '19SE5KR1KSVTIYMRTBJ8VQ3UJGGVFKIK5W' 74 | let chain = item.chain 75 | let name = 'api' 76 | if (chain.chainId == 42) name = 'api-kovan' 77 | else if (chain.chainId == 3) name = 'api-ropsten' 78 | else if (chain.chainId == 5) name = 'api-goerli' 79 | else if (chain.chainId == 11155111) name = 'api-sepolia' 80 | else if (chain.chainId == 1) name = 'api' 81 | else name = '' 82 | response = await fetcher(`https://${name}.etherscan.io/api?module=contract&action=getcontractcreation&contractaddresses=${address}&apikey=${apiKey}`) 83 | } else if (chain.chainId == 56) { 84 | response = await fetcher(`https://api.bscscan.com/api?module=contract&action=getcontractcreation&contractaddresses=${address}`) 85 | } else if (chain.chainId == 137) { 86 | response = await fetcher(`https://api.polygonscan.com/api?module=contract&action=getcontractcreation&contractaddresses=${address}`) 87 | } else if (chain.chainId == 10) { 88 | response = await fetcher(`https://api-optimistic.etherscan.io/api?module=contract&action=getcontractcreation&contractaddresses=${address}`) 89 | } 90 | if (response && response.status === '1' && response.result && response.result.length > 0) { 91 | const contracts = response.result 92 | item.contractCreator = contracts[0].contractCreator 93 | } 94 | return item 95 | } 96 | 97 | export const getContractInfo = async (item) => { 98 | let proxy_address = item.address 99 | let pa = JSON.parse(JSON.stringify(item.proxyAddress || '')) 100 | const chainId = item.chain.chainId 101 | chainsRpc.forEach(chain => { 102 | if (chain.chainId == chainId) { 103 | provider = new ethers.providers.JsonRpcProvider(chain.rpc) 104 | } 105 | }) 106 | if (!provider) { 107 | return item 108 | } 109 | try { 110 | let res = await Promise.all([ 111 | get_address(proxy_address, admin_slot), 112 | get_address(proxy_address, impl_slot), 113 | get_address(proxy_address, eip1822_slot) 114 | ]) 115 | console.log(res) 116 | let admin_address = res[0] 117 | let eip1967_address = res[1] 118 | let eip1822_address = res[2] 119 | item.adminAddress = admin_address 120 | if (admin_address != '0x0000000000000000000000000000000000000000') { 121 | item.isProxy = true 122 | } 123 | if (eip1967_address != '0x0000000000000000000000000000000000000000') { 124 | item.proxyAddress = eip1967_address 125 | } else if (eip1822_address != '0x0000000000000000000000000000000000000000') { 126 | item.proxyAddress = eip1822_address 127 | } 128 | if (pa && pa != item.proxyAddress) { 129 | item.isUpdate = true 130 | } 131 | return item 132 | } catch (error) { 133 | console.log(error) 134 | return item 135 | } 136 | } 137 | 138 | export const getSourceCode = async (contract) => { 139 | let address = contract.proxyAddress || contract.address 140 | let chain = contract.chain 141 | if (!(chain.chainId == 1 || chain.chainId == 42 || chain.chainId == 3 || chain.chainId == 5 || chain.chainId == 11155111)) { 142 | contract.sources = null 143 | contract.isGetSources = true 144 | } else { 145 | let apiKey = '19SE5KR1KSVTIYMRTBJ8VQ3UJGGVFKIK5W' 146 | let name = 'api' 147 | if (chain.chainId == 42) name = 'api-kovan' 148 | else if (chain.chainId == 3) name = 'api-ropsten' 149 | else if (chain.chainId == 5) name = 'api-goerli' 150 | else if (chain.chainId == 11155111) name = 'api-sepolia' 151 | else if (chain.chainId == 1) name = 'api' 152 | else name = '' 153 | if (!name) { 154 | contract.sources = null 155 | } 156 | let data = await fetcher(`https://${name}.etherscan.io/api?module=contract&action=getsourcecode&address=${address}&apikey=${apiKey}`) 157 | let result = data.result 158 | if (data.status == 1) { 159 | result = result[0] 160 | if (result.SourceCode) { 161 | let source = result.SourceCode 162 | let sourcesArr = [] 163 | if (source[0] == '{') { 164 | source = source.slice(1, -1) 165 | source = JSON.parse(source) 166 | let sources = source.sources 167 | for (let k in sources) { 168 | let name = k.split('/').pop() 169 | let item = { 170 | name: name, 171 | content: sources[k].content 172 | } 173 | sourcesArr.push(item) 174 | } 175 | } else { 176 | let item = { 177 | name: 'sol.sol', 178 | content: source 179 | } 180 | sourcesArr.push(item) 181 | } 182 | console.log(sourcesArr) 183 | contract.sources = sourcesArr 184 | contract.isGetSources = true 185 | contract.abi = result.ABI ? JSON.parse(result.ABI) : '' 186 | contract.isUpdate = false 187 | console.log(contract.proxyAddress && contract.sources) 188 | if (contract.proxyAddress && contract.sources) { 189 | contract.verified = true 190 | } else { 191 | contract.verified = false 192 | } 193 | } else { 194 | contract.sources = null 195 | contract.isGetSources = true 196 | if (contract.proxyAddress) { 197 | contract.verified = false 198 | } 199 | } 200 | } else { 201 | contract.sources = null 202 | contract.isGetSources = true 203 | if (contract.proxyAddress) { 204 | contract.verified = false 205 | } 206 | } 207 | } 208 | contract.isGetSources = true 209 | console.log('contract', contract) 210 | return contract 211 | } -------------------------------------------------------------------------------- /src/libs/walletSwitchChain.js: -------------------------------------------------------------------------------- 1 | import { chains } from './chains' 2 | export const walletSwitchChain = (chainId) => { 3 | chainId = '0x' + (+chainId).toString(16) 4 | return new Promise((resolve, reject) => { 5 | if (window.ethereum) { 6 | window.ethereum.request({ 7 | method: 'wallet_switchEthereumChain', 8 | params: [{ chainId }], 9 | }) 10 | .then(() => { 11 | console.log('网络切换成功') 12 | resolve() 13 | }) 14 | .catch(async (e) => { 15 | console.log(e) 16 | if (e.code == 4902) { 17 | let chain = chains.filter(e => e.chainId == chainId) 18 | chain = chain[0] 19 | let rpc = chain.rpc 20 | console.log({ 21 | chainId: '0x' + (+chain.chainId).toString(16), // 目标链ID 22 | chainName: chain.name, 23 | nativeCurrency: chain.nativeCurrency, 24 | rpcUrls: rpc, // 节点 25 | blockExplorerUrls: [chain.infoURL] 26 | }) 27 | window.ethereum.request({ 28 | id: 1, 29 | jsonrpc: "2.0", 30 | method: 'wallet_addEthereumChain', 31 | params: [{ 32 | chainId: '0x' + (+chain.chainId).toString(16), // 目标链ID 33 | chainName: chain.name, 34 | nativeCurrency: chain.nativeCurrency, 35 | rpcUrls: rpc, // 节点 36 | }] 37 | }).then(() => { 38 | resolve() 39 | }).catch(err => { 40 | reject(err) 41 | }) 42 | } else { 43 | reject(e) 44 | } 45 | }) 46 | } 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import './assets/css/reset.scss' 6 | import './assets/css/main.scss' 7 | // import * as fundebug from "fundebug-javascript"; 8 | // import FundebugVue from "fundebug-vue"; 9 | // fundebug.apikey = "948f50789ff7b2290e4aa9bae8b78ec10ef9de1b90131f1ab01901ca002611b2" 10 | import { create, NSelect, NConfigProvider, NMessageProvider, NModal, NDropdown, NDivider, 11 | NFormItem, NInput, NPopconfirm, NTabs, NTabPane, NCollapse, NTree, NDatePicker, NDialog, 12 | NCollapseItem, NPopover, NSpin, NDialogProvider, NInputGroup, NButton, NImage, NTooltip, 13 | NAlert, NNotificationProvider } from 'naive-ui' 14 | import VueHighlightJS from 'vue3-highlightjs' 15 | import 'highlight.js/styles/hybrid.css' 16 | // require('fundebug-revideo'); 17 | const naive = create({ 18 | components: [ NSelect, NConfigProvider, NMessageProvider, NTree, NDropdown, NDivider, 19 | NModal, NFormItem, NInput, NPopconfirm, NTabs, NTabPane, NButton, NDatePicker, NDialog, 20 | NCollapse, NCollapseItem, NPopover, NSpin, NDialogProvider, NInputGroup, NImage, NTooltip, 21 | NAlert, NNotificationProvider ] 22 | }) 23 | createApp(App).use(naive).use(store).use(router).use(VueHighlightJS).mount('#app') 24 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import Home from '../views/Home.vue' 3 | 4 | const routes = [ 5 | { 6 | path: '/:token?', 7 | name: 'Home', 8 | component: Home 9 | } 10 | ] 11 | 12 | const router = createRouter({ 13 | history: createWebHistory(), 14 | routes 15 | }) 16 | 17 | export default router 18 | -------------------------------------------------------------------------------- /src/service/service.js: -------------------------------------------------------------------------------- 1 | import localforage from "localforage"; 2 | localforage.config({ 3 | name: 'DappReader' 4 | }); 5 | export const getLs = (itemName) => { 6 | return new Promise((resolve) => { 7 | localforage.getItem(itemName).then(value => { 8 | if (value !== null) { 9 | resolve(value) 10 | } else { 11 | resolve([]) 12 | } 13 | }).catch(() => { 14 | resolve([]) 15 | }) 16 | }) 17 | } 18 | 19 | export const setLs = (itemName, data) => { 20 | return new Promise((resolve, reject) => { 21 | localforage.setItem(itemName, data).then((value) => { 22 | resolve(value) 23 | }).catch((err) => { 24 | reject(err) 25 | }); 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex' 2 | import { setLs } from '../service/service' 3 | export default createStore({ 4 | state: { 5 | provider: null, 6 | address: '', 7 | network: null, 8 | balance: 0, 9 | activeId: '', 10 | menuList: [], 11 | contractList: [], 12 | isShowLogin: false, 13 | userInfo: {}, 14 | defaultChains: [], 15 | results: {}, 16 | isIframe: false 17 | }, 18 | mutations: { 19 | setAddress(state, value) { 20 | state.address = value 21 | }, 22 | setProvider(state, value) { 23 | state.provider = value 24 | }, 25 | setNetwork(state, value) { 26 | state.network = value 27 | }, 28 | setBalance(state, value) { 29 | state.balance = value 30 | }, 31 | setMenuList(state, value) { 32 | setLs('menuList', value).then(() => { 33 | state.menuList = value 34 | }) 35 | }, 36 | setContractList(state, value) { 37 | setLs('contractList', value).then(() => { 38 | state.contractList = value 39 | }) 40 | }, 41 | setActiveId(state, value) { 42 | setLs('activeId', value).then(() => { 43 | state.activeId = value 44 | }) 45 | }, 46 | setUserInfo(state, value) { 47 | state.userInfo = value 48 | }, 49 | setDefaultChains(state, value) { 50 | state.defaultChains = value 51 | }, 52 | setResults(state, value) { 53 | state.results = value 54 | }, 55 | setIsIframe(state, value) { 56 | state.isIframe = value 57 | }, 58 | init(state) { 59 | state.provider = null 60 | state.wallet = null 61 | state.network = null 62 | state.isShowLogin = false 63 | }, 64 | hiddenLogin(state) { 65 | state.isShowLogin = false 66 | }, 67 | login(state) { 68 | state.isShowLogin = true 69 | } 70 | }, 71 | actions: { 72 | }, 73 | modules: { 74 | } 75 | }) 76 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 167 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import vueJsx from '@vitejs/plugin-vue-jsx' 4 | import Markdown from 'vite-plugin-md' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue(), vueJsx(), Markdown()], 9 | optimizeDeps: { 10 | include: ['color', 'mersenne-twister'] 11 | }, 12 | build: { 13 | minify: 'terser', 14 | terserOptions: { 15 | compress: { 16 | pure_funcs: ['console.log'], 17 | drop_debugger: true, 18 | } 19 | } 20 | } 21 | }) 22 | --------------------------------------------------------------------------------