├── .gitignore ├── docs └── logo.png ├── public ├── icon16.png ├── icon32.png ├── icon48.png ├── icon128.png ├── popup.html └── manifest.json ├── webpack ├── webpack.prod.js ├── webpack.dev.js └── webpack.common.js ├── .vscode ├── settings.json └── tasks.json ├── src ├── content_script.ts ├── background.ts ├── utils.ts └── model.ts ├── tsconfig.json ├── CONTRIBUTING.md ├── .github └── workflows │ └── build.yml ├── package.json ├── LICENSE ├── CHANGELOG.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules/ 3 | dist/ 4 | tmp/ -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StErMi/smartcontract-inspect/HEAD/docs/logo.png -------------------------------------------------------------------------------- /public/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StErMi/smartcontract-inspect/HEAD/public/icon16.png -------------------------------------------------------------------------------- /public/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StErMi/smartcontract-inspect/HEAD/public/icon32.png -------------------------------------------------------------------------------- /public/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StErMi/smartcontract-inspect/HEAD/public/icon48.png -------------------------------------------------------------------------------- /public/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StErMi/smartcontract-inspect/HEAD/public/icon128.png -------------------------------------------------------------------------------- /webpack/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'production' 6 | }); -------------------------------------------------------------------------------- /webpack/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | devtool: 'inline-source-map', 6 | mode: 'development' 7 | }); -------------------------------------------------------------------------------- /public/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Quickly open your favorite Web IDE to review the selected smart contract codebase 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./node_modules/typescript/lib", 3 | "files.eol": "\n", 4 | "json.schemas": [ 5 | { 6 | "fileMatch": [ 7 | "/manifest.json" 8 | ], 9 | "url": "http://json.schemastore.org/chrome-manifest" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /src/content_script.ts: -------------------------------------------------------------------------------- 1 | import { MessageType, WebIde } from './model'; 2 | import { getContractData } from './utils'; 3 | 4 | chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { 5 | if (msg.text === MessageType.FETCH_ETHERSCAN_MESSAGE) { 6 | const webIdeData = getContractData(document.URL, document, WebIde.DETHCODE); 7 | sendResponse(webIdeData); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "target": "es6", 5 | "moduleResolution": "bundler", 6 | "module": "ES6", 7 | "esModuleInterop": true, 8 | "sourceMap": false, 9 | "rootDir": "src", 10 | "outDir": "dist/js", 11 | "noEmitOnError": true, 12 | "jsx": "react", 13 | "typeRoots": [ "node_modules/@types" ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "command": "npm", 6 | "tasks": [ 7 | { 8 | "label": "install", 9 | "type": "shell", 10 | "command": "npm", 11 | "args": ["install"] 12 | }, 13 | { 14 | "label": "update", 15 | "type": "shell", 16 | "command": "npm", 17 | "args": ["update"] 18 | }, 19 | { 20 | "label": "build", 21 | "type": "shell", 22 | "group": "build", 23 | "command": "npm", 24 | "args": ["run", "watch"] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Add support to a new Web IDE 4 | 5 | The new Web IDE must allow opening a smart contract source code without any required authentication or additional steps to view the source code. 6 | 7 | To support a new Web IDE, you need to create an GitHub issue providing 8 | 9 | - Link to the Web IDE 10 | - List of all the supported Block Explorer supported by the new Web IDE 11 | - For each block explorer, a URL to showcase the integration 12 | 13 | ## Add support to a new Block Explorer 14 | 15 | To support a new block explorer, you need to create an GitHub issue providing 16 | 17 | - The block explorer URL 18 | - An example URL of a detail page of a smart contract 19 | - The list of Web IDE (already supported by Smart Contract Inspect) that support the proposed new Block Explorer 20 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: build 5 | 6 | on: 7 | push: 8 | branches: [main] 9 | pull_request: 10 | branches: [main] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [18.x, 20.x] 19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - run: npm ci 28 | - run: npm run build --if-present 29 | -------------------------------------------------------------------------------- /webpack/webpack.common.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const CopyPlugin = require('copy-webpack-plugin'); 4 | const srcDir = path.join(__dirname, '..', 'src'); 5 | 6 | module.exports = { 7 | entry: { 8 | background: path.join(srcDir, 'background.ts'), 9 | content_script: path.join(srcDir, 'content_script.ts'), 10 | }, 11 | output: { 12 | path: path.join(__dirname, '../dist/js'), 13 | filename: '[name].js', 14 | }, 15 | optimization: { 16 | splitChunks: { 17 | name: 'vendor', 18 | chunks(chunk) { 19 | return chunk.name !== 'background'; 20 | }, 21 | }, 22 | }, 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.tsx?$/, 27 | use: 'ts-loader', 28 | exclude: /node_modules/, 29 | }, 30 | ], 31 | }, 32 | resolve: { 33 | extensions: ['.ts', '.tsx', '.js'], 34 | }, 35 | plugins: [ 36 | new CopyPlugin({ 37 | patterns: [{ from: '.', to: '../', context: 'public' }], 38 | options: {}, 39 | }), 40 | ], 41 | }; 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smartcontract-inspector", 3 | "version": "1.0.1", 4 | "description": "Inspect the source code of a Smart Contract with your preferred Web IDE with just one click (or keyboard shortcut)", 5 | "main": "index.js", 6 | "scripts": { 7 | "watch": "rimraf dist && webpack --config webpack/webpack.dev.js --watch", 8 | "build": "rimraf dist && webpack --config webpack/webpack.prod.js", 9 | "clean": "rimraf dist", 10 | "style": "prettier --write \"src/**/*.{ts,tsx}\"" 11 | }, 12 | "author": "", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/StErMi/smartcontract-inspector.git" 17 | }, 18 | "dependencies": {}, 19 | "devDependencies": { 20 | "@types/chrome": "0.0.158", 21 | "copy-webpack-plugin": "^9.0.1", 22 | "glob": "^7.1.6", 23 | "prettier": "^2.2.1", 24 | "rimraf": "^3.0.2 ", 25 | "ts-loader": "^8.0.0", 26 | "typescript": "^5.0.4", 27 | "webpack": "^5.76.0", 28 | "webpack-cli": "^4.0.0", 29 | "webpack-merge": "^5.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 StErMi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/background.ts: -------------------------------------------------------------------------------- 1 | import { ErrorType, MessageType, ResponseData } from './model'; 2 | 3 | const triggerErrorNotification = (error: ErrorType) => { 4 | let message = ''; 5 | if (error === ErrorType.UNKNOWN) { 6 | message = 'Unknown error while processing website'; 7 | } else if (error === ErrorType.SITE_NOT_SUPPORTED) { 8 | message = 'Etherscan/website not supported'; 9 | } else if (error === ErrorType.SITE_CONTENT_MALFORMED) { 10 | message = 'Webpage is for EOA or contract cannot be found'; 11 | } else if (error === ErrorType.WEBIDE_NOT_SUPPORTED) { 12 | message = 'Selected Web IDE not supported for this website'; 13 | } else { 14 | // error === ErrorType.CONTRACT_ADDRESS_CANNOT_PARSE 15 | message = 'Contract address cannot be parsed from URL'; 16 | } 17 | 18 | const options = { 19 | type: 'basic', 20 | title: 'Error', 21 | message: message, 22 | iconUrl: '../icon128.png', 23 | }; 24 | chrome.notifications.create(options); 25 | }; 26 | 27 | chrome.action.onClicked.addListener(async (tab) => { 28 | if (tab && tab.id) { 29 | chrome.tabs.sendMessage(tab.id, { text: MessageType.FETCH_ETHERSCAN_MESSAGE }, function (response: ResponseData) { 30 | if (response.error) { 31 | triggerErrorNotification(response.error); 32 | } else { 33 | if (response.data && response.data.webIdeUrl) { 34 | chrome.tabs.create({ url: response.data.webIdeUrl }); 35 | } else { 36 | triggerErrorNotification(ErrorType.UNKNOWN); 37 | } 38 | } 39 | }); 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "Smart Contract Inspect", 4 | "description": "Inspect the source code of a Smart Contract with your preferred Web IDE with just one click (or keyboard shortcut)", 5 | "version": "1.0.1", 6 | "action": { 7 | "default_icon": { 8 | "16": "icon16.png", 9 | "32": "icon32.png", 10 | "48": "icon48.png", 11 | "128": "icon128.png" 12 | } 13 | }, 14 | "icons": { 15 | "16": "icon16.png", 16 | "32": "icon32.png", 17 | "48": "icon48.png", 18 | "128": "icon128.png" 19 | }, 20 | "content_scripts": [ 21 | { 22 | "matches": [ 23 | "*://*.etherscan.io/*", 24 | "*://*.etherscan.com/*", 25 | "*://*.bscscan.com/*", 26 | "*://*.ftmscan.com/*", 27 | "*://*.polygonscan.com/*", 28 | "*://*.arbiscan.io/*", 29 | "*://*.snowtrace.io/*", 30 | "*://*.cronoscan.com/*", 31 | "*://*.basescan.org/*", 32 | "*://*.fraxscan.com/*", 33 | "*://*.blastscan.io/*" 34 | ], 35 | "js": ["js/content_script.js"] 36 | } 37 | ], 38 | "background": { 39 | "service_worker": "js/background.js" 40 | }, 41 | "permissions": ["activeTab", "notifications"], 42 | "host_permissions": [ 43 | "*://*.etherscan.io/*", 44 | "*://*.etherscan.com/*", 45 | "*://*.bscscan.com/*", 46 | "*://*.ftmscan.com/*", 47 | "*://*.polygonscan.com/*", 48 | "*://*.arbiscan.io/*", 49 | "*://*.snowtrace.io/*", 50 | "*://*.cronoscan.com/*", 51 | "*://*.basescan.org/*", 52 | "*://*.fraxscan.com/*", 53 | "*://*.blastscan.io/*" 54 | ], 55 | "commands": { 56 | "_execute_action": { 57 | "description": "Inspect the source code of a Smart Contract with your preferred Web IDE with just one click (or keyboard shortcut)", 58 | "suggested_key": { 59 | "default": "Ctrl+Period", 60 | "mac": "Command+Period" 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | 6 | ## [Unreleased] 7 | 8 | ### Added 9 | 10 | - TBD 11 | 12 | ### Changed 13 | 14 | - TBD 15 | 16 | ### Removed 17 | 18 | - TBD 19 | 20 | ## [1.0.1] - 2024-04-07 21 | 22 | ### Added 23 | 24 | - [holesky.etherscan.io](https://holesky.etherscan.io/) (Ethereum Holesky Testnet) 25 | - [blastscan.io](https://blastscan.io/) (Blast) 26 | - [sepolia.blastscan.io](https://sepolia.blastscan.io/) (Blast Sepolia Testnet) 27 | - [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io/) (Optimism Sepolia Testnet) 28 | - [sepolia.arbiscan.io](https://sepolia.arbiscan.io/) (Arbitrum Sepolia Testnet) 29 | 30 | ### Removed 31 | 32 | - [goerli.etherscan.io](https://goerli.etherscan.io/) (Ethereum Goerli Testnet) 33 | 34 | ## [1.0.0] - 2024-04-07 35 | 36 | First release 🎉 37 | 38 | ### Added 39 | 40 | - [etherscan.io](https://etherscan.io/) + [etherscan.com](https://etherscan.com/) (Ethereum Mainnet) 41 | - [goerli.etherscan.io](https://goerli.etherscan.io/) (Ethereum Goerli Testnet) 42 | - [bscscan.com](https://bscscan.com/) (Binance Smart Chain) 43 | - [testnet.bscscan.com](https://testnet.bscscan.com/) (Binance Smart Chain Testnet) 44 | - [ftmscan.com](https://ftmscan.com/) (Fantom Testnet) 45 | - [testnet.ftmscan.com](https://testnet.ftmscan.com/) (Fantom Testnet) 46 | - [optimistic.etherscan.io](https://optimistic.etherscan.io/) (Optimism) 47 | - [polygonscan.com](https://polygonscan.com/) (Polygon) 48 | - [mumbai.polygonscan.com](https://mumbai.polygonscan.com/) (Polygon Mumbai Testnet) 49 | - [arbiscan.io](https://arbiscan.io/) (Arbitrum) 50 | - [snowtrace.io](https://snowtrace.io/) (Avalance) 51 | - [testnet.snowtrace.io](https://testnet.snowtrace.io/) (Avalance Fuji Testnet) 52 | - [cronoscan.com](https://cronoscan.com/) (Cronos Mainnet) 53 | - [basescan.org](https://basescan.org/) (Base) 54 | - [sepolia.basescan.org](https://sepolia.basescan.org/) (Base Sepolia Testnet) 55 | - [fraxscan.com](https://fraxscan.com/) (Fraxtal) 56 | - [holesky.fraxscan.com](https://holesky.fraxscan.com/) (Fraxtal Holesky Testnet) 57 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ErrorType, ResponseData, SUPPORTED_WEBSITES, SupportedWebsite, WebIde } from './model'; 2 | 3 | const extractContractAddressFromEtherscan = (url: string) => { 4 | const regex = /0x[a-fA-F0-9]+/g; 5 | const matches = url.match(regex); 6 | return matches ? matches[0] : null; 7 | }; 8 | 9 | const getWebIdeUrlForContractAddress = (website: SupportedWebsite, webIde: WebIde, contractAddress: string) => { 10 | if (webIde === WebIde.DETHCODE) { 11 | return `https://${website.ide[webIde]}.deth.net/address/${contractAddress}`; 12 | } 13 | 14 | // add support to more 15 | return undefined; 16 | }; 17 | 18 | const isContractPage = (domDocument: Document, website: SupportedWebsite) => { 19 | // Snowtrace.io - Avalance/Avalance Fuji custom 20 | // TODO: build enums for chainIds 21 | if (website.chainId === 43113 || website.chainId === 43114) { 22 | const elements = domDocument.getElementsByClassName('nav-link break-all'); 23 | for (const el of elements) { 24 | if ((el as HTMLElement).innerText.toLowerCase() === 'contract') return true; 25 | } 26 | 27 | // if we have not found it, return false 28 | return false; 29 | } 30 | 31 | return domDocument.getElementById('ContentPlaceHolder1_li_contracts') !== null; 32 | }; 33 | 34 | export const getContractData = (url: string, domDocument: Document, webIde: WebIde): ResponseData => { 35 | // get the url 36 | const _url = new URL(url); 37 | 38 | // check if it's one supported by DethCrypto 39 | const hostname = _url.hostname; 40 | 41 | for (const supportedWebsite of SUPPORTED_WEBSITES) { 42 | const matched = supportedWebsite.hostnames.includes(hostname); 43 | if (matched) { 44 | // check if it's a contract, this is valid only for etherscan websites 45 | const isContract = isContractPage(domDocument, supportedWebsite); 46 | 47 | // if it's not a contract but we have already matched the website return null early, it won't match anything else 48 | if (!isContract) { 49 | return { 50 | error: ErrorType.SITE_CONTENT_MALFORMED, 51 | }; 52 | } 53 | 54 | const contractAddress = extractContractAddressFromEtherscan(url); 55 | 56 | // if I can't match the contract address just early return 57 | // do I need to get the IMPL address if it's a proxy? 58 | if (!contractAddress) { 59 | return { 60 | error: ErrorType.CONTRACT_ADDRESS_CANNOT_PARSE, 61 | }; 62 | } 63 | 64 | if (!supportedWebsite.ide[webIde]) { 65 | return { 66 | error: ErrorType.WEBIDE_NOT_SUPPORTED, 67 | }; 68 | } 69 | 70 | const webIdeUrl = getWebIdeUrlForContractAddress(supportedWebsite, webIde, contractAddress); 71 | 72 | return { 73 | data: { 74 | url: url, 75 | website: supportedWebsite, 76 | contract: contractAddress, 77 | webIdeUrl: webIdeUrl, 78 | }, 79 | }; 80 | } 81 | } 82 | 83 | return { error: ErrorType.SITE_NOT_SUPPORTED }; 84 | }; 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | 4 |
5 |

Smart Contract Inspector

6 |

Inspect the source code of a Smart Contract with your preferred Web IDE with just one click (or keyboard shortcut)

7 |

When you are in the detail page of a smart contract on one of the supported Etherscan domains, just click the Smart Contract Inspector icon or hit the Cmd+Dot keyboard shortcut to review the source code in your preferred Web IDE

8 |

9 | 10 | ## Motivation 11 | 12 | I wasted too much important time clicking in the Etherscan interface to just quickly open one instance of Web IDE to properly review the smart contract codebase. 13 | 14 | I wanted an easy and quick solution to open it with just a keyboard shortcuts, something like you can do inside a GitHub repository. 15 | 16 | ## Supported Web IDE 17 | 18 | - [DethCode](https://github.com/dethcrypto/dethcode) 19 | - More to come 20 | 21 | ## Supported Block Explorer websites and blockchains 22 | 23 | - [etherscan.io](https://etherscan.io/) + [etherscan.com](https://etherscan.com/) (Ethereum Mainnet) 24 | - [sepolia.etherscan.io](https://sepolia.etherscan.io/) (Ethereum Sepolia Testnet) 25 | - [holesky.etherscan.io](https://holesky.etherscan.io/) (Ethereum Holesky Testnet) 26 | - [bscscan.com](https://bscscan.com/) (Binance Smart Chain) 27 | - [testnet.bscscan.com](https://testnet.bscscan.com/) (Binance Smart Chain Testnet) 28 | - [ftmscan.com](https://ftmscan.com/) (Fantom Testnet) 29 | - [testnet.ftmscan.com](https://testnet.ftmscan.com/) (Fantom Testnet) 30 | - [optimistic.etherscan.io](https://optimistic.etherscan.io/) (Optimism) 31 | - [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io/) (Optimism Sepolia Testnet) 32 | - [polygonscan.com](https://polygonscan.com/) (Polygon) 33 | - [mumbai.polygonscan.com](https://mumbai.polygonscan.com/) (Polygon Mumbai Testnet) 34 | - [arbiscan.io](https://arbiscan.io/) (Arbitrum) 35 | - [sepolia.arbiscan.io](https://sepolia.arbiscan.io/) (Arbitrum Sepolia Testnet) 36 | - [snowtrace.io](https://snowtrace.io/) (Avalance) 37 | - [testnet.snowtrace.io](https://testnet.snowtrace.io/) (Avalance Fuji Testnet) 38 | - [cronoscan.com](https://cronoscan.com/) (Cronos Mainnet) 39 | - [basescan.org](https://basescan.org/) (Base) 40 | - [sepolia.basescan.org](https://sepolia.basescan.org/) (Base Sepolia Testnet) 41 | - [fraxscan.com](https://fraxscan.com/) (Fraxtal) 42 | - [holesky.fraxscan.com](https://holesky.fraxscan.com/) (Fraxtal Holesky Testnet) 43 | - [blastscan.io](https://blastscan.io/) (Blast) 44 | - [sepolia.blastscan.io](https://sepolia.blastscan.io/) (Blast Sepolia Testnet) 45 | 46 | ## Disclosures 47 | 48 | - Smart Contract Inspector is not affiliated to [DethCode](https://github.com/dethcrypto/dethcode) and their developers 49 | - Smart Contract Inspector is not affiliated to the [Etherscan](https://etherscan.io) platform end their developers 50 | - Smart Contract Inspector is based on the [Chrome Extension TypeScript Starter](https://github.com/chibat/chrome-extension-typescript-starter) template 51 | 52 | ## Contributing and development 53 | 54 | See the [CONTRIBUTING](CONTRIBUTING.md) guidelines. 55 | 56 | ## Social 57 | 58 | Visit my website [https://stermi.xyz](https://stermi.xyz/) 59 | Follow me on [Twitter](https://twitter.com/StErMi). 60 | -------------------------------------------------------------------------------- /src/model.ts: -------------------------------------------------------------------------------- 1 | export enum MessageType { 2 | FETCH_ETHERSCAN_MESSAGE = 'FETCH_ETHERSCAN_MESSAGE', 3 | } 4 | 5 | export enum ErrorType { 6 | UNKNOWN, 7 | // etherscan not found / site not supported by DethCode 8 | SITE_NOT_SUPPORTED, 9 | // cannot find the HTML element to understand if it's a contract or an EOA 10 | SITE_CONTENT_MALFORMED, 11 | // selected webide (DethCode, etc) not supported 12 | WEBIDE_NOT_SUPPORTED, 13 | // contract address cannot be parsed from url 14 | CONTRACT_ADDRESS_CANNOT_PARSE, 15 | } 16 | 17 | export enum WebIde { 18 | DETHCODE = 'dethcode', 19 | } 20 | 21 | export interface ResponseData { 22 | data?: ContractData; 23 | error?: ErrorType; 24 | } 25 | 26 | export interface ContractData { 27 | url: string; 28 | website: SupportedWebsite; 29 | contract: string; 30 | webIdeUrl?: string; 31 | } 32 | 33 | export interface SupportedWebsite { 34 | chainId: number; 35 | name: string; 36 | hostnames: string[]; 37 | ide: { [key in WebIde]?: string }; 38 | } 39 | 40 | export enum Network { 41 | ETHEREUM_MAINNET = 'ethereum-mainnet', 42 | } 43 | 44 | export const SUPPORTED_WEBSITES: SupportedWebsite[] = [ 45 | { 46 | chainId: 1, 47 | name: 'Ethereum Mainnet', 48 | hostnames: ['etherscan.io', 'etherscan.com'], 49 | ide: { dethcode: 'etherscan' }, 50 | }, 51 | { 52 | chainId: 11155111, 53 | name: 'Ethereum Sepolia Testnet', 54 | hostnames: ['sepolia.etherscan.io'], 55 | ide: { dethcode: 'sepolia.etherscan' }, 56 | }, 57 | { 58 | chainId: 17000, 59 | name: 'Ethereum Holesky Testnet', 60 | hostnames: ['holesky.etherscan.io'], 61 | ide: { dethcode: 'holesky.etherscan' }, 62 | }, 63 | { 64 | chainId: 56, 65 | name: 'Binance Smart Chain', 66 | hostnames: ['bscscan.com'], 67 | ide: { dethcode: 'bscscan' }, 68 | }, 69 | { 70 | chainId: 97, 71 | name: 'Binance Smart Chain Testnet', 72 | hostnames: ['testnet.bscscan.com'], 73 | ide: { dethcode: 'testnet.bscscan' }, 74 | }, 75 | { 76 | chainId: 250, 77 | name: 'Fantom', 78 | hostnames: ['ftmscan.com'], 79 | ide: { dethcode: 'ftmscan' }, 80 | }, 81 | { 82 | chainId: 4002, 83 | name: 'Fantom Testnet', 84 | hostnames: ['testnet.ftmscan.com'], 85 | ide: { dethcode: 'testnet.ftmscan' }, 86 | }, 87 | { 88 | chainId: 10, 89 | name: 'Optimism', 90 | hostnames: ['optimistic.etherscan.io'], 91 | ide: { dethcode: 'optimistic.etherscan' }, 92 | }, 93 | { 94 | chainId: 11155420, 95 | name: 'Optimism Sepolia Testnet', 96 | hostnames: ['sepolia-optimistic.etherscan.io'], 97 | ide: { dethcode: 'sepolia-optimistic.etherscan' }, 98 | }, 99 | { 100 | chainId: 137, 101 | name: 'Polygon', 102 | hostnames: ['polygonscan.com'], 103 | ide: { dethcode: 'polygonscan' }, 104 | }, 105 | { 106 | chainId: 8001, 107 | name: 'Polygon Mumbai Testnet', 108 | hostnames: ['mumbai.polygonscan.com'], 109 | ide: { dethcode: 'testnet.polygonscan' }, 110 | }, 111 | { 112 | chainId: 42161, 113 | name: 'Arbitrum', 114 | hostnames: ['arbiscan.io'], 115 | ide: { dethcode: 'arbiscan' }, 116 | }, 117 | { 118 | chainId: 421614, 119 | name: 'Arbitrum Sepolia Testnet', 120 | hostnames: ['sepolia.arbiscan.io'], 121 | ide: { dethcode: 'sepolia.arbiscan' }, 122 | }, 123 | { 124 | chainId: 43114, 125 | name: 'Avalance', 126 | hostnames: ['snowtrace.io'], 127 | ide: { dethcode: 'snowtrace' }, 128 | }, 129 | { 130 | chainId: 43113, 131 | name: 'Avalance Fuji Testnet', 132 | hostnames: ['testnet.snowtrace.io'], 133 | ide: { dethcode: 'testnet.snowtrace' }, 134 | }, 135 | { 136 | chainId: 25, 137 | name: 'Cronos Mainnet', 138 | hostnames: ['cronoscan.com'], 139 | ide: { dethcode: 'cronoscan' }, 140 | }, 141 | { 142 | chainId: 8453, 143 | name: 'Base', 144 | hostnames: ['basescan.org'], 145 | ide: { dethcode: 'basescan' }, 146 | }, 147 | { 148 | chainId: 84532, 149 | name: 'Base Sepolia Testnet', 150 | hostnames: ['sepolia.basescan.org'], 151 | ide: { dethcode: 'sepolia.basescan' }, 152 | }, 153 | { 154 | chainId: 252, 155 | name: 'Fraxtal', 156 | hostnames: ['fraxscan.com'], 157 | ide: { dethcode: 'fraxscan' }, 158 | }, 159 | { 160 | chainId: 2522, 161 | name: 'Fraxtal Holesky Testnet', 162 | hostnames: ['holesky.fraxscan.com'], 163 | ide: { dethcode: 'holesky.fraxscan' }, 164 | }, 165 | { 166 | chainId: 238, 167 | name: 'Blast', 168 | hostnames: ['blastscan.io'], 169 | ide: { dethcode: 'blastscan' }, 170 | }, 171 | { 172 | chainId: 168587773, 173 | name: 'Blast Sepolia Testnet', 174 | hostnames: ['sepolia.blastscan.io'], 175 | ide: { dethcode: 'sepolia.blastscan' }, 176 | }, 177 | ]; 178 | --------------------------------------------------------------------------------