├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── main.yml │ ├── publish.yml │ ├── pull_request.yml │ └── pull_request_dependabot.yml ├── .gitignore ├── .husky └── pre-commit ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.js ├── dist ├── index.min.js └── index.min.js.map ├── example ├── node │ ├── index.ts │ ├── package-lock.json │ └── package.json ├── vanilla-minimal │ └── index.html └── vanilla-vite │ ├── .gitignore │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── public │ └── vite.svg │ ├── src │ ├── counter.ts │ ├── main.ts │ ├── style.css │ ├── typescript.svg │ └── vite-env.d.ts │ └── tsconfig.json ├── lib ├── contract-verifier-ui.d.ts ├── contract-verifier-ui.js ├── contract-verifier-ui.js.map ├── contract-verifier.d.ts ├── contract-verifier.js ├── contract-verifier.js.map ├── dom.d.ts ├── dom.js ├── dom.js.map ├── file-structure.d.ts ├── file-structure.js ├── file-structure.js.map ├── index.d.ts ├── index.js ├── index.js.map ├── web.d.ts ├── web.js └── web.js.map ├── package-lock.json ├── package.json ├── src └── lib │ ├── contract-verifier-ui.ts │ ├── contract-verifier.ts │ ├── declaration.d.ts │ ├── dom.ts │ ├── file-structure.ts │ ├── index.ts │ ├── res │ ├── file-black.svg │ ├── file-white.svg │ ├── folder-closed-black.svg │ ├── folder-closed-white.svg │ ├── folder-open-black.svg │ └── folder-open-white.svg │ ├── style.css │ └── web.ts ├── tsconfig.json └── tslint.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://hge.to/thanks 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | timezone: America/Montreal 9 | open-pull-requests-limit: 10 10 | versioning-strategy: increase 11 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - README.md 7 | - .gitignore 8 | - .github/** 9 | 10 | jobs: 11 | build: 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | node-version: [12.x] 16 | os: [ubuntu-latest] 17 | steps: 18 | - uses: actions/checkout@v1 19 | - name: Use Node.js ${{ matrix.node_version }} 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: ${{ matrix.node_version }} 23 | - name: npm install, build, and test 24 | run: | 25 | npm install 26 | npm run test 27 | env: 28 | CI: true 29 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - README.md 9 | - .gitignore 10 | - .github/** 11 | 12 | jobs: 13 | publish: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v1 17 | - uses: actions/setup-node@v1 18 | with: 19 | node-version: 12 20 | - run: npm install 21 | - run: npm run test -- --coverage --watchAll=false 22 | 23 | - name: Setup GIT 24 | run: | 25 | git reset --hard 26 | git config --local --list 27 | git checkout master 28 | git config user.email "$GH_EMAIL" 29 | git config user.name "Francisco Hodge" 30 | env: 31 | GH_EMAIL: ${{secrets.GH_EMAIL}} 32 | 33 | - name: Bump version 34 | run: | 35 | git reset --hard 36 | npm version patch 37 | npm run build 38 | git add . || true 39 | git commit -m "Build update" || true 40 | git push "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY" 41 | env: 42 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 43 | 44 | - name: npm publish 45 | run: | 46 | npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN 47 | npm run trypublish 48 | env: 49 | NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}} 50 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yml: -------------------------------------------------------------------------------- 1 | name: Build PR (Standard) 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | if: ${{ github.actor != 'dependabot[bot]' }} 9 | strategy: 10 | matrix: 11 | node-version: [12.x] 12 | os: [ubuntu-latest] 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Use Node.js ${{ matrix.node_version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node_version }} 19 | - name: npm install, build, and test 20 | run: | 21 | npm install 22 | npm run test 23 | env: 24 | CI: true 25 | -------------------------------------------------------------------------------- /.github/workflows/pull_request_dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Build PR (Dependabot) 2 | 3 | on: pull_request_target 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | if: ${{ github.actor == 'dependabot[bot]' }} 9 | strategy: 10 | matrix: 11 | node-version: [12.x] 12 | os: [ubuntu-latest] 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | ref: ${{ github.event.pull_request.head.sha }} 17 | - name: Use Node.js ${{ matrix.node_version }} 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node_version }} 21 | - name: npm install, build, and test 22 | run: | 23 | npm install 24 | npm run test 25 | env: 26 | CI: true 27 | - name: Merge PR 28 | if: success() 29 | uses: "actions/github-script@v2" 30 | with: 31 | github-token: "${{ secrets.GH_KEY }}" 32 | script: | 33 | const pullRequest = context.payload.pull_request 34 | const repository = context.repo 35 | 36 | await github.pulls.merge({ 37 | merge_method: "merge", 38 | owner: repository.owner, 39 | pull_number: pullRequest.number, 40 | repo: repository.repo, 41 | }) 42 | - name: Reject PR 43 | if: failure() 44 | uses: peter-evans/close-pull@v1 45 | with: 46 | pull-request-number: ${{github.event.number}} 47 | comment: "Closing PR due to failing tests." 48 | delete-branch: true 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | temp 3 | .DS_Store 4 | *.tgz -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run format 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /tests 6 | /coverage 7 | 8 | # docs 9 | /docs 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | /.github 18 | /demo 19 | .esdoc.json 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # Development folders and files 26 | public 27 | src 28 | scripts 29 | config 30 | .travis.yml 31 | CHANGELOG.md 32 | README.md 33 | webpack.config.js 34 | babel.config.js -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [1.1.1] - 2023-04-18 11 | 12 | ### Changed 13 | - Modified `FuncCompilerVersion` type to be a string to ease future version support 14 | 15 | ## [1.1.0] - 2023-03-12 16 | 17 | ### Added 18 | 19 | - Added testnet support: 20 | - getSourcesJsonUrl - `options` now accept a `testnet` parameter 21 | - getSourcesData - (Breaking) `options` now accepts an `option` parameter, which takes a custom `ipfsConverter` function and `testnet` parameters 22 | 23 | ### Fixed 24 | 25 | - None 26 | 27 | ### Changed 28 | 29 | - None 30 | 31 | ### Removed 32 | 33 | - None -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Orbs 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TON Contract Verifier SDK 2 | 3 | ## TL;DR 4 | TON verifier data fetcher and code viewer with FunC code highlighting 5 | 6 | ## Related repositories 7 | 8 | This repo is a part of the following: 9 | 10 | 1. [contract-verifier-contracts](https://github.com/ton-community/contract-verifier-contracts) - Sources registry contracts which stores an on-chain proof per code cell hash. 11 | 2. [contract-verifier-backend](https://github.com/ton-community/contract-verifier-backend) - Backend for compiling FunC and returning a signature over a message containing the resulting code cell hash. 12 | 3. [contract-verifier-sdk](https://github.com/ton-community/contract-verifier-sdk) (this repo) - A UI component to fetch and display sources from TON blockchain and IPFS, including FunC code highlighting. 13 | 4. [contract-verifier](https://github.com/ton-community/contract-verifier) - A UI app to interact with the backend, contracts and publish an on-chain proof. 14 | 15 | ## ⭐️ Features 16 | - Queries the Sources Registry for the existence of a Source Item contract 17 | - Fetches contract source code from IPFS via a sources.json url 18 | - Displays a code navigator with code highlighting for FunC, FIFT, based on [highlight.js plugin](https://github.com/highlightjs/highlightjs-func) 19 | - Customizable data fetching (IPFS GW, TON API endpoint, verifier id) 20 | 21 | ## 📦 Getting Started 22 | 23 | ### Step 1: Prepare DOM ### 24 | Add this to your HTML structure 25 | ```html 26 |
27 |
28 |
29 |
30 |
31 |
32 | ``` 33 | 34 | ### Installation 35 | 36 | #### NPM 37 | ``` 38 | npm install @ton-community/contract-verifier-sdk 39 | ``` 40 | 41 | #### Web CDN 42 | ``` 43 | 44 | ``` 45 | 46 | ### Usage 47 | 48 | #### Node 49 | ```typescript 50 | import { ContractVerifier } from "@ton-community/contract-verifier-sdk"; 51 | 52 | const ipfsLink = await ContractVerifier.getSourcesJsonUrl( 53 | "45cE5NYJuT5l2bJ+HfRI0hUhR3LsBI6wER6yralqPyY=", 54 | { 55 | testnet: false 56 | } 57 | ); 58 | 59 | const src = await ContractVerifier.getSourcesData(ipfsLink!, {testnet: false}); 60 | 61 | // use contract data 62 | ``` 63 | 64 | #### Browser 65 | ```html 66 | 87 | ``` 88 | 89 | ## ℹ️ Interface 90 | 91 | ### ContractVerifier 92 | ```typescript 93 | interface GetSourcesOptions { 94 | verifier?: string, // Defaults to "orbs.com" 95 | httpApiEndpointV4?: string, // Defaults to an Orbs L3 TON Gateway 96 | testnet?: boolean 97 | } 98 | 99 | // Returns an `ipfs://` prefixed URL if the given code cell hash has a corresponding source verifier contract 100 | async ContractVerifier.getSourcesJsonUrl(codeCellHash: string, options?: GetSourcesOptions): Promise; 101 | 102 | 103 | interface SourcesData { 104 | files: { name: string; content: string }[]; 105 | commandLine: string; 106 | compiler: string; 107 | version: string; 108 | verificationDate: Date; 109 | } 110 | type IpfsUrlConverterFunc (ipfsUrl: string) => string; 111 | 112 | // Returns file names and their source code content 113 | async ContractVerifier.getSourcesData(sourcesJsonUrl: string, options?: { 114 | ipfsConverter?: IpfsUrlConverterFunc; 115 | testnet?: boolean; 116 | }): Promise; 117 | ``` 118 | 119 | ### ContractVerifierUI 120 | 121 | ```typescript 122 | ContractVerifierUI.loadSourcesData(sourcesData: SourcesData, opts: { 123 | containerSelector: string; // main container 124 | fileListSelector?: string; // if omitted, the file list will not be populated and the setCode function can be used instead to switch between files 125 | contentSelector: string; // code container 126 | theme: Theme; // "light" or "dark" 127 | }); 128 | 129 | // To be used usually only if the file list is manually built 130 | ContractVerifierUI.setCode(contentSelector: string, content: string); 131 | ``` 132 | 133 | ## 👀 Demo 134 | 1. Clone this repo 135 | 2. Run `npm install` 136 | 3. Run `npm run build` 137 | 138 | ### Web - Minimal 139 | 1. Navigate to `example/vanilla-minimal` 140 | 4. Open `index.html` 141 | 142 | ### Web - Vanilla 143 | 1. Navigate to `example/vanilla-vite` 144 | 2. Run `npm install` 145 | 3. Run `npm link ../../` 146 | 4. Run `npm run dev` 147 | 148 | ### Node.js 149 | 1. Navigate to `example/node` 150 | 2. Run `npm install` 151 | 3. Run `npm link ../../` 152 | 4. Run `ts-node index.ts` 153 | 154 | ## 💎 Customization 155 | 156 | ### CSS 157 | The widget will attach the following classnames to its components: 158 | ``` 159 | contract-verifier-container 160 | contract-verifier-files 161 | contract-verifier-file 162 | contract-verifier-code 163 | ``` 164 | 165 | Which can be customized according to your needs. 166 | 167 | ## 📔 License 168 | MIT 169 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | let StyleLoader = { 2 | name: "inline-style", 3 | setup({ onLoad }) { 4 | let fs = require("fs"); 5 | onLoad({ filter: /\.css$/ }, async (args) => { 6 | let css = await fs.promises.readFile(args.path, "utf8"); 7 | return { contents: css, loader: "text" }; 8 | }); 9 | }, 10 | }; 11 | 12 | let SVGLoader = { 13 | name: "svg", 14 | setup({ onLoad }) { 15 | let fs = require("fs"); 16 | onLoad({ filter: /\.svg$/ }, async (args) => { 17 | let svg = await fs.promises.readFile(args.path, "utf8"); 18 | return { contents: svg, loader: "text" }; 19 | }); 20 | }, 21 | }; 22 | 23 | const { polyfillNode } = require("esbuild-plugin-polyfill-node"); 24 | 25 | (async () => { 26 | await require("esbuild") 27 | .build({ 28 | plugins: [polyfillNode(), StyleLoader, SVGLoader], 29 | entryPoints: ["./src/lib/web.ts"], 30 | bundle: true, 31 | target: "ES2020", 32 | outfile: "./dist/index.min.js", 33 | sourcemap: true, 34 | minify: true, 35 | }) 36 | .catch(() => process.exit(1)); 37 | })(); 38 | -------------------------------------------------------------------------------- /example/node/index.ts: -------------------------------------------------------------------------------- 1 | import { ContractVerifier } from "@ton-community/contract-verifier-sdk"; 2 | 3 | (async () => { 4 | console.log("Fetching IPFS Link") 5 | const ipfsLink = await ContractVerifier.getSourcesJsonUrl( 6 | "45cE5NYJuT5l2bJ+HfRI0hUhR3LsBI6wER6yralqPyY=" 7 | ); 8 | 9 | console.log(`Got: ${ipfsLink}. Fetching JSON and sources.\n`) 10 | 11 | const src = await ContractVerifier.getSourcesData(ipfsLink!); 12 | 13 | console.log({ 14 | ...src, 15 | files: src.files.map(({ name, content }) => ({ 16 | name, 17 | content: content.slice(0, 50) + "...", 18 | })), 19 | }); 20 | })(); 21 | -------------------------------------------------------------------------------- /example/node/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "node", 9 | "version": "1.0.0", 10 | "license": "ISC" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/vanilla-minimal/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 33 | 34 | 35 |
36 |
37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /example/vanilla-vite/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /example/vanilla-vite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/vanilla-vite/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "example", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "@ton-community/contract-verifier-sdk": "file:../.." 12 | }, 13 | "devDependencies": { 14 | "typescript": "^4.6.4", 15 | "vite": "^3.1.0" 16 | } 17 | }, 18 | "..": { 19 | "name": "@orbs-network/tsv-widget", 20 | "version": "0.0.2", 21 | "extraneous": true, 22 | "license": "MIT", 23 | "dependencies": { 24 | "@types/codemirror": "^5.43.0", 25 | "codemirror": "^5.43.0", 26 | "codemirror-textmate": "git://github.com/orbs-network/codemirror-textmate", 27 | "onigasm": "^2.2.5" 28 | }, 29 | "devDependencies": { 30 | "@babel/cli": "^7.18.10", 31 | "@babel/core": "^7.19.1", 32 | "@babel/plugin-proposal-class-properties": "^7.18.6", 33 | "@babel/polyfill": "^7.12.1", 34 | "@babel/preset-env": "^7.19.1", 35 | "babel-eslint": "^10.1.0", 36 | "babel-loader": "^8.2.5", 37 | "babel-preset-minify": "^0.5.2", 38 | "css-loader": "^6.7.1", 39 | "css-minimizer-webpack-plugin": "^4.1.0", 40 | "eslint": "^8.23.0", 41 | "file-loader": "^6.2.0", 42 | "html-webpack-plugin": "^5.5.0", 43 | "mini-css-extract-plugin": "^2.6.1", 44 | "node-polyfill-webpack-plugin": "^2.0.1", 45 | "style-loader": "^3.3.1", 46 | "terser-webpack-plugin": "^5.3.6", 47 | "to-string-loader": "^1.2.0", 48 | "ts-loader": "^9.4.1", 49 | "url-loader": "^4.1.1", 50 | "webpack": "^5.74.0", 51 | "webpack-cli": "^4.10.0", 52 | "webpack-dev-server": "^4.11.1" 53 | } 54 | }, 55 | "../..": { 56 | "name": "@ton-community/contract-verifier-sdk", 57 | "version": "0.2.1", 58 | "license": "MIT", 59 | "dependencies": { 60 | "@aws-crypto/sha256-js": "^2.0.2", 61 | "@orbs-network/ton-access": "^2.2.2", 62 | "highlight.js": "^11.6.0", 63 | "highlightjs-func": "github:orbs-network/highlightjs-func", 64 | "ton": "^13.3.0" 65 | }, 66 | "devDependencies": { 67 | "@types/node": "^18.11.18", 68 | "esbuild": "^0.16.16", 69 | "esbuild-plugin-polyfill-node": "^0.1.3", 70 | "eslint": "^8.31.0", 71 | "source-map-explorer": "^2.5.3", 72 | "tslint": "^6.1.3", 73 | "tslint-config-prettier": "^1.18.0" 74 | }, 75 | "engines": { 76 | "node": ">=14.16" 77 | } 78 | }, 79 | "node_modules/@esbuild/android-arm": { 80 | "version": "0.15.10", 81 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.10.tgz", 82 | "integrity": "sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==", 83 | "cpu": [ 84 | "arm" 85 | ], 86 | "dev": true, 87 | "optional": true, 88 | "os": [ 89 | "android" 90 | ], 91 | "engines": { 92 | "node": ">=12" 93 | } 94 | }, 95 | "node_modules/@esbuild/linux-loong64": { 96 | "version": "0.15.10", 97 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", 98 | "integrity": "sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==", 99 | "cpu": [ 100 | "loong64" 101 | ], 102 | "dev": true, 103 | "optional": true, 104 | "os": [ 105 | "linux" 106 | ], 107 | "engines": { 108 | "node": ">=12" 109 | } 110 | }, 111 | "node_modules/@ton-community/contract-verifier-sdk": { 112 | "resolved": "../..", 113 | "link": true 114 | }, 115 | "node_modules/esbuild": { 116 | "version": "0.15.10", 117 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", 118 | "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", 119 | "dev": true, 120 | "hasInstallScript": true, 121 | "bin": { 122 | "esbuild": "bin/esbuild" 123 | }, 124 | "engines": { 125 | "node": ">=12" 126 | }, 127 | "optionalDependencies": { 128 | "@esbuild/android-arm": "0.15.10", 129 | "@esbuild/linux-loong64": "0.15.10", 130 | "esbuild-android-64": "0.15.10", 131 | "esbuild-android-arm64": "0.15.10", 132 | "esbuild-darwin-64": "0.15.10", 133 | "esbuild-darwin-arm64": "0.15.10", 134 | "esbuild-freebsd-64": "0.15.10", 135 | "esbuild-freebsd-arm64": "0.15.10", 136 | "esbuild-linux-32": "0.15.10", 137 | "esbuild-linux-64": "0.15.10", 138 | "esbuild-linux-arm": "0.15.10", 139 | "esbuild-linux-arm64": "0.15.10", 140 | "esbuild-linux-mips64le": "0.15.10", 141 | "esbuild-linux-ppc64le": "0.15.10", 142 | "esbuild-linux-riscv64": "0.15.10", 143 | "esbuild-linux-s390x": "0.15.10", 144 | "esbuild-netbsd-64": "0.15.10", 145 | "esbuild-openbsd-64": "0.15.10", 146 | "esbuild-sunos-64": "0.15.10", 147 | "esbuild-windows-32": "0.15.10", 148 | "esbuild-windows-64": "0.15.10", 149 | "esbuild-windows-arm64": "0.15.10" 150 | } 151 | }, 152 | "node_modules/esbuild-android-64": { 153 | "version": "0.15.10", 154 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.10.tgz", 155 | "integrity": "sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==", 156 | "cpu": [ 157 | "x64" 158 | ], 159 | "dev": true, 160 | "optional": true, 161 | "os": [ 162 | "android" 163 | ], 164 | "engines": { 165 | "node": ">=12" 166 | } 167 | }, 168 | "node_modules/esbuild-android-arm64": { 169 | "version": "0.15.10", 170 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.10.tgz", 171 | "integrity": "sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==", 172 | "cpu": [ 173 | "arm64" 174 | ], 175 | "dev": true, 176 | "optional": true, 177 | "os": [ 178 | "android" 179 | ], 180 | "engines": { 181 | "node": ">=12" 182 | } 183 | }, 184 | "node_modules/esbuild-darwin-64": { 185 | "version": "0.15.10", 186 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.10.tgz", 187 | "integrity": "sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==", 188 | "cpu": [ 189 | "x64" 190 | ], 191 | "dev": true, 192 | "optional": true, 193 | "os": [ 194 | "darwin" 195 | ], 196 | "engines": { 197 | "node": ">=12" 198 | } 199 | }, 200 | "node_modules/esbuild-darwin-arm64": { 201 | "version": "0.15.10", 202 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.10.tgz", 203 | "integrity": "sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==", 204 | "cpu": [ 205 | "arm64" 206 | ], 207 | "dev": true, 208 | "optional": true, 209 | "os": [ 210 | "darwin" 211 | ], 212 | "engines": { 213 | "node": ">=12" 214 | } 215 | }, 216 | "node_modules/esbuild-freebsd-64": { 217 | "version": "0.15.10", 218 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.10.tgz", 219 | "integrity": "sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==", 220 | "cpu": [ 221 | "x64" 222 | ], 223 | "dev": true, 224 | "optional": true, 225 | "os": [ 226 | "freebsd" 227 | ], 228 | "engines": { 229 | "node": ">=12" 230 | } 231 | }, 232 | "node_modules/esbuild-freebsd-arm64": { 233 | "version": "0.15.10", 234 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.10.tgz", 235 | "integrity": "sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==", 236 | "cpu": [ 237 | "arm64" 238 | ], 239 | "dev": true, 240 | "optional": true, 241 | "os": [ 242 | "freebsd" 243 | ], 244 | "engines": { 245 | "node": ">=12" 246 | } 247 | }, 248 | "node_modules/esbuild-linux-32": { 249 | "version": "0.15.10", 250 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.10.tgz", 251 | "integrity": "sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==", 252 | "cpu": [ 253 | "ia32" 254 | ], 255 | "dev": true, 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": ">=12" 262 | } 263 | }, 264 | "node_modules/esbuild-linux-64": { 265 | "version": "0.15.10", 266 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.10.tgz", 267 | "integrity": "sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==", 268 | "cpu": [ 269 | "x64" 270 | ], 271 | "dev": true, 272 | "optional": true, 273 | "os": [ 274 | "linux" 275 | ], 276 | "engines": { 277 | "node": ">=12" 278 | } 279 | }, 280 | "node_modules/esbuild-linux-arm": { 281 | "version": "0.15.10", 282 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.10.tgz", 283 | "integrity": "sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==", 284 | "cpu": [ 285 | "arm" 286 | ], 287 | "dev": true, 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ], 292 | "engines": { 293 | "node": ">=12" 294 | } 295 | }, 296 | "node_modules/esbuild-linux-arm64": { 297 | "version": "0.15.10", 298 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.10.tgz", 299 | "integrity": "sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==", 300 | "cpu": [ 301 | "arm64" 302 | ], 303 | "dev": true, 304 | "optional": true, 305 | "os": [ 306 | "linux" 307 | ], 308 | "engines": { 309 | "node": ">=12" 310 | } 311 | }, 312 | "node_modules/esbuild-linux-mips64le": { 313 | "version": "0.15.10", 314 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.10.tgz", 315 | "integrity": "sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==", 316 | "cpu": [ 317 | "mips64el" 318 | ], 319 | "dev": true, 320 | "optional": true, 321 | "os": [ 322 | "linux" 323 | ], 324 | "engines": { 325 | "node": ">=12" 326 | } 327 | }, 328 | "node_modules/esbuild-linux-ppc64le": { 329 | "version": "0.15.10", 330 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.10.tgz", 331 | "integrity": "sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==", 332 | "cpu": [ 333 | "ppc64" 334 | ], 335 | "dev": true, 336 | "optional": true, 337 | "os": [ 338 | "linux" 339 | ], 340 | "engines": { 341 | "node": ">=12" 342 | } 343 | }, 344 | "node_modules/esbuild-linux-riscv64": { 345 | "version": "0.15.10", 346 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.10.tgz", 347 | "integrity": "sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==", 348 | "cpu": [ 349 | "riscv64" 350 | ], 351 | "dev": true, 352 | "optional": true, 353 | "os": [ 354 | "linux" 355 | ], 356 | "engines": { 357 | "node": ">=12" 358 | } 359 | }, 360 | "node_modules/esbuild-linux-s390x": { 361 | "version": "0.15.10", 362 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.10.tgz", 363 | "integrity": "sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==", 364 | "cpu": [ 365 | "s390x" 366 | ], 367 | "dev": true, 368 | "optional": true, 369 | "os": [ 370 | "linux" 371 | ], 372 | "engines": { 373 | "node": ">=12" 374 | } 375 | }, 376 | "node_modules/esbuild-netbsd-64": { 377 | "version": "0.15.10", 378 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.10.tgz", 379 | "integrity": "sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==", 380 | "cpu": [ 381 | "x64" 382 | ], 383 | "dev": true, 384 | "optional": true, 385 | "os": [ 386 | "netbsd" 387 | ], 388 | "engines": { 389 | "node": ">=12" 390 | } 391 | }, 392 | "node_modules/esbuild-openbsd-64": { 393 | "version": "0.15.10", 394 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.10.tgz", 395 | "integrity": "sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==", 396 | "cpu": [ 397 | "x64" 398 | ], 399 | "dev": true, 400 | "optional": true, 401 | "os": [ 402 | "openbsd" 403 | ], 404 | "engines": { 405 | "node": ">=12" 406 | } 407 | }, 408 | "node_modules/esbuild-sunos-64": { 409 | "version": "0.15.10", 410 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.10.tgz", 411 | "integrity": "sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==", 412 | "cpu": [ 413 | "x64" 414 | ], 415 | "dev": true, 416 | "optional": true, 417 | "os": [ 418 | "sunos" 419 | ], 420 | "engines": { 421 | "node": ">=12" 422 | } 423 | }, 424 | "node_modules/esbuild-windows-32": { 425 | "version": "0.15.10", 426 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.10.tgz", 427 | "integrity": "sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==", 428 | "cpu": [ 429 | "ia32" 430 | ], 431 | "dev": true, 432 | "optional": true, 433 | "os": [ 434 | "win32" 435 | ], 436 | "engines": { 437 | "node": ">=12" 438 | } 439 | }, 440 | "node_modules/esbuild-windows-64": { 441 | "version": "0.15.10", 442 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", 443 | "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", 444 | "cpu": [ 445 | "x64" 446 | ], 447 | "dev": true, 448 | "optional": true, 449 | "os": [ 450 | "win32" 451 | ], 452 | "engines": { 453 | "node": ">=12" 454 | } 455 | }, 456 | "node_modules/esbuild-windows-arm64": { 457 | "version": "0.15.10", 458 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.10.tgz", 459 | "integrity": "sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==", 460 | "cpu": [ 461 | "arm64" 462 | ], 463 | "dev": true, 464 | "optional": true, 465 | "os": [ 466 | "win32" 467 | ], 468 | "engines": { 469 | "node": ">=12" 470 | } 471 | }, 472 | "node_modules/fsevents": { 473 | "version": "2.3.2", 474 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 475 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 476 | "dev": true, 477 | "hasInstallScript": true, 478 | "optional": true, 479 | "os": [ 480 | "darwin" 481 | ], 482 | "engines": { 483 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 484 | } 485 | }, 486 | "node_modules/function-bind": { 487 | "version": "1.1.1", 488 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 489 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 490 | "dev": true 491 | }, 492 | "node_modules/has": { 493 | "version": "1.0.3", 494 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 495 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 496 | "dev": true, 497 | "dependencies": { 498 | "function-bind": "^1.1.1" 499 | }, 500 | "engines": { 501 | "node": ">= 0.4.0" 502 | } 503 | }, 504 | "node_modules/is-core-module": { 505 | "version": "2.10.0", 506 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", 507 | "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", 508 | "dev": true, 509 | "dependencies": { 510 | "has": "^1.0.3" 511 | }, 512 | "funding": { 513 | "url": "https://github.com/sponsors/ljharb" 514 | } 515 | }, 516 | "node_modules/nanoid": { 517 | "version": "3.3.4", 518 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 519 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 520 | "dev": true, 521 | "bin": { 522 | "nanoid": "bin/nanoid.cjs" 523 | }, 524 | "engines": { 525 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 526 | } 527 | }, 528 | "node_modules/path-parse": { 529 | "version": "1.0.7", 530 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 531 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 532 | "dev": true 533 | }, 534 | "node_modules/picocolors": { 535 | "version": "1.0.0", 536 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 537 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 538 | "dev": true 539 | }, 540 | "node_modules/postcss": { 541 | "version": "8.4.17", 542 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", 543 | "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", 544 | "dev": true, 545 | "funding": [ 546 | { 547 | "type": "opencollective", 548 | "url": "https://opencollective.com/postcss/" 549 | }, 550 | { 551 | "type": "tidelift", 552 | "url": "https://tidelift.com/funding/github/npm/postcss" 553 | } 554 | ], 555 | "dependencies": { 556 | "nanoid": "^3.3.4", 557 | "picocolors": "^1.0.0", 558 | "source-map-js": "^1.0.2" 559 | }, 560 | "engines": { 561 | "node": "^10 || ^12 || >=14" 562 | } 563 | }, 564 | "node_modules/resolve": { 565 | "version": "1.22.1", 566 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 567 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 568 | "dev": true, 569 | "dependencies": { 570 | "is-core-module": "^2.9.0", 571 | "path-parse": "^1.0.7", 572 | "supports-preserve-symlinks-flag": "^1.0.0" 573 | }, 574 | "bin": { 575 | "resolve": "bin/resolve" 576 | }, 577 | "funding": { 578 | "url": "https://github.com/sponsors/ljharb" 579 | } 580 | }, 581 | "node_modules/rollup": { 582 | "version": "2.78.1", 583 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", 584 | "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", 585 | "dev": true, 586 | "bin": { 587 | "rollup": "dist/bin/rollup" 588 | }, 589 | "engines": { 590 | "node": ">=10.0.0" 591 | }, 592 | "optionalDependencies": { 593 | "fsevents": "~2.3.2" 594 | } 595 | }, 596 | "node_modules/source-map-js": { 597 | "version": "1.0.2", 598 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 599 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 600 | "dev": true, 601 | "engines": { 602 | "node": ">=0.10.0" 603 | } 604 | }, 605 | "node_modules/supports-preserve-symlinks-flag": { 606 | "version": "1.0.0", 607 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 608 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 609 | "dev": true, 610 | "engines": { 611 | "node": ">= 0.4" 612 | }, 613 | "funding": { 614 | "url": "https://github.com/sponsors/ljharb" 615 | } 616 | }, 617 | "node_modules/typescript": { 618 | "version": "4.8.4", 619 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", 620 | "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", 621 | "dev": true, 622 | "bin": { 623 | "tsc": "bin/tsc", 624 | "tsserver": "bin/tsserver" 625 | }, 626 | "engines": { 627 | "node": ">=4.2.0" 628 | } 629 | }, 630 | "node_modules/vite": { 631 | "version": "3.1.7", 632 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.7.tgz", 633 | "integrity": "sha512-5vCAmU4S8lyVdFCInu9M54f/g8qbOMakVw5xJ4pjoaDy5wgy9sLLZkGdSLN52dlsBqh0tBqxjaqqa8LgPqwRAA==", 634 | "dev": true, 635 | "dependencies": { 636 | "esbuild": "^0.15.9", 637 | "postcss": "^8.4.16", 638 | "resolve": "^1.22.1", 639 | "rollup": "~2.78.0" 640 | }, 641 | "bin": { 642 | "vite": "bin/vite.js" 643 | }, 644 | "engines": { 645 | "node": "^14.18.0 || >=16.0.0" 646 | }, 647 | "optionalDependencies": { 648 | "fsevents": "~2.3.2" 649 | }, 650 | "peerDependencies": { 651 | "less": "*", 652 | "sass": "*", 653 | "stylus": "*", 654 | "terser": "^5.4.0" 655 | }, 656 | "peerDependenciesMeta": { 657 | "less": { 658 | "optional": true 659 | }, 660 | "sass": { 661 | "optional": true 662 | }, 663 | "stylus": { 664 | "optional": true 665 | }, 666 | "terser": { 667 | "optional": true 668 | } 669 | } 670 | } 671 | }, 672 | "dependencies": { 673 | "@esbuild/android-arm": { 674 | "version": "0.15.10", 675 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.10.tgz", 676 | "integrity": "sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==", 677 | "dev": true, 678 | "optional": true 679 | }, 680 | "@esbuild/linux-loong64": { 681 | "version": "0.15.10", 682 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", 683 | "integrity": "sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==", 684 | "dev": true, 685 | "optional": true 686 | }, 687 | "@ton-community/contract-verifier-sdk": { 688 | "version": "file:../..", 689 | "requires": { 690 | "@aws-crypto/sha256-js": "^2.0.2", 691 | "@orbs-network/ton-access": "^2.2.2", 692 | "@types/node": "^18.11.18", 693 | "esbuild": "^0.16.16", 694 | "esbuild-plugin-polyfill-node": "^0.1.3", 695 | "eslint": "^8.31.0", 696 | "highlight.js": "^11.6.0", 697 | "highlightjs-func": "github:orbs-network/highlightjs-func", 698 | "source-map-explorer": "^2.5.3", 699 | "ton": "^13.3.0", 700 | "tslint": "^6.1.3", 701 | "tslint-config-prettier": "^1.18.0" 702 | } 703 | }, 704 | "esbuild": { 705 | "version": "0.15.10", 706 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", 707 | "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", 708 | "dev": true, 709 | "requires": { 710 | "@esbuild/android-arm": "0.15.10", 711 | "@esbuild/linux-loong64": "0.15.10", 712 | "esbuild-android-64": "0.15.10", 713 | "esbuild-android-arm64": "0.15.10", 714 | "esbuild-darwin-64": "0.15.10", 715 | "esbuild-darwin-arm64": "0.15.10", 716 | "esbuild-freebsd-64": "0.15.10", 717 | "esbuild-freebsd-arm64": "0.15.10", 718 | "esbuild-linux-32": "0.15.10", 719 | "esbuild-linux-64": "0.15.10", 720 | "esbuild-linux-arm": "0.15.10", 721 | "esbuild-linux-arm64": "0.15.10", 722 | "esbuild-linux-mips64le": "0.15.10", 723 | "esbuild-linux-ppc64le": "0.15.10", 724 | "esbuild-linux-riscv64": "0.15.10", 725 | "esbuild-linux-s390x": "0.15.10", 726 | "esbuild-netbsd-64": "0.15.10", 727 | "esbuild-openbsd-64": "0.15.10", 728 | "esbuild-sunos-64": "0.15.10", 729 | "esbuild-windows-32": "0.15.10", 730 | "esbuild-windows-64": "0.15.10", 731 | "esbuild-windows-arm64": "0.15.10" 732 | } 733 | }, 734 | "esbuild-android-64": { 735 | "version": "0.15.10", 736 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.10.tgz", 737 | "integrity": "sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==", 738 | "dev": true, 739 | "optional": true 740 | }, 741 | "esbuild-android-arm64": { 742 | "version": "0.15.10", 743 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.10.tgz", 744 | "integrity": "sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==", 745 | "dev": true, 746 | "optional": true 747 | }, 748 | "esbuild-darwin-64": { 749 | "version": "0.15.10", 750 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.10.tgz", 751 | "integrity": "sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==", 752 | "dev": true, 753 | "optional": true 754 | }, 755 | "esbuild-darwin-arm64": { 756 | "version": "0.15.10", 757 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.10.tgz", 758 | "integrity": "sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==", 759 | "dev": true, 760 | "optional": true 761 | }, 762 | "esbuild-freebsd-64": { 763 | "version": "0.15.10", 764 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.10.tgz", 765 | "integrity": "sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==", 766 | "dev": true, 767 | "optional": true 768 | }, 769 | "esbuild-freebsd-arm64": { 770 | "version": "0.15.10", 771 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.10.tgz", 772 | "integrity": "sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==", 773 | "dev": true, 774 | "optional": true 775 | }, 776 | "esbuild-linux-32": { 777 | "version": "0.15.10", 778 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.10.tgz", 779 | "integrity": "sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==", 780 | "dev": true, 781 | "optional": true 782 | }, 783 | "esbuild-linux-64": { 784 | "version": "0.15.10", 785 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.10.tgz", 786 | "integrity": "sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==", 787 | "dev": true, 788 | "optional": true 789 | }, 790 | "esbuild-linux-arm": { 791 | "version": "0.15.10", 792 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.10.tgz", 793 | "integrity": "sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==", 794 | "dev": true, 795 | "optional": true 796 | }, 797 | "esbuild-linux-arm64": { 798 | "version": "0.15.10", 799 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.10.tgz", 800 | "integrity": "sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==", 801 | "dev": true, 802 | "optional": true 803 | }, 804 | "esbuild-linux-mips64le": { 805 | "version": "0.15.10", 806 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.10.tgz", 807 | "integrity": "sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==", 808 | "dev": true, 809 | "optional": true 810 | }, 811 | "esbuild-linux-ppc64le": { 812 | "version": "0.15.10", 813 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.10.tgz", 814 | "integrity": "sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==", 815 | "dev": true, 816 | "optional": true 817 | }, 818 | "esbuild-linux-riscv64": { 819 | "version": "0.15.10", 820 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.10.tgz", 821 | "integrity": "sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==", 822 | "dev": true, 823 | "optional": true 824 | }, 825 | "esbuild-linux-s390x": { 826 | "version": "0.15.10", 827 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.10.tgz", 828 | "integrity": "sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==", 829 | "dev": true, 830 | "optional": true 831 | }, 832 | "esbuild-netbsd-64": { 833 | "version": "0.15.10", 834 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.10.tgz", 835 | "integrity": "sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==", 836 | "dev": true, 837 | "optional": true 838 | }, 839 | "esbuild-openbsd-64": { 840 | "version": "0.15.10", 841 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.10.tgz", 842 | "integrity": "sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==", 843 | "dev": true, 844 | "optional": true 845 | }, 846 | "esbuild-sunos-64": { 847 | "version": "0.15.10", 848 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.10.tgz", 849 | "integrity": "sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==", 850 | "dev": true, 851 | "optional": true 852 | }, 853 | "esbuild-windows-32": { 854 | "version": "0.15.10", 855 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.10.tgz", 856 | "integrity": "sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==", 857 | "dev": true, 858 | "optional": true 859 | }, 860 | "esbuild-windows-64": { 861 | "version": "0.15.10", 862 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", 863 | "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", 864 | "dev": true, 865 | "optional": true 866 | }, 867 | "esbuild-windows-arm64": { 868 | "version": "0.15.10", 869 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.10.tgz", 870 | "integrity": "sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==", 871 | "dev": true, 872 | "optional": true 873 | }, 874 | "fsevents": { 875 | "version": "2.3.2", 876 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 877 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 878 | "dev": true, 879 | "optional": true 880 | }, 881 | "function-bind": { 882 | "version": "1.1.1", 883 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 884 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 885 | "dev": true 886 | }, 887 | "has": { 888 | "version": "1.0.3", 889 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 890 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 891 | "dev": true, 892 | "requires": { 893 | "function-bind": "^1.1.1" 894 | } 895 | }, 896 | "is-core-module": { 897 | "version": "2.10.0", 898 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", 899 | "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", 900 | "dev": true, 901 | "requires": { 902 | "has": "^1.0.3" 903 | } 904 | }, 905 | "nanoid": { 906 | "version": "3.3.4", 907 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 908 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 909 | "dev": true 910 | }, 911 | "path-parse": { 912 | "version": "1.0.7", 913 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 914 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 915 | "dev": true 916 | }, 917 | "picocolors": { 918 | "version": "1.0.0", 919 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 920 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 921 | "dev": true 922 | }, 923 | "postcss": { 924 | "version": "8.4.17", 925 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", 926 | "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", 927 | "dev": true, 928 | "requires": { 929 | "nanoid": "^3.3.4", 930 | "picocolors": "^1.0.0", 931 | "source-map-js": "^1.0.2" 932 | } 933 | }, 934 | "resolve": { 935 | "version": "1.22.1", 936 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 937 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 938 | "dev": true, 939 | "requires": { 940 | "is-core-module": "^2.9.0", 941 | "path-parse": "^1.0.7", 942 | "supports-preserve-symlinks-flag": "^1.0.0" 943 | } 944 | }, 945 | "rollup": { 946 | "version": "2.78.1", 947 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", 948 | "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", 949 | "dev": true, 950 | "requires": { 951 | "fsevents": "~2.3.2" 952 | } 953 | }, 954 | "source-map-js": { 955 | "version": "1.0.2", 956 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 957 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 958 | "dev": true 959 | }, 960 | "supports-preserve-symlinks-flag": { 961 | "version": "1.0.0", 962 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 963 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 964 | "dev": true 965 | }, 966 | "typescript": { 967 | "version": "4.8.4", 968 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", 969 | "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", 970 | "dev": true 971 | }, 972 | "vite": { 973 | "version": "3.1.7", 974 | "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.7.tgz", 975 | "integrity": "sha512-5vCAmU4S8lyVdFCInu9M54f/g8qbOMakVw5xJ4pjoaDy5wgy9sLLZkGdSLN52dlsBqh0tBqxjaqqa8LgPqwRAA==", 976 | "dev": true, 977 | "requires": { 978 | "esbuild": "^0.15.9", 979 | "fsevents": "~2.3.2", 980 | "postcss": "^8.4.16", 981 | "resolve": "^1.22.1", 982 | "rollup": "~2.78.0" 983 | } 984 | } 985 | } 986 | } 987 | -------------------------------------------------------------------------------- /example/vanilla-vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "typescript": "^4.6.4", 13 | "vite": "^3.1.0" 14 | }, 15 | "dependencies": { 16 | "@ton-community/contract-verifier-sdk": "file:../.." 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/vanilla-vite/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/vanilla-vite/src/counter.ts: -------------------------------------------------------------------------------- 1 | export function setupCounter(element: HTMLButtonElement) { 2 | let counter = 0 3 | const setCounter = (count: number) => { 4 | counter = count 5 | element.innerHTML = `count is ${counter}` 6 | } 7 | element.addEventListener('click', () => setCounter(++counter)) 8 | setCounter(0) 9 | } 10 | -------------------------------------------------------------------------------- /example/vanilla-vite/src/main.ts: -------------------------------------------------------------------------------- 1 | import "./style.css"; 2 | 3 | import "@ton-community/contract-verifier-sdk"; 4 | 5 | document.querySelector("#app")!.innerHTML = ` 6 |
7 |

Code Verifier UI Demo

8 | 9 |

Full

10 |
11 |
12 |
13 |
14 |
15 |
16 | 17 |

No line numbers

18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 |

No Files

26 |
27 |
28 |
29 |
30 | 31 | 32 |

With Explanation

33 |
34 |
35 |
36 |
37 |
38 | 52 |
53 | 54 |

Vertical

55 |
56 |
57 |
58 |
59 |
60 |
61 | 62 |
63 | `; 64 | 65 | window.onload = async () => { 66 | const ipfslink = await ContractVerifier.getSourcesJsonUrl( 67 | "E/XXoxbG124QU+iKxZtd5loHKjiEUTcdxcW+y7oT9Q4=" 68 | // "/rX/aCDi/w2Ug+fg1iyBfYRniftK5YDIeIZtlZ2r1cA=" 69 | // "p6Jhak1jmgdsL2fnzOBCP9Khwu5VCtZRwe2hbuE7yso=" 70 | // { httpApiEndpoint: "https://scalable-api.tonwhales.com/jsonRPC" } 71 | ); 72 | 73 | if (ipfslink) { 74 | const sourcesData = await ContractVerifier.getSourcesData(ipfslink); 75 | 76 | const theme = 77 | window.matchMedia && 78 | window.matchMedia("(prefers-color-scheme: dark)").matches 79 | ? "dark" 80 | : "light"; 81 | 82 | // Full 83 | ContractVerifierUI.loadSourcesData(sourcesData, { 84 | containerSelector: "#myContainerFull", 85 | fileListSelector: "#myFilesFull", 86 | contentSelector: "#myContentFull", 87 | theme, 88 | }); 89 | 90 | // No line num 91 | ContractVerifierUI.loadSourcesData(sourcesData, { 92 | containerSelector: "#myContainerNoLineNum", 93 | fileListSelector: "#myFilesNoLineNum", 94 | contentSelector: "#myContentNoLineNum", 95 | theme, 96 | hideLineNumbers: true, 97 | }); 98 | 99 | // No files 100 | ContractVerifierUI.loadSourcesData(sourcesData, { 101 | containerSelector: "#myContainerNoFiles", 102 | contentSelector: "#myContentNoFiles", 103 | theme, 104 | }); 105 | 106 | (document.querySelector("#container-nofiles-btn")! as HTMLElement).onclick = 107 | () => { 108 | ContractVerifierUI.setCode( 109 | "#myContentNoFiles", 110 | sourcesData.files[1].content 111 | ); 112 | }; 113 | 114 | // Explanation 115 | ContractVerifierUI.loadSourcesData(sourcesData, { 116 | containerSelector: "#myContainerExplanation", 117 | fileListSelector: "#myFilesExplanation", 118 | contentSelector: "#myContentExplanation", 119 | theme, 120 | }); 121 | 122 | // Vertical 123 | ContractVerifierUI.loadSourcesData(sourcesData, { 124 | containerSelector: "#myContainerVertical", 125 | fileListSelector: "#myFilesVertical", 126 | contentSelector: "#myContentVertical", 127 | theme, 128 | }); 129 | 130 | (document.querySelector("#explanation") as HTMLElement).style.visibility = 131 | ""; 132 | } 133 | }; 134 | -------------------------------------------------------------------------------- /example/vanilla-vite/src/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #242424; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | a { 19 | font-weight: 500; 20 | color: #646cff; 21 | text-decoration: inherit; 22 | } 23 | a:hover { 24 | color: #535bf2; 25 | } 26 | 27 | body { 28 | margin: 0; 29 | display: flex; 30 | place-items: center; 31 | min-width: 320px; 32 | min-height: 100vh; 33 | } 34 | 35 | h1 { 36 | font-size: 3.2em; 37 | line-height: 1.1; 38 | } 39 | 40 | #app { 41 | max-width: 1280px; 42 | margin: 0 auto; 43 | padding: 2rem; 44 | text-align: center; 45 | width: 100%; 46 | } 47 | 48 | .logo { 49 | height: 6em; 50 | padding: 1.5em; 51 | will-change: filter; 52 | } 53 | .logo:hover { 54 | filter: drop-shadow(0 0 2em #646cffaa); 55 | } 56 | .logo.vanilla:hover { 57 | filter: drop-shadow(0 0 2em #3178c6aa); 58 | } 59 | 60 | .card { 61 | padding: 2em; 62 | } 63 | 64 | .read-the-docs { 65 | color: #888; 66 | } 67 | 68 | button { 69 | border-radius: 8px; 70 | border: 1px solid transparent; 71 | padding: 0.6em 1.2em; 72 | font-size: 1em; 73 | font-weight: 500; 74 | font-family: inherit; 75 | background-color: #1a1a1a; 76 | cursor: pointer; 77 | transition: border-color 0.25s; 78 | } 79 | button:hover { 80 | border-color: #646cff; 81 | } 82 | button:focus, 83 | button:focus-visible { 84 | outline: 4px auto -webkit-focus-ring-color; 85 | } 86 | 87 | @media (prefers-color-scheme: light) { 88 | :root { 89 | color: #213547; 90 | background-color: #c6c6c6; 91 | } 92 | a:hover { 93 | color: #747bff; 94 | } 95 | button { 96 | background-color: #f9f9f9; 97 | } 98 | } 99 | 100 | #explanation { 101 | padding-top: 30px; 102 | background-color: black; 103 | } 104 | 105 | .contract-verifier-container { 106 | height: 500px; 107 | } -------------------------------------------------------------------------------- /example/vanilla-vite/src/typescript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/vanilla-vite/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /example/vanilla-vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ESNext", "DOM"], 7 | "moduleResolution": "Node", 8 | "strict": true, 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "noEmit": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "skipLibCheck": true 18 | }, 19 | "include": ["src"], 20 | } 21 | -------------------------------------------------------------------------------- /lib/contract-verifier-ui.d.ts: -------------------------------------------------------------------------------- 1 | import { SourcesData } from "./contract-verifier"; 2 | type Theme = "light" | "dark"; 3 | export declare const classNames: { 4 | CONTAINER: string; 5 | FILES: string; 6 | FILE: string; 7 | FOLDER: string; 8 | TREE_ITEM: string; 9 | FOLDER_CONTAINER: string; 10 | CODE_CONTAINER: string; 11 | CODE_LINES: string; 12 | CODE_CONTENT: string; 13 | }; 14 | export declare const ContractVerifierUI: { 15 | _stylesPopulated: { 16 | internal: boolean; 17 | }; 18 | _populateStyle(theme: "dark" | "light"): void; 19 | _populateCode(contentSelector: string, theme: "dark" | "light"): void; 20 | _setCode({ name, content }: { 21 | name: string; 22 | content: string; 23 | }, codeWrapperEl: HTMLElement, filesListEl?: HTMLElement, fileEl?: HTMLElement): void; 24 | setCode(contentSelector: string, content: string): void; 25 | _populateFiles(fileListSelector: string, contentSelector: string, files: { 26 | name: string; 27 | content: string; 28 | }[], theme: "dark" | "light"): void; 29 | _populateContainer(selector: string, hideLineNumbers: boolean): void; 30 | loadSourcesData(sourcesData: SourcesData, opts: { 31 | containerSelector: string; 32 | fileListSelector?: string; 33 | contentSelector: string; 34 | theme: Theme; 35 | hideLineNumbers?: boolean; 36 | }): void; 37 | }; 38 | export {}; 39 | -------------------------------------------------------------------------------- /lib/contract-verifier-ui.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.ContractVerifierUI = exports.classNames = void 0; 7 | const core_1 = __importDefault(require("highlight.js/lib/core")); 8 | const highlightjs_func_1 = __importDefault(require("highlightjs-func")); 9 | const dom_1 = require("./dom"); 10 | const file_structure_1 = require("./file-structure"); 11 | const style_css_1 = __importDefault(require("./style.css")); 12 | (0, highlightjs_func_1.default)(core_1.default); 13 | exports.classNames = { 14 | CONTAINER: "contract-verifier-container", 15 | FILES: "contract-verifier-files", 16 | FILE: "contract-verifier-file", 17 | FOLDER: "contract-verifier-folder", 18 | TREE_ITEM: "contract-verifier-tree-item", 19 | FOLDER_CONTAINER: "contract-verifier-folder-container", 20 | CODE_CONTAINER: "contract-verifier-code", 21 | CODE_LINES: "contract-verifier-code-lines", 22 | CODE_CONTENT: "contract-verifier-code-content", 23 | }; 24 | exports.ContractVerifierUI = { 25 | _stylesPopulated: { 26 | internal: false, 27 | }, 28 | _populateStyle(theme) { 29 | if (!this._stylesPopulated[theme]) { 30 | this._stylesPopulated[theme] = true; 31 | const styleEl = document.createElement("style"); 32 | styleEl.innerHTML = `${theme === "light" 33 | ? require("highlight.js/styles/atom-one-light.css").toString() 34 | : require("highlight.js/styles/atom-one-dark.css").toString()}`; 35 | document.head.appendChild(styleEl); 36 | } 37 | if (!this._stylesPopulated.internal) { 38 | this._stylesPopulated.internal = true; 39 | const styleEl = document.createElement("style"); 40 | styleEl.innerHTML = style_css_1.default; 41 | document.head.appendChild(styleEl); 42 | } 43 | }, 44 | _populateCode(contentSelector, theme) { 45 | const codeContainer = document.querySelector(contentSelector); 46 | codeContainer.classList.add(exports.classNames.CODE_CONTAINER); 47 | codeContainer.classList.add(theme); 48 | codeContainer.innerHTML = `
`; 49 | }, 50 | _setCode({ name, content }, codeWrapperEl, filesListEl, fileEl) { 51 | if (fileEl?.classList.contains("active")) 52 | return; 53 | codeWrapperEl.scrollTo(0, 0); 54 | content = content.trim(); 55 | const codeEl = codeWrapperEl.querySelector("code"); 56 | codeEl.innerHTML = ""; 57 | codeEl.appendChild((0, dom_1.div)({ className: exports.classNames.CODE_LINES }, content 58 | .split("\n") 59 | .map((_, i) => i + 1) 60 | .join("\n"))); 61 | const contentEl = (0, dom_1.div)({ className: exports.classNames.CODE_CONTENT }, content); 62 | codeEl.appendChild(contentEl); 63 | if (name.match(/\.fif(t)?$/)) { 64 | contentEl.classList.add("language-fift"); 65 | } 66 | else { 67 | contentEl.classList.add("language-func"); 68 | } 69 | core_1.default.highlightElement(contentEl); 70 | filesListEl 71 | ?.querySelector(`.${exports.classNames.FILE}.active`) 72 | ?.classList.remove("active"); 73 | fileEl?.classList.add("active"); 74 | }, 75 | setCode(contentSelector, content) { 76 | this._setCode({ name: "", content }, document.querySelector(contentSelector)); 77 | }, 78 | _populateFiles(fileListSelector, contentSelector, files, theme) { 79 | const filePart = document.querySelector(fileListSelector); 80 | filePart.innerHTML = ""; 81 | filePart.classList.add(theme); 82 | filePart.classList.add(exports.classNames.FILES); 83 | // Prepare folder hierarchy 84 | const root = { 85 | type: "root", 86 | children: [], 87 | }; 88 | files.forEach((file) => { 89 | const nameParts = Array.from(file.name.matchAll(/(?:\/|^)([^\/\n]+)/g)).map((m) => m[1]); 90 | const folders = nameParts.length > 1 ? nameParts.slice(0, nameParts.length - 1) : []; 91 | let levelToPushTo = root; 92 | folders.forEach((folder) => { 93 | let existingFolder = levelToPushTo.children.find((obj) => obj.type === "folder" && obj.name === folder); 94 | if (!existingFolder) { 95 | const newLevel = { 96 | type: "folder", 97 | name: folder, 98 | children: [], 99 | }; 100 | levelToPushTo.children.push(newLevel); 101 | existingFolder = newLevel; 102 | } 103 | levelToPushTo = existingFolder; 104 | }); 105 | levelToPushTo.children.push({ 106 | type: "file", 107 | name: nameParts[nameParts.length - 1], 108 | content: file.content, 109 | }); 110 | }); 111 | function processLevel(level) { 112 | return level.children 113 | .filter((obj) => obj.type === "file") 114 | .map((child) => { 115 | const file = (0, file_structure_1.TreeFile)({ name: child.name }, theme); 116 | file.onclick = () => { 117 | exports.ContractVerifierUI._setCode({ name: child.name, content: child.content }, document.querySelector(contentSelector), document.querySelector(fileListSelector), file); 118 | }; 119 | return file; 120 | }) 121 | .concat(level.children 122 | .filter((obj) => obj.type === "folder") 123 | .map((child) => (0, file_structure_1.TreeFolder)({ name: child.name, opened: true }, theme, ...processLevel(child)))); 124 | } 125 | processLevel(root).forEach((el) => filePart.appendChild(el)); 126 | }, 127 | _populateContainer(selector, hideLineNumbers) { 128 | const el = document.querySelector(selector); 129 | el.classList.add(exports.classNames.CONTAINER); 130 | if (!hideLineNumbers) { 131 | el.classList.add("lineNumbers"); 132 | } 133 | }, 134 | loadSourcesData(sourcesData, opts) { 135 | this._populateContainer(opts.containerSelector, !!opts.hideLineNumbers); 136 | if (opts.fileListSelector) { 137 | this._populateFiles(opts.fileListSelector, opts.contentSelector, sourcesData.files, opts.theme); 138 | } 139 | this._populateStyle(opts.theme); 140 | this._populateCode(opts.contentSelector, opts.theme); 141 | this._setCode(sourcesData.files[0], document.querySelector(opts.contentSelector), document.querySelector(opts.fileListSelector), document.querySelector(`${opts.fileListSelector} .contract-verifier-file`)); 142 | }, 143 | }; 144 | //# sourceMappingURL=contract-verifier-ui.js.map -------------------------------------------------------------------------------- /lib/contract-verifier-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"contract-verifier-ui.js","sourceRoot":"","sources":["../src/lib/contract-verifier-ui.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/contract-verifier.d.ts: -------------------------------------------------------------------------------- 1 | interface GetSourcesOptions { 2 | verifier?: string; 3 | httpApiEndpointV4?: string; 4 | testnet?: boolean; 5 | } 6 | export declare type FuncCompilerVersion = string; 7 | export declare type TactVersion = string; 8 | export declare type FiftVersion = FuncCompilerVersion; 9 | export declare type TolkVersion = string; 10 | export declare type FuncCompilerSettings = { 11 | funcVersion: FuncCompilerVersion; 12 | commandLine: string; 13 | }; 14 | export type FiftCliCompileSettings = { 15 | fiftVersion: FiftVersion; 16 | commandLine: string; 17 | }; 18 | export type TactCliCompileSettings = { 19 | tactVersion: TactVersion; 20 | }; 21 | export type TolkCliCompileSettings = { 22 | tolkVersion: TolkVersion; 23 | }; 24 | export type FuncSource = { 25 | name: string; 26 | content: string; 27 | isEntrypoint: boolean; 28 | }; 29 | export type TolkSource = { 30 | name: string; 31 | content: string; 32 | isEntrypoint: boolean; 33 | }; 34 | export type TactSource = { 35 | name: string; 36 | content: string; 37 | }; 38 | export interface SourcesData { 39 | files: (TactSource | FuncSource | TolkSource)[]; 40 | compiler: "func" | "tact" | "fift" | "tolk"; 41 | compilerSettings: FuncCompilerSettings | FiftCliCompileSettings | TolkCliCompileSettings | TactCliCompileSettings; 42 | verificationDate: Date; 43 | ipfsHttpLink: string; 44 | } 45 | type IpfsUrlConverterFunc = (ipfsUrl: string, testnet: boolean) => string; 46 | export declare const ContractVerifier: { 47 | getSourcesJsonUrl(codeCellHash: string, options?: GetSourcesOptions): Promise; 48 | getSourcesData(sourcesJsonUrl: string, options?: { 49 | ipfsConverter?: IpfsUrlConverterFunc; 50 | testnet?: boolean; 51 | }): Promise; 52 | }; 53 | export {}; 54 | -------------------------------------------------------------------------------- /lib/contract-verifier.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.ContractVerifier = void 0; 4 | const ton_1 = require("ton"); 5 | const ton_access_1 = require("@orbs-network/ton-access"); 6 | const sha256_js_1 = require("@aws-crypto/sha256-js"); 7 | const SOURCES_REGISTRY = ton_1.Address.parse("EQD-BJSVUJviud_Qv7Ymfd3qzXdrmV525e3YDzWQoHIAiInL"); 8 | const SOURCES_REGISTRY_TESTNET = ton_1.Address.parse("EQCsdKYwUaXkgJkz2l0ol6qT_WxeRbE_wBCwnEybmR0u5TO8"); 9 | function toSha256Buffer(s) { 10 | const sha = new sha256_js_1.Sha256(); 11 | sha.update(s); 12 | return Buffer.from(sha.digestSync()); 13 | } 14 | function defaultIpfsConverter(ipfs, testnet) { 15 | let endpoint; 16 | if (testnet) { 17 | endpoint = "https://tonsource-testnet.infura-ipfs.io/ipfs/"; 18 | } 19 | else { 20 | endpoint = "https://files.orbs.network/ipfs/"; 21 | } 22 | return ipfs.replace("ipfs://", endpoint); 23 | } 24 | function bigIntFromBuffer(buffer) { 25 | return BigInt(`0x${buffer.toString("hex")}`); 26 | } 27 | exports.ContractVerifier = { 28 | async getSourcesJsonUrl(codeCellHash, options) { 29 | const tc = new ton_1.TonClient4({ 30 | endpoint: options?.httpApiEndpointV4 ?? 31 | (await (0, ton_access_1.getHttpV4Endpoint)({ 32 | network: options.testnet ? "testnet" : "mainnet", 33 | })), 34 | }); 35 | const { last: { seqno }, } = await tc.getLastBlock(); 36 | const args = new ton_1.TupleBuilder(); 37 | args.writeNumber(bigIntFromBuffer(toSha256Buffer(options?.verifier ?? "orbs.com"))); 38 | args.writeNumber(bigIntFromBuffer(Buffer.from(codeCellHash, "base64"))); 39 | const { result: itemAddRes } = await tc.runMethod(seqno, options.testnet ? SOURCES_REGISTRY_TESTNET : SOURCES_REGISTRY, "get_source_item_address", args.build()); 40 | let reader = new ton_1.TupleReader(itemAddRes); 41 | const sourceItemAddr = reader.readAddress(); 42 | const isDeployed = await tc.isContractDeployed(seqno, sourceItemAddr); 43 | if (isDeployed) { 44 | const { result: sourceItemDataRes } = await tc.runMethod(seqno, sourceItemAddr, "get_source_item_data"); 45 | reader = new ton_1.TupleReader(sourceItemDataRes); 46 | const contentCell = reader.skip(3).readCell().beginParse(); 47 | const version = contentCell.loadUint(8); 48 | if (version !== 1) 49 | throw new Error("Unsupported version"); 50 | const ipfsLink = contentCell.loadStringTail(); 51 | return ipfsLink; 52 | } 53 | return null; 54 | }, 55 | async getSourcesData(sourcesJsonUrl, options) { 56 | const ipfsConverter = options.ipfsConverter ?? defaultIpfsConverter; 57 | const ipfsHttpLink = ipfsConverter(sourcesJsonUrl, !!options.testnet); 58 | const verifiedContract = await (await fetch(ipfsConverter(sourcesJsonUrl, !!options.testnet))).json(); 59 | const files = (await Promise.all(verifiedContract.sources.map(async (source) => { 60 | const url = ipfsConverter(source.url, !!options.testnet); 61 | const content = await fetch(url).then((u) => u.text()); 62 | return { 63 | name: source.filename, 64 | content, 65 | isEntrypoint: source.isEntrypoint, 66 | }; 67 | }))) 68 | .reverse() 69 | .sort((a, b) => { 70 | return Number(b.isEntrypoint) - Number(a.isEntrypoint); 71 | }); 72 | return { 73 | files, 74 | verificationDate: new Date(verifiedContract.verificationDate), 75 | compilerSettings: verifiedContract.compilerSettings, 76 | compiler: verifiedContract.compiler, 77 | ipfsHttpLink, 78 | }; 79 | }, 80 | }; 81 | //# sourceMappingURL=contract-verifier.js.map -------------------------------------------------------------------------------- /lib/contract-verifier.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"contract-verifier.js","sourceRoot":"","sources":["../src/lib/contract-verifier.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/dom.d.ts: -------------------------------------------------------------------------------- 1 | export declare const div: (props: any, ...children: any[]) => any; 2 | export declare const code: (props: any, ...children: any[]) => any; 3 | export declare const img: (props: any, ...children: any[]) => any; 4 | export declare function appendChildren(parent: any, children: any): void; 5 | export declare function setStyle(el: any, style: any): void; 6 | export declare function setClass(el: any, className: any): void; 7 | export declare function setProps(el: any, props: any): void; 8 | export declare function createElement(type: any, props: any, ...children: any[]): any; 9 | -------------------------------------------------------------------------------- /lib/dom.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.createElement = exports.setProps = exports.setClass = exports.setStyle = exports.appendChildren = exports.img = exports.code = exports.div = void 0; 4 | const div = (props, ...children) => createElement("div", props, ...children); 5 | exports.div = div; 6 | const code = (props, ...children) => createElement("code", props, ...children); 7 | exports.code = code; 8 | const img = (props, ...children) => createElement("img", props, ...children); 9 | exports.img = img; 10 | function appendChildren(parent, children) { 11 | for (const child of children) { 12 | if (!child) 13 | continue; 14 | switch (typeof child) { 15 | case "string": 16 | const el = document.createTextNode(child); 17 | parent.appendChild(el); 18 | break; 19 | default: 20 | parent.appendChild(child); 21 | break; 22 | } 23 | } 24 | } 25 | exports.appendChildren = appendChildren; 26 | function setStyle(el, style) { 27 | if (typeof style === "string") { 28 | el.setAttribute("style", style); 29 | } 30 | else { 31 | Object.assign(el.style, style); 32 | } 33 | } 34 | exports.setStyle = setStyle; 35 | function setClass(el, className) { 36 | className.split(/\s/).forEach((element) => { 37 | if (element) { 38 | el.classList.add(element); 39 | } 40 | }); 41 | } 42 | exports.setClass = setClass; 43 | function setProps(el, props) { 44 | const eventRegex = /^on([a-z]+)$/i; 45 | for (const propName in props) { 46 | if (!propName) 47 | continue; 48 | if (propName === "style") { 49 | setStyle(el, props[propName]); 50 | } 51 | else if (propName === "className") { 52 | setClass(el, props[propName]); 53 | } 54 | else if (eventRegex.test(propName)) { 55 | const eventToListen = propName.replace(eventRegex, "$1").toLowerCase(); 56 | el.addEventListener(eventToListen, props[propName]); 57 | } 58 | else { 59 | el.setAttribute(propName, props[propName]); 60 | } 61 | } 62 | } 63 | exports.setProps = setProps; 64 | function createElement(type, props, ...children) { 65 | if (typeof type === "function") { 66 | return type(props); 67 | } 68 | else { 69 | const el = document.createElement(type); 70 | if (props && typeof props === "object") { 71 | setProps(el, props); 72 | } 73 | if (children) { 74 | appendChildren(el, children); 75 | } 76 | return el; 77 | } 78 | } 79 | exports.createElement = createElement; 80 | //# sourceMappingURL=dom.js.map -------------------------------------------------------------------------------- /lib/dom.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"dom.js","sourceRoot":"","sources":["../src/lib/dom.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/file-structure.d.ts: -------------------------------------------------------------------------------- 1 | export declare const TreeFile: ({ name }: { 2 | name: any; 3 | }, theme: any) => any; 4 | export declare const TreeFolder: (props: any, theme: any, ...children: any[]) => any; 5 | -------------------------------------------------------------------------------- /lib/file-structure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.TreeFolder = exports.TreeFile = void 0; 7 | const dom_1 = require("./dom"); 8 | const file_white_svg_1 = __importDefault(require("./res/file-white.svg")); 9 | const file_black_svg_1 = __importDefault(require("./res/file-black.svg")); 10 | const folder_closed_white_svg_1 = __importDefault(require("./res/folder-closed-white.svg")); 11 | const folder_closed_black_svg_1 = __importDefault(require("./res/folder-closed-black.svg")); 12 | const folder_open_white_svg_1 = __importDefault(require("./res/folder-open-white.svg")); 13 | const folder_open_black_svg_1 = __importDefault(require("./res/folder-open-black.svg")); 14 | const contract_verifier_ui_1 = require("./contract-verifier-ui"); 15 | const icons = { 16 | dark: { 17 | file: file_white_svg_1.default, 18 | folder: { 19 | open: folder_open_white_svg_1.default, 20 | closed: folder_closed_white_svg_1.default, 21 | }, 22 | }, 23 | light: { 24 | file: file_black_svg_1.default, 25 | folder: { 26 | open: folder_open_black_svg_1.default, 27 | closed: folder_closed_black_svg_1.default, 28 | }, 29 | }, 30 | }; 31 | const svgToInline = (svg) => `data:image/svg+xml;base64,${Buffer.from(svg, "utf8").toString("base64")}`; 32 | const TreeFile = ({ name }, theme) => { 33 | return (0, dom_1.div)({ className: `${contract_verifier_ui_1.classNames.FILE} ${contract_verifier_ui_1.classNames.TREE_ITEM}` }, (0, dom_1.img)({ 34 | src: svgToInline(icons[theme].file), 35 | }), (0, dom_1.div)(null, name)); 36 | }; 37 | exports.TreeFile = TreeFile; 38 | function changeOpened(theme, event) { 39 | const folderHeader = event.target.classList.contains("folder-header") 40 | ? event.target 41 | : event.target.parentElement; 42 | const opened = folderHeader.getAttribute("opened") === "true"; 43 | const newOpened = !opened; 44 | folderHeader.children[0].attributes.src.value = svgToInline(newOpened ? icons[theme].folder.open : icons[theme].folder.closed); 45 | try { 46 | const sibling = folderHeader.nextElementSibling; 47 | if (newOpened) { 48 | sibling.classList.remove("hide"); 49 | } 50 | else { 51 | sibling.classList.add("hide"); 52 | } 53 | } 54 | catch (e) { 55 | console.warn(`No sibling of elem ${folderHeader} found ...`); 56 | } 57 | folderHeader.setAttribute("opened", newOpened); 58 | } 59 | const TreeFolder = (props, theme, ...children) => { 60 | const opened = props.opened || false; 61 | const folderIcon = icons[theme].folder[opened ? "open" : "closed"]; 62 | const folderName = props.name || "unknown"; 63 | return (0, dom_1.div)({ className: contract_verifier_ui_1.classNames.FOLDER_CONTAINER }, (0, dom_1.div)({ 64 | onClick: changeOpened.bind(this, theme), 65 | className: `folder-header ${contract_verifier_ui_1.classNames.FOLDER} ${contract_verifier_ui_1.classNames.TREE_ITEM}`, 66 | opened, 67 | }, (0, dom_1.img)({ 68 | src: svgToInline(folderIcon), 69 | }), (0, dom_1.div)(null, folderName)), (0, dom_1.div)({ className: `${opened ? "" : "hide"} folder-content` }, ...children)); 70 | }; 71 | exports.TreeFolder = TreeFolder; 72 | //# sourceMappingURL=file-structure.js.map -------------------------------------------------------------------------------- /lib/file-structure.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"file-structure.js","sourceRoot":"","sources":["../src/lib/file-structure.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./contract-verifier"; 2 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./contract-verifier"), exports); 18 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /lib/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC"} -------------------------------------------------------------------------------- /lib/web.d.ts: -------------------------------------------------------------------------------- 1 | import { ContractVerifier as _ContractVerifier } from "./contract-verifier"; 2 | import { ContractVerifierUI as _ContractVerifierUI } from "./contract-verifier-ui"; 3 | declare global { 4 | var ContractVerifier: typeof _ContractVerifier; 5 | var ContractVerifierUI: typeof _ContractVerifierUI; 6 | } 7 | export { ContractVerifierUI } from "./contract-verifier-ui"; 8 | export * from "./contract-verifier"; 9 | -------------------------------------------------------------------------------- /lib/web.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.ContractVerifierUI = void 0; 18 | const contract_verifier_1 = require("./contract-verifier"); 19 | const contract_verifier_ui_1 = require("./contract-verifier-ui"); 20 | window.ContractVerifier = contract_verifier_1.ContractVerifier; 21 | window.ContractVerifierUI = contract_verifier_ui_1.ContractVerifierUI; 22 | var contract_verifier_ui_2 = require("./contract-verifier-ui"); 23 | Object.defineProperty(exports, "ContractVerifierUI", { enumerable: true, get: function () { return contract_verifier_ui_2.ContractVerifierUI; } }); 24 | __exportStar(require("./contract-verifier"), exports); 25 | //# sourceMappingURL=web.js.map -------------------------------------------------------------------------------- /lib/web.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/lib/web.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2DAA4E;AAC5E,iEAAmF;AAOnF,MAAM,CAAC,gBAAgB,GAAG,oCAAiB,CAAC;AAC5C,MAAM,CAAC,kBAAkB,GAAG,yCAAmB,CAAC;AAEhD,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAC3B,sDAAoC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ton-community/contract-verifier-sdk", 3 | "version": "1.4.0", 4 | "description": "TON verifier SDK - sources fetcher + code viewer for FunC with code highlighting ", 5 | "exports": { 6 | "node": "./lib/index.js", 7 | "import": "./dist/index.min.js" 8 | }, 9 | "types": "lib/web.d.ts", 10 | "files": [ 11 | "lib/**/**", 12 | "dist/index.min.js" 13 | ], 14 | "scripts": { 15 | "start": "webpack-dev-server --hot", 16 | "npm-publish": "npm publish --access=public", 17 | "cleanup": "rimraf ./lib", 18 | "build:web:min": "node build.js", 19 | "build:web": "rimraf ./dist && npm run build:web:min", 20 | "build": "npm run lint && rimraf ./lib && tsc && npm run build:web", 21 | "format": "prettier --write \"src/**/*.ts\"", 22 | "lint": "npx tslint -p tsconfig.json", 23 | "prepare": "npm run build", 24 | "prepublishOnly": "npm test && npm run lint", 25 | "preversion": "npm run lint", 26 | "version": "npm run format && git add -A src", 27 | "test": "" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "https://github.com/ton-community/contract-verifier-sdk" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/ton-community/contract-verifier-sdk/issues" 35 | }, 36 | "author": "Shahar Yakir", 37 | "license": "MIT", 38 | "homepage": "https://github.com/ton-community/contract-verifier-sdk", 39 | "keywords": [ 40 | "ton", 41 | "source", 42 | "verifier", 43 | "widget", 44 | "sources" 45 | ], 46 | "dependencies": { 47 | "@aws-crypto/sha256-js": "^2.0.2", 48 | "@orbs-network/ton-access": "^2.3.3", 49 | "highlight.js": "11.6.0", 50 | "highlightjs-func": "github:orbs-network/highlightjs-func", 51 | "husky": "^9.0.11", 52 | "prettier": "^3.2.5", 53 | "ton": "^13.4.1", 54 | "ton-core": "^0.48.0" 55 | }, 56 | "devDependencies": { 57 | "@types/node": "^18.11.18", 58 | "esbuild": "^0.16.16", 59 | "esbuild-plugin-polyfill-node": "^0.1.3", 60 | "eslint": "^8.31.0", 61 | "source-map-explorer": "^2.5.3", 62 | "tslint": "^6.1.3", 63 | "tslint-config-prettier": "^1.18.0" 64 | }, 65 | "engines": { 66 | "node": ">=14.16" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/lib/contract-verifier-ui.ts: -------------------------------------------------------------------------------- 1 | import hljs from "highlight.js/lib/core"; 2 | import hljsDefine from "highlightjs-func"; 3 | import { SourcesData } from "./contract-verifier"; 4 | import { div } from "./dom"; 5 | import { TreeFile, TreeFolder } from "./file-structure"; 6 | import style from "./style.css"; 7 | 8 | hljsDefine(hljs); 9 | 10 | type Theme = "light" | "dark"; 11 | 12 | export const classNames = { 13 | CONTAINER: "contract-verifier-container", 14 | FILES: "contract-verifier-files", 15 | FILE: "contract-verifier-file", 16 | FOLDER: "contract-verifier-folder", 17 | TREE_ITEM: "contract-verifier-tree-item", 18 | FOLDER_CONTAINER: "contract-verifier-folder-container", 19 | CODE_CONTAINER: "contract-verifier-code", 20 | CODE_LINES: "contract-verifier-code-lines", 21 | CODE_CONTENT: "contract-verifier-code-content", 22 | }; 23 | 24 | export const ContractVerifierUI = { 25 | _stylesPopulated: { 26 | internal: false, 27 | }, 28 | _populateStyle(theme: "dark" | "light") { 29 | if (!this._stylesPopulated[theme]) { 30 | this._stylesPopulated[theme] = true; 31 | const styleEl = document.createElement("style"); 32 | styleEl.innerHTML = `${ 33 | theme === "light" 34 | ? require("highlight.js/styles/atom-one-light.css").toString() 35 | : require("highlight.js/styles/atom-one-dark.css").toString() 36 | }`; 37 | 38 | document.head.appendChild(styleEl); 39 | } 40 | if (!this._stylesPopulated.internal) { 41 | this._stylesPopulated.internal = true; 42 | const styleEl = document.createElement("style"); 43 | styleEl.innerHTML = style; 44 | document.head.appendChild(styleEl); 45 | } 46 | }, 47 | _populateCode(contentSelector: string, theme: "dark" | "light") { 48 | const codeContainer = document.querySelector(contentSelector); 49 | codeContainer.classList.add(classNames.CODE_CONTAINER); 50 | codeContainer.classList.add(theme); 51 | codeContainer.innerHTML = `
`; 52 | }, 53 | 54 | _setCode( 55 | { name, content }: { name: string; content: string }, 56 | codeWrapperEl: HTMLElement, 57 | filesListEl?: HTMLElement, 58 | fileEl?: HTMLElement, 59 | ) { 60 | if (fileEl?.classList.contains("active")) return; 61 | codeWrapperEl.scrollTo(0, 0); 62 | content = content.trim(); 63 | const codeEl = codeWrapperEl.querySelector("code"); 64 | codeEl.innerHTML = ""; 65 | codeEl.appendChild( 66 | div( 67 | { className: classNames.CODE_LINES }, 68 | content 69 | .split("\n") 70 | .map((_, i) => i + 1) 71 | .join("\n"), 72 | ), 73 | ); 74 | 75 | const contentEl = div({ className: classNames.CODE_CONTENT }, content); 76 | codeEl.appendChild(contentEl); 77 | 78 | if (name.match(/\.fif(t)?$/)) { 79 | contentEl.classList.add("language-fift"); 80 | } else { 81 | contentEl.classList.add("language-func"); 82 | } 83 | 84 | hljs.highlightElement(contentEl); 85 | 86 | filesListEl 87 | ?.querySelector(`.${classNames.FILE}.active`) 88 | ?.classList.remove("active"); 89 | 90 | fileEl?.classList.add("active"); 91 | }, 92 | 93 | setCode(contentSelector: string, content: string) { 94 | this._setCode( 95 | { name: "", content }, 96 | document.querySelector(contentSelector), 97 | ); 98 | }, 99 | 100 | _populateFiles( 101 | fileListSelector: string, 102 | contentSelector: string, 103 | files: { name: string; content: string }[], 104 | theme: "dark" | "light", 105 | ) { 106 | const filePart = document.querySelector(fileListSelector); 107 | filePart.innerHTML = ""; 108 | filePart.classList.add(theme); 109 | filePart.classList.add(classNames.FILES); 110 | 111 | // Prepare folder hierarchy 112 | const root = { 113 | type: "root", 114 | children: [], 115 | }; 116 | 117 | files.forEach((file) => { 118 | const nameParts = Array.from( 119 | file.name.matchAll(/(?:\/|^)([^\/\n]+)/g), 120 | ).map((m) => m[1]); 121 | 122 | const folders = 123 | nameParts.length > 1 ? nameParts.slice(0, nameParts.length - 1) : []; 124 | 125 | let levelToPushTo = root; 126 | 127 | folders.forEach((folder) => { 128 | let existingFolder = levelToPushTo.children.find( 129 | (obj) => obj.type === "folder" && obj.name === folder, 130 | ); 131 | 132 | if (!existingFolder) { 133 | const newLevel = { 134 | type: "folder", 135 | name: folder, 136 | children: [], 137 | }; 138 | levelToPushTo.children.push(newLevel); 139 | 140 | existingFolder = newLevel; 141 | } 142 | 143 | levelToPushTo = existingFolder; 144 | }); 145 | 146 | levelToPushTo.children.push({ 147 | type: "file", 148 | name: nameParts[nameParts.length - 1], 149 | content: file.content, 150 | }); 151 | }); 152 | 153 | function processLevel(level) { 154 | return level.children 155 | .filter((obj) => obj.type === "file") 156 | .map((child) => { 157 | const file = TreeFile({ name: child.name }, theme); 158 | file.onclick = () => { 159 | ContractVerifierUI._setCode( 160 | { name: child.name, content: child.content }, 161 | document.querySelector(contentSelector), 162 | document.querySelector(fileListSelector), 163 | file, 164 | ); 165 | }; 166 | return file; 167 | }) 168 | .concat( 169 | level.children 170 | .filter((obj) => obj.type === "folder") 171 | .map((child) => 172 | TreeFolder( 173 | { name: child.name, opened: true }, 174 | theme, 175 | ...processLevel(child), 176 | ), 177 | ), 178 | ); 179 | } 180 | 181 | processLevel(root).forEach((el) => filePart.appendChild(el)); 182 | }, 183 | 184 | _populateContainer(selector: string, hideLineNumbers: boolean) { 185 | const el = document.querySelector(selector); 186 | el.classList.add(classNames.CONTAINER); 187 | 188 | if (!hideLineNumbers) { 189 | el.classList.add("lineNumbers"); 190 | } 191 | }, 192 | 193 | loadSourcesData( 194 | sourcesData: SourcesData, 195 | opts: { 196 | containerSelector: string; 197 | fileListSelector?: string; 198 | contentSelector: string; 199 | theme: Theme; 200 | hideLineNumbers?: boolean; 201 | }, 202 | ) { 203 | this._populateContainer(opts.containerSelector, !!opts.hideLineNumbers); 204 | 205 | if (opts.fileListSelector) { 206 | this._populateFiles( 207 | opts.fileListSelector, 208 | opts.contentSelector, 209 | sourcesData.files, 210 | opts.theme, 211 | ); 212 | } 213 | this._populateStyle(opts.theme); 214 | this._populateCode(opts.contentSelector, opts.theme); 215 | this._setCode( 216 | sourcesData.files[0], 217 | document.querySelector(opts.contentSelector), 218 | document.querySelector(opts.fileListSelector), 219 | document.querySelector( 220 | `${opts.fileListSelector} .contract-verifier-file`, 221 | ), // Get first file 222 | ); 223 | }, 224 | }; 225 | -------------------------------------------------------------------------------- /src/lib/contract-verifier.ts: -------------------------------------------------------------------------------- 1 | import { TonClient4, Address, TupleReader, TupleBuilder } from "ton"; 2 | import { getHttpV4Endpoint } from "@orbs-network/ton-access"; 3 | import { Sha256 } from "@aws-crypto/sha256-js"; 4 | 5 | interface GetSourcesOptions { 6 | verifier?: string; 7 | httpApiEndpointV4?: string; 8 | testnet?: boolean; 9 | } 10 | 11 | export declare type FuncCompilerVersion = string; 12 | export declare type TactVersion = string; 13 | export declare type FiftVersion = FuncCompilerVersion; // Fift is tied to a FunC version 14 | export declare type TolkVersion = string; 15 | 16 | export declare type FuncCompilerSettings = { 17 | funcVersion: FuncCompilerVersion; 18 | commandLine: string; 19 | }; 20 | export type FiftCliCompileSettings = { 21 | fiftVersion: FiftVersion; 22 | commandLine: string; 23 | }; 24 | export type TactCliCompileSettings = { 25 | tactVersion: TactVersion; 26 | }; 27 | 28 | export type TolkCliCompileSettings = { 29 | tolkVersion: TolkVersion; 30 | }; 31 | 32 | 33 | export type FuncSource = { 34 | name: string; 35 | content: string; 36 | isEntrypoint: boolean; 37 | }; 38 | export type TolkSource = { 39 | name: string; 40 | content: string; 41 | isEntrypoint: boolean; 42 | } 43 | 44 | export type TactSource = { 45 | name: string; 46 | content: string; 47 | }; 48 | 49 | export interface SourcesData { 50 | files: (TactSource | FuncSource | TolkSource)[]; 51 | compiler: "func" | "tact" | "fift" | "tolk"; 52 | compilerSettings: 53 | | FuncCompilerSettings 54 | | FiftCliCompileSettings 55 | | TolkCliCompileSettings 56 | | TactCliCompileSettings; 57 | verificationDate: Date; 58 | ipfsHttpLink: string; 59 | } 60 | 61 | type IpfsUrlConverterFunc = (ipfsUrl: string, testnet: boolean) => string; 62 | 63 | const SOURCES_REGISTRY = Address.parse( 64 | "EQD-BJSVUJviud_Qv7Ymfd3qzXdrmV525e3YDzWQoHIAiInL", 65 | ); 66 | const SOURCES_REGISTRY_TESTNET = Address.parse( 67 | "EQCsdKYwUaXkgJkz2l0ol6qT_WxeRbE_wBCwnEybmR0u5TO8", 68 | ); 69 | 70 | function toSha256Buffer(s: string) { 71 | const sha = new Sha256(); 72 | sha.update(s); 73 | return Buffer.from(sha.digestSync()); 74 | } 75 | 76 | function defaultIpfsConverter(ipfs: string, testnet: boolean) { 77 | let endpoint: string; 78 | 79 | if (testnet) { 80 | endpoint = "https://tonsource-testnet.infura-ipfs.io/ipfs/"; 81 | } else { 82 | endpoint = "https://files.orbs.network/ipfs/"; 83 | } 84 | 85 | return ipfs.replace("ipfs://", endpoint); 86 | } 87 | 88 | function bigIntFromBuffer(buffer: Buffer) { 89 | return BigInt(`0x${buffer.toString("hex")}`); 90 | } 91 | 92 | export const ContractVerifier = { 93 | async getSourcesJsonUrl( 94 | codeCellHash: string, 95 | options?: GetSourcesOptions, 96 | ): Promise { 97 | const tc = new TonClient4({ 98 | endpoint: 99 | options?.httpApiEndpointV4 ?? 100 | (await getHttpV4Endpoint({ 101 | network: options.testnet ? "testnet" : "mainnet", 102 | })), 103 | }); 104 | const { 105 | last: { seqno }, 106 | } = await tc.getLastBlock(); 107 | 108 | const args = new TupleBuilder(); 109 | args.writeNumber( 110 | bigIntFromBuffer(toSha256Buffer(options?.verifier ?? "orbs.com")), 111 | ); 112 | args.writeNumber(bigIntFromBuffer(Buffer.from(codeCellHash, "base64"))); 113 | const { result: itemAddRes } = await tc.runMethod( 114 | seqno, 115 | options.testnet ? SOURCES_REGISTRY_TESTNET : SOURCES_REGISTRY, 116 | "get_source_item_address", 117 | args.build(), 118 | ); 119 | 120 | let reader = new TupleReader(itemAddRes); 121 | const sourceItemAddr = reader.readAddress(); 122 | const isDeployed = await tc.isContractDeployed(seqno, sourceItemAddr); 123 | 124 | if (isDeployed) { 125 | const { result: sourceItemDataRes } = await tc.runMethod( 126 | seqno, 127 | sourceItemAddr, 128 | "get_source_item_data", 129 | ); 130 | 131 | reader = new TupleReader(sourceItemDataRes); 132 | const contentCell = reader.skip(3).readCell().beginParse(); 133 | const version = contentCell.loadUint(8); 134 | if (version !== 1) throw new Error("Unsupported version"); 135 | const ipfsLink = contentCell.loadStringTail(); 136 | 137 | return ipfsLink; 138 | } 139 | return null; 140 | }, 141 | 142 | async getSourcesData( 143 | sourcesJsonUrl: string, 144 | options?: { 145 | ipfsConverter?: IpfsUrlConverterFunc; 146 | testnet?: boolean; 147 | }, 148 | ): Promise { 149 | const ipfsConverter = options.ipfsConverter ?? defaultIpfsConverter; 150 | const ipfsHttpLink = ipfsConverter(sourcesJsonUrl, !!options.testnet); 151 | 152 | const verifiedContract = await ( 153 | await fetch(ipfsConverter(sourcesJsonUrl, !!options.testnet)) 154 | ).json(); 155 | 156 | const files = ( 157 | await Promise.all( 158 | verifiedContract.sources.map( 159 | async (source: { 160 | url: string; 161 | filename: string; 162 | isEntrypoint?: boolean; 163 | }) => { 164 | const url = ipfsConverter(source.url, !!options.testnet); 165 | const content = await fetch(url).then((u) => u.text()); 166 | return { 167 | name: source.filename, 168 | content, 169 | isEntrypoint: source.isEntrypoint, 170 | }; 171 | }, 172 | ), 173 | ) 174 | ) 175 | .reverse() 176 | .sort((a, b) => { 177 | return Number(b.isEntrypoint) - Number(a.isEntrypoint); 178 | }); 179 | 180 | return { 181 | files, 182 | verificationDate: new Date(verifiedContract.verificationDate), 183 | compilerSettings: verifiedContract.compilerSettings, 184 | compiler: verifiedContract.compiler, 185 | ipfsHttpLink, 186 | }; 187 | }, 188 | }; 189 | -------------------------------------------------------------------------------- /src/lib/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.css"; 2 | declare module "*.svg"; 3 | -------------------------------------------------------------------------------- /src/lib/dom.ts: -------------------------------------------------------------------------------- 1 | export const div = (props, ...children) => 2 | createElement("div", props, ...children); 3 | export const code = (props, ...children) => 4 | createElement("code", props, ...children); 5 | export const img = (props, ...children) => 6 | createElement("img", props, ...children); 7 | 8 | export function appendChildren(parent, children) { 9 | for (const child of children) { 10 | if (!child) continue; 11 | switch (typeof child) { 12 | case "string": 13 | const el = document.createTextNode(child); 14 | parent.appendChild(el); 15 | break; 16 | default: 17 | parent.appendChild(child); 18 | break; 19 | } 20 | } 21 | } 22 | 23 | export function setStyle(el, style) { 24 | if (typeof style === "string") { 25 | el.setAttribute("style", style); 26 | } else { 27 | Object.assign(el.style, style); 28 | } 29 | } 30 | 31 | export function setClass(el, className) { 32 | className.split(/\s/).forEach((element) => { 33 | if (element) { 34 | el.classList.add(element); 35 | } 36 | }); 37 | } 38 | 39 | export function setProps(el, props) { 40 | const eventRegex = /^on([a-z]+)$/i; 41 | for (const propName in props) { 42 | if (!propName) continue; 43 | 44 | if (propName === "style") { 45 | setStyle(el, props[propName]); 46 | } else if (propName === "className") { 47 | setClass(el, props[propName]); 48 | } else if (eventRegex.test(propName)) { 49 | const eventToListen = propName.replace(eventRegex, "$1").toLowerCase(); 50 | el.addEventListener(eventToListen, props[propName]); 51 | } else { 52 | el.setAttribute(propName, props[propName]); 53 | } 54 | } 55 | } 56 | 57 | export function createElement(type, props, ...children) { 58 | if (typeof type === "function") { 59 | return type(props); 60 | } else { 61 | const el = document.createElement(type); 62 | if (props && typeof props === "object") { 63 | setProps(el, props); 64 | } 65 | if (children) { 66 | appendChildren(el, children); 67 | } 68 | return el; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/lib/file-structure.ts: -------------------------------------------------------------------------------- 1 | import { div, img } from "./dom"; 2 | import fileWhite from "./res/file-white.svg"; 3 | import fileBlack from "./res/file-black.svg"; 4 | import folderClosedWhite from "./res/folder-closed-white.svg"; 5 | import folderClosedBlack from "./res/folder-closed-black.svg"; 6 | import folderOpenWhite from "./res/folder-open-white.svg"; 7 | import folderOpenBlack from "./res/folder-open-black.svg"; 8 | import { classNames } from "./contract-verifier-ui"; 9 | 10 | const icons = { 11 | dark: { 12 | file: fileWhite, 13 | folder: { 14 | open: folderOpenWhite, 15 | closed: folderClosedWhite, 16 | }, 17 | }, 18 | light: { 19 | file: fileBlack, 20 | folder: { 21 | open: folderOpenBlack, 22 | closed: folderClosedBlack, 23 | }, 24 | }, 25 | }; 26 | 27 | const svgToInline = (svg) => 28 | `data:image/svg+xml;base64,${Buffer.from(svg, "utf8").toString("base64")}`; 29 | 30 | export const TreeFile = ({ name }, theme) => { 31 | return div( 32 | { className: `${classNames.FILE} ${classNames.TREE_ITEM}` }, 33 | img({ 34 | src: svgToInline(icons[theme].file), 35 | }), 36 | div(null, name), 37 | ); 38 | }; 39 | 40 | function changeOpened(theme, event) { 41 | const folderHeader = event.target.classList.contains("folder-header") 42 | ? event.target 43 | : event.target.parentElement; 44 | const opened = folderHeader.getAttribute("opened") === "true"; 45 | const newOpened = !opened; 46 | 47 | folderHeader.children[0].attributes.src.value = svgToInline( 48 | newOpened ? icons[theme].folder.open : icons[theme].folder.closed, 49 | ); 50 | 51 | try { 52 | const sibling = folderHeader.nextElementSibling; 53 | if (newOpened) { 54 | sibling.classList.remove("hide"); 55 | } else { 56 | sibling.classList.add("hide"); 57 | } 58 | } catch (e) { 59 | console.warn(`No sibling of elem ${folderHeader} found ...`); 60 | } 61 | 62 | folderHeader.setAttribute("opened", newOpened); 63 | } 64 | 65 | export const TreeFolder = (props, theme, ...children) => { 66 | const opened = props.opened || false; 67 | const folderIcon = icons[theme].folder[opened ? "open" : "closed"]; 68 | const folderName = props.name || "unknown"; 69 | 70 | return div( 71 | { className: classNames.FOLDER_CONTAINER }, 72 | div( 73 | { 74 | onClick: changeOpened.bind(this, theme), 75 | className: `folder-header ${classNames.FOLDER} ${classNames.TREE_ITEM}`, 76 | opened, 77 | }, 78 | img({ 79 | src: svgToInline(folderIcon), 80 | }), 81 | div(null, folderName), 82 | ), 83 | div({ className: `${opened ? "" : "hide"} folder-content` }, ...children), 84 | ); 85 | }; 86 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./contract-verifier"; 2 | -------------------------------------------------------------------------------- /src/lib/res/file-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/lib/res/file-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/lib/res/folder-closed-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/lib/res/folder-closed-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/lib/res/folder-open-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/lib/res/folder-open-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/lib/style.css: -------------------------------------------------------------------------------- 1 | .contract-verifier-container { 2 | display: flex; 3 | height: 100%; 4 | } 5 | 6 | .contract-verifier-code { 7 | text-align: left; 8 | overflow: auto; 9 | height: 100%; 10 | width: 100%; 11 | } 12 | 13 | .contract-verifier-code.dark { 14 | background: #232222; 15 | } 16 | 17 | .contract-verifier-code code { 18 | display: flex; 19 | padding: 0.5em; 20 | } 21 | 22 | .contract-verifier-code code div { 23 | background: transparent; 24 | } 25 | 26 | .contract-verifier-code code .contract-verifier-code-lines { 27 | padding: 0 20px 0 0; 28 | text-align: right; 29 | display: none; 30 | } 31 | 32 | .contract-verifier-container.lineNumbers .contract-verifier-code-lines { 33 | display: initial; 34 | } 35 | 36 | .contract-verifier-code code.dark .contract-verifier-code-lines { 37 | color: #7e7e7e; 38 | } 39 | 40 | .contract-verifier-code code.light .contract-verifier-code-lines { 41 | color: #728a96; 42 | } 43 | 44 | .contract-verifier-code pre { 45 | margin: 0; 46 | } 47 | 48 | .contract-verifier-files { 49 | text-align: left; 50 | flex-shrink: 0; 51 | display: flex; 52 | flex-direction: column; 53 | width: 200px; 54 | overflow-y: auto; 55 | } 56 | 57 | .contract-verifier-files.dark { 58 | background: #28292d; 59 | color: white; 60 | } 61 | 62 | .contract-verifier-files.light { 63 | background: #fff; 64 | } 65 | 66 | .contract-verifier-tree-item { 67 | padding: 10px 6px; 68 | cursor: pointer; 69 | display: flex; 70 | gap: 4px; 71 | user-select: none; 72 | } 73 | 74 | .contract-verifier-files.dark .contract-verifier-tree-item:hover { 75 | filter: brightness(0.8); 76 | } 77 | 78 | .contract-verifier-files.light .contract-verifier-tree-item:hover { 79 | background-color: #f6f6f6; 80 | } 81 | 82 | .contract-verifier-files.dark .contract-verifier-file.active { 83 | background: #232222; 84 | } 85 | 86 | .contract-verifier-files.light .contract-verifier-file.active { 87 | background: #f2f2f2; 88 | } 89 | 90 | .contract-verifier-files .hide { 91 | display: none; 92 | } 93 | 94 | .contract-verifier-folder-container > .folder-content { 95 | padding-left: 12px; 96 | } 97 | -------------------------------------------------------------------------------- /src/lib/web.ts: -------------------------------------------------------------------------------- 1 | import { ContractVerifier as _ContractVerifier } from "./contract-verifier"; 2 | import { ContractVerifierUI as _ContractVerifierUI } from "./contract-verifier-ui"; 3 | 4 | declare global { 5 | var ContractVerifier: typeof _ContractVerifier; 6 | var ContractVerifierUI: typeof _ContractVerifierUI; 7 | } 8 | 9 | window.ContractVerifier = _ContractVerifier; 10 | window.ContractVerifierUI = _ContractVerifierUI; 11 | 12 | export { ContractVerifierUI } from "./contract-verifier-ui"; 13 | export * from "./contract-verifier"; 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "outDir": "./lib", 7 | "strict": false, 8 | "sourceMap": true, 9 | "esModuleInterop": true, 10 | "isolatedModules": true 11 | }, 12 | "include": ["src"], 13 | "exclude": ["src/demo", "build", "example", "node_modules", "lib"] 14 | } 15 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended", 4 | "tslint-config-prettier" 5 | ], 6 | "rules": { 7 | "no-console": false, 8 | "comment-format": false, 9 | "no-empty": false 10 | } 11 | } --------------------------------------------------------------------------------