├── .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 |
--------------------------------------------------------------------------------